Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: ext/background.js

Issue 29958567: Issue 7104 - Clear style sheets when frame structure is updated (Closed) Base URL: https://hg.adblockplus.org/adblockpluschrome/
Left Patch Set: Created Dec. 4, 2018, 2:33 p.m.
Right Patch Set: Update comment Created Dec. 19, 2018, 1:47 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | lib/contentFiltering.js » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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-present eyeo GmbH 3 * Copyright (C) 2006-present 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 framesOfTabs.set(tabId, frames); 126 framesOfTabs.set(tabId, frames);
127 } 127 }
128 128
129 let frame = frames.get(frameId); 129 let frame = frames.get(frameId);
130 if (!frame) 130 if (!frame)
131 { 131 {
132 frame = {}; 132 frame = {};
133 frames.set(frameId, frame); 133 frames.set(frameId, frame);
134 } 134 }
135 135
136 frame.state = Object.create(null);
137
136 return frame; 138 return frame;
137 } 139 }
138 140
139 function updatePageFrameStructure(frameId, tabId, url, parentFrameId) 141 function updatePageFrameStructure(frameId, tabId, url, parentFrameId)
140 { 142 {
141 if (frameId == 0) 143 if (frameId == 0)
142 { 144 {
143 let page = new Page({id: tabId, url}); 145 let page = new Page({id: tabId, url});
144 146
145 removeFromAllPageMaps(tabId); 147 removeFromAllPageMaps(tabId);
146 148
147 browser.tabs.get(tabId, () => 149 browser.tabs.get(tabId, () =>
148 { 150 {
149 // If the tab is prerendered, browser.tabs.get() sets 151 // If the tab is prerendered, browser.tabs.get() sets
150 // browser.runtime.lastError and we have to dispatch the onLoading 152 // browser.runtime.lastError and we have to dispatch the onLoading
151 // event, since the onUpdated event isn't dispatched for prerendered 153 // event, since the onUpdated event isn't dispatched for prerendered
152 // tabs. However, we have to keep relying on the onUpdated event for 154 // tabs. However, we have to keep relying on the onUpdated event for
153 // tabs that are already visible. Otherwise browser action changes get 155 // tabs that are already visible. Otherwise browser action changes get
154 // overridden when Chrome automatically resets them on navigation. 156 // overridden when Chrome automatically resets them on navigation.
155 if (browser.runtime.lastError) 157 if (browser.runtime.lastError)
156 ext.pages.onLoading._dispatch(page); 158 ext.pages.onLoading._dispatch(page);
157 }); 159 });
158 } 160 }
159 161
160 // Update frame URL and parent in frame structure 162 // Update frame URL and parent in frame structure
161 let frame = createFrame(tabId, frameId); 163 let frame = createFrame(tabId, frameId);
162 frame.url = new URL(url); 164 frame.url = new URL(url);
163 165
164 let frames = framesOfTabs.get(tabId); 166 let frames = framesOfTabs.get(tabId);
165 let parentFrame = frames.get(parentFrameId); 167 let parentFrame;
166 if (!parentFrame && parentFrameId > 0) 168
167 parentFrame = frames.get(0); 169 if (parentFrameId > -1)
170 {
171 if (parentFrameId != frameId)
172 parentFrame = frames.get(parentFrameId);
173 if (!parentFrame && parentFrameId != 0 && frameId != 0)
174 parentFrame = frames.get(0);
175 }
168 176
169 if (parentFrame) 177 if (parentFrame)
170 frame.parent = parentFrame; 178 frame.parent = parentFrame;
171
172 frame.injectedStyleSheets = null;
173 } 179 }
174 180
175 browser.webRequest.onHeadersReceived.addListener(details => 181 browser.webRequest.onHeadersReceived.addListener(details =>
176 { 182 {
177 // We have to update the frame structure when switching to a new 183 // We have to update the frame structure when switching to a new
178 // document, so that we process any further requests made by that 184 // document, so that we process any further requests made by that
179 // document in the right context. Unfortunately, we cannot rely 185 // document in the right context. Unfortunately, we cannot rely
180 // on webNavigation.onCommitted since it isn't guaranteed to fire 186 // on webNavigation.onCommitted since it isn't guaranteed to fire
181 // before any subresources start downloading[1]. As an 187 // before any subresources start downloading[1]. As an
182 // alternative we use webRequest.onHeadersReceived for HTTP(S) 188 // alternative we use webRequest.onHeadersReceived for HTTP(S)
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 // frames here. 265 // frames here.
260 if (details.url.startsWith("about:") || details.url.startsWith("data:")) 266 if (details.url.startsWith("about:") || details.url.startsWith("data:"))
261 { 267 {
262 updatePageFrameStructure(details.frameId, details.tabId, details.url, 268 updatePageFrameStructure(details.frameId, details.tabId, details.url,
263 details.parentFrameId); 269 details.parentFrameId);
264 } 270 }
265 }); 271 });
266 272
267 browser.webNavigation.onCommitted.addListener(details => 273 browser.webNavigation.onCommitted.addListener(details =>
268 { 274 {
275 // Unfortunately, Chrome doesn't provide the parent frame ID in the
276 // onCommitted event[1]. So, unless the navigation is for a top-level
277 // frame, we assume its parent frame is the top-level frame.
278 // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=908380
279 let {frameId, tabId, parentFrameId, url} = details;
280 if (typeof parentFrameId == "undefined")
281 parentFrameId = frameId == 0 ? -1 : 0;
282
269 // We have to update the frame structure for documents that weren't 283 // We have to update the frame structure for documents that weren't
270 // loaded over HTTP (including documents cached by Service Workers), 284 // loaded over HTTP (including documents cached by Service Workers),
271 // when the navigation occurs. However, we must be careful to not 285 // when the navigation occurs. However, we must be careful to not
272 // update the state of the same document twice, otherewise the number 286 // update the state of the same document twice, otherewise the number
273 // of any ads blocked already and any recorded sitekey could get lost. 287 // of any ads blocked already and any recorded sitekey could get lost.
274 let frame = ext.getFrame(details.tabId, details.frameId); 288 let frame = ext.getFrame(tabId, frameId);
275 if (!frame || frame.url.href != details.url) 289 if (!frame || frame.url.href != url)
276 { 290 updatePageFrameStructure(frameId, tabId, url, parentFrameId);
277 updatePageFrameStructure(details.frameId, details.tabId, details.url,
278 details.parentFrameId);
279 }
280 }); 291 });
281 292
282 function forgetTab(tabId) 293 function forgetTab(tabId)
283 { 294 {
284 ext.pages.onRemoved._dispatch(tabId); 295 ext.pages.onRemoved._dispatch(tabId);
285 296
286 removeFromAllPageMaps(tabId); 297 removeFromAllPageMaps(tabId);
287 framesOfTabs.delete(tabId); 298 framesOfTabs.delete(tabId);
288 } 299 }
289 300
(...skipping 13 matching lines...) Expand all
303 /* Browser actions */ 314 /* Browser actions */
304 315
305 let BrowserAction = function(tabId) 316 let BrowserAction = function(tabId)
306 { 317 {
307 this._tabId = tabId; 318 this._tabId = tabId;
308 this._changes = null; 319 this._changes = null;
309 }; 320 };
310 BrowserAction.prototype = { 321 BrowserAction.prototype = {
311 _applyChanges() 322 _applyChanges()
312 { 323 {
313 if ("iconPath" in this._changes) 324 return Promise.all(Object.keys(this._changes).map(change =>
314 { 325 {
315 // Firefox for Android displays the browser action not as an icon but 326 // Firefox for Android displays the browser action not as an icon but
316 // as a menu item. There is no icon, but such an option may be added in 327 // as a menu item. There is no icon, but such an option may be added
317 // the future. 328 // in the future.
318 // https://bugzilla.mozilla.org/show_bug.cgi?id=1331746 329 // https://bugzilla.mozilla.org/show_bug.cgi?id=1331746
319 if ("setIcon" in browser.browserAction) 330 if (change == "iconPath" && "setIcon" in browser.browserAction)
320 { 331 {
321 let path = { 332 let path = {
322 16: this._changes.iconPath.replace("$size", "16"), 333 16: this._changes.iconPath.replace("$size", "16"),
323 19: this._changes.iconPath.replace("$size", "19"), 334 19: this._changes.iconPath.replace("$size", "19"),
324 20: this._changes.iconPath.replace("$size", "20"), 335 20: this._changes.iconPath.replace("$size", "20"),
325 32: this._changes.iconPath.replace("$size", "32"), 336 32: this._changes.iconPath.replace("$size", "32"),
326 38: this._changes.iconPath.replace("$size", "38"), 337 38: this._changes.iconPath.replace("$size", "38"),
327 40: this._changes.iconPath.replace("$size", "40") 338 40: this._changes.iconPath.replace("$size", "40")
328 }; 339 };
329 try 340 try
330 { 341 {
331 browser.browserAction.setIcon({tabId: this._tabId, path}); 342 return browser.browserAction.setIcon({tabId: this._tabId, path});
332 } 343 }
333 catch (e) 344 catch (e)
334 { 345 {
335 // Edge throws if passed icon sizes different than 19,20,38,40px. 346 // Edge throws if passed icon sizes different than 19,20,38,40px.
336 delete path[16]; 347 delete path[16];
337 delete path[32]; 348 delete path[32];
338 browser.browserAction.setIcon({tabId: this._tabId, path}); 349 return browser.browserAction.setIcon({tabId: this._tabId, path});
339 } 350 }
340 } 351 }
341 } 352
342
343 if ("badgeText" in this._changes)
344 {
345 // There is no badge on Firefox for Android; the browser action is 353 // There is no badge on Firefox for Android; the browser action is
346 // simply a menu item. 354 // simply a menu item.
347 if ("setBadgeText" in browser.browserAction) 355 if (change == "badgeText" && "setBadgeText" in browser.browserAction)
348 { 356 return browser.browserAction.setBadgeText({
349 browser.browserAction.setBadgeText({
350 tabId: this._tabId, 357 tabId: this._tabId,
351 text: this._changes.badgeText 358 text: this._changes.badgeText
352 }); 359 });
353 } 360
354 }
355
356 if ("badgeColor" in this._changes)
357 {
358 // There is no badge on Firefox for Android; the browser action is 361 // There is no badge on Firefox for Android; the browser action is
359 // simply a menu item. 362 // simply a menu item.
360 if ("setBadgeBackgroundColor" in browser.browserAction) 363 if (change == "badgeColor" &&
361 { 364 "setBadgeBackgroundColor" in browser.browserAction)
362 browser.browserAction.setBadgeBackgroundColor({ 365 return browser.browserAction.setBadgeBackgroundColor({
363 tabId: this._tabId, 366 tabId: this._tabId,
364 color: this._changes.badgeColor 367 color: this._changes.badgeColor
365 }); 368 });
369 }));
370 },
371 _addChange(name, value)
372 {
373 let onReplaced = (addedTabId, removedTabId) =>
374 {
375 if (addedTabId == this._tabId)
376 {
377 browser.tabs.onReplaced.removeListener(onReplaced);
378 this._applyChanges().then(() =>
379 {
380 this._changes = null;
381 });
366 } 382 }
383 };
384 if (!this._changes)
385 this._changes = {};
386
387 this._changes[name] = value;
388 if (!browser.tabs.onReplaced.hasListener(onReplaced))
389 {
390 this._applyChanges().then(() =>
391 {
392 this._changes = null;
393 }).catch(() =>
394 {
395 // If the tab is prerendered, browser.browserAction.set* fails
396 // and we have to delay our changes until the currently visible tab
397 // is replaced with the prerendered tab.
398 browser.tabs.onReplaced.addListener(onReplaced);
399 });
367 } 400 }
368
369 this._changes = null;
370 },
371 _queueChanges()
372 {
373 browser.tabs.get(this._tabId, () =>
374 {
375 // If the tab is prerendered, browser.tabs.get() sets
376 // browser.runtime.lastError and we have to delay our changes
377 // until the currently visible tab is replaced with the
378 // prerendered tab. Otherwise browser.browserAction.set* fails.
379 if (browser.runtime.lastError)
380 {
381 let onReplaced = (addedTabId, removedTabId) =>
382 {
383 if (addedTabId == this._tabId)
384 {
385 browser.tabs.onReplaced.removeListener(onReplaced);
386 this._applyChanges();
387 }
388 };
389 browser.tabs.onReplaced.addListener(onReplaced);
390 }
391 else
392 {
393 this._applyChanges();
394 }
395 });
396 },
397 _addChange(name, value)
398 {
399 if (!this._changes)
400 {
401 this._changes = {};
402 this._queueChanges();
403 }
404
405 this._changes[name] = value;
406 }, 401 },
407 setIcon(path) 402 setIcon(path)
408 { 403 {
409 this._addChange("iconPath", path); 404 this._addChange("iconPath", path);
410 }, 405 },
411 setBadge(badge) 406 setBadge(badge)
412 { 407 {
413 if (!badge) 408 if (!badge)
414 { 409 {
415 this._addChange("badgeText", ""); 410 this._addChange("badgeText", "");
(...skipping 29 matching lines...) Expand all
445 if (details && details.length > 0) 440 if (details && details.length > 0)
446 { 441 {
447 let frames = new Map(); 442 let frames = new Map();
448 framesOfTabs.set(tab.id, frames); 443 framesOfTabs.set(tab.id, frames);
449 444
450 for (let detail of details) 445 for (let detail of details)
451 { 446 {
452 let frame = {url: new URL(detail.url)}; 447 let frame = {url: new URL(detail.url)};
453 frames.set(detail.frameId, frame); 448 frames.set(detail.frameId, frame);
454 449
455 if (detail.parentFrameId != -1) 450 if (detail.parentFrameId > -1)
456 { 451 {
457 frame.parent = frames.get(detail.parentFrameId); 452 if (detail.frameId != detail.parentFrameId)
458 453 frame.parent = frames.get(detail.parentFrameId);
459 if (!frame.parent && detail.parentFrameId > 0) 454
455 if (!frame.parent &&
456 detail.frameId != 0 && detail.parentFrameId != 0)
457 {
460 frame.parent = frames.get(0); 458 frame.parent = frames.get(0);
459 }
461 } 460 }
462 } 461 }
463 } 462 }
464 }); 463 });
465 }); 464 });
466 }); 465 });
467 466
468 467
469 /* Message passing */ 468 /* Message passing */
470 469
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 return frames.get(0) || null; 519 return frames.get(0) || null;
521 } 520 }
522 }; 521 };
523 } 522 }
524 523
525 return ext.onMessage._dispatch( 524 return ext.onMessage._dispatch(
526 message, sender, sendResponse 525 message, sender, sendResponse
527 ).includes(true); 526 ).includes(true);
528 }); 527 });
529 } 528 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld