| 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 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 sendMessage(message, responseCallback) | 50 sendMessage(message, responseCallback) |
| 51 { | 51 { |
| 52 chrome.tabs.sendMessage(this.id, message, responseCallback); | 52 chrome.tabs.sendMessage(this.id, message, responseCallback); |
| 53 } | 53 } |
| 54 }; | 54 }; |
| 55 | 55 |
| 56 ext.getPage = id => new Page({id: parseInt(id, 10)}); | 56 ext.getPage = id => new Page({id: parseInt(id, 10)}); |
| 57 | 57 |
| 58 function afterTabLoaded(callback) | 58 function afterTabLoaded(callback) |
| 59 { | 59 { |
| 60 return openedTab => | 60 return openedTab => |
| 61 { | 61 { |
| 62 let onUpdated = (tabId, changeInfo, tab) => | 62 let onUpdated = (tabId, changeInfo, tab) => |
| 63 { | 63 { |
| 64 if (tabId == openedTab.id && changeInfo.status == "complete") | 64 if (tabId == openedTab.id && changeInfo.status == "complete") |
| 65 { | 65 { |
| 66 chrome.tabs.onUpdated.removeListener(onUpdated); | 66 chrome.tabs.onUpdated.removeListener(onUpdated); |
| 67 callback(new Page(openedTab)); | 67 callback(new Page(openedTab)); |
| 68 } | 68 } |
| 69 }; | 69 }; |
| 70 chrome.tabs.onUpdated.addListener(onUpdated); | 70 chrome.tabs.onUpdated.addListener(onUpdated); |
| 71 }; | 71 }; |
| 72 } | 72 } |
| 73 | 73 |
| 74 ext.pages = { | 74 ext.pages = { |
| 75 open(url, callback) | 75 open(url, callback) |
| 76 { | 76 { |
| 77 chrome.tabs.create({url: url}, callback && afterTabLoaded(callback)); | 77 chrome.tabs.create({url}, callback && afterTabLoaded(callback)); |
| 78 }, | 78 }, |
| 79 query(info, callback) | 79 query(info, callback) |
| 80 { | 80 { |
| 81 let rawInfo = {}; | 81 let rawInfo = {}; |
| 82 for (let property in info) | 82 for (let property in info) |
| 83 { | 83 { |
| 84 switch (property) | 84 switch (property) |
| 85 { | 85 { |
| 86 case "active": | 86 case "active": |
| 87 case "lastFocusedWindow": | 87 case "lastFocusedWindow": |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 let frame = createFrame(details.tabId, details.frameId); | 124 let frame = createFrame(details.tabId, details.frameId); |
| 125 frame.parent = framesOfTabs[details.tabId][details.parentFrameId] || null; | 125 frame.parent = framesOfTabs[details.tabId][details.parentFrameId] || null; |
| 126 }); | 126 }); |
| 127 | 127 |
| 128 let eagerlyUpdatedPages = new ext.PageMap(); | 128 let eagerlyUpdatedPages = new ext.PageMap(); |
| 129 | 129 |
| 130 ext._updatePageFrameStructure = (frameId, tabId, url, eager) => | 130 ext._updatePageFrameStructure = (frameId, tabId, url, eager) => |
| 131 { | 131 { |
| 132 if (frameId == 0) | 132 if (frameId == 0) |
| 133 { | 133 { |
| 134 let page = new Page({id: tabId, url: url}); | 134 let page = new Page({id: tabId, url}); |
| 135 | 135 |
| 136 if (eagerlyUpdatedPages.get(page) != url) | 136 if (eagerlyUpdatedPages.get(page) != url) |
| 137 { | 137 { |
| 138 ext._removeFromAllPageMaps(tabId); | 138 ext._removeFromAllPageMaps(tabId); |
| 139 | 139 |
| 140 // 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 |
| 141 // 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 |
| 142 // trashing the page structure if the onCommitted event is then fired | 142 // trashing the page structure if the onCommitted event is then fired |
| 143 // for the page. | 143 // for the page. |
| 144 if (eager) | 144 if (eager) |
| 145 eagerlyUpdatedPages.set(page, url); | 145 eagerlyUpdatedPages.set(page, url); |
| 146 | 146 |
| 147 chrome.tabs.get(tabId, () => | 147 chrome.tabs.get(tabId, () => |
| 148 { | 148 { |
| 149 // If the tab is prerendered, chrome.tabs.get() sets | 149 // If the tab is prerendered, chrome.tabs.get() sets |
| 150 // chrome.runtime.lastError and we have to dispatch the onLoading even
t, | 150 // chrome.runtime.lastError and we have to dispatch the |
| 151 // since the onUpdated event isn't dispatched for prerendered tabs. | 151 // onLoading event, since the onUpdated event isn't |
| 152 // However, we have to keep relying on the unUpdated event for tabs th
at | 152 // dispatched for prerendered tabs. However, we have to |
| 153 // are already visible. Otherwise browser action changes get overridde
n | 153 // keep relying on the unUpdated event for tabs that are |
| 154 // when Chrome automatically resets them on navigation. | 154 // already visible. Otherwise browser action changes get |
| 155 // overridden when Chrome automatically resets them on |
| 156 // navigation. |
| 155 if (chrome.runtime.lastError) | 157 if (chrome.runtime.lastError) |
| 156 ext.pages.onLoading._dispatch(page); | 158 ext.pages.onLoading._dispatch(page); |
| 157 }); | 159 }); |
| 158 } | 160 } |
| 159 } | 161 } |
| 160 | 162 |
| 161 // Update frame URL in frame structure | 163 // Update frame URL in frame structure |
| 162 let frame = createFrame(tabId, frameId); | 164 let frame = createFrame(tabId, frameId); |
| 163 frame.url = new URL(url); | 165 frame.url = new URL(url); |
| 164 }; | 166 }; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 chrome.browserAction.setBadgeBackgroundColor({ | 229 chrome.browserAction.setBadgeBackgroundColor({ |
| 228 tabId: this._tabId, | 230 tabId: this._tabId, |
| 229 color: this._changes.badgeColor | 231 color: this._changes.badgeColor |
| 230 }); | 232 }); |
| 231 } | 233 } |
| 232 | 234 |
| 233 this._changes = null; | 235 this._changes = null; |
| 234 }, | 236 }, |
| 235 _queueChanges() | 237 _queueChanges() |
| 236 { | 238 { |
| 237 chrome.tabs.get(this._tabId, function() | 239 chrome.tabs.get(this._tabId, () => |
| 238 { | 240 { |
| 239 // If the tab is prerendered, chrome.tabs.get() sets | 241 // If the tab is prerendered, chrome.tabs.get() sets |
| 240 // chrome.runtime.lastError and we have to delay our changes | 242 // chrome.runtime.lastError and we have to delay our changes |
| 241 // until the currently visible tab is replaced with the | 243 // until the currently visible tab is replaced with the |
| 242 // prerendered tab. Otherwise chrome.browserAction.set* fails. | 244 // prerendered tab. Otherwise chrome.browserAction.set* fails. |
| 243 if (chrome.runtime.lastError) | 245 if (chrome.runtime.lastError) |
| 244 { | 246 { |
| 245 let onReplaced = (addedTabId, removedTabId) => | 247 let onReplaced = (addedTabId, removedTabId) => |
| 246 { | 248 { |
| 247 if (addedTabId == this._tabId) | 249 if (addedTabId == this._tabId) |
| 248 { | 250 { |
| 249 chrome.tabs.onReplaced.removeListener(onReplaced); | 251 chrome.tabs.onReplaced.removeListener(onReplaced); |
| 250 this._applyChanges(); | 252 this._applyChanges(); |
| 251 } | 253 } |
| 252 }; | 254 }; |
| 253 chrome.tabs.onReplaced.addListener(onReplaced); | 255 chrome.tabs.onReplaced.addListener(onReplaced); |
| 254 } | 256 } |
| 255 else | 257 else |
| 256 { | |
| 257 this._applyChanges(); | 258 this._applyChanges(); |
| 258 } | 259 }); |
| 259 }.bind(this)); | |
| 260 }, | 260 }, |
| 261 _addChange(name, value) | 261 _addChange(name, value) |
| 262 { | 262 { |
| 263 if (!this._changes) | 263 if (!this._changes) |
| 264 { | 264 { |
| 265 this._changes = {}; | 265 this._changes = {}; |
| 266 this._queueChanges(); | 266 this._queueChanges(); |
| 267 } | 267 } |
| 268 | 268 |
| 269 this._changes[name] = value; | 269 this._changes[name] = value; |
| 270 }, | 270 }, |
| 271 setIcon(path) | 271 setIcon(path) |
| 272 { | 272 { |
| 273 this._addChange("iconPath", path); | 273 this._addChange("iconPath", path); |
| 274 }, | 274 }, |
| 275 setBadge(badge) | 275 setBadge(badge) |
| 276 { | 276 { |
| 277 if (!badge) | 277 if (!badge) |
| 278 { | |
| 279 this._addChange("badgeText", ""); | 278 this._addChange("badgeText", ""); |
| 280 } | |
| 281 else | 279 else |
| 282 { | 280 { |
| 283 if ("number" in badge) | 281 if ("number" in badge) |
| 284 this._addChange("badgeText", badge.number.toString()); | 282 this._addChange("badgeText", badge.number.toString()); |
| 285 | 283 |
| 286 if ("color" in badge) | 284 if ("color" in badge) |
| 287 this._addChange("badgeColor", badge.color); | 285 this._addChange("badgeColor", badge.color); |
| 288 } | 286 } |
| 289 } | 287 } |
| 290 }; | 288 }; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 | 369 |
| 372 /* Web requests */ | 370 /* Web requests */ |
| 373 | 371 |
| 374 let framesOfTabs = Object.create(null); | 372 let framesOfTabs = Object.create(null); |
| 375 | 373 |
| 376 ext.getFrame = (tabId, frameId) => | 374 ext.getFrame = (tabId, frameId) => |
| 377 { | 375 { |
| 378 return (framesOfTabs[tabId] || {})[frameId]; | 376 return (framesOfTabs[tabId] || {})[frameId]; |
| 379 }; | 377 }; |
| 380 | 378 |
| 381 let handlerBehaviorChangedQuota = chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANG
ED_CALLS_PER_10_MINUTES; | 379 let handlerBehaviorChangedQuota = |
| 380 chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES; |
| 382 | 381 |
| 383 function propagateHandlerBehaviorChange() | 382 function propagateHandlerBehaviorChange() |
| 384 { | 383 { |
| 385 // Make sure to not call handlerBehaviorChanged() more often than allowed | 384 // Make sure to not call handlerBehaviorChanged() more often than allowed |
| 386 // by chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. | 385 // by chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. |
| 387 // Otherwise Chrome notifies the user that this extension is causing issues. | 386 // Otherwise Chrome notifies the user that this extension is causing issues. |
| 388 if (handlerBehaviorChangedQuota > 0) | 387 if (handlerBehaviorChangedQuota > 0) |
| 389 { | 388 { |
| 390 chrome.webNavigation.onBeforeNavigate.removeListener(propagateHandlerBehav
iorChange); | 389 chrome.webNavigation.onBeforeNavigate.removeListener( |
| 390 propagateHandlerBehaviorChange |
| 391 ); |
| 391 chrome.webRequest.handlerBehaviorChanged(); | 392 chrome.webRequest.handlerBehaviorChanged(); |
| 392 | 393 |
| 393 handlerBehaviorChangedQuota--; | 394 handlerBehaviorChangedQuota--; |
| 394 setTimeout(() => { handlerBehaviorChangedQuota++; }, 600000); | 395 setTimeout(() => { handlerBehaviorChangedQuota++; }, 600000); |
| 395 } | 396 } |
| 396 } | 397 } |
| 397 | 398 |
| 398 ext.webRequest = { | 399 ext.webRequest = { |
| 399 onBeforeRequest: new ext._EventTarget(), | 400 onBeforeRequest: new ext._EventTarget(), |
| 400 handlerBehaviorChanged() | 401 handlerBehaviorChanged() |
| 401 { | 402 { |
| 402 // Defer handlerBehaviorChanged() until navigation occurs. | 403 // Defer handlerBehaviorChanged() until navigation occurs. |
| 403 // There wouldn't be any visible effect when calling it earlier, | 404 // There wouldn't be any visible effect when calling it earlier, |
| 404 // but it's an expensive operation and that way we avoid to call | 405 // but it's an expensive operation and that way we avoid to call |
| 405 // it multiple times, if multiple filters are added/removed. | 406 // it multiple times, if multiple filters are added/removed. |
| 406 let onBeforeNavigate = chrome.webNavigation.onBeforeNavigate; | 407 let {onBeforeNavigate} = chrome.webNavigation; |
| 407 if (!onBeforeNavigate.hasListener(propagateHandlerBehaviorChange)) | 408 if (!onBeforeNavigate.hasListener(propagateHandlerBehaviorChange)) |
| 408 onBeforeNavigate.addListener(propagateHandlerBehaviorChange); | 409 onBeforeNavigate.addListener(propagateHandlerBehaviorChange); |
| 409 } | 410 } |
| 410 }; | 411 }; |
| 411 | 412 |
| 412 chrome.tabs.query({}, tabs => | 413 chrome.tabs.query({}, tabs => |
| 413 { | 414 { |
| 414 tabs.forEach(tab => | 415 tabs.forEach(tab => |
| 415 { | 416 { |
| 416 chrome.webNavigation.getAllFrames({tabId: tab.id}, details => | 417 chrome.webNavigation.getAllFrames({tabId: tab.id}, details => |
| 417 { | 418 { |
| 418 if (details && details.length > 0) | 419 if (details && details.length > 0) |
| 419 { | 420 { |
| 420 let frames = framesOfTabs[tab.id] = Object.create(null); | 421 let frames = framesOfTabs[tab.id] = Object.create(null); |
| 421 | 422 |
| 422 for (let i = 0; i < details.length; i++) | 423 for (let i = 0; i < details.length; i++) |
| 423 frames[details[i].frameId] = {url: new URL(details[i].url), parent:
null}; | 424 { |
| 425 frames[details[i].frameId] = { |
| 426 url: new URL(details[i].url), |
| 427 parent: null |
| 428 }; |
| 429 } |
| 424 | 430 |
| 425 for (let i = 0; i < details.length; i++) | 431 for (let i = 0; i < details.length; i++) |
| 426 { | 432 { |
| 427 let parentFrameId = details[i].parentFrameId; | 433 let {parentFrameId} = details[i]; |
| 428 | 434 |
| 429 if (parentFrameId != -1) | 435 if (parentFrameId != -1) |
| 430 frames[details[i].frameId].parent = frames[parentFrameId]; | 436 frames[details[i].frameId].parent = frames[parentFrameId]; |
| 431 } | 437 } |
| 432 } | 438 } |
| 433 }); | 439 }); |
| 434 }); | 440 }); |
| 435 }); | 441 }); |
| 436 | 442 |
| 437 chrome.webRequest.onBeforeRequest.addListener(details => | 443 chrome.webRequest.onBeforeRequest.addListener(details => |
| 438 { | 444 { |
| 439 // The high-level code isn't interested in requests that aren't | 445 // The high-level code isn't interested in requests that aren't |
| 440 // related to a tab or requests loading a top-level document, | 446 // related to a tab or requests loading a top-level document, |
| 441 // those should never be blocked. | 447 // those should never be blocked. |
| 442 if (details.tabId == -1 || details.type == "main_frame") | 448 if (details.tabId == -1 || details.type == "main_frame") |
| 443 return; | 449 return; |
| 444 | 450 |
| 445 // We are looking for the frame that contains the element which | 451 // We are looking for the frame that contains the element which |
| 446 // has triggered this request. For most requests (e.g. images) we | 452 // has triggered this request. For most requests (e.g. images) we |
| 447 // can just use the request's frame ID, but for subdocument requests | 453 // can just use the request's frame ID, but for subdocument requests |
| 448 // (e.g. iframes) we must instead use the request's parent frame ID. | 454 // (e.g. iframes) we must instead use the request's parent frame ID. |
| 449 let frameId; | 455 let {frameId, type} = details; |
| 450 let requestType; | 456 if (type == "sub_frame") |
| 451 if (details.type == "sub_frame") | |
| 452 { | 457 { |
| 453 frameId = details.parentFrameId; | 458 frameId = details.parentFrameId; |
| 454 requestType = "SUBDOCUMENT"; | 459 type = "SUBDOCUMENT"; |
| 455 } | |
| 456 else | |
| 457 { | |
| 458 frameId = details.frameId; | |
| 459 requestType = details.type.toUpperCase(); | |
| 460 } | 460 } |
| 461 | 461 |
| 462 let frame = ext.getFrame(details.tabId, frameId); | 462 let frame = ext.getFrame(details.tabId, frameId); |
| 463 if (frame) | 463 if (frame) |
| 464 { | 464 { |
| 465 let results = ext.webRequest.onBeforeRequest._dispatch( | 465 let results = ext.webRequest.onBeforeRequest._dispatch( |
| 466 new URL(details.url), | 466 new URL(details.url), |
| 467 requestType, | 467 type.toUpperCase(), |
| 468 new Page({id: details.tabId}), | 468 new Page({id: details.tabId}), |
| 469 frame | 469 frame |
| 470 ); | 470 ); |
| 471 | 471 |
| 472 if (results.indexOf(false) != -1) | 472 if (results.indexOf(false) != -1) |
| 473 return {cancel: true}; | 473 return {cancel: true}; |
| 474 } | 474 } |
| 475 }, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); | 475 }, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); |
| 476 | 476 |
| 477 | 477 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 497 | 497 |
| 498 let frame = frames[rawSender.frameId]; | 498 let frame = frames[rawSender.frameId]; |
| 499 if (frame) | 499 if (frame) |
| 500 return frame.parent; | 500 return frame.parent; |
| 501 | 501 |
| 502 return frames[0]; | 502 return frames[0]; |
| 503 } | 503 } |
| 504 }; | 504 }; |
| 505 } | 505 } |
| 506 | 506 |
| 507 return ext.onMessage._dispatch(message, sender, sendResponse).indexOf(true)
!= -1; | 507 return ext.onMessage._dispatch( |
| 508 message, sender, sendResponse |
| 509 ).indexOf(true) != -1; |
| 508 }); | 510 }); |
| 509 | 511 |
| 510 | 512 |
| 511 /* Storage */ | 513 /* Storage */ |
| 512 | 514 |
| 513 ext.storage = { | 515 ext.storage = { |
| 514 get(keys, callback) | 516 get(keys, callback) |
| 515 { | 517 { |
| 516 chrome.storage.local.get(keys, callback); | 518 chrome.storage.local.get(keys, callback); |
| 517 }, | 519 }, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 528 onChanged: chrome.storage.onChanged | 530 onChanged: chrome.storage.onChanged |
| 529 }; | 531 }; |
| 530 | 532 |
| 531 /* Options */ | 533 /* Options */ |
| 532 | 534 |
| 533 if ("openOptionsPage" in chrome.runtime) | 535 if ("openOptionsPage" in chrome.runtime) |
| 534 { | 536 { |
| 535 ext.showOptions = callback => | 537 ext.showOptions = callback => |
| 536 { | 538 { |
| 537 if (!callback) | 539 if (!callback) |
| 538 { | |
| 539 chrome.runtime.openOptionsPage(); | 540 chrome.runtime.openOptionsPage(); |
| 540 } | |
| 541 else | 541 else |
| 542 { | 542 { |
| 543 chrome.runtime.openOptionsPage(() => | 543 chrome.runtime.openOptionsPage(() => |
| 544 { | 544 { |
| 545 if (chrome.runtime.lastError) | 545 if (chrome.runtime.lastError) |
| 546 return; | 546 return; |
| 547 | 547 |
| 548 chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => | 548 chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => |
| 549 { | 549 { |
| 550 if (tabs.length > 0) | 550 if (tabs.length > 0) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 { | 582 { |
| 583 let tab = tabs[0]; | 583 let tab = tabs[0]; |
| 584 | 584 |
| 585 chrome.windows.update(tab.windowId, {focused: true}); | 585 chrome.windows.update(tab.windowId, {focused: true}); |
| 586 chrome.tabs.update(tab.id, {active: true}); | 586 chrome.tabs.update(tab.id, {active: true}); |
| 587 | 587 |
| 588 if (callback) | 588 if (callback) |
| 589 callback(new Page(tab)); | 589 callback(new Page(tab)); |
| 590 } | 590 } |
| 591 else | 591 else |
| 592 { | |
| 593 ext.pages.open(optionsUrl, callback); | 592 ext.pages.open(optionsUrl, callback); |
| 594 } | |
| 595 }); | 593 }); |
| 596 }); | 594 }); |
| 597 }; | 595 }; |
| 598 } | 596 } |
| 599 | 597 |
| 600 /* Windows */ | 598 /* Windows */ |
| 601 ext.windows = { | 599 ext.windows = { |
| 602 create(createData, callback) | 600 create(createData, callback) |
| 603 { | 601 { |
| 604 chrome.windows.create(createData, createdWindow => | 602 chrome.windows.create(createData, createdWindow => |
| 605 { | 603 { |
| 606 afterTabLoaded(callback)(createdWindow.tabs[0]); | 604 afterTabLoaded(callback)(createdWindow.tabs[0]); |
| 607 }); | 605 }); |
| 608 } | 606 } |
| 609 }; | 607 }; |
| 610 } | 608 } |
| OLD | NEW |