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 |