| 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-2017 eyeo GmbH | 3 * Copyright (C) 2006-present 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 /* globals checkShareResource, getDocLink, i18nFormatDateTime, openSharePopup, | 18 /* globals checkShareResource, getDocLink, i18nFormatDateTime, openSharePopup, |
| 19 setLinks, E */ | 19 setLinks, E */ |
| 20 | 20 |
| 21 "use strict"; | 21 "use strict"; |
| 22 | 22 |
| 23 { | 23 { |
| 24 let subscriptionsMap = Object.create(null); | 24 let subscriptionsMap = Object.create(null); |
| 25 let filtersMap = Object.create(null); | 25 let filtersMap = Object.create(null); |
| 26 let collections = Object.create(null); | 26 let collections = Object.create(null); |
| 27 let acceptableAdsUrl = null; | 27 let acceptableAdsUrl = null; |
| 28 let acceptableAdsPrivacyUrl = null; | 28 let acceptableAdsPrivacyUrl = null; |
| 29 let isCustomFiltersLoaded = false; | 29 let isCustomFiltersLoaded = false; |
| 30 let isSubscriptionsLoaded = false; | |
| 31 let {getMessage} = ext.i18n; | 30 let {getMessage} = ext.i18n; |
| 32 let customFilters = []; | 31 let customFilters = []; |
| 33 let filterErrors = new Map([ | 32 let filterErrors = new Map([ |
| 34 ["synchronize_invalid_url", | 33 ["synchronize_invalid_url", |
| 35 "options_filterList_lastDownload_invalidURL"], | 34 "options_filterList_lastDownload_invalidURL"], |
| 36 ["synchronize_connection_error", | 35 ["synchronize_connection_error", |
| 37 "options_filterList_lastDownload_connectionError"], | 36 "options_filterList_lastDownload_connectionError"], |
| 38 ["synchronize_invalid_data", | 37 ["synchronize_invalid_data", |
| 39 "options_filterList_lastDownload_invalidData"], | 38 "options_filterList_lastDownload_invalidData"], |
| 40 ["synchronize_checksum_mismatch", | 39 ["synchronize_checksum_mismatch", |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 listItem.setAttribute("role", "section"); | 134 listItem.setAttribute("role", "section"); |
| 136 | 135 |
| 137 let tooltip = listItem.querySelector("[data-tooltip]"); | 136 let tooltip = listItem.querySelector("[data-tooltip]"); |
| 138 if (tooltip) | 137 if (tooltip) |
| 139 { | 138 { |
| 140 let tooltipId = tooltip.getAttribute("data-tooltip"); | 139 let tooltipId = tooltip.getAttribute("data-tooltip"); |
| 141 tooltipId = tooltipId.replace("%value%", item.recommended); | 140 tooltipId = tooltipId.replace("%value%", item.recommended); |
| 142 if (getMessage(tooltipId)) | 141 if (getMessage(tooltipId)) |
| 143 { | 142 { |
| 144 tooltip.setAttribute("data-tooltip", tooltipId); | 143 tooltip.setAttribute("data-tooltip", tooltipId); |
| 145 } | |
| 146 else | |
| 147 { | |
| 148 tooltip.parentNode.removeChild(tooltip); | |
| 149 } | 144 } |
| 150 } | 145 } |
| 151 | 146 |
| 152 for (let control of listItem.querySelectorAll(".control")) | 147 for (let control of listItem.querySelectorAll(".control")) |
| 153 { | 148 { |
| 154 if (control.hasAttribute("title")) | 149 if (control.hasAttribute("title")) |
| 155 { | 150 { |
| 156 let titleValue = getMessage(control.getAttribute("title")); | 151 let titleValue = getMessage(control.getAttribute("title")); |
| 157 control.setAttribute("title", titleValue); | 152 control.setAttribute("title", titleValue); |
| 158 } | 153 } |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 335 let nextElement = focusables[index]; | 330 let nextElement = focusables[index]; |
| 336 if (!nextElement) | 331 if (!nextElement) |
| 337 return false; | 332 return false; |
| 338 | 333 |
| 339 nextElement.focus(); | 334 nextElement.focus(); |
| 340 return true; | 335 return true; |
| 341 } | 336 } |
| 342 | 337 |
| 343 collections.protection = new Collection([ | 338 collections.protection = new Collection([ |
| 344 { | 339 { |
| 345 id: "recommend-security-list-table" | 340 id: "recommend-protection-list-table" |
| 346 } | 341 } |
| 347 ]); | 342 ]); |
| 348 collections.langs = new Collection([ | 343 collections.langs = new Collection([ |
| 349 { | 344 { |
| 350 id: "blocking-languages-table", | 345 id: "blocking-languages-table", |
| 351 emptyText: ["options_language_empty"] | 346 emptyText: ["options_language_empty"] |
| 352 } | 347 } |
| 353 ]); | 348 ]); |
| 354 collections.allLangs = new Collection([ | 349 collections.allLangs = new Collection([ |
| 355 { | 350 { |
| 356 id: "all-lang-table-add", | 351 id: "all-lang-table-add", |
| 357 emptyText: ["options_dialog_language_other_empty"] | 352 emptyText: ["options_dialog_language_other_empty"] |
| 358 } | 353 } |
| 359 ]); | 354 ]); |
| 360 collections.custom = new Collection([ | 355 collections.more = new Collection([ |
| 361 { | 356 { |
| 362 id: "custom-list-table" | 357 id: "more-list-table" |
| 363 } | 358 } |
| 364 ]); | 359 ]); |
| 365 collections.whitelist = new Collection([ | 360 collections.whitelist = new Collection([ |
| 366 { | 361 { |
| 367 id: "whitelisting-table", | 362 id: "whitelisting-table", |
| 368 emptyText: ["options_whitelist_empty_1", "options_whitelist_empty_2"] | 363 emptyText: ["options_whitelist_empty_1", "options_whitelist_empty_2"] |
| 369 } | 364 } |
| 370 ]); | 365 ]); |
| 371 collections.filterLists = new Collection([ | 366 collections.filterLists = new Collection([ |
| 372 { | 367 { |
| 373 id: "all-filter-lists-table", | 368 id: "all-filter-lists-table", |
| 374 useOriginalTitle: true | 369 useOriginalTitle: true |
| 375 } | 370 } |
| 376 ]); | 371 ]); |
| 377 | 372 |
| 378 function addSubscription(subscription) | 373 function addSubscription(subscription) |
| 379 { | 374 { |
| 375 let {disabled} = subscription; | |
| 380 let collection = null; | 376 let collection = null; |
| 381 if (subscription.recommended) | 377 if (subscription.recommended) |
| 382 { | 378 { |
| 383 if (subscription.recommended == "ads") | 379 if (subscription.recommended == "ads") |
| 384 { | 380 { |
| 385 if (subscription.disabled == false) | 381 if (disabled == false) |
| 386 collection = collections.langs; | 382 collection = collections.langs; |
| 387 | 383 |
| 388 collections.allLangs.addItem(subscription); | 384 collections.allLangs.addItem(subscription); |
| 389 } | 385 } |
| 390 else | 386 else |
| 391 { | 387 { |
| 392 collection = collections.protection; | 388 collection = collections.protection; |
| 393 } | 389 } |
| 394 } | 390 } |
| 395 else if (!isAcceptableAds(subscription.url)) | 391 else if (!isAcceptableAds(subscription.url) && disabled == false) |
| 396 { | 392 { |
| 397 collection = collections.custom; | 393 collection = collections.more; |
| 398 } | 394 } |
| 399 | 395 |
| 400 if (collection) | 396 if (collection) |
| 401 collection.addItem(subscription); | 397 collection.addItem(subscription); |
| 402 | 398 |
| 403 subscriptionsMap[subscription.url] = subscription; | 399 subscriptionsMap[subscription.url] = subscription; |
| 404 updateTooltips(); | 400 updateTooltips(); |
| 405 } | 401 } |
| 406 | 402 |
| 407 function updateSubscription(subscription) | 403 function updateSubscription(subscription) |
| 408 { | 404 { |
| 409 for (let name in collections) | 405 for (let name in collections) |
| 410 collections[name].updateItem(subscription); | 406 collections[name].updateItem(subscription); |
| 411 | 407 |
| 412 if (subscription.recommended == "ads") | 408 if (subscription.recommended == "ads") |
| 413 { | 409 { |
| 414 if (subscription.disabled) | 410 if (subscription.disabled) |
| 415 collections.langs.removeItem(subscription); | 411 collections.langs.removeItem(subscription); |
| 416 else | 412 else |
| 417 collections.langs.addItem(subscription); | 413 collections.langs.addItem(subscription); |
| 418 } | 414 } |
| 419 else if (!subscription.recommended && !isAcceptableAds(subscription.url)) | 415 else if (!subscription.recommended && !isAcceptableAds(subscription.url)) |
| 420 { | 416 { |
| 421 if (subscription.disabled == false) | 417 if (subscription.disabled == false) |
| 422 { | 418 { |
| 423 collections.custom.addItem(subscription); | 419 collections.more.addItem(subscription); |
| 424 updateTooltips(); | 420 updateTooltips(); |
| 425 } | 421 } |
| 426 else | 422 else |
| 427 { | 423 { |
| 428 collections.custom.removeItem(subscription); | 424 collections.more.removeItem(subscription); |
| 429 } | 425 } |
| 430 } | 426 } |
| 431 } | 427 } |
| 432 | 428 |
| 433 function updateFilter(filter) | 429 function updateFilter(filter) |
| 434 { | 430 { |
| 435 let match = filter.text.match(whitelistedDomainRegexp); | 431 let match = filter.text.match(whitelistedDomainRegexp); |
| 436 if (match && !filtersMap[filter.text]) | 432 if (match && !filtersMap[filter.text]) |
| 437 { | 433 { |
| 438 filter.title = match[1]; | 434 filter.title = match[1]; |
| 439 collections.whitelist.addItem(filter); | 435 collections.whitelist.addItem(filter); |
| 436 if (isCustomFiltersLoaded) | |
| 437 { | |
| 438 let text = getMessage("options_whitelist_notification", [filter.title]); | |
| 439 showNotification(text); | |
| 440 } | |
| 440 } | 441 } |
| 441 else | 442 else |
| 442 { | 443 { |
| 443 customFilters.push(filter.text); | 444 customFilters.push(filter.text); |
| 444 if (isCustomFiltersLoaded) | 445 if (isCustomFiltersLoaded) |
| 445 updateCustomFiltersUi(); | 446 updateCustomFiltersUi(); |
| 446 } | 447 } |
| 447 | 448 |
| 448 filtersMap[filter.text] = filter; | 449 filtersMap[filter.text] = filter; |
| 449 } | 450 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 521 } | 522 } |
| 522 | 523 |
| 523 function sendMessageHandleErrors(message, onSuccess) | 524 function sendMessageHandleErrors(message, onSuccess) |
| 524 { | 525 { |
| 525 ext.backgroundPage.sendMessage(message, (errors) => | 526 ext.backgroundPage.sendMessage(message, (errors) => |
| 526 { | 527 { |
| 527 if (errors.length > 0) | 528 if (errors.length > 0) |
| 528 alert(errors.join("\n")); | 529 alert(errors.join("\n")); |
| 529 else if (onSuccess) | 530 else if (onSuccess) |
| 530 onSuccess(); | 531 onSuccess(); |
| 531 }); | |
| 532 } | |
| 533 | |
| 534 function openDocLink(id) | |
| 535 { | |
| 536 getDocLink(id, (link) => | |
| 537 { | |
| 538 if (id == "share-general") | |
| 539 openSharePopup(link); | |
| 540 else | |
| 541 location.href = link; | |
| 542 }); | 532 }); |
| 543 } | 533 } |
| 544 | 534 |
| 545 function switchTab(id) | 535 function switchTab(id) |
| 546 { | 536 { |
| 547 location.hash = id; | 537 location.hash = id; |
| 548 } | 538 } |
| 549 | 539 |
| 550 function execAction(action, element) | 540 function execAction(action, element) |
| 551 { | 541 { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 586 break; | 576 break; |
| 587 } | 577 } |
| 588 } | 578 } |
| 589 break; | 579 break; |
| 590 case "close-dialog": | 580 case "close-dialog": |
| 591 closeDialog(); | 581 closeDialog(); |
| 592 break; | 582 break; |
| 593 case "edit-custom-filters": | 583 case "edit-custom-filters": |
| 594 setCustomFiltersView("write"); | 584 setCustomFiltersView("write"); |
| 595 break; | 585 break; |
| 586 case "hide-notification": | |
| 587 hideNotification(); | |
| 588 break; | |
| 596 case "import-subscription": { | 589 case "import-subscription": { |
| 597 let url = E("blockingList-textbox").value; | 590 let url = E("blockingList-textbox").value; |
| 598 addEnableSubscription(url); | 591 addEnableSubscription(url); |
| 599 closeDialog(); | 592 closeDialog(); |
| 600 break; | 593 break; |
| 601 } | 594 } |
| 602 case "open-context-menu": { | 595 case "open-context-menu": { |
| 603 let listItem = findParentData(element, "access", true); | 596 let listItem = findParentData(element, "access", true); |
| 604 if (listItem && !listItem.classList.contains("show-context-menu")) | 597 if (listItem && !listItem.classList.contains("show-context-menu")) |
| 605 listItem.classList.add("show-context-menu"); | 598 listItem.classList.add("show-context-menu"); |
| 606 break; | 599 break; |
| 607 } | 600 } |
| 608 case "open-dialog": { | 601 case "open-dialog": { |
| 609 let dialog = findParentData(element, "dialog", false); | 602 let dialog = findParentData(element, "dialog", false); |
| 610 openDialog(dialog); | 603 openDialog(dialog); |
| 611 break; | |
| 612 } | |
| 613 case "open-doclink": { | |
| 614 let doclink = findParentData(element, "doclink", false); | |
| 615 openDocLink(doclink); | |
| 616 break; | 604 break; |
| 617 } | 605 } |
| 618 case "remove-filter": | 606 case "remove-filter": |
| 619 ext.backgroundPage.sendMessage({ | 607 ext.backgroundPage.sendMessage({ |
| 620 type: "filters.remove", | 608 type: "filters.remove", |
| 621 text: findParentData(element, "access", false) | 609 text: findParentData(element, "access", false) |
| 622 }); | 610 }); |
| 623 break; | 611 break; |
| 624 case "remove-subscription": | 612 case "remove-subscription": |
| 625 ext.backgroundPage.sendMessage({ | 613 ext.backgroundPage.sendMessage({ |
| 626 type: "subscriptions.remove", | 614 type: "subscriptions.remove", |
| 627 url: findParentData(element, "access", false) | 615 url: findParentData(element, "access", false) |
| 628 }); | 616 }); |
| 629 break; | 617 break; |
| 630 case "save-custom-filters": | 618 case "save-custom-filters": |
| 631 sendMessageHandleErrors({ | 619 sendMessageHandleErrors({ |
| 632 type: "filters.importRaw", | 620 type: "filters.importRaw", |
| 633 text: E("custom-filters-raw").value, | 621 text: E("custom-filters-raw").value, |
| 634 removeExisting: true | 622 removeExisting: true |
| 635 }, | 623 }, |
| 636 () => | 624 () => |
| 637 { | 625 { |
| 638 setCustomFiltersView("read"); | 626 setCustomFiltersView("read"); |
| 639 }); | 627 }); |
| 640 break; | 628 break; |
| 641 case "switch-acceptable-ads": | 629 case "switch-acceptable-ads": |
| 642 let value = element.value; | 630 let value = element.value || element.dataset.value; |
| 643 ext.backgroundPage.sendMessage({ | 631 ext.backgroundPage.sendMessage({ |
| 644 type: value == "privacy" ? "subscriptions.add" : | 632 type: value == "privacy" ? "subscriptions.add" : |
| 645 "subscriptions.remove", | 633 "subscriptions.remove", |
| 646 url: acceptableAdsPrivacyUrl | 634 url: acceptableAdsPrivacyUrl |
| 647 }); | 635 }); |
| 648 ext.backgroundPage.sendMessage({ | 636 ext.backgroundPage.sendMessage({ |
| 649 type: value == "ads" ? "subscriptions.add" : "subscriptions.remove", | 637 type: value == "ads" ? "subscriptions.add" : "subscriptions.remove", |
| 650 url: acceptableAdsUrl | 638 url: acceptableAdsUrl |
| 651 }); | 639 }); |
| 652 break; | 640 break; |
| 653 case "switch-tab": | 641 case "switch-tab": |
| 654 let tabId = findParentData(element, "tab", false); | 642 switchTab(element.getAttribute("href").substr(1)); |
| 655 switchTab(tabId); | |
| 656 break; | 643 break; |
| 657 case "toggle-disable-subscription": | 644 case "toggle-disable-subscription": |
| 658 ext.backgroundPage.sendMessage({ | 645 ext.backgroundPage.sendMessage({ |
| 659 type: "subscriptions.toggle", | 646 type: "subscriptions.toggle", |
| 660 keepInstalled: true, | 647 keepInstalled: true, |
| 661 url: findParentData(element, "access", false) | 648 url: findParentData(element, "access", false) |
| 662 }); | 649 }); |
| 663 break; | 650 break; |
| 664 case "toggle-pref": | 651 case "toggle-pref": |
| 665 ext.backgroundPage.sendMessage({ | 652 ext.backgroundPage.sendMessage({ |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 682 case "update-all-subscriptions": | 669 case "update-all-subscriptions": |
| 683 ext.backgroundPage.sendMessage({ | 670 ext.backgroundPage.sendMessage({ |
| 684 type: "subscriptions.update" | 671 type: "subscriptions.update" |
| 685 }); | 672 }); |
| 686 break; | 673 break; |
| 687 case "update-subscription": | 674 case "update-subscription": |
| 688 ext.backgroundPage.sendMessage({ | 675 ext.backgroundPage.sendMessage({ |
| 689 type: "subscriptions.update", | 676 type: "subscriptions.update", |
| 690 url: findParentData(element, "access", false) | 677 url: findParentData(element, "access", false) |
| 691 }); | 678 }); |
| 679 break; | |
| 680 case "validate-import-subscription": | |
| 681 let form = findParentData(element, "validation", true); | |
| 682 if (!form) | |
| 683 return; | |
| 684 | |
| 685 if (form.checkValidity()) | |
| 686 { | |
| 687 addEnableSubscription(E("import-list-url").value, | |
| 688 E("import-list-title").value); | |
| 689 form.reset(); | |
| 690 closeDialog(); | |
| 691 } | |
| 692 else | |
| 693 { | |
| 694 form.querySelector(":invalid").focus(); | |
| 695 } | |
| 692 break; | 696 break; |
| 693 } | 697 } |
| 694 } | 698 } |
| 695 | 699 |
| 696 function setCustomFiltersView(mode) | 700 function setCustomFiltersView(mode) |
| 697 { | 701 { |
| 698 let customFiltersElement = E("custom-filters-raw"); | 702 let customFiltersElement = E("custom-filters-raw"); |
| 699 updateCustomFiltersUi(); | 703 updateCustomFiltersUi(); |
| 700 if (mode == "read") | 704 if (mode == "read") |
| 701 { | 705 { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 758 let container = findParentData(element, "action", true); | 762 let container = findParentData(element, "action", true); |
| 759 if (!container || !container.hasAttribute("data-keys")) | 763 if (!container || !container.hasAttribute("data-keys")) |
| 760 return; | 764 return; |
| 761 | 765 |
| 762 let keys = container.getAttribute("data-keys").split(" "); | 766 let keys = container.getAttribute("data-keys").split(" "); |
| 763 if (keys.indexOf(key) < 0) | 767 if (keys.indexOf(key) < 0) |
| 764 return; | 768 return; |
| 765 | 769 |
| 766 if (element.getAttribute("role") == "tab") | 770 if (element.getAttribute("role") == "tab") |
| 767 { | 771 { |
| 772 let parent = element.parentElement; | |
| 768 if (key == "ArrowLeft" || key == "ArrowUp") | 773 if (key == "ArrowLeft" || key == "ArrowUp") |
| 769 element = element.previousElementSibling || container.lastElementChild; | 774 parent = parent.previousElementSibling || container.lastElementChild; |
| 770 else if (key == "ArrowRight" || key == "ArrowDown") | 775 else if (key == "ArrowRight" || key == "ArrowDown") |
| 771 element = element.nextElementSibling || container.firstElementChild; | 776 parent = parent.nextElementSibling || container.firstElementChild; |
| 777 element = parent.firstElementChild; | |
| 772 } | 778 } |
| 773 | 779 |
| 774 let actions = container.getAttribute("data-action").split(","); | 780 let actions = container.getAttribute("data-action").split(","); |
| 775 for (let action of actions) | 781 for (let action of actions) |
| 776 { | 782 { |
| 777 execAction(action, element); | 783 execAction(action, element); |
| 778 } | 784 } |
| 779 } | 785 } |
| 780 | 786 |
| 781 function selectTabItem(tabId, container, focus) | 787 function selectTabItem(tabId, container, focus) |
| 782 { | 788 { |
| 783 // Show tab content | 789 // Show tab content |
| 784 document.body.setAttribute("data-tab", tabId); | 790 document.body.setAttribute("data-tab", tabId); |
| 785 | 791 |
| 786 // Select tab | 792 // Select tab |
| 787 let tabList = container.querySelector("[role='tablist']"); | 793 let tabList = container.querySelector("[role='tablist']"); |
| 788 if (!tabList) | 794 if (!tabList) |
| 789 return null; | 795 return null; |
| 790 | 796 |
| 791 let previousTab = tabList.querySelector("[aria-selected]"); | 797 let previousTab = tabList.querySelector("[aria-selected]"); |
| 792 previousTab.removeAttribute("aria-selected"); | 798 previousTab.removeAttribute("aria-selected"); |
| 793 previousTab.setAttribute("tabindex", -1); | 799 previousTab.setAttribute("tabindex", -1); |
| 794 | 800 |
| 795 let tab = tabList.querySelector("li[data-tab='" + tabId + "']"); | 801 let tab = tabList.querySelector("a[href='#" + tabId + "']"); |
| 796 tab.setAttribute("aria-selected", true); | 802 tab.setAttribute("aria-selected", true); |
| 797 tab.setAttribute("tabindex", 0); | 803 tab.setAttribute("tabindex", 0); |
| 798 | 804 |
| 799 let tabContentId = tab.getAttribute("aria-controls"); | 805 let tabContentId = tab.getAttribute("aria-controls"); |
| 800 let tabContent = document.getElementById(tabContentId); | 806 let tabContent = document.getElementById(tabContentId); |
| 801 | 807 |
| 802 if (tab && focus) | 808 if (tab && focus) |
| 803 tab.focus(); | 809 tab.focus(); |
| 804 | 810 |
| 805 return tabContent; | 811 return tabContent; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 827 { | 833 { |
| 828 populateLists(); | 834 populateLists(); |
| 829 | 835 |
| 830 // Initialize navigation sidebar | 836 // Initialize navigation sidebar |
| 831 ext.backgroundPage.sendMessage({ | 837 ext.backgroundPage.sendMessage({ |
| 832 type: "app.get", | 838 type: "app.get", |
| 833 what: "addonVersion" | 839 what: "addonVersion" |
| 834 }, | 840 }, |
| 835 (addonVersion) => | 841 (addonVersion) => |
| 836 { | 842 { |
| 837 E("abp-version").textContent = addonVersion; | 843 E("abp-version").textContent = getMessage("options_dialog_about_version", |
| 838 }); | 844 [addonVersion]); |
| 839 getDocLink("releases", (link) => | 845 }); |
| 840 { | 846 |
| 841 E("link-version").setAttribute("href", link); | |
| 842 }); | |
| 843 | |
| 844 updateShareLink(); | |
| 845 updateTooltips(); | 847 updateTooltips(); |
| 846 | 848 |
| 847 // Initialize interactive UI elements | 849 // Initialize interactive UI elements |
| 848 document.body.addEventListener("click", onClick, false); | 850 document.body.addEventListener("click", onClick, false); |
| 849 document.body.addEventListener("keyup", onKeyUp, false); | 851 document.body.addEventListener("keyup", onKeyUp, false); |
| 850 let exampleValue = getMessage("options_whitelist_placeholder_example", | 852 let exampleValue = getMessage("options_whitelist_placeholder_example", |
| 851 ["www.example.com"]); | 853 ["www.example.com"]); |
| 852 E("whitelisting-textbox").setAttribute("placeholder", exampleValue); | 854 E("whitelisting-textbox").setAttribute("placeholder", exampleValue); |
| 853 E("whitelisting-textbox").addEventListener("keyup", (e) => | 855 E("whitelisting-textbox").addEventListener("keyup", (e) => |
| 854 { | 856 { |
| 855 E("whitelisting-add-button").disabled = !e.target.value; | 857 E("whitelisting-add-button").disabled = !e.target.value; |
| 856 }, false); | 858 }, false); |
| 857 | 859 |
| 860 getDocLink("contribute", (link) => | |
| 861 { | |
| 862 E("contribute").href = link; | |
| 863 }); | |
| 858 getDocLink("acceptable_ads_criteria", (link) => | 864 getDocLink("acceptable_ads_criteria", (link) => |
| 859 { | 865 { |
| 860 setLinks("enable-aa-description", link); | 866 setLinks("enable-aa-description", link); |
| 861 }); | 867 }); |
| 862 | 868 |
| 863 // Advanced tab | 869 // Advanced tab |
| 864 let customize = document.querySelectorAll("#customize li[data-pref]"); | 870 let customize = document.querySelectorAll("#customize li[data-pref]"); |
| 865 customize = Array.prototype.map.call(customize, (checkbox) => | 871 customize = Array.prototype.map.call(customize, (checkbox) => |
| 866 { | 872 { |
| 867 return checkbox.getAttribute("data-pref"); | 873 return checkbox.getAttribute("data-pref"); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 889 | 895 |
| 890 getDocLink("subscriptions", (link) => | 896 getDocLink("subscriptions", (link) => |
| 891 { | 897 { |
| 892 setLinks("filter-lists-description", link); | 898 setLinks("filter-lists-description", link); |
| 893 }); | 899 }); |
| 894 | 900 |
| 895 E("custom-filters-raw").setAttribute("placeholder", | 901 E("custom-filters-raw").setAttribute("placeholder", |
| 896 getMessage("options_customFilters_edit_placeholder", ["/ads/track/*"])); | 902 getMessage("options_customFilters_edit_placeholder", ["/ads/track/*"])); |
| 897 | 903 |
| 898 // Help tab | 904 // Help tab |
| 899 getDocLink("faq", (link) => | 905 getDocLink("adblock_plus_report_issue", (link) => |
| 900 { | 906 { |
| 901 E("link-faq").setAttribute("href", link); | 907 setLinks("report-issue", link); |
| 908 }); | |
| 909 getDocLink("adblock_plus_report_ad", (link) => | |
| 910 { | |
| 911 setLinks("report-ad", link); | |
| 912 }); | |
| 913 getDocLink("adblock_plus_report_bug", (link) => | |
| 914 { | |
| 915 setLinks("report-bug", link); | |
| 916 }); | |
| 917 getDocLink("reporter_other_link", (link) => | |
| 918 { | |
| 919 setLinks("report-forum", link); | |
| 902 }); | 920 }); |
| 903 getDocLink("social_twitter", (link) => | 921 getDocLink("social_twitter", (link) => |
| 904 { | 922 { |
| 905 E("link-twitter").setAttribute("href", link); | 923 E("twitter").setAttribute("href", link); |
| 906 }); | 924 }); |
| 907 getDocLink("social_facebook", (link) => | 925 getDocLink("social_facebook", (link) => |
| 908 { | 926 { |
| 909 E("link-facebook").setAttribute("href", link); | 927 E("facebook").setAttribute("href", link); |
| 910 }); | 928 }); |
| 911 getDocLink("social_gplus", (link) => | 929 getDocLink("social_gplus", (link) => |
| 912 { | 930 { |
| 913 E("link-gplus").setAttribute("href", link); | 931 E("google-plus").setAttribute("href", link); |
| 914 }); | |
| 915 getDocLink("social_renren", (link) => | |
| 916 { | |
| 917 E("link-renren").setAttribute("href", link); | |
| 918 }); | 932 }); |
| 919 getDocLink("social_weibo", (link) => | 933 getDocLink("social_weibo", (link) => |
| 920 { | 934 { |
| 921 E("link-weibo").setAttribute("href", link); | 935 E("weibo").setAttribute("href", link); |
| 922 }); | |
| 923 | |
| 924 // Set forum link | |
| 925 ext.backgroundPage.sendMessage({ | |
| 926 type: "app.get", | |
| 927 what: "platform" | |
| 928 }, | |
| 929 (platform) => | |
| 930 { | |
| 931 ext.backgroundPage.sendMessage({ | |
| 932 type: "app.get", | |
| 933 what: "application" | |
| 934 }, | |
| 935 (application) => | |
| 936 { | |
| 937 if (platform == "chromium" && application != "opera") | |
| 938 application = "chrome"; | |
| 939 | |
| 940 getDocLink(application + "_support", (link) => | |
| 941 { | |
| 942 E("link-forum").setAttribute("href", link); | |
| 943 }); | |
| 944 }); | |
| 945 }); | 936 }); |
| 946 | 937 |
| 947 E("dialog").addEventListener("keydown", function(e) | 938 E("dialog").addEventListener("keydown", function(e) |
| 948 { | 939 { |
| 949 switch (getKey(e)) | 940 switch (getKey(e)) |
| 950 { | 941 { |
| 951 case "Escape": | 942 case "Escape": |
| 952 closeDialog(); | 943 closeDialog(); |
| 953 break; | 944 break; |
| 954 case "Tab": | 945 case "Tab": |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 991 | 982 |
| 992 function closeDialog() | 983 function closeDialog() |
| 993 { | 984 { |
| 994 let dialog = E("dialog"); | 985 let dialog = E("dialog"); |
| 995 dialog.setAttribute("aria-hidden", true); | 986 dialog.setAttribute("aria-hidden", true); |
| 996 dialog.removeAttribute("aria-labelledby"); | 987 dialog.removeAttribute("aria-labelledby"); |
| 997 document.body.removeAttribute("data-dialog"); | 988 document.body.removeAttribute("data-dialog"); |
| 998 focusedBeforeDialog.focus(); | 989 focusedBeforeDialog.focus(); |
| 999 } | 990 } |
| 1000 | 991 |
| 1001 function setDntNotification(state) | 992 function showNotification(text) |
| 1002 { | 993 { |
| 1003 if (state) | 994 E("notification").setAttribute("aria-hidden", false); |
| 1004 E("acceptable-ads").classList.add("show-dnt-notification"); | 995 E("notification-text").textContent = text; |
| 1005 else | 996 setTimeout(hideNotification, 3000); |
| 1006 E("acceptable-ads").classList.remove("show-dnt-notification"); | 997 } |
| 998 | |
| 999 function hideNotification() | |
| 1000 { | |
| 1001 E("notification").setAttribute("aria-hidden", true); | |
| 1002 E("notification-text").textContent = ""; | |
| 1007 } | 1003 } |
| 1008 | 1004 |
| 1009 function setAcceptableAds() | 1005 function setAcceptableAds() |
| 1010 { | 1006 { |
| 1011 let optionsContainer = E("acceptable-ads"); | 1007 let option = "none"; |
| 1012 optionsContainer.querySelector("[value='none']").checked = true; | 1008 document.forms["acceptable-ads"].classList.remove("show-dnt-notification"); |
| 1013 for (let url in subscriptionsMap) | 1009 if (acceptableAdsUrl in subscriptionsMap) |
| 1014 { | 1010 { |
| 1015 if (url == acceptableAdsPrivacyUrl) | 1011 option = "ads"; |
| 1016 { | 1012 } |
| 1017 optionsContainer.querySelector("[value='privacy']").checked = true; | 1013 else if (acceptableAdsPrivacyUrl in subscriptionsMap) |
| 1018 } | 1014 { |
| 1019 if (url == acceptableAdsUrl) | 1015 option = "privacy"; |
| 1020 { | 1016 |
| 1021 optionsContainer.querySelector("[value='ads']").checked = true; | 1017 if (!navigator.doNotTrack) |
| 1022 break; | 1018 document.forms["acceptable-ads"].classList.add("show-dnt-notification"); |
| 1023 } | 1019 } |
| 1024 } | 1020 document.forms["acceptable-ads"]["acceptable-ads"].value = option; |
| 1025 } | 1021 } |
| 1026 | 1022 |
| 1027 function isAcceptableAds(url) | 1023 function isAcceptableAds(url) |
| 1028 { | 1024 { |
| 1029 return url == acceptableAdsUrl || url == acceptableAdsPrivacyUrl; | 1025 return url == acceptableAdsUrl || url == acceptableAdsPrivacyUrl; |
| 1030 } | 1026 } |
| 1031 | 1027 |
| 1032 function isPrivacyAndAdsEnabled() | 1028 function hasPrivacyConflict() |
|
Thomas Greiner
2017/08/25 18:44:52
This function is a bit difficult to understand so
saroyanm
2017/08/27 16:25:28
Agree, thanks.
saroyanm
2017/09/14 21:56:14
Done.
| |
| 1033 { | 1029 { |
| 1034 let isAcceptableAds = subscriptionsMap[acceptableAdsUrl]; | 1030 let acceptableAdsList = subscriptionsMap[acceptableAdsUrl]; |
| 1035 isAcceptableAds = isAcceptableAds && isAcceptableAds.disabled == false; | 1031 let privacyList = null; |
| 1036 for (let url in subscriptionsMap) | 1032 for (let url in subscriptionsMap) |
| 1037 { | 1033 { |
| 1038 let subscription = subscriptionsMap[url]; | 1034 let subscription = subscriptionsMap[url]; |
| 1039 if (subscription.recommended == "privacy") | 1035 if (subscription.recommended == "privacy") |
| 1040 return subscription.disabled == false && isAcceptableAds; | 1036 { |
| 1041 } | 1037 privacyList = subscription; |
| 1038 break; | |
| 1039 } | |
| 1040 } | |
| 1041 return acceptableAdsList && acceptableAdsList.disabled == false && | |
| 1042 privacyList && privacyList.disabled == false; | |
| 1042 } | 1043 } |
| 1043 | 1044 |
| 1044 function populateLists() | 1045 function populateLists() |
| 1045 { | 1046 { |
| 1046 subscriptionsMap = Object.create(null); | 1047 subscriptionsMap = Object.create(null); |
| 1047 filtersMap = Object.create(null); | 1048 filtersMap = Object.create(null); |
| 1048 | 1049 |
| 1049 // Empty collections and lists | 1050 // Empty collections and lists |
| 1050 for (let property in collections) | 1051 for (let property in collections) |
| 1051 collections[property].clearAll(); | 1052 collections[property].clearAll(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1096 | 1097 |
| 1097 // Load user subscriptions | 1098 // Load user subscriptions |
| 1098 ext.backgroundPage.sendMessage({ | 1099 ext.backgroundPage.sendMessage({ |
| 1099 type: "subscriptions.get", | 1100 type: "subscriptions.get", |
| 1100 downloadable: true | 1101 downloadable: true |
| 1101 }, | 1102 }, |
| 1102 (subscriptions) => | 1103 (subscriptions) => |
| 1103 { | 1104 { |
| 1104 for (let subscription of subscriptions) | 1105 for (let subscription of subscriptions) |
| 1105 onSubscriptionMessage("added", subscription); | 1106 onSubscriptionMessage("added", subscription); |
| 1106 isSubscriptionsLoaded = true; | |
| 1107 }); | 1107 }); |
| 1108 }); | 1108 }); |
| 1109 }); | 1109 }); |
| 1110 } | 1110 } |
| 1111 | 1111 |
| 1112 function addWhitelistedDomain() | 1112 function addWhitelistedDomain() |
| 1113 { | 1113 { |
| 1114 let domain = E("whitelisting-textbox"); | 1114 let domain = E("whitelisting-textbox"); |
| 1115 for (let whitelistItem of collections.whitelist.items) | 1115 for (let whitelistItem of collections.whitelist.items) |
| 1116 { | 1116 { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1155 ext.backgroundPage.sendMessage(message); | 1155 ext.backgroundPage.sendMessage(message); |
| 1156 } | 1156 } |
| 1157 | 1157 |
| 1158 function onFilterMessage(action, filter) | 1158 function onFilterMessage(action, filter) |
| 1159 { | 1159 { |
| 1160 switch (action) | 1160 switch (action) |
| 1161 { | 1161 { |
| 1162 case "added": | 1162 case "added": |
| 1163 filter[timestampUI] = Date.now(); | 1163 filter[timestampUI] = Date.now(); |
| 1164 updateFilter(filter); | 1164 updateFilter(filter); |
| 1165 updateShareLink(); | |
| 1166 break; | 1165 break; |
| 1167 case "loaded": | 1166 case "loaded": |
| 1168 populateLists(); | 1167 populateLists(); |
| 1169 break; | 1168 break; |
| 1170 case "removed": | 1169 case "removed": |
| 1171 let knownFilter = filtersMap[filter.text]; | 1170 let knownFilter = filtersMap[filter.text]; |
| 1172 if (whitelistedDomainRegexp.test(knownFilter.text)) | 1171 if (whitelistedDomainRegexp.test(knownFilter.text)) |
| 1173 collections.whitelist.removeItem(knownFilter); | 1172 collections.whitelist.removeItem(knownFilter); |
| 1174 else | 1173 else |
| 1175 removeCustomFilter(filter.text); | 1174 removeCustomFilter(filter.text); |
| 1176 | 1175 |
| 1177 delete filtersMap[filter.text]; | 1176 delete filtersMap[filter.text]; |
| 1178 updateShareLink(); | |
| 1179 break; | 1177 break; |
| 1180 } | 1178 } |
| 1181 } | 1179 } |
| 1182 | 1180 |
| 1183 function onSubscriptionMessage(action, subscription) | 1181 function onSubscriptionMessage(action, subscription) |
| 1184 { | 1182 { |
| 1185 if (subscription.url in subscriptionsMap) | 1183 if (subscription.url in subscriptionsMap) |
| 1186 { | 1184 { |
| 1187 let knownSubscription = subscriptionsMap[subscription.url]; | 1185 let knownSubscription = subscriptionsMap[subscription.url]; |
| 1188 for (let property in subscription) | 1186 for (let property in subscription) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1200 updateSubscription(subscription); | 1198 updateSubscription(subscription); |
| 1201 break; | 1199 break; |
| 1202 case "downloading": | 1200 case "downloading": |
| 1203 case "downloadStatus": | 1201 case "downloadStatus": |
| 1204 case "homepage": | 1202 case "homepage": |
| 1205 case "lastDownload": | 1203 case "lastDownload": |
| 1206 case "title": | 1204 case "title": |
| 1207 updateSubscription(subscription); | 1205 updateSubscription(subscription); |
| 1208 break; | 1206 break; |
| 1209 case "added": | 1207 case "added": |
| 1210 let url = subscription.url; | 1208 let {url, recommended} = subscription; |
| 1211 if (url in subscriptionsMap) | 1209 if (url in subscriptionsMap) |
| 1212 updateSubscription(subscription); | 1210 updateSubscription(subscription); |
| 1213 else | 1211 else |
| 1214 addSubscription(subscription); | 1212 addSubscription(subscription); |
| 1215 | 1213 |
| 1216 if (isAcceptableAds(url)) | 1214 if (isAcceptableAds(url)) |
| 1217 setAcceptableAds(); | 1215 setAcceptableAds(); |
| 1218 | 1216 |
| 1219 if (url == acceptableAdsPrivacyUrl) | 1217 if ((url == acceptableAdsUrl || recommended == "privacy") && |
| 1220 { | 1218 hasPrivacyConflict()) |
| 1221 if (!navigator.doNotTrack) | 1219 { |
| 1222 setDntNotification(true); | 1220 getPref("ui_warn_tracking", (showTrackingWarning) => |
| 1223 } | 1221 { |
| 1224 | 1222 if (showTrackingWarning) |
| 1225 if (url == acceptableAdsUrl || subscription.recommended == "privacy") | 1223 openDialog("tracking"); |
| 1226 { | 1224 }); |
| 1227 if (isSubscriptionsLoaded && isPrivacyAndAdsEnabled()) | |
|
Thomas Greiner
2017/08/25 18:44:51
Why is checking for `isSubscriptionsLoaded` necess
saroyanm
2017/08/27 16:25:28
I did it in order not to show on each load of the
Thomas Greiner
2017/08/29 10:20:41
So it's a stopgap solution until we have the prefe
saroyanm
2017/09/14 21:56:14
Done.
| |
| 1228 openDialog("tracking"); | |
|
saroyanm
2017/08/19 00:00:40
In specs it says that "This is a one time message"
Thomas Greiner
2017/08/25 18:44:51
Yes. Probably best to prefix the preference name w
saroyanm
2017/08/27 16:25:28
Thanks, I'll have a look into this.
saroyanm
2017/09/14 21:56:14
Done.
| |
| 1229 } | 1225 } |
| 1230 | 1226 |
| 1231 collections.filterLists.addItem(subscription); | 1227 collections.filterLists.addItem(subscription); |
| 1232 break; | 1228 break; |
| 1233 case "removed": | 1229 case "removed": |
| 1234 if (subscription.recommended) | 1230 if (subscription.recommended) |
| 1235 { | 1231 { |
| 1236 subscription.disabled = true; | 1232 subscription.disabled = true; |
| 1237 onSubscriptionMessage("disabled", subscription); | 1233 onSubscriptionMessage("disabled", subscription); |
| 1238 } | 1234 } |
| 1239 else if (isAcceptableAds(subscription.url)) | 1235 else |
| 1240 { | 1236 { |
| 1241 if (subscription.url == acceptableAdsPrivacyUrl) | 1237 delete subscriptionsMap[subscription.url]; |
| 1238 if (isAcceptableAds(subscription.url)) | |
| 1242 { | 1239 { |
| 1243 setDntNotification(false); | 1240 setAcceptableAds(); |
| 1244 } | 1241 } |
| 1245 | 1242 else |
| 1246 delete subscriptionsMap[subscription.url]; | 1243 { |
| 1247 setAcceptableAds(); | 1244 collections.more.removeItem(subscription); |
| 1248 } | 1245 } |
| 1249 else | |
| 1250 { | |
| 1251 collections.custom.removeItem(subscription); | |
| 1252 delete subscriptionsMap[subscription.url]; | |
| 1253 } | 1246 } |
| 1254 collections.filterLists.removeItem(subscription); | 1247 collections.filterLists.removeItem(subscription); |
| 1255 break; | 1248 break; |
| 1256 } | 1249 } |
| 1257 | |
| 1258 updateShareLink(); | |
| 1259 } | 1250 } |
| 1260 | 1251 |
| 1261 function hidePref(key, value) | 1252 function hidePref(key, value) |
| 1262 { | 1253 { |
| 1263 let element = document.querySelector("[data-pref='" + key + "']"); | 1254 let element = document.querySelector("[data-pref='" + key + "']"); |
| 1264 if (element) | 1255 if (element) |
| 1265 element.setAttribute("aria-hidden", value); | 1256 element.setAttribute("aria-hidden", value); |
| 1266 } | 1257 } |
| 1267 | 1258 |
| 1268 function getPref(key, callback) | 1259 function getPref(key, callback) |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1307 case "notifications_showui": | 1298 case "notifications_showui": |
| 1308 hidePref("notifications_ignoredcategories", !value); | 1299 hidePref("notifications_ignoredcategories", !value); |
| 1309 break; | 1300 break; |
| 1310 } | 1301 } |
| 1311 | 1302 |
| 1312 let checkbox = document.querySelector( | 1303 let checkbox = document.querySelector( |
| 1313 "[data-pref='" + key + "'] button[role='checkbox']" | 1304 "[data-pref='" + key + "'] button[role='checkbox']" |
| 1314 ); | 1305 ); |
| 1315 if (checkbox) | 1306 if (checkbox) |
| 1316 checkbox.setAttribute("aria-checked", value); | 1307 checkbox.setAttribute("aria-checked", value); |
| 1317 } | |
| 1318 | |
| 1319 function updateShareLink() | |
| 1320 { | |
| 1321 let shareResources = [ | |
| 1322 "https://facebook.com/plugins/like.php?", | |
| 1323 "https://platform.twitter.com/widgets/", | |
| 1324 "https://apis.google.com/se/0/_/+1/fastbutton?" | |
| 1325 ]; | |
| 1326 let isAnyBlocked = false; | |
| 1327 let checksRemaining = shareResources.length; | |
| 1328 | |
| 1329 function onResult(isBlocked) | |
| 1330 { | |
| 1331 isAnyBlocked |= isBlocked; | |
| 1332 if (!--checksRemaining) | |
| 1333 { | |
| 1334 // Hide the share tab if a script on the share page would be blocked | |
| 1335 E("tab-share").hidden = isAnyBlocked; | |
| 1336 } | |
| 1337 } | |
| 1338 | |
| 1339 for (let sharedResource of shareResources) | |
| 1340 checkShareResource(sharedResource, onResult); | |
| 1341 } | 1308 } |
| 1342 | 1309 |
| 1343 function updateTooltips() | 1310 function updateTooltips() |
| 1344 { | 1311 { |
| 1345 let anchors = document.querySelectorAll(":not(.tooltip) > [data-tooltip]"); | 1312 let anchors = document.querySelectorAll(":not(.tooltip) > [data-tooltip]"); |
| 1346 for (let anchor of anchors) | 1313 for (let anchor of anchors) |
| 1347 { | 1314 { |
| 1348 let id = anchor.getAttribute("data-tooltip"); | 1315 let id = anchor.getAttribute("data-tooltip"); |
| 1349 | 1316 |
| 1350 let wrapper = document.createElement("div"); | 1317 let wrapper = document.createElement("div"); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1398 type: "app.listen", | 1365 type: "app.listen", |
| 1399 filter: ["addSubscription", "focusSection"] | 1366 filter: ["addSubscription", "focusSection"] |
| 1400 }); | 1367 }); |
| 1401 ext.backgroundPage.sendMessage({ | 1368 ext.backgroundPage.sendMessage({ |
| 1402 type: "filters.listen", | 1369 type: "filters.listen", |
| 1403 filter: ["added", "loaded", "removed"] | 1370 filter: ["added", "loaded", "removed"] |
| 1404 }); | 1371 }); |
| 1405 ext.backgroundPage.sendMessage({ | 1372 ext.backgroundPage.sendMessage({ |
| 1406 type: "prefs.listen", | 1373 type: "prefs.listen", |
| 1407 filter: ["notifications_ignoredcategories", "notifications_showui", | 1374 filter: ["notifications_ignoredcategories", "notifications_showui", |
| 1408 "show_devtools_panel", "shouldShowBlockElementMenu"] | 1375 "show_devtools_panel", "shouldShowBlockElementMenu", |
| 1376 "ui_warn_tracking"] | |
| 1409 }); | 1377 }); |
| 1410 ext.backgroundPage.sendMessage({ | 1378 ext.backgroundPage.sendMessage({ |
| 1411 type: "subscriptions.listen", | 1379 type: "subscriptions.listen", |
| 1412 filter: ["added", "disabled", "homepage", "lastDownload", "removed", | 1380 filter: ["added", "disabled", "homepage", "lastDownload", "removed", |
| 1413 "title", "downloadStatus", "downloading"] | 1381 "title", "downloadStatus", "downloading"] |
| 1414 }); | 1382 }); |
| 1415 | 1383 |
| 1416 window.addEventListener("DOMContentLoaded", onDOMLoaded, false); | 1384 window.addEventListener("DOMContentLoaded", onDOMLoaded, false); |
| 1417 window.addEventListener("hashchange", onHashChange, false); | 1385 window.addEventListener("hashchange", onHashChange, false); |
| 1418 } | 1386 } |
| LEFT | RIGHT |