| 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 | 
|   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|   12  * GNU General Public License for more details. |   12  * GNU General Public License for more details. | 
|   13  * |   13  * | 
|   14  * You should have received a copy of the GNU General Public License |   14  * You should have received a copy of the GNU General Public License | 
|   15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. |   15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
|   16  */ |   16  */ | 
|   17  |   17  | 
|   18 (function() |  | 
|   19 { |   18 { | 
|   20   /* Pages */ |   19   /* Pages */ | 
|   21  |   20  | 
|   22   var Page = ext.Page = function(tab) |   21   let Page = ext.Page = function(tab) | 
|   23   { |   22   { | 
|   24     this.id = tab.id; |   23     this.id = tab.id; | 
|   25     this._url = tab.url && new URL(tab.url); |   24     this._url = tab.url && new URL(tab.url); | 
|   26  |   25  | 
|   27     this.browserAction = new BrowserAction(tab.id); |   26     this.browserAction = new BrowserAction(tab.id); | 
|   28     this.contextMenus = new ContextMenus(this); |   27     this.contextMenus = new ContextMenus(this); | 
|   29   }; |   28   }; | 
|   30   Page.prototype = { |   29   Page.prototype = { | 
|   31     get url() |   30     get url() | 
|   32     { |   31     { | 
|   33       // usually our Page objects are created from Chrome's Tab objects, which |   32       // usually our Page objects are created from Chrome's Tab objects, which | 
|   34       // provide the url. So we can return the url given in the constructor. |   33       // provide the url. So we can return the url given in the constructor. | 
|   35       if (this._url) |   34       if (this._url) | 
|   36         return this._url; |   35         return this._url; | 
|   37  |   36  | 
|   38       // but sometimes we only have the tab id when we create a Page object. |   37       // but sometimes we only have the tab id when we create a Page object. | 
|   39       // In that case we get the url from top frame of the tab, recorded by |   38       // In that case we get the url from top frame of the tab, recorded by | 
|   40       // the onBeforeRequest handler. |   39       // the onBeforeRequest handler. | 
|   41       var frames = framesOfTabs[this.id]; |   40       let frames = framesOfTabs[this.id]; | 
|   42       if (frames) |   41       if (frames) | 
|   43       { |   42       { | 
|   44         var frame = frames[0]; |   43         let frame = frames[0]; | 
|   45         if (frame) |   44         if (frame) | 
|   46           return frame.url; |   45           return frame.url; | 
|   47       } |   46       } | 
|   48     }, |   47     }, | 
|   49     sendMessage: function(message, responseCallback) |   48     sendMessage: function(message, responseCallback) | 
|   50     { |   49     { | 
|   51       chrome.tabs.sendMessage(this.id, message, responseCallback); |   50       chrome.tabs.sendMessage(this.id, message, responseCallback); | 
|   52     } |   51     } | 
|   53   }; |   52   }; | 
|   54  |   53  | 
|   55   ext.getPage = function(id) |   54   ext.getPage = id => new Page({id: parseInt(id, 10)}); | 
|   56   { |  | 
|   57     return new Page({id: parseInt(id, 10)}); |  | 
|   58   }; |  | 
|   59  |   55  | 
|   60   function afterTabLoaded(callback) |   56   function afterTabLoaded(callback) | 
|   61   { |   57   { | 
|   62      return function(openedTab) |   58      return openedTab => | 
|   63      { |   59      { | 
|   64        var onUpdated = function(tabId, changeInfo, tab) |   60        let onUpdated = (tabId, changeInfo, tab) => | 
|   65        { |   61        { | 
|   66          if (tabId == openedTab.id && changeInfo.status == "complete") |   62          if (tabId == openedTab.id && changeInfo.status == "complete") | 
|   67          { |   63          { | 
|   68            chrome.tabs.onUpdated.removeListener(onUpdated); |   64            chrome.tabs.onUpdated.removeListener(onUpdated); | 
|   69            callback(new Page(openedTab)); |   65            callback(new Page(openedTab)); | 
|   70          } |   66          } | 
|   71        }; |   67        }; | 
|   72        chrome.tabs.onUpdated.addListener(onUpdated); |   68        chrome.tabs.onUpdated.addListener(onUpdated); | 
|   73      }; |   69      }; | 
|   74   } |   70   } | 
|   75  |   71  | 
|   76   ext.pages = { |   72   ext.pages = { | 
|   77     open: function(url, callback) |   73     open: (url, callback) => | 
|   78     { |   74     { | 
|   79       chrome.tabs.create({url: url}, callback && afterTabLoaded(callback)); |   75       chrome.tabs.create({url: url}, callback && afterTabLoaded(callback)); | 
|   80     }, |   76     }, | 
|   81     query: function(info, callback) |   77     query: (info, callback) => | 
|   82     { |   78     { | 
|   83       var rawInfo = {}; |   79       let rawInfo = {}; | 
|   84       for (var property in info) |   80       for (let property in info) | 
|   85       { |   81       { | 
|   86         switch (property) |   82         switch (property) | 
|   87         { |   83         { | 
|   88           case "active": |   84           case "active": | 
|   89           case "lastFocusedWindow": |   85           case "lastFocusedWindow": | 
|   90             rawInfo[property] = info[property]; |   86             rawInfo[property] = info[property]; | 
|   91         } |   87         } | 
|   92       } |   88       } | 
|   93  |   89  | 
|   94       chrome.tabs.query(rawInfo, function(tabs) |   90       chrome.tabs.query(rawInfo, tabs => | 
|   95       { |   91       { | 
|   96         callback(tabs.map(function(tab) |   92         callback(tabs.map(tab => new Page(tab))); | 
|   97         { |  | 
|   98           return new Page(tab); |  | 
|   99         })); |  | 
|  100       }); |   93       }); | 
|  101     }, |   94     }, | 
|  102     onLoading: new ext._EventTarget(), |   95     onLoading: new ext._EventTarget(), | 
|  103     onActivated: new ext._EventTarget(), |   96     onActivated: new ext._EventTarget(), | 
|  104     onRemoved: new ext._EventTarget() |   97     onRemoved: new ext._EventTarget() | 
|  105   }; |   98   }; | 
|  106  |   99  | 
|  107   chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) |  100   chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => | 
|  108   { |  101   { | 
|  109     if (changeInfo.status == "loading") |  102     if (changeInfo.status == "loading") | 
|  110       ext.pages.onLoading._dispatch(new Page(tab)); |  103       ext.pages.onLoading._dispatch(new Page(tab)); | 
|  111   }); |  104   }); | 
|  112  |  105  | 
|  113   function createFrame(tabId, frameId) |  106   function createFrame(tabId, frameId) | 
|  114   { |  107   { | 
|  115     var frames = framesOfTabs[tabId]; |  108     let frames = framesOfTabs[tabId]; | 
|  116     if (!frames) |  109     if (!frames) | 
|  117       frames = framesOfTabs[tabId] = Object.create(null); |  110       frames = framesOfTabs[tabId] = Object.create(null); | 
|  118  |  111  | 
|  119     var frame = frames[frameId]; |  112     let frame = frames[frameId]; | 
|  120     if (!frame) |  113     if (!frame) | 
|  121       frame = frames[frameId] = {}; |  114       frame = frames[frameId] = {}; | 
|  122  |  115  | 
|  123     return frame; |  116     return frame; | 
|  124   } |  117   } | 
|  125  |  118  | 
|  126   chrome.webNavigation.onBeforeNavigate.addListener(function(details) |  119   chrome.webNavigation.onBeforeNavigate.addListener(details => | 
|  127   { |  120   { | 
|  128     // Capture parent frame here because onCommitted doesn't get this info. |  121     // Capture parent frame here because onCommitted doesn't get this info. | 
|  129     var frame = createFrame(details.tabId, details.frameId); |  122     let frame = createFrame(details.tabId, details.frameId); | 
|  130     frame.parent = framesOfTabs[details.tabId][details.parentFrameId] || null; |  123     frame.parent = framesOfTabs[details.tabId][details.parentFrameId] || null; | 
|  131   }); |  124   }); | 
|  132  |  125  | 
|  133   var eagerlyUpdatedPages = new ext.PageMap(); |  126   let eagerlyUpdatedPages = new ext.PageMap(); | 
|  134  |  127  | 
|  135   ext._updatePageFrameStructure = function(frameId, tabId, url, eager) |  128   ext._updatePageFrameStructure = (frameId, tabId, url, eager) => | 
|  136   { |  129   { | 
|  137     if (frameId == 0) |  130     if (frameId == 0) | 
|  138     { |  131     { | 
|  139       let page = new Page({id: tabId, url: url}); |  132       let page = new Page({id: tabId, url: url}); | 
|  140  |  133  | 
|  141       if (eagerlyUpdatedPages.get(page) != url) |  134       if (eagerlyUpdatedPages.get(page) != url) | 
|  142       { |  135       { | 
|  143         ext._removeFromAllPageMaps(tabId); |  136         ext._removeFromAllPageMaps(tabId); | 
|  144  |  137  | 
|  145         // When a sitekey header is received we must immediately update the page |  138         // When a sitekey header is received we must immediately update the page | 
|  146         // structure in order to record and use the key. We want to avoid |  139         // structure in order to record and use the key. We want to avoid | 
|  147         // trashing the page structure if the onCommitted event is then fired |  140         // trashing the page structure if the onCommitted event is then fired | 
|  148         // for the page. |  141         // for the page. | 
|  149         if (eager) |  142         if (eager) | 
|  150           eagerlyUpdatedPages.set(page, url); |  143           eagerlyUpdatedPages.set(page, url); | 
|  151  |  144  | 
|  152         chrome.tabs.get(tabId, function() |  145         chrome.tabs.get(tabId, () => | 
|  153         { |  146         { | 
|  154           // If the tab is prerendered, chrome.tabs.get() sets |  147           // If the tab is prerendered, chrome.tabs.get() sets | 
|  155           // chrome.runtime.lastError and we have to dispatch the onLoading even
     t, |  148           // chrome.runtime.lastError and we have to dispatch the onLoading even
     t, | 
|  156           // since the onUpdated event isn't dispatched for prerendered tabs. |  149           // since the onUpdated event isn't dispatched for prerendered tabs. | 
|  157           // However, we have to keep relying on the unUpdated event for tabs th
     at |  150           // However, we have to keep relying on the unUpdated event for tabs th
     at | 
|  158           // are already visible. Otherwise browser action changes get overridde
     n |  151           // are already visible. Otherwise browser action changes get overridde
     n | 
|  159           // when Chrome automatically resets them on navigation. |  152           // when Chrome automatically resets them on navigation. | 
|  160           if (chrome.runtime.lastError) |  153           if (chrome.runtime.lastError) | 
|  161             ext.pages.onLoading._dispatch(page); |  154             ext.pages.onLoading._dispatch(page); | 
|  162         }); |  155         }); | 
|  163       } |  156       } | 
|  164     } |  157     } | 
|  165  |  158  | 
|  166     // Update frame URL in frame structure |  159     // Update frame URL in frame structure | 
|  167     var frame = createFrame(tabId, frameId); |  160     let frame = createFrame(tabId, frameId); | 
|  168     frame.url = new URL(url); |  161     frame.url = new URL(url); | 
|  169   }; |  162   }; | 
|  170  |  163  | 
|  171   chrome.webNavigation.onCommitted.addListener(function(details) |  164   chrome.webNavigation.onCommitted.addListener(details => | 
|  172   { |  165   { | 
|  173     ext._updatePageFrameStructure(details.frameId, details.tabId, details.url); |  166     ext._updatePageFrameStructure(details.frameId, details.tabId, details.url); | 
|  174   }); |  167   }); | 
|  175  |  168  | 
|  176   function forgetTab(tabId) |  169   function forgetTab(tabId) | 
|  177   { |  170   { | 
|  178     ext.pages.onRemoved._dispatch(tabId); |  171     ext.pages.onRemoved._dispatch(tabId); | 
|  179  |  172  | 
|  180     ext._removeFromAllPageMaps(tabId); |  173     ext._removeFromAllPageMaps(tabId); | 
|  181     delete framesOfTabs[tabId]; |  174     delete framesOfTabs[tabId]; | 
|  182   } |  175   } | 
|  183  |  176  | 
|  184   chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) |  177   chrome.tabs.onReplaced.addListener((addedTabId, removedTabId) => | 
|  185   { |  178   { | 
|  186     forgetTab(removedTabId); |  179     forgetTab(removedTabId); | 
|  187   }); |  180   }); | 
|  188  |  181  | 
|  189   chrome.tabs.onRemoved.addListener(forgetTab); |  182   chrome.tabs.onRemoved.addListener(forgetTab); | 
|  190  |  183  | 
|  191   chrome.tabs.onActivated.addListener(function(details) |  184   chrome.tabs.onActivated.addListener(details => | 
|  192   { |  185   { | 
|  193     ext.pages.onActivated._dispatch(new Page({id: details.tabId})); |  186     ext.pages.onActivated._dispatch(new Page({id: details.tabId})); | 
|  194   }); |  187   }); | 
|  195  |  188  | 
|  196  |  189  | 
|  197   /* Browser actions */ |  190   /* Browser actions */ | 
|  198  |  191  | 
|  199   var BrowserAction = function(tabId) |  192   let BrowserAction = function(tabId) | 
|  200   { |  193   { | 
|  201     this._tabId = tabId; |  194     this._tabId = tabId; | 
|  202     this._changes = null; |  195     this._changes = null; | 
|  203   }; |  196   }; | 
|  204   BrowserAction.prototype = { |  197   BrowserAction.prototype = { | 
|  205     _applyChanges: function() |  198     _applyChanges: function() | 
|  206     { |  199     { | 
|  207       if ("iconPath" in this._changes) |  200       if ("iconPath" in this._changes) | 
|  208       { |  201       { | 
|  209         chrome.browserAction.setIcon({ |  202         chrome.browserAction.setIcon({ | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
|  240     _queueChanges: function() |  233     _queueChanges: function() | 
|  241     { |  234     { | 
|  242       chrome.tabs.get(this._tabId, function() |  235       chrome.tabs.get(this._tabId, function() | 
|  243       { |  236       { | 
|  244         // If the tab is prerendered, chrome.tabs.get() sets |  237         // If the tab is prerendered, chrome.tabs.get() sets | 
|  245         // chrome.runtime.lastError and we have to delay our changes |  238         // chrome.runtime.lastError and we have to delay our changes | 
|  246         // until the currently visible tab is replaced with the |  239         // until the currently visible tab is replaced with the | 
|  247         // prerendered tab. Otherwise chrome.browserAction.set* fails. |  240         // prerendered tab. Otherwise chrome.browserAction.set* fails. | 
|  248         if (chrome.runtime.lastError) |  241         if (chrome.runtime.lastError) | 
|  249         { |  242         { | 
|  250           var onReplaced = function(addedTabId, removedTabId) |  243           let onReplaced = (addedTabId, removedTabId) => | 
|  251           { |  244           { | 
|  252             if (addedTabId == this._tabId) |  245             if (addedTabId == this._tabId) | 
|  253             { |  246             { | 
|  254               chrome.tabs.onReplaced.removeListener(onReplaced); |  247               chrome.tabs.onReplaced.removeListener(onReplaced); | 
|  255               this._applyChanges(); |  248               this._applyChanges(); | 
|  256             } |  249             } | 
|  257           }.bind(this); |  250           }; | 
|  258           chrome.tabs.onReplaced.addListener(onReplaced); |  251           chrome.tabs.onReplaced.addListener(onReplaced); | 
|  259         } |  252         } | 
|  260         else |  253         else | 
|  261         { |  254         { | 
|  262           this._applyChanges(); |  255           this._applyChanges(); | 
|  263         } |  256         } | 
|  264       }.bind(this)); |  257       }.bind(this)); | 
|  265     }, |  258     }, | 
|  266     _addChange: function(name, value) |  259     _addChange: function(name, value) | 
|  267     { |  260     { | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|  290  |  283  | 
|  291         if ("color" in badge) |  284         if ("color" in badge) | 
|  292           this._addChange("badgeColor", badge.color); |  285           this._addChange("badgeColor", badge.color); | 
|  293       } |  286       } | 
|  294     } |  287     } | 
|  295   }; |  288   }; | 
|  296  |  289  | 
|  297  |  290  | 
|  298   /* Context menus */ |  291   /* Context menus */ | 
|  299  |  292  | 
|  300   var contextMenuItems = new ext.PageMap(); |  293   let contextMenuItems = new ext.PageMap(); | 
|  301   var contextMenuUpdating = false; |  294   let contextMenuUpdating = false; | 
|  302  |  295  | 
|  303   var updateContextMenu = function() |  296   let updateContextMenu = () => | 
|  304   { |  297   { | 
|  305     if (contextMenuUpdating) |  298     if (contextMenuUpdating) | 
|  306       return; |  299       return; | 
|  307  |  300  | 
|  308     contextMenuUpdating = true; |  301     contextMenuUpdating = true; | 
|  309  |  302  | 
|  310     chrome.tabs.query({active: true, lastFocusedWindow: true}, function(tabs) |  303     chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => | 
|  311     { |  304     { | 
|  312       chrome.contextMenus.removeAll(function() |  305       chrome.contextMenus.removeAll(() => | 
|  313       { |  306       { | 
|  314         contextMenuUpdating = false; |  307         contextMenuUpdating = false; | 
|  315  |  308  | 
|  316         if (tabs.length == 0) |  309         if (tabs.length == 0) | 
|  317           return; |  310           return; | 
|  318  |  311  | 
|  319         var items = contextMenuItems.get({id: tabs[0].id}); |  312         let items = contextMenuItems.get({id: tabs[0].id}); | 
|  320  |  313  | 
|  321         if (!items) |  314         if (!items) | 
|  322           return; |  315           return; | 
|  323  |  316  | 
|  324         items.forEach(function(item) |  317         items.forEach(item => | 
|  325         { |  318         { | 
|  326           chrome.contextMenus.create({ |  319           chrome.contextMenus.create({ | 
|  327             title: item.title, |  320             title: item.title, | 
|  328             contexts: item.contexts, |  321             contexts: item.contexts, | 
|  329             onclick: function(info, tab) |  322             onclick: (info, tab) => | 
|  330             { |  323             { | 
|  331               item.onclick(new Page(tab)); |  324               item.onclick(new Page(tab)); | 
|  332             } |  325             } | 
|  333           }); |  326           }); | 
|  334         }); |  327         }); | 
|  335       }); |  328       }); | 
|  336     }); |  329     }); | 
|  337   }; |  330   }; | 
|  338  |  331  | 
|  339   var ContextMenus = function(page) |  332   let ContextMenus = function(page) | 
|  340   { |  333   { | 
|  341     this._page = page; |  334     this._page = page; | 
|  342   }; |  335   }; | 
|  343   ContextMenus.prototype = { |  336   ContextMenus.prototype = { | 
|  344     create: function(item) |  337     create: function(item) | 
|  345     { |  338     { | 
|  346       var items = contextMenuItems.get(this._page); |  339       let items = contextMenuItems.get(this._page); | 
|  347       if (!items) |  340       if (!items) | 
|  348         contextMenuItems.set(this._page, items = []); |  341         contextMenuItems.set(this._page, items = []); | 
|  349  |  342  | 
|  350       items.push(item); |  343       items.push(item); | 
|  351       updateContextMenu(); |  344       updateContextMenu(); | 
|  352     }, |  345     }, | 
|  353     remove: function(item) |  346     remove: function(item) | 
|  354     { |  347     { | 
|  355       let items = contextMenuItems.get(this._page); |  348       let items = contextMenuItems.get(this._page); | 
|  356       if (items) |  349       if (items) | 
|  357       { |  350       { | 
|  358         let index = items.indexOf(item); |  351         let index = items.indexOf(item); | 
|  359         if (index != -1) |  352         if (index != -1) | 
|  360         { |  353         { | 
|  361           items.splice(index, 1); |  354           items.splice(index, 1); | 
|  362           updateContextMenu(); |  355           updateContextMenu(); | 
|  363         } |  356         } | 
|  364       } |  357       } | 
|  365     } |  358     } | 
|  366   }; |  359   }; | 
|  367  |  360  | 
|  368   chrome.tabs.onActivated.addListener(updateContextMenu); |  361   chrome.tabs.onActivated.addListener(updateContextMenu); | 
|  369  |  362  | 
|  370   chrome.windows.onFocusChanged.addListener(function(windowId) |  363   chrome.windows.onFocusChanged.addListener(windowId => | 
|  371   { |  364   { | 
|  372     if (windowId != chrome.windows.WINDOW_ID_NONE) |  365     if (windowId != chrome.windows.WINDOW_ID_NONE) | 
|  373       updateContextMenu(); |  366       updateContextMenu(); | 
|  374   }); |  367   }); | 
|  375  |  368  | 
|  376  |  369  | 
|  377   /* Web requests */ |  370   /* Web requests */ | 
|  378  |  371  | 
|  379   var framesOfTabs = Object.create(null); |  372   let framesOfTabs = Object.create(null); | 
|  380  |  373  | 
|  381   ext.getFrame = function(tabId, frameId) |  374   ext.getFrame = (tabId, frameId) => | 
|  382   { |  375   { | 
|  383     return (framesOfTabs[tabId] || {})[frameId]; |  376     return (framesOfTabs[tabId] || {})[frameId]; | 
|  384   }; |  377   }; | 
|  385  |  378  | 
|  386   var handlerBehaviorChangedQuota = chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANG
     ED_CALLS_PER_10_MINUTES; |  379   let handlerBehaviorChangedQuota = chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANG
     ED_CALLS_PER_10_MINUTES; | 
|  387  |  380  | 
|  388   function propagateHandlerBehaviorChange() |  381   function propagateHandlerBehaviorChange() | 
|  389   { |  382   { | 
|  390     // Make sure to not call handlerBehaviorChanged() more often than allowed |  383     // Make sure to not call handlerBehaviorChanged() more often than allowed | 
|  391     // by chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. |  384     // by chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. | 
|  392     // Otherwise Chrome notifies the user that this extension is causing issues. |  385     // Otherwise Chrome notifies the user that this extension is causing issues. | 
|  393     if (handlerBehaviorChangedQuota > 0) |  386     if (handlerBehaviorChangedQuota > 0) | 
|  394     { |  387     { | 
|  395       chrome.webNavigation.onBeforeNavigate.removeListener(propagateHandlerBehav
     iorChange); |  388       chrome.webNavigation.onBeforeNavigate.removeListener(propagateHandlerBehav
     iorChange); | 
|  396       chrome.webRequest.handlerBehaviorChanged(); |  389       chrome.webRequest.handlerBehaviorChanged(); | 
|  397  |  390  | 
|  398       handlerBehaviorChangedQuota--; |  391       handlerBehaviorChangedQuota--; | 
|  399       setTimeout(function() { handlerBehaviorChangedQuota++; }, 600000); |  392       setTimeout(() => { handlerBehaviorChangedQuota++; }, 600000); | 
|  400     } |  393     } | 
|  401   } |  394   } | 
|  402  |  395  | 
|  403   ext.webRequest = { |  396   ext.webRequest = { | 
|  404     onBeforeRequest: new ext._EventTarget(), |  397     onBeforeRequest: new ext._EventTarget(), | 
|  405     handlerBehaviorChanged: function() |  398     handlerBehaviorChanged: () => | 
|  406     { |  399     { | 
|  407       // Defer handlerBehaviorChanged() until navigation occurs. |  400       // Defer handlerBehaviorChanged() until navigation occurs. | 
|  408       // There wouldn't be any visible effect when calling it earlier, |  401       // There wouldn't be any visible effect when calling it earlier, | 
|  409       // but it's an expensive operation and that way we avoid to call |  402       // but it's an expensive operation and that way we avoid to call | 
|  410       // it multiple times, if multiple filters are added/removed. |  403       // it multiple times, if multiple filters are added/removed. | 
|  411       var onBeforeNavigate = chrome.webNavigation.onBeforeNavigate; |  404       let onBeforeNavigate = chrome.webNavigation.onBeforeNavigate; | 
|  412       if (!onBeforeNavigate.hasListener(propagateHandlerBehaviorChange)) |  405       if (!onBeforeNavigate.hasListener(propagateHandlerBehaviorChange)) | 
|  413         onBeforeNavigate.addListener(propagateHandlerBehaviorChange); |  406         onBeforeNavigate.addListener(propagateHandlerBehaviorChange); | 
|  414     } |  407     } | 
|  415   }; |  408   }; | 
|  416  |  409  | 
|  417   chrome.tabs.query({}, function(tabs) |  410   chrome.tabs.query({}, tabs => | 
|  418   { |  411   { | 
|  419     tabs.forEach(function(tab) |  412     tabs.forEach(tab => | 
|  420     { |  413     { | 
|  421       chrome.webNavigation.getAllFrames({tabId: tab.id}, function(details) |  414       chrome.webNavigation.getAllFrames({tabId: tab.id}, details => | 
|  422       { |  415       { | 
|  423         if (details && details.length > 0) |  416         if (details && details.length > 0) | 
|  424         { |  417         { | 
|  425           var frames = framesOfTabs[tab.id] = Object.create(null); |  418           let frames = framesOfTabs[tab.id] = Object.create(null); | 
|  426  |  419  | 
|  427           for (var i = 0; i < details.length; i++) |  420           for (let i = 0; i < details.length; i++) | 
|  428             frames[details[i].frameId] = {url: new URL(details[i].url), parent: 
     null}; |  421             frames[details[i].frameId] = {url: new URL(details[i].url), parent: 
     null}; | 
|  429  |  422  | 
|  430           for (var i = 0; i < details.length; i++) |  423           for (let i = 0; i < details.length; i++) | 
|  431           { |  424           { | 
|  432             var parentFrameId = details[i].parentFrameId; |  425             let parentFrameId = details[i].parentFrameId; | 
|  433  |  426  | 
|  434             if (parentFrameId != -1) |  427             if (parentFrameId != -1) | 
|  435               frames[details[i].frameId].parent = frames[parentFrameId]; |  428               frames[details[i].frameId].parent = frames[parentFrameId]; | 
|  436           } |  429           } | 
|  437         } |  430         } | 
|  438       }); |  431       }); | 
|  439     }); |  432     }); | 
|  440   }); |  433   }); | 
|  441  |  434  | 
|  442   chrome.webRequest.onBeforeRequest.addListener(function(details) |  435   chrome.webRequest.onBeforeRequest.addListener(details => | 
|  443   { |  436   { | 
|  444     // The high-level code isn't interested in requests that aren't |  437     // The high-level code isn't interested in requests that aren't | 
|  445     // related to a tab or requests loading a top-level document, |  438     // related to a tab or requests loading a top-level document, | 
|  446     // those should never be blocked. |  439     // those should never be blocked. | 
|  447     if (details.tabId == -1 || details.type == "main_frame") |  440     if (details.tabId == -1 || details.type == "main_frame") | 
|  448       return; |  441       return; | 
|  449  |  442  | 
|  450     // We are looking for the frame that contains the element which |  443     // We are looking for the frame that contains the element which | 
|  451     // has triggered this request. For most requests (e.g. images) we |  444     // has triggered this request. For most requests (e.g. images) we | 
|  452     // can just use the request's frame ID, but for subdocument requests |  445     // can just use the request's frame ID, but for subdocument requests | 
|  453     // (e.g. iframes) we must instead use the request's parent frame ID. |  446     // (e.g. iframes) we must instead use the request's parent frame ID. | 
|  454     var frameId; |  447     let frameId; | 
|  455     var requestType; |  448     let requestType; | 
|  456     if (details.type == "sub_frame") |  449     if (details.type == "sub_frame") | 
|  457     { |  450     { | 
|  458       frameId = details.parentFrameId; |  451       frameId = details.parentFrameId; | 
|  459       requestType = "SUBDOCUMENT"; |  452       requestType = "SUBDOCUMENT"; | 
|  460     } |  453     } | 
|  461     else |  454     else | 
|  462     { |  455     { | 
|  463       frameId = details.frameId; |  456       frameId = details.frameId; | 
|  464       requestType = details.type.toUpperCase(); |  457       requestType = details.type.toUpperCase(); | 
|  465     } |  458     } | 
|  466  |  459  | 
|  467     var frame = ext.getFrame(details.tabId, frameId); |  460     let frame = ext.getFrame(details.tabId, frameId); | 
|  468     if (frame) |  461     if (frame) | 
|  469     { |  462     { | 
|  470       var results = ext.webRequest.onBeforeRequest._dispatch( |  463       let results = ext.webRequest.onBeforeRequest._dispatch( | 
|  471         new URL(details.url), |  464         new URL(details.url), | 
|  472         requestType, |  465         requestType, | 
|  473         new Page({id: details.tabId}), |  466         new Page({id: details.tabId}), | 
|  474         frame |  467         frame | 
|  475       ); |  468       ); | 
|  476  |  469  | 
|  477       if (results.indexOf(false) != -1) |  470       if (results.indexOf(false) != -1) | 
|  478         return {cancel: true}; |  471         return {cancel: true}; | 
|  479     } |  472     } | 
|  480   }, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); |  473   }, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); | 
|  481  |  474  | 
|  482  |  475  | 
|  483   /* Message passing */ |  476   /* Message passing */ | 
|  484  |  477  | 
|  485   chrome.runtime.onMessage.addListener(function(message, rawSender, sendResponse
     ) |  478   chrome.runtime.onMessage.addListener((message, rawSender, sendResponse) => | 
|  486   { |  479   { | 
|  487     var sender = {}; |  480     let sender = {}; | 
|  488  |  481  | 
|  489     // Add "page" and "frame" if the message was sent by a content script. |  482     // Add "page" and "frame" if the message was sent by a content script. | 
|  490     // If sent by popup or the background page itself, there is no "tab". |  483     // If sent by popup or the background page itself, there is no "tab". | 
|  491     if ("tab" in rawSender) |  484     if ("tab" in rawSender) | 
|  492     { |  485     { | 
|  493       sender.page = new Page(rawSender.tab); |  486       sender.page = new Page(rawSender.tab); | 
|  494       sender.frame = { |  487       sender.frame = { | 
|  495         url: new URL(rawSender.url), |  488         url: new URL(rawSender.url), | 
|  496         get parent() |  489         get parent() | 
|  497         { |  490         { | 
|  498           var frames = framesOfTabs[rawSender.tab.id]; |  491           let frames = framesOfTabs[rawSender.tab.id]; | 
|  499  |  492  | 
|  500           if (!frames) |  493           if (!frames) | 
|  501             return null; |  494             return null; | 
|  502  |  495  | 
|  503           var frame = frames[rawSender.frameId]; |  496           let frame = frames[rawSender.frameId]; | 
|  504           if (frame) |  497           if (frame) | 
|  505             return frame.parent; |  498             return frame.parent; | 
|  506  |  499  | 
|  507           return frames[0]; |  500           return frames[0]; | 
|  508         } |  501         } | 
|  509       }; |  502       }; | 
|  510     } |  503     } | 
|  511  |  504  | 
|  512     return ext.onMessage._dispatch(message, sender, sendResponse).indexOf(true) 
     != -1; |  505     return ext.onMessage._dispatch(message, sender, sendResponse).indexOf(true) 
     != -1; | 
|  513   }); |  506   }); | 
|  514  |  507  | 
|  515  |  508  | 
|  516   /* Storage */ |  509   /* Storage */ | 
|  517  |  510  | 
|  518   ext.storage = { |  511   ext.storage = { | 
|  519     get: function(keys, callback) |  512     get: (keys, callback) => | 
|  520     { |  513     { | 
|  521       chrome.storage.local.get(keys, callback); |  514       chrome.storage.local.get(keys, callback); | 
|  522     }, |  515     }, | 
|  523     set: function(key, value, callback) |  516     set: (key, value, callback) => | 
|  524     { |  517     { | 
|  525       let items = {}; |  518       let items = {}; | 
|  526       items[key] = value; |  519       items[key] = value; | 
|  527       chrome.storage.local.set(items, callback); |  520       chrome.storage.local.set(items, callback); | 
|  528     }, |  521     }, | 
|  529     remove: function(key, callback) |  522     remove: (key, callback) => | 
|  530     { |  523     { | 
|  531       chrome.storage.local.remove(key, callback); |  524       chrome.storage.local.remove(key, callback); | 
|  532     }, |  525     }, | 
|  533     onChanged: chrome.storage.onChanged |  526     onChanged: chrome.storage.onChanged | 
|  534   }; |  527   }; | 
|  535  |  528  | 
|  536   /* Options */ |  529   /* Options */ | 
|  537  |  530  | 
|  538   if ("openOptionsPage" in chrome.runtime) |  531   if ("openOptionsPage" in chrome.runtime) | 
|  539   { |  532   { | 
|  540     ext.showOptions = function(callback) |  533     ext.showOptions = callback => | 
|  541     { |  534     { | 
|  542       if (!callback) |  535       if (!callback) | 
|  543       { |  536       { | 
|  544         chrome.runtime.openOptionsPage(); |  537         chrome.runtime.openOptionsPage(); | 
|  545       } |  538       } | 
|  546       else |  539       else | 
|  547       { |  540       { | 
|  548         chrome.runtime.openOptionsPage(() => |  541         chrome.runtime.openOptionsPage(() => | 
|  549         { |  542         { | 
|  550           if (chrome.runtime.lastError) |  543           if (chrome.runtime.lastError) | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  561             } |  554             } | 
|  562           }); |  555           }); | 
|  563         }); |  556         }); | 
|  564       } |  557       } | 
|  565     }; |  558     }; | 
|  566   } |  559   } | 
|  567   else |  560   else | 
|  568   { |  561   { | 
|  569     // Edge does not yet support runtime.openOptionsPage (tested version 38) |  562     // Edge does not yet support runtime.openOptionsPage (tested version 38) | 
|  570     // and so this workaround needs to stay for now. |  563     // and so this workaround needs to stay for now. | 
|  571     ext.showOptions = function(callback) |  564     ext.showOptions = callback => | 
|  572     { |  565     { | 
|  573       chrome.windows.getLastFocused(function(win) |  566       chrome.windows.getLastFocused(win => | 
|  574       { |  567       { | 
|  575         var optionsUrl = chrome.extension.getURL("options.html"); |  568         let optionsUrl = chrome.extension.getURL("options.html"); | 
|  576         var queryInfo = {url: optionsUrl}; |  569         let queryInfo = {url: optionsUrl}; | 
|  577  |  570  | 
|  578         // extension pages can't be accessed in incognito windows. In order to |  571         // extension pages can't be accessed in incognito windows. In order to | 
|  579         // correctly mimic the way in which Chrome opens extension options, |  572         // correctly mimic the way in which Chrome opens extension options, | 
|  580         // we have to focus the options page in any other window. |  573         // we have to focus the options page in any other window. | 
|  581         if (!win.incognito) |  574         if (!win.incognito) | 
|  582           queryInfo.windowId = win.id; |  575           queryInfo.windowId = win.id; | 
|  583  |  576  | 
|  584         chrome.tabs.query(queryInfo, function(tabs) |  577         chrome.tabs.query(queryInfo, tabs => | 
|  585         { |  578         { | 
|  586           if (tabs.length > 0) |  579           if (tabs.length > 0) | 
|  587           { |  580           { | 
|  588             var tab = tabs[0]; |  581             let tab = tabs[0]; | 
|  589  |  582  | 
|  590             chrome.windows.update(tab.windowId, {focused: true}); |  583             chrome.windows.update(tab.windowId, {focused: true}); | 
|  591             chrome.tabs.update(tab.id, {active: true}); |  584             chrome.tabs.update(tab.id, {active: true}); | 
|  592  |  585  | 
|  593             if (callback) |  586             if (callback) | 
|  594               callback(new Page(tab)); |  587               callback(new Page(tab)); | 
|  595           } |  588           } | 
|  596           else |  589           else | 
|  597           { |  590           { | 
|  598             ext.pages.open(optionsUrl, callback); |  591             ext.pages.open(optionsUrl, callback); | 
|  599           } |  592           } | 
|  600         }); |  593         }); | 
|  601       }); |  594       }); | 
|  602     }; |  595     }; | 
|  603   } |  596   } | 
|  604  |  597  | 
|  605   /* Windows */ |  598   /* Windows */ | 
|  606   ext.windows = { |  599   ext.windows = { | 
|  607     create: function(createData, callback) |  600     create: (createData, callback) => | 
|  608     { |  601     { | 
|  609       chrome.windows.create(createData, function(createdWindow) |  602       chrome.windows.create(createData, createdWindow => | 
|  610       { |  603       { | 
|  611         afterTabLoaded(callback)(createdWindow.tabs[0]); |  604         afterTabLoaded(callback)(createdWindow.tabs[0]); | 
|  612       }); |  605       }); | 
|  613     } |  606     } | 
|  614   }; |  607   }; | 
|  615 })(); |  608 } | 
| OLD | NEW |