| 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-2017 eyeo GmbH | 3  * Copyright (C) 2006-2017 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 "use strict"; | 18 "use strict"; | 
| 19 | 19 | 
| 20 (function() | 20 (function() | 
| 21 { | 21 { | 
| 22   let nonEmptyPageMaps = Object.create(null); | 22   let nonEmptyPageMaps = new Set(); | 
| 23   let pageMapCounter = 0; |  | 
| 24 | 23 | 
| 25   let PageMap = ext.PageMap = function() | 24   let PageMap = ext.PageMap = function() | 
| 26   { | 25   { | 
| 27     this._map = Object.create(null); | 26     this._map = new Map(); | 
| 28     this._id = ++pageMapCounter; |  | 
| 29   }; | 27   }; | 
| 30   PageMap.prototype = { | 28   PageMap.prototype = { | 
| 31     _delete(id) | 29     _delete(id) | 
| 32     { | 30     { | 
| 33       delete this._map[id]; | 31       this._map.delete(id); | 
| 34 | 32 | 
| 35       if (Object.keys(this._map).length == 0) | 33       if (this._map.size == 0) | 
| 36         delete nonEmptyPageMaps[this._id]; | 34         nonEmptyPageMaps.delete(this); | 
| 37     }, | 35     }, | 
| 38     keys() | 36     keys() | 
| 39     { | 37     { | 
| 40       return Object.keys(this._map).map(ext.getPage); | 38       return this._map.keys(); | 
| 41     }, | 39     }, | 
| 42     get(page) | 40     get(page) | 
| 43     { | 41     { | 
| 44       return this._map[page.id]; | 42       return this._map.get(page.id); | 
| 45     }, | 43     }, | 
| 46     set(page, value) | 44     set(page, value) | 
| 47     { | 45     { | 
| 48       this._map[page.id] = value; | 46       this._map.set(page.id, value); | 
| 49       nonEmptyPageMaps[this._id] = this; | 47       nonEmptyPageMaps.add(this); | 
| 50     }, | 48     }, | 
| 51     has(page) | 49     has(page) | 
| 52     { | 50     { | 
| 53       return page.id in this._map; | 51       return this._map.has(page.id); | 
| 54     }, | 52     }, | 
| 55     clear() | 53     clear() | 
| 56     { | 54     { | 
| 57       for (let id in this._map) | 55       this._map.clear(); | 
| 58         this._delete(id); | 56       nonEmptyPageMaps.delete(this); | 
| 59     }, | 57     }, | 
| 60     delete(page) | 58     delete(page) | 
| 61     { | 59     { | 
| 62       this._delete(page.id); | 60       this._delete(page.id); | 
| 63     } | 61     } | 
| 64   }; | 62   }; | 
| 65 | 63 | 
| 66   ext._removeFromAllPageMaps = pageId => | 64   ext._removeFromAllPageMaps = pageId => | 
| 67   { | 65   { | 
| 68     for (let pageMapId in nonEmptyPageMaps) | 66     for (let pageMap of nonEmptyPageMaps) | 
| 69       nonEmptyPageMaps[pageMapId]._delete(pageId); | 67       pageMap._delete(pageId); | 
| 70   }; | 68   }; | 
| 71 | 69 | 
| 72   /* Pages */ | 70   /* Pages */ | 
| 73 | 71 | 
| 74   let Page = ext.Page = function(tab) | 72   let Page = ext.Page = function(tab) | 
| 75   { | 73   { | 
| 76     this.id = tab.id; | 74     this.id = tab.id; | 
| 77     this._url = tab.url && new URL(tab.url); | 75     this._url = tab.url && new URL(tab.url); | 
| 78 | 76 | 
| 79     this.browserAction = new BrowserAction(tab.id); | 77     this.browserAction = new BrowserAction(tab.id); | 
| 80     this.contextMenus = new ContextMenus(this); | 78     this.contextMenus = new ContextMenus(this); | 
| 81   }; | 79   }; | 
| 82   Page.prototype = { | 80   Page.prototype = { | 
| 83     get url() | 81     get url() | 
| 84     { | 82     { | 
| 85       // usually our Page objects are created from Chrome's Tab objects, which | 83       // usually our Page objects are created from Chrome's Tab objects, which | 
| 86       // provide the url. So we can return the url given in the constructor. | 84       // provide the url. So we can return the url given in the constructor. | 
| 87       if (this._url) | 85       if (this._url) | 
| 88         return this._url; | 86         return this._url; | 
| 89 | 87 | 
| 90       // but sometimes we only have the tab id when we create a Page object. | 88       // but sometimes we only have the tab id when we create a Page object. | 
| 91       // In that case we get the url from top frame of the tab, recorded by | 89       // In that case we get the url from top frame of the tab, recorded by | 
| 92       // the onBeforeRequest handler. | 90       // the onBeforeRequest handler. | 
| 93       let frames = framesOfTabs[this.id]; | 91       let frames = framesOfTabs.get(this.id); | 
| 94       if (frames) | 92       if (frames) | 
| 95       { | 93       { | 
| 96         let frame = frames[0]; | 94         let frame = frames.get(0); | 
| 97         if (frame) | 95         if (frame) | 
| 98           return frame.url; | 96           return frame.url; | 
| 99       } | 97       } | 
| 100     }, | 98     }, | 
| 101     sendMessage(message, responseCallback) | 99     sendMessage(message, responseCallback) | 
| 102     { | 100     { | 
| 103       chrome.tabs.sendMessage(this.id, message, responseCallback); | 101       chrome.tabs.sendMessage(this.id, message, responseCallback); | 
| 104     } | 102     } | 
| 105   }; | 103   }; | 
| 106 | 104 | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 151   }; | 149   }; | 
| 152 | 150 | 
| 153   chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => | 151   chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => | 
| 154   { | 152   { | 
| 155     if (changeInfo.status == "loading") | 153     if (changeInfo.status == "loading") | 
| 156       ext.pages.onLoading._dispatch(new Page(tab)); | 154       ext.pages.onLoading._dispatch(new Page(tab)); | 
| 157   }); | 155   }); | 
| 158 | 156 | 
| 159   function createFrame(tabId, frameId) | 157   function createFrame(tabId, frameId) | 
| 160   { | 158   { | 
| 161     let frames = framesOfTabs[tabId]; | 159     let frames = framesOfTabs.get(tabId); | 
| 162     if (!frames) | 160     if (!frames) | 
| 163       frames = framesOfTabs[tabId] = Object.create(null); | 161     { | 
|  | 162       frames = new Map(); | 
|  | 163       framesOfTabs.set(tabId, frames); | 
|  | 164     } | 
| 164 | 165 | 
| 165     let frame = frames[frameId]; | 166     let frame = frames.get(frameId); | 
| 166     if (!frame) | 167     if (!frame) | 
| 167       frame = frames[frameId] = {}; | 168     { | 
|  | 169       frame = {}; | 
|  | 170       frames.set(frameId, frame); | 
|  | 171     } | 
| 168 | 172 | 
| 169     return frame; | 173     return frame; | 
| 170   } | 174   } | 
| 171 | 175 | 
| 172   function updatePageFrameStructure(frameId, tabId, url, parentFrameId) | 176   function updatePageFrameStructure(frameId, tabId, url, parentFrameId) | 
| 173   { | 177   { | 
| 174     if (frameId == 0) | 178     if (frameId == 0) | 
| 175     { | 179     { | 
| 176       let page = new Page({id: tabId, url}); | 180       let page = new Page({id: tabId, url}); | 
| 177 | 181 | 
| 178       ext._removeFromAllPageMaps(tabId); | 182       ext._removeFromAllPageMaps(tabId); | 
| 179 | 183 | 
| 180       chrome.tabs.get(tabId, () => | 184       chrome.tabs.get(tabId, () => | 
| 181       { | 185       { | 
| 182         // If the tab is prerendered, chrome.tabs.get() sets | 186         // If the tab is prerendered, chrome.tabs.get() sets | 
| 183         // chrome.runtime.lastError and we have to dispatch the onLoading event, | 187         // chrome.runtime.lastError and we have to dispatch the onLoading event, | 
| 184         // since the onUpdated event isn't dispatched for prerendered tabs. | 188         // since the onUpdated event isn't dispatched for prerendered tabs. | 
| 185         // However, we have to keep relying on the unUpdated event for tabs that | 189         // However, we have to keep relying on the unUpdated event for tabs that | 
| 186         // are already visible. Otherwise browser action changes get overridden | 190         // are already visible. Otherwise browser action changes get overridden | 
| 187         // when Chrome automatically resets them on navigation. | 191         // when Chrome automatically resets them on navigation. | 
| 188         if (chrome.runtime.lastError) | 192         if (chrome.runtime.lastError) | 
| 189           ext.pages.onLoading._dispatch(page); | 193           ext.pages.onLoading._dispatch(page); | 
| 190       }); | 194       }); | 
| 191     } | 195     } | 
| 192 | 196 | 
| 193     // Update frame parent and URL in frame structure | 197     // Update frame URL and parent in frame structure | 
| 194     let frame = createFrame(tabId, frameId); | 198     let frame = createFrame(tabId, frameId); | 
| 195     frame.url = new URL(url); | 199     frame.url = new URL(url); | 
| 196     frame.parent = framesOfTabs[tabId][parentFrameId] || null; | 200 | 
|  | 201     let parentFrame = framesOfTabs.get(tabId).get(parentFrameId); | 
|  | 202     if (parentFrame) | 
|  | 203       frame.parent = parentFrame; | 
| 197   } | 204   } | 
| 198 | 205 | 
| 199   chrome.webRequest.onHeadersReceived.addListener(details => | 206   chrome.webRequest.onHeadersReceived.addListener(details => | 
| 200   { | 207   { | 
| 201     // We have to update the frame structure when switching to a new | 208     // We have to update the frame structure when switching to a new | 
| 202     // document, so that we process any further requests made by that | 209     // document, so that we process any further requests made by that | 
| 203     // document in the right context. Unfortunately, we cannot rely | 210     // document in the right context. Unfortunately, we cannot rely | 
| 204     // on webNavigation.onCommitted since it isn't guaranteed to fire | 211     // on webNavigation.onCommitted since it isn't guaranteed to fire | 
| 205     // before any subresources start downloading[1]. As an | 212     // before any subresources start downloading[1]. As an | 
| 206     // alternative we use webRequest.onHeadersReceived for HTTP(S) | 213     // alternative we use webRequest.onHeadersReceived for HTTP(S) | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 285       updatePageFrameStructure(details.frameId, details.tabId, details.url, | 292       updatePageFrameStructure(details.frameId, details.tabId, details.url, | 
| 286                                details.parentFrameId); | 293                                details.parentFrameId); | 
| 287     } | 294     } | 
| 288   }); | 295   }); | 
| 289 | 296 | 
| 290   function forgetTab(tabId) | 297   function forgetTab(tabId) | 
| 291   { | 298   { | 
| 292     ext.pages.onRemoved._dispatch(tabId); | 299     ext.pages.onRemoved._dispatch(tabId); | 
| 293 | 300 | 
| 294     ext._removeFromAllPageMaps(tabId); | 301     ext._removeFromAllPageMaps(tabId); | 
| 295     delete framesOfTabs[tabId]; | 302     framesOfTabs.delete(tabId); | 
| 296   } | 303   } | 
| 297 | 304 | 
| 298   chrome.tabs.onReplaced.addListener((addedTabId, removedTabId) => | 305   chrome.tabs.onReplaced.addListener((addedTabId, removedTabId) => | 
| 299   { | 306   { | 
| 300     forgetTab(removedTabId); | 307     forgetTab(removedTabId); | 
| 301   }); | 308   }); | 
| 302 | 309 | 
| 303   chrome.tabs.onRemoved.addListener(forgetTab); | 310   chrome.tabs.onRemoved.addListener(forgetTab); | 
| 304 | 311 | 
| 305   chrome.tabs.onActivated.addListener(details => | 312   chrome.tabs.onActivated.addListener(details => | 
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 483 | 490 | 
| 484   chrome.windows.onFocusChanged.addListener(windowId => | 491   chrome.windows.onFocusChanged.addListener(windowId => | 
| 485   { | 492   { | 
| 486     if (windowId != chrome.windows.WINDOW_ID_NONE) | 493     if (windowId != chrome.windows.WINDOW_ID_NONE) | 
| 487       updateContextMenu(); | 494       updateContextMenu(); | 
| 488   }); | 495   }); | 
| 489 | 496 | 
| 490 | 497 | 
| 491   /* Web requests */ | 498   /* Web requests */ | 
| 492 | 499 | 
| 493   let framesOfTabs = Object.create(null); | 500   let framesOfTabs = new Map(); | 
| 494 | 501 | 
| 495   ext.getFrame = (tabId, frameId) => | 502   ext.getFrame = (tabId, frameId) => | 
| 496   { | 503   { | 
| 497     return (framesOfTabs[tabId] || {})[frameId]; | 504     let frames = framesOfTabs.get(tabId); | 
|  | 505     return frames && frames.get(frameId); | 
| 498   }; | 506   }; | 
| 499 | 507 | 
| 500   let handlerBehaviorChangedQuota = | 508   let handlerBehaviorChangedQuota = | 
| 501     chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES; | 509     chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES; | 
| 502 | 510 | 
| 503   function propagateHandlerBehaviorChange() | 511   function propagateHandlerBehaviorChange() | 
| 504   { | 512   { | 
| 505     // Make sure to not call handlerBehaviorChanged() more often than allowed | 513     // Make sure to not call handlerBehaviorChanged() more often than allowed | 
| 506     // by chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. | 514     // by chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. | 
| 507     // Otherwise Chrome notifies the user that this extension is causing issues. | 515     // Otherwise Chrome notifies the user that this extension is causing issues. | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 532   }; | 540   }; | 
| 533 | 541 | 
| 534   chrome.tabs.query({}, tabs => | 542   chrome.tabs.query({}, tabs => | 
| 535   { | 543   { | 
| 536     tabs.forEach(tab => | 544     tabs.forEach(tab => | 
| 537     { | 545     { | 
| 538       chrome.webNavigation.getAllFrames({tabId: tab.id}, details => | 546       chrome.webNavigation.getAllFrames({tabId: tab.id}, details => | 
| 539       { | 547       { | 
| 540         if (details && details.length > 0) | 548         if (details && details.length > 0) | 
| 541         { | 549         { | 
| 542           let frames = framesOfTabs[tab.id] = Object.create(null); | 550           let frames = new Map(); | 
|  | 551           framesOfTabs.set(tab.id, frames); | 
| 543 | 552 | 
| 544           for (let i = 0; i < details.length; i++) | 553           for (let detail of details) | 
| 545           { | 554           { | 
| 546             frames[details[i].frameId] = { | 555             let frame = {url: new URL(detail.url)}; | 
| 547               url: new URL(details[i].url), | 556             frames.set(detail.frameId, frame); | 
| 548               parent: null |  | 
| 549             }; |  | 
| 550           } |  | 
| 551 | 557 | 
| 552           for (let i = 0; i < details.length; i++) | 558             if (detail.parentFrameId != -1) | 
| 553           { | 559               frame.parent = frames.get(detail.parentFrameId); | 
| 554             let {parentFrameId} = details[i]; |  | 
| 555 |  | 
| 556             if (parentFrameId != -1) |  | 
| 557               frames[details[i].frameId].parent = frames[parentFrameId]; |  | 
| 558           } | 560           } | 
| 559         } | 561         } | 
| 560       }); | 562       }); | 
| 561     }); | 563     }); | 
| 562   }); | 564   }); | 
| 563 | 565 | 
| 564   chrome.webRequest.onBeforeRequest.addListener(details => | 566   chrome.webRequest.onBeforeRequest.addListener(details => | 
| 565   { | 567   { | 
| 566     // The high-level code isn't interested in requests that aren't | 568     // The high-level code isn't interested in requests that aren't | 
| 567     // related to a tab or requests loading a top-level document, | 569     // related to a tab or requests loading a top-level document, | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 608 | 610 | 
| 609     // Add "page" and "frame" if the message was sent by a content script. | 611     // Add "page" and "frame" if the message was sent by a content script. | 
| 610     // If sent by popup or the background page itself, there is no "tab". | 612     // If sent by popup or the background page itself, there is no "tab". | 
| 611     if ("tab" in rawSender) | 613     if ("tab" in rawSender) | 
| 612     { | 614     { | 
| 613       sender.page = new Page(rawSender.tab); | 615       sender.page = new Page(rawSender.tab); | 
| 614       sender.frame = { | 616       sender.frame = { | 
| 615         url: new URL(rawSender.url), | 617         url: new URL(rawSender.url), | 
| 616         get parent() | 618         get parent() | 
| 617         { | 619         { | 
| 618           let frames = framesOfTabs[rawSender.tab.id]; | 620           let frames = framesOfTabs.get(rawSender.tab.id); | 
| 619 | 621 | 
| 620           if (!frames) | 622           if (!frames) | 
| 621             return null; | 623             return null; | 
| 622 | 624 | 
| 623           let frame = frames[rawSender.frameId]; | 625           let frame = frames.get(rawSender.frameId); | 
| 624           if (frame) | 626           if (frame) | 
| 625             return frame.parent; | 627             return frame.parent || null; | 
| 626 | 628 | 
| 627           return frames[0]; | 629           return frames.get(0) || null; | 
| 628         } | 630         } | 
| 629       }; | 631       }; | 
| 630     } | 632     } | 
| 631 | 633 | 
| 632     return ext.onMessage._dispatch( | 634     return ext.onMessage._dispatch( | 
| 633       message, sender, sendResponse | 635       message, sender, sendResponse | 
| 634     ).indexOf(true) != -1; | 636     ).indexOf(true) != -1; | 
| 635   }); | 637   }); | 
| 636 | 638 | 
| 637 | 639 | 
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 728   ext.windows = { | 730   ext.windows = { | 
| 729     create(createData, callback) | 731     create(createData, callback) | 
| 730     { | 732     { | 
| 731       chrome.windows.create(createData, createdWindow => | 733       chrome.windows.create(createData, createdWindow => | 
| 732       { | 734       { | 
| 733         afterTabLoaded(callback)(createdWindow.tabs[0]); | 735         afterTabLoaded(callback)(createdWindow.tabs[0]); | 
| 734       }); | 736       }); | 
| 735     } | 737     } | 
| 736   }; | 738   }; | 
| 737 }()); | 739 }()); | 
| OLD | NEW | 
|---|