| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <http://adblockplus.org/>, | 2 * This file is part of Adblock Plus <http://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2013 Eyeo GmbH | 3 * Copyright (C) 2006-2013 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 | 106 |
| 107 var result = defaultMatcher.matchesAny(url, type || "DOCUMENT", extractHostFro mURL(parentUrl || url), false); | 107 var result = defaultMatcher.matchesAny(url, type || "DOCUMENT", extractHostFro mURL(parentUrl || url), false); |
| 108 return (result instanceof WhitelistFilter ? result : null); | 108 return (result instanceof WhitelistFilter ? result : null); |
| 109 } | 109 } |
| 110 | 110 |
| 111 var activeNotification = null; | 111 var activeNotification = null; |
| 112 | 112 |
| 113 // Adds or removes page action icon according to options. | 113 // Adds or removes page action icon according to options. |
| 114 function refreshIconAndContextMenu(tab) | 114 function refreshIconAndContextMenu(tab) |
| 115 { | 115 { |
| 116 if(!/^https?:/.test(tab.url)) | 116 if(!/^https?:/.test(tab.url)) |
|
Felix Dahlke
2013/10/24 16:30:34
What if tab is null or undefined? Can that still h
Sebastian Noack
2013/10/25 09:55:03
Did you had a look at the calling code? Maybe I mi
| |
| 117 return; | 117 return; |
| 118 | 118 |
| 119 var excluded = isWhitelisted(tab.url); | |
| 120 var iconFilename; | 119 var iconFilename; |
| 121 | 120 if (require("info").platform == "safari") |
| 122 if (window.safari || !excluded) | 121 // There is no grayscale version of the icon for whitelisted tabs |
|
Felix Dahlke
2013/10/24 16:30:34
Why do we always show the normal icon on Safari? D
Sebastian Noack
2013/10/25 09:55:03
First of all because of in Safari icons are global
| |
| 123 iconFilename = "icons/abp-18.png"; | 122 // when using Safari, because icons are grayscale already and icons |
| 123 // aren't per tab in Safari. | |
| 124 iconFilename = "icons/abp-16.png" | |
| 124 else | 125 else |
| 125 iconFilename = "icons/abp-18-whitelisted.png"; | 126 { |
| 127 var excluded = isWhitelisted(tab.url); | |
| 128 iconFilename = excluded ? "icons/abp-19-whitelisted.png" : "icons/abp-19.png "; | |
| 129 } | |
| 126 | 130 |
| 127 tab.pageAction.setIcon(iconFilename); | 131 tab.pageAction.setIcon(iconFilename); |
| 128 tab.pageAction.setTitle("Adblock Plus"); | 132 tab.pageAction.setTitle(ext.i18n.getMessage("name")); |
| 129 | 133 |
| 130 iconAnimation.registerTab(tab, iconFilename); | 134 iconAnimation.registerTab(tab, iconFilename); |
| 131 | 135 |
| 132 if (localStorage.shouldShowIcon == "false") | 136 if (localStorage.shouldShowIcon == "false") |
| 133 tab.pageAction.hide(); | 137 tab.pageAction.hide(); |
| 134 else | 138 else |
| 135 tab.pageAction.show(); | 139 tab.pageAction.show(); |
| 136 | 140 |
| 137 // Set context menu status according to whether current tab has whitelisted do main | 141 if (require("info").platform == "chromium") // TODO: Implement context menus f or Safari |
| 138 if (excluded) | 142 // Set context menu status according to whether current tab has whitelisted domain |
| 139 if (window.chrome) // TODO: Implement context menus for Safari | 143 if (excluded) |
|
Felix Dahlke
2013/10/24 16:30:34
The surrounding |if (excluded)| needs braces, othe
Sebastian Noack
2013/10/25 09:55:03
Oh, you are right.
| |
| 140 chrome.contextMenus.removeAll(); | 144 chrome.contextMenus.removeAll(); |
| 141 else | 145 else |
| 142 showContextMenu(); | 146 showContextMenu(); |
| 143 } | 147 } |
| 144 | 148 |
| 145 /** | 149 /** |
| 146 * Old versions stored filter data in the localStorage object, this will import | 150 * Old versions stored filter data in the localStorage object, this will import |
| 147 * it into FilterStorage properly. | 151 * it into FilterStorage properly. |
| 148 */ | 152 */ |
| 149 function importOldData() | 153 function importOldData() |
| 150 { | 154 { |
| 151 function addSubscription(url, title) | 155 function addSubscription(url, title) |
| 152 { | 156 { |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 } | 364 } |
| 361 else | 365 else |
| 362 addAcceptable = false; | 366 addAcceptable = false; |
| 363 } | 367 } |
| 364 | 368 |
| 365 if (!addSubscription && !addAcceptable) | 369 if (!addSubscription && !addAcceptable) |
| 366 return; | 370 return; |
| 367 | 371 |
| 368 function notifyUser() | 372 function notifyUser() |
| 369 { | 373 { |
| 370 ext.windows.getLastFocused(function(win) { | 374 ext.windows.getLastFocused(function(win) |
|
Felix Dahlke
2013/10/24 16:30:34
Opening braces always go on their own line, except
Sebastian Noack
2013/10/25 09:55:03
I thought we go with Mozilla coding style?
Felix Dahlke
2013/10/25 14:43:08
No, we have our own: https://adblockplus.org/en/co
| |
| 375 { | |
| 371 win.openTab(ext.getURL("firstRun.html")); | 376 win.openTab(ext.getURL("firstRun.html")); |
| 372 }); | 377 }); |
| 373 } | 378 } |
| 374 | 379 |
| 375 if (addSubscription) | 380 if (addSubscription) |
| 376 { | 381 { |
| 377 // Load subscriptions data | 382 // Load subscriptions data |
| 378 var request = new XMLHttpRequest(); | 383 var request = new XMLHttpRequest(); |
| 379 request.open("GET", "subscriptions.xml"); | 384 request.open("GET", "subscriptions.xml"); |
| 380 request.addEventListener("load", function() | 385 request.addEventListener("load", function() |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 395 }, false); | 400 }, false); |
| 396 request.send(null); | 401 request.send(null); |
| 397 } | 402 } |
| 398 else | 403 else |
| 399 notifyUser(); | 404 notifyUser(); |
| 400 } | 405 } |
| 401 | 406 |
| 402 // Set up context menu for user selection of elements to block | 407 // Set up context menu for user selection of elements to block |
| 403 function showContextMenu() | 408 function showContextMenu() |
| 404 { | 409 { |
| 405 if (!window.chrome) // TODO: Implement context menus for Safari | |
| 406 return; | |
| 407 | |
| 408 chrome.contextMenus.removeAll(function() | 410 chrome.contextMenus.removeAll(function() |
| 409 { | 411 { |
| 410 if(typeof localStorage["shouldShowBlockElementMenu"] == "string" && localSto rage["shouldShowBlockElementMenu"] == "true") | 412 if(typeof localStorage["shouldShowBlockElementMenu"] == "string" && localSto rage["shouldShowBlockElementMenu"] == "true") |
| 411 { | 413 { |
| 412 chrome.contextMenus.create({"title": chrome.i18n.getMessage("block_element "), "contexts": ["image", "video", "audio"], "onclick": function(info, tab) | 414 chrome.contextMenus.create({"title": chrome.i18n.getMessage("block_element "), "contexts": ["image", "video", "audio"], "onclick": function(info, tab) |
| 413 { | 415 { |
| 414 if(info.srcUrl) | 416 if(info.srcUrl) |
| 415 chrome.tabs.sendRequest(tab.id, {reqtype: "clickhide-new-filter", fi lter: info.srcUrl}); | 417 chrome.tabs.sendRequest(tab.id, {reqtype: "clickhide-new-filter", fi lter: info.srcUrl}); |
| 416 }}); | 418 }}); |
| 417 } | 419 } |
| 418 }); | 420 }); |
| 419 } | 421 } |
| 420 | 422 |
| 423 /** | |
| 424 * Opens options tab or focuses an existing one, within the last focused window . | |
| 425 * @param {Function} callback function to be called with the | |
| 426 Tab object of the options tab | |
| 427 */ | |
| 421 function openOptions(callback) | 428 function openOptions(callback) |
|
Felix Dahlke
2013/10/24 16:30:34
Why remove the docs?
Sebastian Noack
2013/10/25 09:55:03
The old docs are deprecated now (the callback is c
Felix Dahlke
2013/11/10 01:07:00
Yeah I guess it's fine, most functions here don't
Wladimir Palant
2013/11/13 07:16:27
I would actually prefer keeping and updating the d
| |
| 422 { | 429 { |
| 423 ext.windows.getLastFocused(function(win) { | 430 ext.windows.getLastFocused(function(win) |
| 424 win.getAllTabs(function(tabs) { | 431 { |
| 432 win.getAllTabs(function(tabs) | |
| 433 { | |
| 425 var optionsUrl = ext.getURL("options.html"); | 434 var optionsUrl = ext.getURL("options.html"); |
| 426 | 435 |
| 427 for (var i = 0; i < tabs.length; i++) | 436 for (var i = 0; i < tabs.length; i++) |
| 428 if (tabs[i].url == optionsUrl) { | 437 { |
| 438 if (tabs[i].url == optionsUrl) | |
| 439 { | |
| 429 tabs[i].activate(); | 440 tabs[i].activate(); |
| 430 if (callback) | 441 if (callback) |
| 431 callback(tabs[i]); | 442 callback(tabs[i]); |
| 432 return; | 443 return; |
| 433 } | 444 } |
| 434 | 445 } |
| 435 win.openTab(optionsUrl, callback && function(tab) { | 446 |
| 447 win.openTab(optionsUrl, callback && function(tab) | |
| 448 { | |
| 436 tab.onCompleted.addListener(callback); | 449 tab.onCompleted.addListener(callback); |
| 437 }); | 450 }); |
| 438 }); | 451 }); |
| 439 }); | 452 }); |
| 440 } | 453 } |
| 441 | 454 |
| 442 function IconAnimation() { | |
| 443 this._icons = new TabMap(); | |
| 444 this._animatedTabs = new TabMap(); | |
| 445 this._step = 0; | |
| 446 }; | |
| 447 IconAnimation.prototype = { | |
| 448 update: function(severity) { | |
| 449 if (severity == this._severity) | |
| 450 return; | |
| 451 | |
| 452 if (!this._severity) | |
| 453 this._start(); | |
| 454 | |
| 455 this._severity = severity; | |
| 456 }, | |
| 457 stop: function() { | |
| 458 clearInterval(this._interval); | |
| 459 | |
| 460 delete this._interval; | |
| 461 delete this._severity; | |
| 462 | |
| 463 this._animatedTabs.clear(); | |
| 464 }, | |
| 465 registerTab: function(tab, icon) { | |
| 466 this._icons.set(tab, icon); | |
| 467 | |
| 468 if (this._animatedTabs.has(tab)) | |
| 469 this._updateIcon(tab); | |
| 470 }, | |
| 471 _start: function() { | |
| 472 this._interval = setInterval(function() { | |
| 473 this._getVisibleTabs(function(tabs) { | |
| 474 if (tabs.length == 0) | |
| 475 return; | |
| 476 | |
| 477 for (var i = 0; i < tabs.length; i++) | |
| 478 this._animatedTabs.set(tabs[i], null); | |
| 479 | |
| 480 var interval = setInterval(function() { | |
| 481 this._step++; | |
| 482 tabs.forEach(this._updateIcon.bind(this)); | |
|
Felix Dahlke
2013/10/24 16:30:34
Is the |bind(this)| actually necessary here?
Sebastian Noack
2013/10/25 09:55:03
Yes, it is. _updateIcon() needs this._step and thi
| |
| 483 | |
| 484 if (this._step < 10) | |
| 485 return; | |
| 486 | |
| 487 clearInterval(interval); | |
| 488 setTimeout(function() { | |
| 489 interval = setInterval(function() { | |
| 490 this._step--; | |
| 491 tabs.forEach(this._updateIcon.bind(this)); | |
| 492 | |
| 493 if (this._step > 0) | |
| 494 return; | |
| 495 | |
| 496 clearInterval(interval); | |
| 497 this._animatedTabs.clear(); | |
| 498 }.bind(this), 100); | |
| 499 }.bind(this), 1000); | |
| 500 }.bind(this), 100); | |
| 501 }.bind(this)); | |
| 502 }.bind(this), 15000); | |
| 503 }, | |
| 504 _getVisibleTabs: function(callback) { | |
| 505 ext.windows.getAll(function(windows) { | |
| 506 var tabs = []; | |
| 507 var n = windows.length; | |
|
Felix Dahlke
2013/10/24 16:30:34
I'd love a more descriptive variable name here. So
| |
| 508 | |
| 509 for (var i = 0; i < windows.length; i++) { | |
| 510 if (!windows[i].visible) { | |
| 511 if (tabs.length == --n) | |
|
Felix Dahlke
2013/10/24 16:30:34
tabs.length will always be 0 here, won't it? In th
Sebastian Noack
2013/10/25 09:55:03
Yes it is. When writing the code I felt it would b
| |
| 512 callback(tabs); | |
| 513 | |
| 514 continue; | |
| 515 } | |
| 516 | |
| 517 windows[i].getActiveTab(function(tab) { | |
| 518 tabs.push(tab); | |
| 519 | |
| 520 if (tabs.length == n) | |
| 521 callback(tabs); | |
| 522 }); | |
| 523 } | |
| 524 }); | |
| 525 }, | |
| 526 _updateIcon: function(tab) { | |
| 527 var path = this._icons.get(tab); | |
| 528 | |
| 529 if (!path) | |
| 530 return; | |
| 531 | |
| 532 if (this._step > 0) { | |
| 533 var suffix = "-notification-" + this._severity; | |
| 534 | |
| 535 if (this._step < 10) | |
| 536 suffix += "-" + this._step; | |
| 537 | |
| 538 path = path.replace(/(?=\..+$)/, suffix); | |
| 539 } | |
| 540 | |
| 541 tab.pageAction.setIcon(path); | |
| 542 } | |
| 543 }; | |
| 544 var iconAnimation = new IconAnimation(); | |
|
Felix Dahlke
2013/10/24 16:30:34
If there's only one instance of IconAnimation, I'd
| |
| 545 | |
| 546 function prepareNotificationIconAndPopup() | 455 function prepareNotificationIconAndPopup() |
| 547 { | 456 { |
| 548 activeNotification.onClicked = function() { | 457 activeNotification.onClicked = function() |
| 458 { | |
| 549 iconAnimation.stop(); | 459 iconAnimation.stop(); |
| 550 activeNotification = null; | 460 activeNotification = null; |
| 551 }; | 461 }; |
| 552 | 462 |
| 553 iconAnimation.update(activeNotification.severity); | 463 iconAnimation.update(activeNotification.severity); |
| 554 } | 464 } |
| 555 | 465 |
| 556 function showNotification(notification) | 466 function showNotification(notification) |
| 557 { | 467 { |
| 558 activeNotification = notification; | 468 activeNotification = notification; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 574 * frame data. | 484 * frame data. |
| 575 */ | 485 */ |
| 576 function getFrameId(tab, url) | 486 function getFrameId(tab, url) |
| 577 { | 487 { |
| 578 for (var frameId in frames.get(tab)) | 488 for (var frameId in frames.get(tab)) |
| 579 if (getFrameUrl(tab, frameId) == url) | 489 if (getFrameUrl(tab, frameId) == url) |
| 580 return frameId; | 490 return frameId; |
| 581 return -1; | 491 return -1; |
| 582 } | 492 } |
| 583 | 493 |
| 584 ext.onMessage.addListener(function (msg, sender, sendResponse) { | 494 ext.onMessage.addListener(function (msg, sender, sendResponse) |
| 495 { | |
| 585 switch (msg.type) | 496 switch (msg.type) |
| 586 { | 497 { |
| 587 case "get-settings": | 498 case "get-selectors": |
| 588 var hostDomain = null; | |
| 589 var selectors = null; | 499 var selectors = null; |
| 590 | |
| 591 var frameId = sender.tab ? getFrameId(sender.tab, msg.frameUrl) : -1; | 500 var frameId = sender.tab ? getFrameId(sender.tab, msg.frameUrl) : -1; |
| 592 var enabled = false; | 501 |
| 593 | 502 if (!isFrameWhitelisted(sender.tab, frameId, "DOCUMENT") && |
| 594 if (!isFrameWhitelisted(sender.tab, frameId, "DOCUMENT")) | 503 !isFrameWhitelisted(sender.tab, frameId, "ELEMHIDE")) |
|
Felix Dahlke
2013/10/24 16:30:34
I prefer the old code (enabled variable) to nested
| |
| 595 if (!isFrameWhitelisted(sender.tab, frameId, "ELEMHIDE")) { | 504 { |
| 596 var enabled = true; | 505 var noStyleRules = false; |
| 597 | 506 var host = extractHostFromURL(msg.frameUrl); |
| 598 if (msg.selectors) | 507 for (var i = 0; i < noStyleRulesHosts.length; i++) |
| 599 { | 508 { |
| 600 var noStyleRules = false; | 509 var noStyleHost = noStyleRulesHosts[i]; |
| 601 var host = extractHostFromURL(msg.frameUrl); | 510 if (host == noStyleHost || (host.length > noStyleHost.length && |
| 602 hostDomain = getBaseDomain(host); | 511 host.substr(host.length - noStyleHost.leng th - 1) == "." + noStyleHost)) |
| 603 for (var i = 0; i < noStyleRulesHosts.length; i++) | |
| 604 { | 512 { |
| 605 var noStyleHost = noStyleRulesHosts[i]; | 513 noStyleRules = true; |
| 606 if (host == noStyleHost || (host.length > noStyleHost.length && | |
| 607 host.substr(host.length - noStyleHost.le ngth - 1) == "." + noStyleHost)) | |
| 608 { | |
| 609 noStyleRules = true; | |
| 610 } | |
| 611 } | |
| 612 selectors = ElemHide.getSelectorsForDomain(host, false); | |
| 613 if (noStyleRules) | |
| 614 { | |
| 615 selectors = selectors.filter(function(s) | |
| 616 { | |
| 617 return !/\[style[\^\$]?=/.test(s); | |
| 618 }); | |
| 619 } | 514 } |
| 620 } | 515 } |
| 621 } | 516 selectors = ElemHide.getSelectorsForDomain(host, false); |
| 622 | 517 if (noStyleRules) |
| 623 sendResponse({enabled: enabled, hostDomain: hostDomain, selectors: selecto rs}); | 518 { |
| 519 selectors = selectors.filter(function(s) | |
| 520 { | |
| 521 return !/\[style[\^\$]?=/.test(s); | |
| 522 }); | |
| 523 } | |
| 524 } | |
| 525 | |
| 526 sendResponse(selectors); | |
| 624 break; | 527 break; |
| 625 case "should-collapse": | 528 case "should-collapse": |
| 626 var frameId = sender.tab ? getFrameId(sender.tab, msg.documentUrl) : -1; | 529 var frameId = sender.tab ? getFrameId(sender.tab, msg.documentUrl) : -1; |
| 627 | 530 |
| 628 if (isFrameWhitelisted(sender.tab, frameId, "DOCUMENT")) | 531 if (isFrameWhitelisted(sender.tab, frameId, "DOCUMENT")) |
| 629 { | 532 { |
| 630 sendResponse(false); | 533 sendResponse(false); |
| 631 break; | 534 break; |
| 632 } | 535 } |
| 633 | 536 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 655 } | 558 } |
| 656 break; | 559 break; |
| 657 case "add-filters": | 560 case "add-filters": |
| 658 if (msg.filters && msg.filters.length) | 561 if (msg.filters && msg.filters.length) |
| 659 { | 562 { |
| 660 for (var i = 0; i < msg.filters.length; i++) | 563 for (var i = 0; i < msg.filters.length; i++) |
| 661 FilterStorage.addFilter(Filter.fromText(msg.filters[i])); | 564 FilterStorage.addFilter(Filter.fromText(msg.filters[i])); |
| 662 } | 565 } |
| 663 break; | 566 break; |
| 664 case "add-subscription": | 567 case "add-subscription": |
| 665 openOptions(function(tab) { | 568 openOptions(function(tab) |
| 569 { | |
| 666 tab.sendMessage(msg); | 570 tab.sendMessage(msg); |
| 667 }); | 571 }); |
| 668 break; | 572 break; |
| 669 case "forward": | 573 case "forward": |
| 670 tab.sendMessage(msg.payload, sendResponse); | 574 tab.sendMessage(msg.payload, sendResponse); |
| 671 break; | 575 break; |
| 672 default: | 576 default: |
| 673 sendResponse({}); | 577 sendResponse({}); |
| 674 break; | 578 break; |
| 675 } | 579 } |
| 676 }); | 580 }); |
| 677 | 581 |
| 678 // Show icon as page action for all tabs that already exist | 582 // Show icon as page action for all tabs that already exist |
| 679 ext.windows.getAll(function(windows) { | 583 ext.windows.getAll(function(windows) |
| 584 { | |
| 680 for (var i = 0; i < windows.length; i++) | 585 for (var i = 0; i < windows.length; i++) |
| 681 windows[i].getAllTabs(function(tabs) { | 586 { |
| 587 windows[i].getAllTabs(function(tabs) | |
| 588 { | |
| 682 tabs.forEach(refreshIconAndContextMenu); | 589 tabs.forEach(refreshIconAndContextMenu); |
| 683 }); | 590 }); |
| 591 } | |
| 684 }); | 592 }); |
| 685 | 593 |
| 686 // Update icon if a tab changes location | 594 // Update icon if a tab changes location |
| 687 ext.tabs.onBeforeNavigate.addListener(function(tab) { | 595 ext.tabs.onBeforeNavigate.addListener(function(tab) |
| 596 { | |
| 688 tab.sendMessage({type: "clickhide-deactivate"}); | 597 tab.sendMessage({type: "clickhide-deactivate"}); |
| 689 refreshIconAndContextMenu(tab); | 598 refreshIconAndContextMenu(tab); |
| 690 }); | 599 }); |
| 691 | 600 |
| 692 setTimeout(function() | 601 setTimeout(function() |
| 693 { | 602 { |
| 694 var notificationToShow = Notification.getNextToShow(); | 603 var notificationToShow = Notification.getNextToShow(); |
| 695 if (notificationToShow) | 604 if (notificationToShow) |
| 696 showNotification(notificationToShow); | 605 showNotification(notificationToShow); |
| 697 }, 3 * 60 * 1000); | 606 }, 3 * 60 * 1000); |
| LEFT | RIGHT |