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 |