| 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-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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 91       let frames = framesOfTabs.get(this.id); | 91       let frames = framesOfTabs.get(this.id); | 
| 92       if (frames) | 92       if (frames) | 
| 93       { | 93       { | 
| 94         let frame = frames.get(0); | 94         let frame = frames.get(0); | 
| 95         if (frame) | 95         if (frame) | 
| 96           return frame.url; | 96           return frame.url; | 
| 97       } | 97       } | 
| 98     }, | 98     }, | 
| 99     sendMessage(message, responseCallback) | 99     sendMessage(message, responseCallback) | 
| 100     { | 100     { | 
| 101       chrome.tabs.sendMessage(this.id, message, responseCallback); | 101       browser.tabs.sendMessage(this.id, message, responseCallback); | 
| 102     } | 102     } | 
| 103   }; | 103   }; | 
| 104 | 104 | 
| 105   ext.getPage = id => new Page({id: parseInt(id, 10)}); | 105   ext.getPage = id => new Page({id: parseInt(id, 10)}); | 
| 106 | 106 | 
| 107   function afterTabLoaded(callback) | 107   function afterTabLoaded(callback) | 
| 108   { | 108   { | 
| 109     return openedTab => | 109     return openedTab => | 
| 110     { | 110     { | 
| 111       let onUpdated = (tabId, changeInfo, tab) => | 111       let onUpdated = (tabId, changeInfo, tab) => | 
| 112       { | 112       { | 
| 113         if (tabId == openedTab.id && changeInfo.status == "complete") | 113         if (tabId == openedTab.id && changeInfo.status == "complete") | 
| 114         { | 114         { | 
| 115           chrome.tabs.onUpdated.removeListener(onUpdated); | 115           browser.tabs.onUpdated.removeListener(onUpdated); | 
| 116           callback(new Page(openedTab)); | 116           callback(new Page(openedTab)); | 
| 117         } | 117         } | 
| 118       }; | 118       }; | 
| 119       chrome.tabs.onUpdated.addListener(onUpdated); | 119       browser.tabs.onUpdated.addListener(onUpdated); | 
| 120     }; | 120     }; | 
| 121   } | 121   } | 
| 122 | 122 | 
| 123   ext.pages = { | 123   ext.pages = { | 
| 124     onLoading: new ext._EventTarget(), | 124     onLoading: new ext._EventTarget(), | 
| 125     onActivated: new ext._EventTarget(), | 125     onActivated: new ext._EventTarget(), | 
| 126     onRemoved: new ext._EventTarget() | 126     onRemoved: new ext._EventTarget() | 
| 127   }; | 127   }; | 
| 128 | 128 | 
| 129   chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => | 129   browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => | 
| 130   { | 130   { | 
| 131     if (changeInfo.status == "loading") | 131     if (changeInfo.status == "loading") | 
| 132       ext.pages.onLoading._dispatch(new Page(tab)); | 132       ext.pages.onLoading._dispatch(new Page(tab)); | 
| 133   }); | 133   }); | 
| 134 | 134 | 
| 135   function createFrame(tabId, frameId) | 135   function createFrame(tabId, frameId) | 
| 136   { | 136   { | 
| 137     let frames = framesOfTabs.get(tabId); | 137     let frames = framesOfTabs.get(tabId); | 
| 138     if (!frames) | 138     if (!frames) | 
| 139     { | 139     { | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 152   } | 152   } | 
| 153 | 153 | 
| 154   function updatePageFrameStructure(frameId, tabId, url, parentFrameId) | 154   function updatePageFrameStructure(frameId, tabId, url, parentFrameId) | 
| 155   { | 155   { | 
| 156     if (frameId == 0) | 156     if (frameId == 0) | 
| 157     { | 157     { | 
| 158       let page = new Page({id: tabId, url}); | 158       let page = new Page({id: tabId, url}); | 
| 159 | 159 | 
| 160       ext._removeFromAllPageMaps(tabId); | 160       ext._removeFromAllPageMaps(tabId); | 
| 161 | 161 | 
| 162       chrome.tabs.get(tabId, () => | 162       browser.tabs.get(tabId, () => | 
| 163       { | 163       { | 
| 164         // If the tab is prerendered, chrome.tabs.get() sets | 164         // If the tab is prerendered, browser.tabs.get() sets | 
| 165         // chrome.runtime.lastError and we have to dispatch the onLoading event, | 165         // browser.runtime.lastError and we have to dispatch the onLoading | 
| 166         // since the onUpdated event isn't dispatched for prerendered tabs. | 166         // event, since the onUpdated event isn't dispatched for prerendered | 
| 167         // However, we have to keep relying on the unUpdated event for tabs that | 167         // tabs. However, we have to keep relying on the onUpdated event for | 
| 168         // are already visible. Otherwise browser action changes get overridden | 168         // tabs that are already visible. Otherwise browser action changes get | 
| 169         // when Chrome automatically resets them on navigation. | 169         // overridden when Chrome automatically resets them on navigation. | 
| 170         if (chrome.runtime.lastError) | 170         if (browser.runtime.lastError) | 
| 171           ext.pages.onLoading._dispatch(page); | 171           ext.pages.onLoading._dispatch(page); | 
| 172       }); | 172       }); | 
| 173     } | 173     } | 
| 174 | 174 | 
| 175     // Update frame URL and parent in frame structure | 175     // Update frame URL and parent in frame structure | 
| 176     let frame = createFrame(tabId, frameId); | 176     let frame = createFrame(tabId, frameId); | 
| 177     frame.url = new URL(url); | 177     frame.url = new URL(url); | 
| 178 | 178 | 
| 179     let parentFrame = framesOfTabs.get(tabId).get(parentFrameId); | 179     let parentFrame = framesOfTabs.get(tabId).get(parentFrameId); | 
| 180     if (parentFrame) | 180     if (parentFrame) | 
| 181       frame.parent = parentFrame; | 181       frame.parent = parentFrame; | 
| 182   } | 182   } | 
| 183 | 183 | 
| 184   chrome.webRequest.onHeadersReceived.addListener(details => | 184   browser.webRequest.onHeadersReceived.addListener(details => | 
| 185   { | 185   { | 
| 186     // We have to update the frame structure when switching to a new | 186     // We have to update the frame structure when switching to a new | 
| 187     // document, so that we process any further requests made by that | 187     // document, so that we process any further requests made by that | 
| 188     // document in the right context. Unfortunately, we cannot rely | 188     // document in the right context. Unfortunately, we cannot rely | 
| 189     // on webNavigation.onCommitted since it isn't guaranteed to fire | 189     // on webNavigation.onCommitted since it isn't guaranteed to fire | 
| 190     // before any subresources start downloading[1]. As an | 190     // before any subresources start downloading[1]. As an | 
| 191     // alternative we use webRequest.onHeadersReceived for HTTP(S) | 191     // alternative we use webRequest.onHeadersReceived for HTTP(S) | 
| 192     // URLs, being careful to ignore any responses that won't cause | 192     // URLs, being careful to ignore any responses that won't cause | 
| 193     // the document to be replaced. | 193     // the document to be replaced. | 
| 194     // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=665843 | 194     // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=665843 | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 252           return; | 252           return; | 
| 253       } | 253       } | 
| 254     } | 254     } | 
| 255 | 255 | 
| 256     updatePageFrameStructure(details.frameId, details.tabId, details.url, | 256     updatePageFrameStructure(details.frameId, details.tabId, details.url, | 
| 257                              details.parentFrameId); | 257                              details.parentFrameId); | 
| 258   }, | 258   }, | 
| 259   {types: ["main_frame", "sub_frame"], urls: ["http://*/*", "https://*/*"]}, | 259   {types: ["main_frame", "sub_frame"], urls: ["http://*/*", "https://*/*"]}, | 
| 260   ["responseHeaders"]); | 260   ["responseHeaders"]); | 
| 261 | 261 | 
| 262   chrome.webNavigation.onBeforeNavigate.addListener(details => | 262   browser.webNavigation.onBeforeNavigate.addListener(details => | 
| 263   { | 263   { | 
| 264     // Since we can only listen for HTTP(S) responses using | 264     // Since we can only listen for HTTP(S) responses using | 
| 265     // webRequest.onHeadersReceived we must update the page structure here for | 265     // webRequest.onHeadersReceived we must update the page structure here for | 
| 266     // other navigations. | 266     // other navigations. | 
| 267     let url = new URL(details.url); | 267     let url = new URL(details.url); | 
| 268     if (url.protocol != "http:" && url.protocol != "https:") | 268     if (url.protocol != "http:" && url.protocol != "https:") | 
| 269     { | 269     { | 
| 270       updatePageFrameStructure(details.frameId, details.tabId, details.url, | 270       updatePageFrameStructure(details.frameId, details.tabId, details.url, | 
| 271                                details.parentFrameId); | 271                                details.parentFrameId); | 
| 272     } | 272     } | 
| 273   }); | 273   }); | 
| 274 | 274 | 
| 275   function forgetTab(tabId) | 275   function forgetTab(tabId) | 
| 276   { | 276   { | 
| 277     ext.pages.onRemoved._dispatch(tabId); | 277     ext.pages.onRemoved._dispatch(tabId); | 
| 278 | 278 | 
| 279     ext._removeFromAllPageMaps(tabId); | 279     ext._removeFromAllPageMaps(tabId); | 
| 280     framesOfTabs.delete(tabId); | 280     framesOfTabs.delete(tabId); | 
| 281   } | 281   } | 
| 282 | 282 | 
| 283   chrome.tabs.onReplaced.addListener((addedTabId, removedTabId) => | 283   browser.tabs.onReplaced.addListener((addedTabId, removedTabId) => | 
| 284   { | 284   { | 
| 285     forgetTab(removedTabId); | 285     forgetTab(removedTabId); | 
| 286   }); | 286   }); | 
| 287 | 287 | 
| 288   chrome.tabs.onRemoved.addListener(forgetTab); | 288   browser.tabs.onRemoved.addListener(forgetTab); | 
| 289 | 289 | 
| 290   chrome.tabs.onActivated.addListener(details => | 290   browser.tabs.onActivated.addListener(details => | 
| 291   { | 291   { | 
| 292     ext.pages.onActivated._dispatch(new Page({id: details.tabId})); | 292     ext.pages.onActivated._dispatch(new Page({id: details.tabId})); | 
| 293   }); | 293   }); | 
| 294 | 294 | 
| 295 | 295 | 
| 296   /* Browser actions */ | 296   /* Browser actions */ | 
| 297 | 297 | 
| 298   let BrowserAction = function(tabId) | 298   let BrowserAction = function(tabId) | 
| 299   { | 299   { | 
| 300     this._tabId = tabId; | 300     this._tabId = tabId; | 
| 301     this._changes = null; | 301     this._changes = null; | 
| 302   }; | 302   }; | 
| 303   BrowserAction.prototype = { | 303   BrowserAction.prototype = { | 
| 304     _applyChanges() | 304     _applyChanges() | 
| 305     { | 305     { | 
| 306       if ("iconPath" in this._changes) | 306       if ("iconPath" in this._changes) | 
| 307       { | 307       { | 
| 308         // Firefox for Android displays the browser action not as an icon but | 308         // Firefox for Android displays the browser action not as an icon but | 
| 309         // as a menu item. There is no icon, but such an option may be added in | 309         // as a menu item. There is no icon, but such an option may be added in | 
| 310         // the future. | 310         // the future. | 
| 311         // https://bugzilla.mozilla.org/show_bug.cgi?id=1331746 | 311         // https://bugzilla.mozilla.org/show_bug.cgi?id=1331746 | 
| 312         if ("setIcon" in chrome.browserAction) | 312         if ("setIcon" in browser.browserAction) | 
| 313         { | 313         { | 
| 314           let path = { | 314           let path = { | 
| 315             16: this._changes.iconPath.replace("$size", "16"), | 315             16: this._changes.iconPath.replace("$size", "16"), | 
| 316             19: this._changes.iconPath.replace("$size", "19"), | 316             19: this._changes.iconPath.replace("$size", "19"), | 
| 317             20: this._changes.iconPath.replace("$size", "20"), | 317             20: this._changes.iconPath.replace("$size", "20"), | 
| 318             32: this._changes.iconPath.replace("$size", "32"), | 318             32: this._changes.iconPath.replace("$size", "32"), | 
| 319             38: this._changes.iconPath.replace("$size", "38"), | 319             38: this._changes.iconPath.replace("$size", "38"), | 
| 320             40: this._changes.iconPath.replace("$size", "40") | 320             40: this._changes.iconPath.replace("$size", "40") | 
| 321           }; | 321           }; | 
| 322           try | 322           try | 
| 323           { | 323           { | 
| 324             chrome.browserAction.setIcon({tabId: this._tabId, path}); | 324             browser.browserAction.setIcon({tabId: this._tabId, path}); | 
| 325           } | 325           } | 
| 326           catch (e) | 326           catch (e) | 
| 327           { | 327           { | 
| 328             // Edge throws if passed icon sizes different than 19,20,38,40px. | 328             // Edge throws if passed icon sizes different than 19,20,38,40px. | 
| 329             delete path[16]; | 329             delete path[16]; | 
| 330             delete path[32]; | 330             delete path[32]; | 
| 331             chrome.browserAction.setIcon({tabId: this._tabId, path}); | 331             browser.browserAction.setIcon({tabId: this._tabId, path}); | 
| 332           } | 332           } | 
| 333         } | 333         } | 
| 334       } | 334       } | 
| 335 | 335 | 
| 336       if ("badgeText" in this._changes) | 336       if ("badgeText" in this._changes) | 
| 337       { | 337       { | 
| 338         // There is no badge on Firefox for Android; the browser action is | 338         // There is no badge on Firefox for Android; the browser action is | 
| 339         // simply a menu item. | 339         // simply a menu item. | 
| 340         if ("setBadgeText" in chrome.browserAction) | 340         if ("setBadgeText" in browser.browserAction) | 
| 341         { | 341         { | 
| 342           chrome.browserAction.setBadgeText({ | 342           browser.browserAction.setBadgeText({ | 
| 343             tabId: this._tabId, | 343             tabId: this._tabId, | 
| 344             text: this._changes.badgeText | 344             text: this._changes.badgeText | 
| 345           }); | 345           }); | 
| 346         } | 346         } | 
| 347       } | 347       } | 
| 348 | 348 | 
| 349       if ("badgeColor" in this._changes) | 349       if ("badgeColor" in this._changes) | 
| 350       { | 350       { | 
| 351         // There is no badge on Firefox for Android; the browser action is | 351         // There is no badge on Firefox for Android; the browser action is | 
| 352         // simply a menu item. | 352         // simply a menu item. | 
| 353         if ("setBadgeBackgroundColor" in chrome.browserAction) | 353         if ("setBadgeBackgroundColor" in browser.browserAction) | 
| 354         { | 354         { | 
| 355           chrome.browserAction.setBadgeBackgroundColor({ | 355           browser.browserAction.setBadgeBackgroundColor({ | 
| 356             tabId: this._tabId, | 356             tabId: this._tabId, | 
| 357             color: this._changes.badgeColor | 357             color: this._changes.badgeColor | 
| 358           }); | 358           }); | 
| 359         } | 359         } | 
| 360       } | 360       } | 
| 361 | 361 | 
| 362       this._changes = null; | 362       this._changes = null; | 
| 363     }, | 363     }, | 
| 364     _queueChanges() | 364     _queueChanges() | 
| 365     { | 365     { | 
| 366       chrome.tabs.get(this._tabId, () => | 366       browser.tabs.get(this._tabId, () => | 
| 367       { | 367       { | 
| 368         // If the tab is prerendered, chrome.tabs.get() sets | 368         // If the tab is prerendered, browser.tabs.get() sets | 
| 369         // chrome.runtime.lastError and we have to delay our changes | 369         // browser.runtime.lastError and we have to delay our changes | 
| 370         // until the currently visible tab is replaced with the | 370         // until the currently visible tab is replaced with the | 
| 371         // prerendered tab. Otherwise chrome.browserAction.set* fails. | 371         // prerendered tab. Otherwise browser.browserAction.set* fails. | 
| 372         if (chrome.runtime.lastError) | 372         if (browser.runtime.lastError) | 
| 373         { | 373         { | 
| 374           let onReplaced = (addedTabId, removedTabId) => | 374           let onReplaced = (addedTabId, removedTabId) => | 
| 375           { | 375           { | 
| 376             if (addedTabId == this._tabId) | 376             if (addedTabId == this._tabId) | 
| 377             { | 377             { | 
| 378               chrome.tabs.onReplaced.removeListener(onReplaced); | 378               browser.tabs.onReplaced.removeListener(onReplaced); | 
| 379               this._applyChanges(); | 379               this._applyChanges(); | 
| 380             } | 380             } | 
| 381           }; | 381           }; | 
| 382           chrome.tabs.onReplaced.addListener(onReplaced); | 382           browser.tabs.onReplaced.addListener(onReplaced); | 
| 383         } | 383         } | 
| 384         else | 384         else | 
| 385         { | 385         { | 
| 386           this._applyChanges(); | 386           this._applyChanges(); | 
| 387         } | 387         } | 
| 388       }); | 388       }); | 
| 389     }, | 389     }, | 
| 390     _addChange(name, value) | 390     _addChange(name, value) | 
| 391     { | 391     { | 
| 392       if (!this._changes) | 392       if (!this._changes) | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
| 421 | 421 | 
| 422   /* Context menus */ | 422   /* Context menus */ | 
| 423 | 423 | 
| 424   let contextMenuItems = new ext.PageMap(); | 424   let contextMenuItems = new ext.PageMap(); | 
| 425   let contextMenuUpdating = false; | 425   let contextMenuUpdating = false; | 
| 426 | 426 | 
| 427   let updateContextMenu = () => | 427   let updateContextMenu = () => | 
| 428   { | 428   { | 
| 429     // Firefox for Android does not support context menus. | 429     // Firefox for Android does not support context menus. | 
| 430     // https://bugzilla.mozilla.org/show_bug.cgi?id=1269062 | 430     // https://bugzilla.mozilla.org/show_bug.cgi?id=1269062 | 
| 431     if (!("contextMenus" in chrome) || contextMenuUpdating) | 431     if (!("contextMenus" in browser) || contextMenuUpdating) | 
| 432       return; | 432       return; | 
| 433 | 433 | 
| 434     contextMenuUpdating = true; | 434     contextMenuUpdating = true; | 
| 435 | 435 | 
| 436     chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => | 436     browser.tabs.query({active: true, lastFocusedWindow: true}, tabs => | 
| 437     { | 437     { | 
| 438       chrome.contextMenus.removeAll(() => | 438       browser.contextMenus.removeAll(() => | 
| 439       { | 439       { | 
| 440         contextMenuUpdating = false; | 440         contextMenuUpdating = false; | 
| 441 | 441 | 
| 442         if (tabs.length == 0) | 442         if (tabs.length == 0) | 
| 443           return; | 443           return; | 
| 444 | 444 | 
| 445         let items = contextMenuItems.get({id: tabs[0].id}); | 445         let items = contextMenuItems.get({id: tabs[0].id}); | 
| 446 | 446 | 
| 447         if (!items) | 447         if (!items) | 
| 448           return; | 448           return; | 
| 449 | 449 | 
| 450         items.forEach(item => | 450         items.forEach(item => | 
| 451         { | 451         { | 
| 452           chrome.contextMenus.create({ | 452           browser.contextMenus.create({ | 
| 453             title: item.title, | 453             title: item.title, | 
| 454             contexts: item.contexts, | 454             contexts: item.contexts, | 
| 455             onclick(info, tab) | 455             onclick(info, tab) | 
| 456             { | 456             { | 
| 457               item.onclick(new Page(tab)); | 457               item.onclick(new Page(tab)); | 
| 458             } | 458             } | 
| 459           }); | 459           }); | 
| 460         }); | 460         }); | 
| 461       }); | 461       }); | 
| 462     }); | 462     }); | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 484         let index = items.indexOf(item); | 484         let index = items.indexOf(item); | 
| 485         if (index != -1) | 485         if (index != -1) | 
| 486         { | 486         { | 
| 487           items.splice(index, 1); | 487           items.splice(index, 1); | 
| 488           updateContextMenu(); | 488           updateContextMenu(); | 
| 489         } | 489         } | 
| 490       } | 490       } | 
| 491     } | 491     } | 
| 492   }; | 492   }; | 
| 493 | 493 | 
| 494   chrome.tabs.onActivated.addListener(updateContextMenu); | 494   browser.tabs.onActivated.addListener(updateContextMenu); | 
| 495 | 495 | 
| 496   if ("windows" in chrome) | 496   if ("windows" in browser) | 
| 497   { | 497   { | 
| 498     chrome.windows.onFocusChanged.addListener(windowId => | 498     browser.windows.onFocusChanged.addListener(windowId => | 
| 499     { | 499     { | 
| 500       if (windowId != chrome.windows.WINDOW_ID_NONE) | 500       if (windowId != browser.windows.WINDOW_ID_NONE) | 
| 501         updateContextMenu(); | 501         updateContextMenu(); | 
| 502     }); | 502     }); | 
| 503   } | 503   } | 
| 504 | 504 | 
| 505 | 505 | 
| 506   /* Web requests */ | 506   /* Web requests */ | 
| 507 | 507 | 
| 508   let framesOfTabs = new Map(); | 508   let framesOfTabs = new Map(); | 
| 509 | 509 | 
| 510   ext.getFrame = (tabId, frameId) => | 510   ext.getFrame = (tabId, frameId) => | 
| 511   { | 511   { | 
| 512     let frames = framesOfTabs.get(tabId); | 512     let frames = framesOfTabs.get(tabId); | 
| 513     return frames && frames.get(frameId); | 513     return frames && frames.get(frameId); | 
| 514   }; | 514   }; | 
| 515 | 515 | 
| 516   let handlerBehaviorChangedQuota = | 516   let handlerBehaviorChangedQuota = | 
| 517     chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES; | 517     browser.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES; | 
| 518 | 518 | 
| 519   function propagateHandlerBehaviorChange() | 519   function propagateHandlerBehaviorChange() | 
| 520   { | 520   { | 
| 521     // Make sure to not call handlerBehaviorChanged() more often than allowed | 521     // Make sure to not call handlerBehaviorChanged() more often than allowed | 
| 522     // by chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. | 522     // by browser.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. | 
| 523     // Otherwise Chrome notifies the user that this extension is causing issues. | 523     // Otherwise Chrome notifies the user that this extension is causing issues. | 
| 524     if (handlerBehaviorChangedQuota > 0) | 524     if (handlerBehaviorChangedQuota > 0) | 
| 525     { | 525     { | 
| 526       chrome.webNavigation.onBeforeNavigate.removeListener( | 526       browser.webNavigation.onBeforeNavigate.removeListener( | 
| 527         propagateHandlerBehaviorChange | 527         propagateHandlerBehaviorChange | 
| 528       ); | 528       ); | 
| 529       chrome.webRequest.handlerBehaviorChanged(); | 529       browser.webRequest.handlerBehaviorChanged(); | 
| 530 | 530 | 
| 531       handlerBehaviorChangedQuota--; | 531       handlerBehaviorChangedQuota--; | 
| 532       setTimeout(() => { handlerBehaviorChangedQuota++; }, 600000); | 532       setTimeout(() => { handlerBehaviorChangedQuota++; }, 600000); | 
| 533     } | 533     } | 
| 534   } | 534   } | 
| 535 | 535 | 
| 536   ext.webRequest = { | 536   ext.webRequest = { | 
| 537     onBeforeRequest: new ext._EventTarget(), | 537     onBeforeRequest: new ext._EventTarget(), | 
| 538     handlerBehaviorChanged() | 538     handlerBehaviorChanged() | 
| 539     { | 539     { | 
| 540       // Defer handlerBehaviorChanged() until navigation occurs. | 540       // Defer handlerBehaviorChanged() until navigation occurs. | 
| 541       // There wouldn't be any visible effect when calling it earlier, | 541       // There wouldn't be any visible effect when calling it earlier, | 
| 542       // but it's an expensive operation and that way we avoid to call | 542       // but it's an expensive operation and that way we avoid to call | 
| 543       // it multiple times, if multiple filters are added/removed. | 543       // it multiple times, if multiple filters are added/removed. | 
| 544       let {onBeforeNavigate} = chrome.webNavigation; | 544       let {onBeforeNavigate} = browser.webNavigation; | 
| 545       if (!onBeforeNavigate.hasListener(propagateHandlerBehaviorChange)) | 545       if (!onBeforeNavigate.hasListener(propagateHandlerBehaviorChange)) | 
| 546         onBeforeNavigate.addListener(propagateHandlerBehaviorChange); | 546         onBeforeNavigate.addListener(propagateHandlerBehaviorChange); | 
| 547     } | 547     } | 
| 548   }; | 548   }; | 
| 549 | 549 | 
| 550   chrome.tabs.query({}, tabs => | 550   browser.tabs.query({}, tabs => | 
| 551   { | 551   { | 
| 552     tabs.forEach(tab => | 552     tabs.forEach(tab => | 
| 553     { | 553     { | 
| 554       chrome.webNavigation.getAllFrames({tabId: tab.id}, details => | 554       browser.webNavigation.getAllFrames({tabId: tab.id}, details => | 
| 555       { | 555       { | 
| 556         if (details && details.length > 0) | 556         if (details && details.length > 0) | 
| 557         { | 557         { | 
| 558           let frames = new Map(); | 558           let frames = new Map(); | 
| 559           framesOfTabs.set(tab.id, frames); | 559           framesOfTabs.set(tab.id, frames); | 
| 560 | 560 | 
| 561           for (let detail of details) | 561           for (let detail of details) | 
| 562           { | 562           { | 
| 563             let frame = {url: new URL(detail.url)}; | 563             let frame = {url: new URL(detail.url)}; | 
| 564             frames.set(detail.frameId, frame); | 564             frames.set(detail.frameId, frame); | 
| 565 | 565 | 
| 566             if (detail.parentFrameId != -1) | 566             if (detail.parentFrameId != -1) | 
| 567               frame.parent = frames.get(detail.parentFrameId); | 567               frame.parent = frames.get(detail.parentFrameId); | 
| 568           } | 568           } | 
| 569         } | 569         } | 
| 570       }); | 570       }); | 
| 571     }); | 571     }); | 
| 572   }); | 572   }); | 
| 573 | 573 | 
| 574   chrome.webRequest.onBeforeRequest.addListener(details => | 574   browser.webRequest.onBeforeRequest.addListener(details => | 
| 575   { | 575   { | 
| 576     // The high-level code isn't interested in requests that aren't | 576     // The high-level code isn't interested in requests that aren't | 
| 577     // related to a tab or requests loading a top-level document, | 577     // related to a tab or requests loading a top-level document, | 
| 578     // those should never be blocked. | 578     // those should never be blocked. | 
| 579     if (details.type == "main_frame") | 579     if (details.type == "main_frame") | 
| 580       return; | 580       return; | 
| 581 | 581 | 
| 582     // Filter out requests from non web protocols. Ideally, we'd explicitly | 582     // Filter out requests from non web protocols. Ideally, we'd explicitly | 
| 583     // specify the protocols we are interested in (i.e. http://, https://, | 583     // specify the protocols we are interested in (i.e. http://, https://, | 
| 584     // ws:// and wss://) with the url patterns, given below, when adding this | 584     // ws:// and wss://) with the url patterns, given below, when adding this | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 608     } | 608     } | 
| 609 | 609 | 
| 610     if (ext.webRequest.onBeforeRequest._dispatch( | 610     if (ext.webRequest.onBeforeRequest._dispatch( | 
| 611         url, type, page, frame).includes(false)) | 611         url, type, page, frame).includes(false)) | 
| 612       return {cancel: true}; | 612       return {cancel: true}; | 
| 613   }, {urls: ["<all_urls>"]}, ["blocking"]); | 613   }, {urls: ["<all_urls>"]}, ["blocking"]); | 
| 614 | 614 | 
| 615 | 615 | 
| 616   /* Message passing */ | 616   /* Message passing */ | 
| 617 | 617 | 
| 618   chrome.runtime.onMessage.addListener((message, rawSender, sendResponse) => | 618   browser.runtime.onMessage.addListener((message, rawSender, sendResponse) => | 
| 619   { | 619   { | 
| 620     let sender = {}; | 620     let sender = {}; | 
| 621 | 621 | 
| 622     // Add "page" and "frame" if the message was sent by a content script. | 622     // Add "page" and "frame" if the message was sent by a content script. | 
| 623     // If sent by popup or the background page itself, there is no "tab". | 623     // If sent by popup or the background page itself, there is no "tab". | 
| 624     if ("tab" in rawSender) | 624     if ("tab" in rawSender) | 
| 625     { | 625     { | 
| 626       sender.page = new Page(rawSender.tab); | 626       sender.page = new Page(rawSender.tab); | 
| 627       sender.frame = { | 627       sender.frame = { | 
| 628         id: rawSender.frameId, | 628         id: rawSender.frameId, | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 649       message, sender, sendResponse | 649       message, sender, sendResponse | 
| 650     ).includes(true); | 650     ).includes(true); | 
| 651   }); | 651   }); | 
| 652 | 652 | 
| 653 | 653 | 
| 654   /* Storage */ | 654   /* Storage */ | 
| 655 | 655 | 
| 656   ext.storage = { | 656   ext.storage = { | 
| 657     get(keys, callback) | 657     get(keys, callback) | 
| 658     { | 658     { | 
| 659       chrome.storage.local.get(keys, callback); | 659       browser.storage.local.get(keys, callback); | 
| 660     }, | 660     }, | 
| 661     set(key, value, callback) | 661     set(key, value, callback) | 
| 662     { | 662     { | 
| 663       let items = {}; | 663       let items = {}; | 
| 664       items[key] = value; | 664       items[key] = value; | 
| 665       chrome.storage.local.set(items, callback); | 665       browser.storage.local.set(items, callback); | 
| 666     }, | 666     }, | 
| 667     remove(key, callback) | 667     remove(key, callback) | 
| 668     { | 668     { | 
| 669       chrome.storage.local.remove(key, callback); | 669       browser.storage.local.remove(key, callback); | 
| 670     }, | 670     }, | 
| 671     onChanged: chrome.storage.onChanged | 671     onChanged: browser.storage.onChanged | 
| 672   }; | 672   }; | 
| 673 | 673 | 
| 674   /* Windows */ | 674   /* Windows */ | 
| 675   ext.windows = { | 675   ext.windows = { | 
| 676     create(createData, callback) | 676     create(createData, callback) | 
| 677     { | 677     { | 
| 678       chrome.windows.create(createData, createdWindow => | 678       browser.windows.create(createData, createdWindow => | 
| 679       { | 679       { | 
| 680         afterTabLoaded(callback)(createdWindow.tabs[0]); | 680         afterTabLoaded(callback)(createdWindow.tabs[0]); | 
| 681       }); | 681       }); | 
| 682     } | 682     } | 
| 683   }; | 683   }; | 
| 684 }()); | 684 }()); | 
| OLD | NEW | 
|---|