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