| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 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-2015 Eyeo GmbH | 3 * Copyright (C) 2006-2015 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 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 ext.getFrame = function(tabId, frameId) | 324 ext.getFrame = function(tabId, frameId) |
| 325 { | 325 { |
| 326 return (framesOfTabs[tabId] || {})[frameId]; | 326 return (framesOfTabs[tabId] || {})[frameId]; |
| 327 }; | 327 }; |
| 328 | 328 |
| 329 ext.webRequest = { | 329 ext.webRequest = { |
| 330 onBeforeRequest: new ext._EventTarget(), | 330 onBeforeRequest: new ext._EventTarget(), |
| 331 handlerBehaviorChanged: chrome.webRequest.handlerBehaviorChanged | 331 handlerBehaviorChanged: chrome.webRequest.handlerBehaviorChanged |
| 332 }; | 332 }; |
| 333 | 333 |
| 334 // Since Chrome 38 requests of type 'object' (e.g. requests | |
| 335 // initiated by Flash) are mistakenly reported with the type 'other'. | |
| 336 // https://code.google.com/p/chromium/issues/detail?id=410382 | |
| 337 if (parseInt(navigator.userAgent.match(/\bChrome\/(\d+)/)[1], 10) >= 38) | |
| 338 { | |
| 339 ext.webRequest.indistinguishableTypes = [ | |
| 340 ["OTHER", "OBJECT", "OBJECT_SUBREQUEST"] | |
| 341 ]; | |
| 342 } | |
| 343 else | |
| 344 { | |
| 345 ext.webRequest.indistinguishableTypes = [ | |
| 346 ["OBJECT", "OBJECT_SUBREQUEST"], | |
| 347 ["OTHER", "MEDIA", "FONT"] | |
| 348 ]; | |
| 349 } | |
| 350 | |
| 334 chrome.tabs.query({}, function(tabs) | 351 chrome.tabs.query({}, function(tabs) |
| 335 { | 352 { |
| 336 tabs.forEach(function(tab) | 353 tabs.forEach(function(tab) |
| 337 { | 354 { |
| 338 chrome.webNavigation.getAllFrames({tabId: tab.id}, function(details) | 355 chrome.webNavigation.getAllFrames({tabId: tab.id}, function(details) |
| 339 { | 356 { |
| 340 if (details && details.length > 0) | 357 if (details && details.length > 0) |
| 341 { | 358 { |
| 342 var frames = framesOfTabs[tab.id] = Object.create(null); | 359 var frames = framesOfTabs[tab.id] = Object.create(null); |
| 343 | 360 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 359 chrome.webRequest.onBeforeRequest.addListener(function(details) | 376 chrome.webRequest.onBeforeRequest.addListener(function(details) |
| 360 { | 377 { |
| 361 try | 378 try |
| 362 { | 379 { |
| 363 // the high-level code isn't interested in requests that aren't related | 380 // the high-level code isn't interested in requests that aren't related |
| 364 // to a tab and since those can only be handled in Chrome, we ignore | 381 // to a tab and since those can only be handled in Chrome, we ignore |
| 365 // them here instead of in the browser independent high-level code. | 382 // them here instead of in the browser independent high-level code. |
| 366 if (details.tabId == -1) | 383 if (details.tabId == -1) |
| 367 return; | 384 return; |
| 368 | 385 |
| 369 var requestType = details.type; | 386 var isMainFrame = details.type == "main_frame" || ( |
| 370 var isMainFrame = requestType == "main_frame" || ( | |
| 371 | 387 |
| 372 // assume that the first request belongs to the top frame. Chrome | 388 // assume that the first request belongs to the top frame. Chrome |
| 373 // may give the top frame the type "object" instead of "main_frame". | 389 // may give the top frame the type "object" instead of "main_frame". |
| 374 // https://code.google.com/p/chromium/issues/detail?id=281711 | 390 // https://code.google.com/p/chromium/issues/detail?id=281711 |
| 375 details.frameId == 0 && !(details.tabId in framesOfTabs) | 391 details.frameId == 0 && !(details.tabId in framesOfTabs) |
| 376 ); | 392 ); |
| 377 | 393 |
| 378 var frames = null; | 394 var frames = null; |
| 379 if (!isMainFrame) | 395 if (!isMainFrame) |
| 380 frames = framesOfTabs[details.tabId]; | 396 frames = framesOfTabs[details.tabId]; |
| 381 if (!frames) | 397 if (!frames) |
| 382 frames = framesOfTabs[details.tabId] = Object.create(null); | 398 frames = framesOfTabs[details.tabId] = Object.create(null); |
| 383 | 399 |
| 384 var frame = null; | 400 var frame = null; |
| 385 var url = new URL(details.url); | 401 var url = new URL(details.url); |
| 386 if (!isMainFrame) | 402 if (!isMainFrame) |
| 387 { | 403 { |
| 388 // we are looking for the frame that contains the element that | 404 // we are looking for the frame that contains the element that |
| 389 // is about to load, however if a frame is loading the surrounding | 405 // is about to load, however if a frame is loading the surrounding |
| 390 // frame is indicated by parentFrameId instead of frameId | 406 // frame is indicated by parentFrameId instead of frameId |
| 391 var frameId; | 407 var frameId; |
| 392 if (requestType == "sub_frame") | 408 var requestType; |
| 409 if (details.type == "sub_frame") | |
| 410 { | |
| 393 frameId = details.parentFrameId; | 411 frameId = details.parentFrameId; |
| 412 requestType = "SUBDOCUMENT"; | |
| 413 } | |
| 394 else | 414 else |
| 415 { | |
| 395 frameId = details.frameId; | 416 frameId = details.frameId; |
| 417 requestType = details.type.toUpperCase(); | |
| 418 } | |
| 396 | 419 |
| 397 frame = frames[frameId] || frames[Object.keys(frames)[0]]; | 420 frame = frames[frameId] || frames[Object.keys(frames)[0]]; |
| 398 | 421 |
| 399 if (frame) | 422 if (frame) |
| 400 { | 423 { |
| 401 // Since Chrome 38 requests of type 'object' (e.g. requests | |
| 402 // initiated by Flash) are mistakenly reported with the type 'other'. | |
| 403 // https://code.google.com/p/chromium/issues/detail?id=410382 | |
| 404 if (requestType == "other" && parseInt(navigator.userAgent.match(/\bCh rome\/(\d+)/)[1], 10) >= 38) | |
| 405 requestType = "object"; | |
| 406 | |
| 407 var results = ext.webRequest.onBeforeRequest._dispatch( | 424 var results = ext.webRequest.onBeforeRequest._dispatch( |
| 408 url, | 425 url, |
| 409 requestType, | 426 requestType, |
| 410 new Page({id: details.tabId}), | 427 new Page({id: details.tabId}), |
| 411 frame | 428 frame |
| 412 ); | 429 ); |
| 413 | 430 |
| 414 if (results.indexOf(false) != -1) | 431 if (results.indexOf(false) != -1) |
| 415 return {cancel: true}; | 432 return {cancel: true}; |
| 416 } | 433 } |
| 417 } | 434 } |
| 418 | 435 |
| 419 if (isMainFrame || details.type == "sub_frame") | 436 if (isMainFrame || details.type == "sub_frame") |
| 420 frames[details.frameId] = {url: url, parent: frame}; | 437 frames[details.frameId] = {url: url, parent: frame}; |
| 421 } | 438 } |
| 422 catch (e) | 439 catch (e) |
| 423 { | 440 { |
| 424 // recent versions of Chrome cancel the request when an error occurs in | 441 // recent versions of Chrome cancel the request when an error occurs in |
| 425 // the onBeforeRequest listener. However in our case it is preferred, to | 442 // the onBeforeRequest listener. However in our case it is preferred, to |
| 426 // let potentially some ads through, rather than blocking legit requests. | 443 // let potentially some ads through, rather than blocking legit requests. |
| 427 console.error(e); | 444 console.error(e); |
| 428 } | 445 } |
| 429 }, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); | 446 }, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); |
| 430 | 447 |
| 431 | 448 |
| 432 /* Message passing */ | 449 /* Message passing */ |
| 433 | 450 |
| 434 chrome.runtime.onMessage.addListener(function(message, rawSender, sendResponse ) | 451 chrome.runtime.onMessage.addListener(function(message, rawSender, sendResponse ) |
| 435 { | 452 { |
| 436 var sender = { | 453 var sender = {}; |
| 437 page: new Page(rawSender.tab), | 454 |
| 438 frame: { | 455 // Add "page" and "frame" if the message was sent by a content script. |
| 456 // If sent by popup or the background page itself, there is no "tab". | |
| 457 if ("tab" in rawSender) | |
| 458 { | |
| 459 sender.page = new Page(rawSender.tab); | |
| 460 sender.frame = { | |
| 439 url: new URL(rawSender.url), | 461 url: new URL(rawSender.url), |
| 440 get parent() | 462 get parent() |
| 441 { | 463 { |
| 442 var frames = framesOfTabs[rawSender.tab.id]; | 464 var frames = framesOfTabs[rawSender.tab.id]; |
| 443 | 465 |
| 444 if (!frames) | 466 if (!frames) |
| 445 return null; | 467 return null; |
| 446 | 468 |
| 447 if ("frameId" in rawSender) | 469 if ("frameId" in rawSender) |
| 448 { | 470 { |
| 449 // Chrome 41+ | 471 // Chrome 41+ |
| 450 var frame = frames[rawSender.frameId]; | 472 var frame = frames[rawSender.frameId]; |
| 451 if (frame) | 473 if (frame) |
| 452 return frame.parent; | 474 return frame.parent; |
| 453 } | 475 } |
| 454 else | 476 else |
| 455 { | 477 { |
| 456 // Chrome 28-40 | 478 // Chrome 28-40 |
| 457 for (var frameId in frames) | 479 for (var frameId in frames) |
| 458 { | 480 { |
| 459 if (frames[frameId].url.href == this.url.href) | 481 if (frames[frameId].url.href == this.url.href) |
| 460 return frames[frameId].parent; | 482 return frames[frameId].parent; |
| 461 } | 483 } |
| 462 } | 484 } |
| 463 | 485 |
| 464 return frames[0]; | 486 return frames[0]; |
| 465 } | 487 } |
| 466 } | 488 }; |
| 467 }; | 489 } |
| 468 | 490 |
| 469 return ext.onMessage._dispatch(message, sender, sendResponse).indexOf(true) != -1; | 491 return ext.onMessage._dispatch(message, sender, sendResponse).indexOf(true) != -1; |
| 470 }); | 492 }); |
| 471 | 493 |
| 472 // We have to ensure there is at least one listener for the onConnect event. | 494 // We have to ensure there is at least one listener for the onConnect event. |
| 473 // Otherwise we can't connect a port later, which we need to do in order to | 495 // Otherwise we can't connect a port later, which we need to do in order to |
| 474 // detect when the extension is reloaded, disabled or uninstalled. | 496 // detect when the extension is reloaded, disabled or uninstalled. |
| 475 chrome.runtime.onConnect.addListener(function() {}); | 497 chrome.runtime.onConnect.addListener(function() {}); |
| 476 | 498 |
| 477 | 499 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 488 items[key] = value; | 510 items[key] = value; |
| 489 chrome.storage.local.set(items, callback); | 511 chrome.storage.local.set(items, callback); |
| 490 }, | 512 }, |
| 491 remove: function(key, callback) | 513 remove: function(key, callback) |
| 492 { | 514 { |
| 493 chrome.storage.local.remove(key, callback); | 515 chrome.storage.local.remove(key, callback); |
| 494 }, | 516 }, |
| 495 onChanged: chrome.storage.onChanged, | 517 onChanged: chrome.storage.onChanged, |
| 496 | 518 |
| 497 // Migrate localStorage to chrome.storage.local, | 519 // Migrate localStorage to chrome.storage.local, |
| 498 // ignoring unkown and inavlid preferences. | 520 // ignoring unkown and invalid preferences. |
| 499 migratePrefs: function(prefs) | 521 migratePrefs: function(hooks) |
| 500 { | 522 { |
| 501 var items = {}; | 523 var items = {}; |
| 502 | 524 |
| 503 for (let key in localStorage) | 525 for (let key in localStorage) |
| 504 { | 526 { |
| 505 var value = localStorage[key]; | 527 var item = hooks.map(key, localStorage[key]); |
| 506 | 528 if (item) |
| 507 if (key in prefs) | 529 items[item.key] = item.value; |
| 508 { | |
| 509 try | |
| 510 { | |
| 511 items["pref:" + key] = JSON.parse(value); | |
|
kzar
2015/03/09 15:10:29
Nit: Shouldn't this make use of the const keyPrefi
Sebastian Noack
2015/03/09 15:21:37
It's not available here, and IMO not worth beeing
kzar
2015/03/09 15:24:28
Fair enough, yea I agree it doesn't really matter.
| |
| 512 } | |
| 513 catch (e) | |
| 514 { | |
| 515 } | |
| 516 } | |
| 517 else if (key == "currentVersion") | |
| 518 { | |
| 519 items[key] = value; | |
| 520 } | |
| 521 } | 530 } |
| 522 | 531 |
| 523 chrome.storage.local.set(items, function() { | 532 chrome.storage.local.set(items, function() { |
| 524 localStorage.clear(); | 533 localStorage.clear(); |
| 534 hooks.done(); | |
| 525 }); | 535 }); |
| 526 } | 536 } |
| 527 }; | 537 }; |
| 528 | 538 |
| 529 /* Options */ | 539 /* Options */ |
| 530 | 540 |
| 531 ext.showOptions = function(callback) | 541 ext.showOptions = function(callback) |
| 532 { | 542 { |
| 533 chrome.windows.getLastFocused(function(win) | 543 chrome.windows.getLastFocused(function(win) |
| 534 { | 544 { |
| 535 var optionsUrl = chrome.extension.getURL("options.html"); | 545 var optionsUrl = chrome.extension.getURL("options.html"); |
| 536 var queryInfo = {url: optionsUrl}; | 546 var queryInfo = {url: optionsUrl}; |
| 537 | 547 |
| 538 // extension pages can't be accessed in incognito windows. In order to | 548 // extension pages can't be accessed in incognito windows. In order to |
| 539 // correctly mimic the way in which Chrome opens extension options, | 549 // correctly mimic the way in which Chrome opens extension options, |
| 540 // we have to focus the options page in any other window. | 550 // we have to focus the options page in any other window. |
| 541 if (!win.incognito) | 551 if (!win.incognito) |
| 542 queryInfo.windowId = win.id; | 552 queryInfo.windowId = win.id; |
| 543 | 553 |
| 544 chrome.tabs.query(queryInfo, function(tabs) | 554 chrome.tabs.query(queryInfo, function(tabs) |
| 545 { | 555 { |
| 546 if (tabs.length > 0) | 556 if (tabs.length > 0) |
| 547 { | 557 { |
| 548 var tab = tabs[0]; | 558 var tab = tabs[0]; |
| 549 | 559 |
| 550 chrome.windows.update(tab.windowId, {focused: true}); | 560 chrome.windows.update(tab.windowId, {focused: true}); |
| 551 chrome.tabs.highlight( | 561 chrome.tabs.update(tab.id, {active: true}); |
| 552 { | |
| 553 windowId: tab.windowId, | |
| 554 tabs: [tab.index] | |
| 555 }, | |
| 556 function() {} | |
| 557 ); | |
| 558 | 562 |
| 559 if (callback) | 563 if (callback) |
| 560 callback(new Page(tab)); | 564 callback(new Page(tab)); |
| 561 } | 565 } |
| 562 else | 566 else |
| 563 { | 567 { |
| 564 ext.pages.open(optionsUrl, callback); | 568 ext.pages.open(optionsUrl, callback); |
| 565 } | 569 } |
| 566 }); | 570 }); |
| 567 }); | 571 }); |
| 568 }; | 572 }; |
| 569 })(); | 573 })(); |
| LEFT | RIGHT |