| OLD | NEW |
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2016 Eyeo GmbH | 3 * Copyright (C) 2006-2016 Eyeo GmbH |
| 4 * | 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 * | 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 if (!frames) | 111 if (!frames) |
| 112 frames = framesOfTabs[tabId] = Object.create(null); | 112 frames = framesOfTabs[tabId] = Object.create(null); |
| 113 | 113 |
| 114 let frame = frames[frameId]; | 114 let frame = frames[frameId]; |
| 115 if (!frame) | 115 if (!frame) |
| 116 frame = frames[frameId] = {}; | 116 frame = frames[frameId] = {}; |
| 117 | 117 |
| 118 return frame; | 118 return frame; |
| 119 } | 119 } |
| 120 | 120 |
| 121 chrome.webNavigation.onBeforeNavigate.addListener(details => | 121 function updatePageFrameStructure(frameId, tabId, url) |
| 122 { | |
| 123 // Capture parent frame here because onCommitted doesn't get this info. | |
| 124 let frame = createFrame(details.tabId, details.frameId); | |
| 125 frame.parent = framesOfTabs[details.tabId][details.parentFrameId] || null; | |
| 126 }); | |
| 127 | |
| 128 let eagerlyUpdatedPages = new ext.PageMap(); | |
| 129 | |
| 130 ext._updatePageFrameStructure = (frameId, tabId, url, eager) => | |
| 131 { | 122 { |
| 132 if (frameId == 0) | 123 if (frameId == 0) |
| 133 { | 124 { |
| 134 let page = new Page({id: tabId, url: url}); | 125 let page = new Page({id: tabId, url: url}); |
| 135 | 126 |
| 136 if (eagerlyUpdatedPages.get(page) != url) | 127 chrome.tabs.get(tabId, () => |
| 137 { | 128 { |
| 138 ext._removeFromAllPageMaps(tabId); | 129 // If the tab is prerendered, chrome.tabs.get() sets |
| 139 | 130 // chrome.runtime.lastError and we have to dispatch the onLoading event, |
| 140 // When a sitekey header is received we must immediately update the page | 131 // since the onUpdated event isn't dispatched for prerendered tabs. |
| 141 // structure in order to record and use the key. We want to avoid | 132 // However, we have to keep relying on the unUpdated event for tabs that |
| 142 // trashing the page structure if the onCommitted event is then fired | 133 // are already visible. Otherwise browser action changes get overridden |
| 143 // for the page. | 134 // when Chrome automatically resets them on navigation. |
| 144 if (eager) | 135 if (chrome.runtime.lastError) |
| 145 eagerlyUpdatedPages.set(page, url); | 136 ext.pages.onLoading._dispatch(page); |
| 146 | 137 }); |
| 147 chrome.tabs.get(tabId, () => | |
| 148 { | |
| 149 // If the tab is prerendered, chrome.tabs.get() sets | |
| 150 // chrome.runtime.lastError and we have to dispatch the onLoading even
t, | |
| 151 // since the onUpdated event isn't dispatched for prerendered tabs. | |
| 152 // However, we have to keep relying on the unUpdated event for tabs th
at | |
| 153 // are already visible. Otherwise browser action changes get overridde
n | |
| 154 // when Chrome automatically resets them on navigation. | |
| 155 if (chrome.runtime.lastError) | |
| 156 ext.pages.onLoading._dispatch(page); | |
| 157 }); | |
| 158 } | |
| 159 } | 138 } |
| 160 | 139 |
| 161 // Update frame URL in frame structure | 140 // Update frame URL in frame structure |
| 162 let frame = createFrame(tabId, frameId); | 141 let frame = createFrame(tabId, frameId); |
| 163 frame.url = new URL(url); | 142 frame.url = new URL(url); |
| 164 }; | 143 }; |
| 165 | 144 |
| 166 chrome.webNavigation.onCommitted.addListener(details => | 145 chrome.webNavigation.onCommitted.addListener(details => |
| 167 { | 146 { |
| 168 ext._updatePageFrameStructure(details.frameId, details.tabId, details.url); | 147 updatePageFrameStructure(details.frameId, details.tabId, details.url); |
| 148 }); |
| 149 |
| 150 chrome.webRequest.onHeadersReceived.addListener(details => |
| 151 { |
| 152 // Ideally we would only need the above chrome.webNavigation.onCommitted |
| 153 // listener to update the page state but unfortunately pages can make web |
| 154 // requests before their onCommitted event fires[1]. |
| 155 // So for HTTP/S requests we can also use onHeadersReceived, being careful |
| 156 // to ignore responses which won't directly result in a navigation, for |
| 157 // example redirections. |
| 158 // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=665843 |
| 159 /**** FIXME - Check Chromium code to ensure we got these right! ****/ |
| 160 if (!(details.statusCode > 299 && details.statusCode < 400 && |
| 161 details.statusCode != 304) || details.statusCode == 204) |
| 162 updatePageFrameStructure(details.frameId, details.tabId, details.url); |
| 163 }, {types: ["main_frame", "sub_frame"], urls: ["http://*/*", "https://*/*"]}); |
| 164 |
| 165 chrome.webNavigation.onBeforeNavigate.addListener(details => |
| 166 { |
| 167 // Capture parent frame here because onCommitted doesn't get this info. |
| 168 let frame = createFrame(details.tabId, details.frameId); |
| 169 frame.parent = framesOfTabs[details.tabId][details.parentFrameId] || null; |
| 170 |
| 171 // Since we can only listen for HTTP/S requests with onHeadersReceived we |
| 172 // must update the page structure here for other navigations which might |
| 173 // result in further requests. |
| 174 let url = new URL(details.url); |
| 175 if (url.protocol == "about:" || url.protocol == "data:") |
| 176 updatePageFrameStructure(details.frameId, details.tabId, details.url); |
| 169 }); | 177 }); |
| 170 | 178 |
| 171 function forgetTab(tabId) | 179 function forgetTab(tabId) |
| 172 { | 180 { |
| 173 ext.pages.onRemoved._dispatch(tabId); | 181 ext.pages.onRemoved._dispatch(tabId); |
| 174 | 182 |
| 175 ext._removeFromAllPageMaps(tabId); | 183 ext._removeFromAllPageMaps(tabId); |
| 176 delete framesOfTabs[tabId]; | 184 delete framesOfTabs[tabId]; |
| 177 } | 185 } |
| 178 | 186 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 chrome.browserAction.setBadgeBackgroundColor({ | 235 chrome.browserAction.setBadgeBackgroundColor({ |
| 228 tabId: this._tabId, | 236 tabId: this._tabId, |
| 229 color: this._changes.badgeColor | 237 color: this._changes.badgeColor |
| 230 }); | 238 }); |
| 231 } | 239 } |
| 232 | 240 |
| 233 this._changes = null; | 241 this._changes = null; |
| 234 }, | 242 }, |
| 235 _queueChanges() | 243 _queueChanges() |
| 236 { | 244 { |
| 237 chrome.tabs.get(this._tabId, function() | 245 chrome.tabs.get(this._tabId, () => |
| 238 { | 246 { |
| 239 // If the tab is prerendered, chrome.tabs.get() sets | 247 // If the tab is prerendered, chrome.tabs.get() sets |
| 240 // chrome.runtime.lastError and we have to delay our changes | 248 // chrome.runtime.lastError and we have to delay our changes |
| 241 // until the currently visible tab is replaced with the | 249 // until the currently visible tab is replaced with the |
| 242 // prerendered tab. Otherwise chrome.browserAction.set* fails. | 250 // prerendered tab. Otherwise chrome.browserAction.set* fails. |
| 243 if (chrome.runtime.lastError) | 251 if (chrome.runtime.lastError) |
| 244 { | 252 { |
| 245 let onReplaced = (addedTabId, removedTabId) => | 253 let onReplaced = (addedTabId, removedTabId) => |
| 246 { | 254 { |
| 247 if (addedTabId == this._tabId) | 255 if (addedTabId == this._tabId) |
| 248 { | 256 { |
| 249 chrome.tabs.onReplaced.removeListener(onReplaced); | 257 chrome.tabs.onReplaced.removeListener(onReplaced); |
| 250 this._applyChanges(); | 258 this._applyChanges(); |
| 251 } | 259 } |
| 252 }; | 260 }; |
| 253 chrome.tabs.onReplaced.addListener(onReplaced); | 261 chrome.tabs.onReplaced.addListener(onReplaced); |
| 254 } | 262 } |
| 255 else | 263 else |
| 256 { | 264 { |
| 257 this._applyChanges(); | 265 this._applyChanges(); |
| 258 } | 266 } |
| 259 }.bind(this)); | 267 }); |
| 260 }, | 268 }, |
| 261 _addChange(name, value) | 269 _addChange(name, value) |
| 262 { | 270 { |
| 263 if (!this._changes) | 271 if (!this._changes) |
| 264 { | 272 { |
| 265 this._changes = {}; | 273 this._changes = {}; |
| 266 this._queueChanges(); | 274 this._queueChanges(); |
| 267 } | 275 } |
| 268 | 276 |
| 269 this._changes[name] = value; | 277 this._changes[name] = value; |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 ext.windows = { | 609 ext.windows = { |
| 602 create(createData, callback) | 610 create(createData, callback) |
| 603 { | 611 { |
| 604 chrome.windows.create(createData, createdWindow => | 612 chrome.windows.create(createData, createdWindow => |
| 605 { | 613 { |
| 606 afterTabLoaded(callback)(createdWindow.tabs[0]); | 614 afterTabLoaded(callback)(createdWindow.tabs[0]); |
| 607 }); | 615 }); |
| 608 } | 616 } |
| 609 }; | 617 }; |
| 610 } | 618 } |
| OLD | NEW |