diff options
Diffstat (limited to 'helpers/DATA/firefox/trisquel/extensions/spyblock@gnu.org/lib/ui.js')
-rw-r--r-- | helpers/DATA/firefox/trisquel/extensions/spyblock@gnu.org/lib/ui.js | 1973 |
1 files changed, 0 insertions, 1973 deletions
diff --git a/helpers/DATA/firefox/trisquel/extensions/spyblock@gnu.org/lib/ui.js b/helpers/DATA/firefox/trisquel/extensions/spyblock@gnu.org/lib/ui.js deleted file mode 100644 index 668e356..0000000 --- a/helpers/DATA/firefox/trisquel/extensions/spyblock@gnu.org/lib/ui.js +++ /dev/null @@ -1,1973 +0,0 @@ -/* - * This file is part of Adblock Plus <http://adblockplus.org/>, - * Copyright (C) 2006-2014 Eyeo GmbH - * - * Adblock Plus is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * Adblock Plus is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. - */ - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -let {Utils} = require("utils"); -let {Prefs} = require("prefs"); -let {Policy} = require("contentPolicy"); -let {FilterStorage} = require("filterStorage"); -let {FilterNotifier} = require("filterNotifier"); -let {RequestNotifier} = require("requestNotifier"); -let {Filter} = require("filterClasses"); -let {Subscription, SpecialSubscription, DownloadableSubscription} = require("subscriptionClasses"); -let {Synchronizer} = require("synchronizer"); -let {KeySelector} = require("keySelector"); -let {Notification} = require("notification"); -let {initAntiAdblockNotification} = require("antiadblockInit"); - -let CustomizableUI = null; - -/** - * Filter corresponding with "disable on site" menu item (set in fillIconMent()). - * @type Filter - */ -let siteWhitelist = null; -/** - * Filter corresponding with "disable on site" menu item (set in fillIconMenu()). - * @type Filter - */ -let pageWhitelist = null; - -/** - * Window containing the detached list of blockable items. - * @type Window - */ -let detachedBottombar = null; - -/** - * Object initializing add-on options, observes add-on manager notifications - * about add-on options being opened. - * @type nsIObserver - */ -let optionsObserver = -{ - init: function() - { - Services.obs.addObserver(this, "addon-options-displayed", true); - onShutdown.add(function() - { - Services.obs.removeObserver(this, "addon-options-displayed"); - }.bind(this)); - }, - - /** - * Initializes options in add-on manager when they show up. - */ - initOptionsDoc: function(/**Document*/ doc) - { - function hideElement(id, hide) - { - let element = doc.getElementById(id); - if (element) - element.collapsed = hide; - } - function setChecked(id, checked) - { - let element = doc.getElementById(id); - if (element) - element.value = checked; - } - function addCommandHandler(id, handler) - { - let element = doc.getElementById(id); - if (element) - element.addEventListener("command", handler, false); - } - - Utils.splitAllLabels(doc); - - addCommandHandler("adblockplus-filters", UI.openFiltersDialog.bind(UI)); - - let {Sync} = require("sync"); - let syncEngine = Sync.getEngine(); - hideElement("adblockplus-sync", !syncEngine); - - let {defaultToolbarPosition, statusbarPosition} = require("appSupport"); - let hasToolbar = defaultToolbarPosition; - let hasStatusBar = statusbarPosition; - - hideElement("adblockplus-showintoolbar", !hasToolbar); - hideElement("adblockplus-showinstatusbar", !hasStatusBar); - - let checkbox = doc.querySelector("setting[type=bool]"); - if (checkbox) - initCheckboxes(); - - function initCheckboxes() - { - if (!("value" in checkbox)) - { - // XBL bindings didn't apply yet (bug 708397), try later - Utils.runAsync(initCheckboxes); - return; - } - - setChecked("adblockplus-savestats", Prefs.savestats); - addCommandHandler("adblockplus-savestats", function() - { - UI.toggleSaveStats(doc.defaultView); - this.value = Prefs.savestats; - }); - - let hasAcceptableAds = FilterStorage.subscriptions.some((subscription) => subscription instanceof DownloadableSubscription && - subscription.url == Prefs.subscriptions_exceptionsurl); - setChecked("adblockplus-acceptableAds", hasAcceptableAds); - addCommandHandler("adblockplus-acceptableAds", function() - { - this.value = UI.toggleAcceptableAds(); - }); - - setChecked("adblockplus-sync", syncEngine && syncEngine.enabled); - addCommandHandler("adblockplus-sync", function() - { - this.value = UI.toggleSync(); - }); - - setChecked("adblockplus-showintoolbar", UI.isToolbarIconVisible()); - addCommandHandler("adblockplus-showintoolbar", function() - { - UI.toggleToolbarIcon(); - this.value = UI.isToolbarIconVisible(); - }); - - let list = doc.getElementById("adblockplus-subscription-list"); - if (list) - { - // Load subscriptions data - let request = new XMLHttpRequest(); - request.mozBackgroundRequest = true; - request.open("GET", "chrome://adblockplus/content/ui/subscriptions.xml"); - request.addEventListener("load", function() - { - if (onShutdown.done) - return; - - let currentSubscription = FilterStorage.subscriptions.filter((subscription) => subscription instanceof DownloadableSubscription && - subscription.url != Prefs.subscriptions_exceptionsurl); - currentSubscription = (currentSubscription.length ? currentSubscription[0] : null); - - let subscriptions =request.responseXML.getElementsByTagName("subscription"); - for (let i = 0; i < subscriptions.length; i++) - { - let item = subscriptions[i]; - let url = item.getAttribute("url"); - if (!url) - continue; - - list.appendItem(item.getAttribute("title"), url, null); - if (currentSubscription && url == currentSubscription.url) - list.selectedIndex = list.itemCount - 1; - - if (currentSubscription && list.selectedIndex < 0) - { - list.appendItem(currentSubscription.title, currentSubscription.url, null); - list.selectedIndex = list.itemCount - 1; - } - } - - var listener = function() - { - if (list.value) - UI.setSubscription(list.value, list.label); - } - list.addEventListener("command", listener, false); - - // xul:menulist in Fennec is broken and doesn't trigger any events - // on selection. Have to detect selectIndex changes instead. - // See https://bugzilla.mozilla.org/show_bug.cgi?id=891736 - list.watch("selectedIndex", function(prop, oldval, newval) - { - Utils.runAsync(listener); - return newval; - }); - }, false); - request.send(); - } - } - }, - - observe: function(subject, topic, data) - { - let {addonID} = require("info") - if (data != addonID) - return; - - this.initOptionsDoc(subject.QueryInterface(Ci.nsIDOMDocument)); - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]) -}; -optionsObserver.init(); - -/** - * Session restore observer instance, stored to prevent it from being garbage - * collected. - * @type SessionRestoreObserver - */ -let sessionRestoreObserver = null; - -/** - * Observer waiting for the browsing session to be restored on startup. - */ -function SessionRestoreObserver(/**function*/ callback) -{ - sessionRestoreObserver = this; - - this.callback = callback; - Services.obs.addObserver(this, "sessionstore-windows-restored", true); - - // Just in case, don't wait longer than 5 seconds - this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this.timer.init(this, 5000, Ci.nsITimer.TYPE_ONE_SHOT); -} -SessionRestoreObserver.prototype = -{ - callback: null, - timer: null, - observe: function(subject, topic, data) - { - Services.obs.removeObserver(this, "sessionstore-windows-restored"); - sessionRestoreObserver = null; - - this.timer.cancel(); - this.timer = null; - - if (!onShutdown.done) - this.callback(); - }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]) -} - -/** - * Timer used to delay notification handling. - * @type nsITimer - */ -let notificationTimer = null; - -let UI = exports.UI = -{ - /** - * Gets called on startup, initializes UI integration. - */ - init: function() - { - // We should call initDone once both overlay and filters are loaded - let overlayLoaded = false; - let filtersLoaded = false; - let sessionRestored = false; - - // Start loading overlay - let request = new XMLHttpRequest(); - request.mozBackgroundRequest = true; - request.open("GET", "chrome://adblockplus/content/ui/overlay.xul"); - request.addEventListener("load", function(event) - { - if (onShutdown.done) - return; - - this.processOverlay(request.responseXML.documentElement); - - // Don't wait for the rest of the startup sequence, add icon already - this.addToolbarButton(); - - overlayLoaded = true; - if (overlayLoaded && filtersLoaded && sessionRestored) - this.initDone(); - }.bind(this), false); - request.send(null); - - // Wait for filters to load - if (FilterStorage._loading) - { - let listener = function(action) - { - if (action != "load") - return; - - FilterNotifier.removeListener(listener); - filtersLoaded = true; - if (overlayLoaded && filtersLoaded && sessionRestored) - this.initDone(); - }.bind(this); - FilterNotifier.addListener(listener); - } - else - filtersLoaded = true; - - // Initialize UI after the session is restored - let window = this.currentWindow; - if (!window && "nsISessionStore" in Ci) - { - // No application windows yet, the application must be starting up. Wait - // for session to be restored before initializing our UI. - new SessionRestoreObserver(function() - { - sessionRestored = true; - if (overlayLoaded && filtersLoaded && sessionRestored) - this.initDone(); - }.bind(this)); - } - else - sessionRestored = true; - }, - - /** - * Provesses overlay document data and initializes overlay property. - */ - processOverlay: function(/**Element*/ root) - { - Utils.splitAllLabels(root); - - let specialElements = {"abp-status-popup": true, "abp-status": true, "abp-toolbarbutton": true, "abp-menuitem": true, "abp-bottombar-container": true}; - - this.overlay = {all: []}; - - // Remove whitespace text nodes - let walker = root.ownerDocument.createTreeWalker( - root, Ci.nsIDOMNodeFilter.SHOW_TEXT, - (node) => !/\S/.test(node.nodeValue), false - ); - let whitespaceNodes = []; - while (walker.nextNode()) - whitespaceNodes.push(walker.currentNode); - - for (let i = 0; i < whitespaceNodes.length; i++) - whitespaceNodes[i].parentNode.removeChild(whitespaceNodes[i]); - - // Put overlay elements into appropriate fields - while (root.firstElementChild) - { - let child = root.firstElementChild; - if (child.getAttribute("id") in specialElements) - this.overlay[child.getAttribute("id")] = child; - else - this.overlay.all.push(child); - root.removeChild(child); - } - - // Read overlay attributes - this.overlay.attributes = {}; - for (let i = 0; i < root.attributes.length; i++) - this.overlay.attributes[root.attributes[i].name] = root.attributes[i].value; - - // Copy context menu into the toolbar icon and Tools menu item - function fixId(element, newId) - { - if (element.hasAttribute("id")) - element.setAttribute("id", element.getAttribute("id").replace("abp-status", newId)); - - for (let i = 0, len = element.children.length; i < len; i++) - fixId(element.children[i], newId); - - return element; - } - - if ("abp-status-popup" in this.overlay) - { - let menuSource = this.overlay["abp-status-popup"]; - delete this.overlay["abp-status-popup"]; - - if (this.overlay.all.length) - this.overlay.all[0].appendChild(menuSource); - if ("abp-toolbarbutton" in this.overlay) - this.overlay["abp-toolbarbutton"].appendChild(fixId(menuSource.cloneNode(true), "abp-toolbar")); - if ("abp-menuitem" in this.overlay) - this.overlay["abp-menuitem"].appendChild(fixId(menuSource.cloneNode(true), "abp-menuitem")); - } - }, - - /** - * Gets called once the initialization is finished and Adblock Plus elements - * can be added to the UI. - */ - initDone: function() - { - // The icon might be added already, make sure its state is correct - this.updateState(); - - // Listen for pref and filters changes - Prefs.addListener(function(name) - { - if (name == "enabled" || name == "defaulttoolbaraction" || name == "defaultstatusbaraction") - this.updateState(); - else if (name == "showinstatusbar") - { - for (let window in this.applicationWindows) - this.updateStatusbarIcon(window); - } - }.bind(this)); - FilterNotifier.addListener(function(action) - { - if (/^(filter|subscription)\.(added|removed|disabled|updated)$/.test(action) || action == "load") - this.updateState(); - }.bind(this)); - - notificationTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - notificationTimer.initWithCallback(this.showNextNotification.bind(this), - 3 * 60 * 1000, Ci.nsITimer.TYPE_ONE_SHOT); - onShutdown.add(() => notificationTimer.cancel()); - - // Add "anti-adblock messages" notification - initAntiAdblockNotification(); - - let documentCreationObserver = { - observe: function(subject, topic, data) - { - if (!(subject instanceof Ci.nsIDOMWindow)) - return; - - this.showNextNotification(subject.location.href); - }.bind(UI) - }; - Services.obs.addObserver(documentCreationObserver, "content-document-global-created", false); - onShutdown.add(function() - { - Services.obs.removeObserver(documentCreationObserver, "content-document-global-created", false); - }); - - // Execute first-run actions if a window is open already, otherwise it - // will happen in applyToWindow() when a window is opened. - this.firstRunActions(this.currentWindow); - }, - - addToolbarButton: function() - { - let {WindowObserver} = require("windowObserver"); - new WindowObserver(this); - - let {defaultToolbarPosition} = require("appSupport"); - if ("abp-toolbarbutton" in this.overlay && defaultToolbarPosition) - { - try - { - ({CustomizableUI}) = Cu.import("resource:///modules/CustomizableUI.jsm", null); - } - catch (e) - { - // No built-in CustomizableUI API, use our own implementation. - ({CustomizableUI}) = require("customizableUI"); - } - - CustomizableUI.createWidget({ - id: "abp-toolbarbutton", - type: "custom", - positionAttribute: "abp-iconposition", // For emulation only - defaultArea: defaultToolbarPosition.parent, - defaultBefore: defaultToolbarPosition.before, // For emulation only - defaultAfter: defaultToolbarPosition.after, // For emulation only - removable: true, - onBuild: function(document) - { - let node = document.importNode(this.overlay["abp-toolbarbutton"], true); - node.addEventListener("click", this.onIconClick, false); - node.addEventListener("command", this.onIconClick, false); - this.updateIconState(document.defaultView, node); - return node; - }.bind(this), - onAdded: function(node) - { - // For emulation only, this callback isn't part of the official - // CustomizableUI API. - this.updateIconState(node.ownerDocument.defaultView, node); - }.bind(this), - }); - onShutdown.add(CustomizableUI.destroyWidget.bind(CustomizableUI, "abp-toolbarbutton")); - } - }, - - firstRunActions: function(window) - { - if (this.firstRunDone || !window || FilterStorage._loading) - return; - - this.firstRunDone = true; - - let {addonVersion} = require("info"); - let prevVersion = Prefs.currentVersion; - if (prevVersion != addonVersion) - { - Prefs.currentVersion = addonVersion; - this.addSubscription(window, prevVersion); - } - }, - - /** - * Will be set to true after the check whether first-run actions should run - * has been performed. - * @type Boolean - */ - firstRunDone: false, - - /** - * Initializes Adblock Plus UI in a window. - */ - applyToWindow: function(/**Window*/ window, /**Boolean*/ noDelay) - { - let {delayInitialization, isKnownWindow, getBrowser, addBrowserLocationListener, addBrowserClickListener} = require("appSupport"); - if (window.document.documentElement.id == "CustomizeToolbarWindow" || isKnownWindow(window)) - { - // Add style processing instruction - let style = window.document.createProcessingInstruction("xml-stylesheet", 'class="adblockplus-node" href="chrome://adblockplus/skin/overlay.css" type="text/css"'); - window.document.insertBefore(style, window.document.firstChild); - } - - if (!isKnownWindow(window)) - return; - - // Thunderbird windows will not be initialized at this point, execute - // delayed - if (!noDelay && delayInitialization) - { - Utils.runAsync(this.applyToWindow.bind(this, window, true)); - return; - } - - // Add general items to the document - for (let i = 0; i < this.overlay.all.length; i++) - window.document.documentElement.appendChild(this.overlay.all[i].cloneNode(true)); - - // Add status bar icon - this.updateStatusbarIcon(window); - - // Add tools menu item - if ("abp-menuitem" in this.overlay) - { - let {toolsMenu} = require("appSupport"); - let [parent, before] = this.resolveInsertionPoint(window, toolsMenu); - if (parent) - parent.insertBefore(this.overlay["abp-menuitem"].cloneNode(true), before); - } - - // Attach event handlers - for (let i = 0; i < eventHandlers.length; i++) - { - let [id, event, handler] = eventHandlers[i]; - let element = window.document.getElementById(id); - if (element) - element.addEventListener(event, handler.bind(null, window), false); - } - window.addEventListener("popupshowing", this.onPopupShowing, false); - window.addEventListener("keypress", this.onKeyPress, false); - - addBrowserLocationListener(window, function() - { - this.updateIconState(window, window.document.getElementById("abp-status")); - this.updateIconState(window, window.document.getElementById("abp-toolbarbutton")); - }.bind(this)); - addBrowserClickListener(window, this.onBrowserClick.bind(this, window)); - - window.document.getElementById("abp-notification-close").addEventListener("command", function(event) - { - window.document.getElementById("abp-notification").hidePopup(); - }, false); - - // First-run actions? - this.firstRunActions(window); - - // Some people actually switch off browser.frames.enabled and are surprised - // that things stop working... - window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell) - .allowSubframes = true; - }, - - /** - * Removes Adblock Plus UI from a window. - */ - removeFromWindow: function(/**Window*/ window) - { - let {isKnownWindow, removeBrowserLocationListeners, removeBrowserClickListeners} = require("appSupport"); - if (window.document.documentElement.id == "CustomizeToolbarWindow" || isKnownWindow(window)) - { - // Remove style processing instruction - for (let child = window.document.firstChild; child; child = child.nextSibling) - if (child.nodeType == child.PROCESSING_INSTRUCTION_NODE && child.data.indexOf("adblockplus-node") >= 0) - child.parentNode.removeChild(child); - } - - if (!isKnownWindow(window)) - return; - - for (let id in this.overlay) - { - if (id == "all") - { - let list = this.overlay[id]; - for (let i = 0; i < list.length; i++) - { - let clone = window.document.getElementById(list[i].getAttribute("id")); - if (clone) - clone.parentNode.removeChild(clone); - } - } - else - { - let clone = window.document.getElementById(id); - if (clone) - clone.parentNode.removeChild(clone); - } - } - - window.removeEventListener("popupshowing", this.onPopupShowing, false); - window.removeEventListener("keypress", this.onKeyPress, false); - removeBrowserLocationListeners(window); - removeBrowserClickListeners(window); - }, - - /** - * The overlay information to be used when adding elements to the UI. - * @type Object - */ - overlay: null, - - /** - * Iterator for application windows that Adblock Plus should apply to. - * @type Iterator - */ - get applicationWindows() - { - let {isKnownWindow} = require("appSupport"); - - let enumerator = Services.wm.getZOrderDOMWindowEnumerator(null, true); - if (!enumerator.hasMoreElements()) - { - // On Linux the list returned will be empty, see bug 156333. Fall back to random order. - enumerator = Services.wm.getEnumerator(null); - } - while (enumerator.hasMoreElements()) - { - let window = enumerator.getNext().QueryInterface(Ci.nsIDOMWindow); - if (isKnownWindow(window)) - yield window; - } - }, - - /** - * Returns the top-most application window or null if none exists. - * @type Window - */ - get currentWindow() - { - for (let window of this.applicationWindows) - return window; - return null; - }, - - /** - * Opens a URL in the browser window. If browser window isn't passed as parameter, - * this function attempts to find a browser window. If an event is passed in - * it should be passed in to the browser if possible (will e.g. open a tab in - * background depending on modifiers keys). - */ - loadInBrowser: function(/**String*/ url, /**Window*/ currentWindow, /**Event*/ event) - { - if (!currentWindow) - currentWindow = this.currentWindow; - - let {addTab} = require("appSupport"); - if (currentWindow && addTab) - addTab(currentWindow, url, event); - else - { - let protocolService = Cc["@mozilla.org/uriloader/external-protocol-service;1"].getService(Ci.nsIExternalProtocolService); - protocolService.loadURI(Services.io.newURI(url, null, null), null); - } - }, - - /** - * Opens a pre-defined documentation link in the browser window. This will - * send the UI language to adblockplus.org so that the correct language - * version of the page can be selected. - */ - loadDocLink: function(/**String*/ linkID, /**Window*/ window) - { - let link = Utils.getDocLink(linkID); - this.loadInBrowser(link, window); - }, - - - /** - * Brings up the filter composer dialog to block an item. - */ - blockItem: function(/**Window*/ window, /**Node*/ node, /**RequestEntry*/ item) - { - if (!item) - return; - - window.openDialog("chrome://adblockplus/content/ui/composer.xul", "_blank", "chrome,centerscreen,resizable,dialog=no,dependent", [node], item); - }, - - /** - * Opens filter preferences dialog or focuses an already open dialog. - * @param {Filter} [filter] filter to be selected - */ - openFiltersDialog: function(filter) - { - let existing = Services.wm.getMostRecentWindow("abp:filters"); - if (existing) - { - try - { - existing.focus(); - } catch (e) {} - if (filter) - existing.SubscriptionActions.selectFilter(filter); - } - else - { - Services.ww.openWindow(null, "chrome://adblockplus/content/ui/filters.xul", "_blank", "chrome,centerscreen,resizable,dialog=no", {wrappedJSObject: filter}); - } - }, - - /** - * Opens report wizard for the current page. - */ - openReportDialog: function(/**Window*/ window) - { - let wnd = Services.wm.getMostRecentWindow("abp:sendReport"); - if (wnd) - wnd.focus(); - else - { - let uri = this.getCurrentLocation(window); - if (uri) - { - let {getBrowser} = require("appSupport"); - window.openDialog("chrome://adblockplus/content/ui/sendReport.xul", "_blank", "chrome,centerscreen,resizable=no", getBrowser(window).contentWindow, uri); - } - } - }, - - /** - * Opens our contribution page. - */ - openContributePage: function(/**Window*/ window) - { - this.loadDocLink("contribute", window); - }, - - /** - * Executed on first run, adds a filter subscription and notifies that user - * about that. - */ - addSubscription: function(/**Window*/ window, /**String*/ prevVersion) - { - // Add "acceptable ads" subscription for new users and user updating from old ABP versions. - // Don't add it for users of privacy subscriptions (use a hardcoded list for now). - let addAcceptable = (Services.vc.compare(prevVersion, "2.0") < 0); - let privacySubscriptions = { - "https://easylist-downloads.adblockplus.org/easyprivacy+easylist.txt": true, - "https://easylist-downloads.adblockplus.org/easyprivacy.txt": true, - "https://secure.fanboy.co.nz/fanboy-tracking.txt": true, - "https://fanboy-adblock-list.googlecode.com/hg/fanboy-adblocklist-stats.txt": true, - "https://bitbucket.org/fanboy/fanboyadblock/raw/tip/fanboy-adblocklist-stats.txt": true, - "https://hg01.codeplex.com/fanboyadblock/raw-file/tip/fanboy-adblocklist-stats.txt": true, - "https://adversity.googlecode.com/hg/Adversity-Tracking.txt": true - }; - if (FilterStorage.subscriptions.some((subscription) => subscription.url == Prefs.subscriptions_exceptionsurl || subscription.url in privacySubscriptions)) - addAcceptable = false; - - // Don't add subscription if the user has a subscription already - let addSubscription = true; - //if (FilterStorage.subscriptions.some((subscription) => subscription instanceof DownloadableSubscription && subscription.url != Prefs.subscriptions_exceptionsurl)) - addSubscription = false; - - // If this isn't the first run, only add subscription if the user has no custom filters - if (addSubscription && Services.vc.compare(prevVersion, "0.0") > 0) - { - if (FilterStorage.subscriptions.some((subscription) => subscription.url != Prefs.subscriptions_exceptionsurl && subscription.filters.length)) - addSubscription = false; - } - - // Add "acceptable ads" subscription - if (false) - { - let subscription = Subscription.fromURL(Prefs.subscriptions_exceptionsurl); - if (subscription) - { - subscription.title = "Allow non-intrusive advertising"; - FilterStorage.addSubscription(subscription); - if (subscription instanceof DownloadableSubscription && !subscription.lastDownload) - Synchronizer.execute(subscription); - } - else - addAcceptable = false; - } - - /* Add "anti-adblock messages" subscription for new users and users updating from old ABP versions - if (Services.vc.compare(prevVersion, "2.5") < 0) - { - let subscription = Subscription.fromURL(Prefs.subscriptions_antiadblockurl); - if (subscription && !(subscription.url in FilterStorage.knownSubscriptions)) - { - subscription.disabled = true; - FilterStorage.addSubscription(subscription); - if (subscription instanceof DownloadableSubscription && !subscription.lastDownload) - Synchronizer.execute(subscription); - } - }*/ - - // Extra subsriptions - let subscription = Subscription.fromURL("http://gnuzilla.gnu.org/filters/blacklist.txt"); - subscription.disabled = false; - FilterStorage.addSubscription(subscription); - Synchronizer.execute(subscription); - - let subscription = Subscription.fromURL("http://gnuzilla.gnu.org/filters/third-party.txt"); - subscription.disabled = false; - FilterStorage.addSubscription(subscription); - Synchronizer.execute(subscription); - - let subscription = Subscription.fromURL("http://gnuzilla.gnu.org/filters/javascript.txt"); - subscription.disabled = true; - FilterStorage.addSubscription(subscription); - Synchronizer.execute(subscription); - - if (!addSubscription && !addAcceptable) - return; - - function notifyUser() - {return; - let {addTab} = require("appSupport"); - if (addTab) - { - addTab(window, "chrome://adblockplus/content/ui/firstRun.html"); - } - else - { - let dialogSource = '\ - <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>\ - <dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="document.title=content.document.title" buttons="accept" width="500" height="600">\ - <iframe type="content-primary" flex="1" src="chrome://adblockplus/content/ui/firstRun.html"/>\ - </dialog>'; - Services.ww.openWindow(window, - "data:application/vnd.mozilla.xul+xml," + encodeURIComponent(dialogSource), - "_blank", "chrome,centerscreen,resizable,dialog=no", null); - } - } - - if (addSubscription) - { - // Load subscriptions data - let request = new XMLHttpRequest(); - request.mozBackgroundRequest = true; - request.open("GET", "chrome://adblockplus/content/ui/subscriptions.xml"); - request.addEventListener("load", function() - { - if (onShutdown.done) - return; - - let node = Utils.chooseFilterSubscription(request.responseXML.getElementsByTagName("subscription")); - let subscription = (node ? Subscription.fromURL(node.getAttribute("url")) : null); - if (subscription) - { - FilterStorage.addSubscription(subscription); - subscription.disabled = false; - subscription.title = node.getAttribute("title"); - subscription.homepage = node.getAttribute("homepage"); - if (subscription instanceof DownloadableSubscription && !subscription.lastDownload) - Synchronizer.execute(subscription); - - notifyUser(); - } - }, false); - request.send(); - } - else - notifyUser(); - }, - - /** - * Handles clicks inside the browser's content area, will intercept clicks on - * abp: links. This can be called either with an event object or with the link - * target (if it is the former then link target will be retrieved from event - * target). - */ - onBrowserClick: function (/**Window*/ window, /**Event*/ event, /**String*/ linkTarget) - { - if (event) - { - // Ignore right-clicks - if (event.button == 2) - return; - - // Search the link associated with the click - let link = event.target; - while (link && !(link instanceof Ci.nsIDOMHTMLAnchorElement)) - link = link.parentNode; - - if (!link || link.protocol != "abp:") - return; - - // This is our link - make sure the browser doesn't handle it - event.preventDefault(); - event.stopPropagation(); - - linkTarget = link.href; - } - - let match = /^abp:\/*subscribe\/*\?(.*)/i.exec(linkTarget); - if (!match) - return; - - // Decode URL parameters - let title = null; - let url = null; - let mainSubscriptionTitle = null; - let mainSubscriptionURL = null; - for (let param of match[1].split('&')) - { - let parts = param.split("=", 2); - if (parts.length != 2 || !/\S/.test(parts[1])) - continue; - switch (parts[0]) - { - case "title": - title = decodeURIComponent(parts[1]); - break; - case "location": - url = decodeURIComponent(parts[1]); - break; - case "requiresTitle": - mainSubscriptionTitle = decodeURIComponent(parts[1]); - break; - case "requiresLocation": - mainSubscriptionURL = decodeURIComponent(parts[1]); - break; - } - } - if (!url) - return; - - // Default title to the URL - if (!title) - title = url; - - // Main subscription needs both title and URL - if (mainSubscriptionTitle && !mainSubscriptionURL) - mainSubscriptionTitle = null; - if (mainSubscriptionURL && !mainSubscriptionTitle) - mainSubscriptionURL = null; - - // Trim spaces in title and URL - title = title.replace(/^\s+/, "").replace(/\s+$/, ""); - url = url.replace(/^\s+/, "").replace(/\s+$/, ""); - if (mainSubscriptionURL) - { - mainSubscriptionTitle = mainSubscriptionTitle.replace(/^\s+/, "").replace(/\s+$/, ""); - mainSubscriptionURL = mainSubscriptionURL.replace(/^\s+/, "").replace(/\s+$/, ""); - } - - // Verify that the URL is valid - url = Utils.makeURI(url); - if (!url || (url.scheme != "http" && url.scheme != "https" && url.scheme != "ftp")) - return; - url = url.spec; - - if (mainSubscriptionURL) - { - mainSubscriptionURL = Utils.makeURI(mainSubscriptionURL); - if (!mainSubscriptionURL || (mainSubscriptionURL.scheme != "http" && mainSubscriptionURL.scheme != "https" && mainSubscriptionURL.scheme != "ftp")) - mainSubscriptionURL = mainSubscriptionTitle = null; - else - mainSubscriptionURL = mainSubscriptionURL.spec; - } - - this.openSubscriptionDialog(window, url, title, mainSubscriptionURL, mainSubscriptionTitle); - }, - - /** - * Opens a dialog letting the user confirm/adjust a filter subscription to - * be added. - */ - openSubscriptionDialog: function(/**Window*/ window, /**String*/ url, /**String*/ title, /**String*/ mainURL, /**String*/ mainTitle) - { - let subscription = {url: url, title: title, disabled: false, external: false, - mainSubscriptionTitle: mainTitle, mainSubscriptionURL: mainURL}; - window.openDialog("chrome://adblockplus/content/ui/subscriptionSelection.xul", "_blank", - "chrome,centerscreen,resizable,dialog=no", subscription, null); - }, - - /** - * Retrieves the current location of the browser. - */ - getCurrentLocation: function(/**Window*/ window) /**nsIURI*/ - { - let {getCurrentLocation} = require("appSupport"); - let result = getCurrentLocation(window); - return (result ? Utils.unwrapURL(result) : null); - }, - - /** - * Looks up an element with given ID in the window. If a list of IDs is given - * will try all of them until an element exists. - */ - findElement: function(/**Window*/ window, /**String|String[]*/ id) /**Element*/ - { - if (id instanceof Array) - { - for (let candidate of id) - { - let result = window.document.getElementById(candidate); - if (result) - return result; - } - return null; - } - else - return window.document.getElementById(id); - }, - - /** - * Resolves an insertion point as specified in appSupport module. Returns - * two elements: the parent element and the element to insert before. - */ - resolveInsertionPoint: function(/**Window*/ window, /**Object*/ insertionPoint) /**Element[]*/ - { - let parent = null; - let before = null; - if (insertionPoint) - { - if ("parent" in insertionPoint) - parent = this.findElement(window, insertionPoint.parent); - - if (parent && "before" in insertionPoint) - before = this.findElement(window, insertionPoint.before); - - if (parent && !before && "after" in insertionPoint) - { - let after = this.findElement(window, insertionPoint.after); - if (after) - before = after.nextElementSibling; - } - - if (before && before.parentNode != parent) - before = null; - } - - return [parent, before]; - }, - - /** - * Toggles visibility state of the toolbar icon. - */ - toggleToolbarIcon: function() - { - if (!CustomizableUI) - return; - if (this.isToolbarIconVisible()) - CustomizableUI.removeWidgetFromArea("abp-toolbarbutton"); - else - { - let {defaultToolbarPosition} = require("appSupport"); - CustomizableUI.addWidgetToArea("abp-toolbarbutton", defaultToolbarPosition.parent); - } - }, - - /** - * Updates Adblock Plus icon state for all windows. - */ - updateState: function() - { - for (let window in this.applicationWindows) - { - this.updateIconState(window, window.document.getElementById("abp-status")); - this.updateIconState(window, window.document.getElementById("abp-toolbarbutton")); - } - }, - - /** - * Updates Adblock Plus icon state for a single application window. - */ - updateIconState: function(/**Window*/ window, /**Element*/ icon) - { - if (!icon) - return; - - let state = (Prefs.enabled ? "active" : "disabled"); - if (state == "active") - { - let location = this.getCurrentLocation(window); - if (location && Policy.isWhitelisted(location.spec)) - state = "whitelisted"; - } - - let popupId = "abp-status-popup"; - if (icon.localName == "statusbarpanel") - { - if (Prefs.defaultstatusbaraction == 0) - { - icon.setAttribute("popup", popupId); - icon.removeAttribute("context"); - } - else - { - icon.removeAttribute("popup"); - icon.setAttribute("context", popupId); - } - } - else - { - if (Prefs.defaulttoolbaraction == 0) - { - icon.setAttribute("type", "menu"); - icon.removeAttribute("context"); - } - else - { - icon.setAttribute("type", "menu-button"); - icon.setAttribute("context", popupId); - } - } - - icon.setAttribute("abpstate", state); - }, - - /** - * Shows or hides status bar icons in all windows, according to pref. - */ - updateStatusbarIcon: function(/**Window*/ window) - { - if (!("abp-status" in this.overlay)) - return; - - let {statusbarPosition} = require("appSupport"); - if (!statusbarPosition) - return; - - let icon = window.document.getElementById("abp-status"); - if (Prefs.showinstatusbar && !icon) - { - let [parent, before] = this.resolveInsertionPoint(window, statusbarPosition); - if (!parent) - return; - - parent.insertBefore(this.overlay["abp-status"].cloneNode(true), before); - - icon = window.document.getElementById("abp-status"); - this.updateIconState(window, icon); - icon.addEventListener("click", this.onIconClick, false); - } - else if (!Prefs.showinstatusbar && icon) - icon.parentNode.removeChild(icon); - }, - - /** - * Toggles the value of a boolean preference. - */ - togglePref: function(/**String*/ pref) - { - Prefs[pref] = !Prefs[pref]; - }, - - /** - * If the given filter is already in user's list, removes it from the list. Otherwise adds it. - */ - toggleFilter: function(/**Filter*/ filter) - { - if (filter.subscriptions.length) - { - if (filter.disabled || filter.subscriptions.some((subscription) => !(subscription instanceof SpecialSubscription))) - filter.disabled = !filter.disabled; - else - FilterStorage.removeFilter(filter); - } - else - FilterStorage.addFilter(filter); - }, - - - /** - * Toggles "Count filter hits" option. - */ - toggleSaveStats: function(window) - { - if (Prefs.savestats) - { - if (!Utils.confirm(window, Utils.getString("clearStats_warning"))) - return; - - FilterStorage.resetHitCounts(); - Prefs.savestats = false; - } - else - Prefs.savestats = true; - }, - - /** - * Sets the current filter subscription in a single-subscription scenario, - * all other subscriptions will be removed. - */ - setSubscription: function(url, title) - { - let subscription = Subscription.fromURL(url); - let currentSubscriptions = FilterStorage.subscriptions.filter( - ((subscription) => subscription instanceof DownloadableSubscription && subscription.url != Prefs.subscriptions_exceptionsurl) - ); - if (!subscription || currentSubscriptions.indexOf(subscription) >= 0) - return; - - for (let i = 0; i < currentSubscriptions.length; i++) - FilterStorage.removeSubscription(currentSubscriptions[i]); - - subscription.title = title; - FilterStorage.addSubscription(subscription); - if (subscription instanceof DownloadableSubscription && !subscription.lastDownload) - Synchronizer.execute(subscription); - }, - - /** - * Adds or removes "non-intrisive ads" filter list. - * @return {Boolean} true if the filter list has been added - **/ - toggleAcceptableAds: function() - { - let subscription = Subscription.fromURL(Prefs.subscriptions_exceptionsurl); - if (!subscription) - return false; - - subscription.disabled = false; - subscription.title = "Allow non-intrusive advertising"; - if (subscription.url in FilterStorage.knownSubscriptions) - FilterStorage.removeSubscription(subscription); - else - { - FilterStorage.addSubscription(subscription); - if (subscription instanceof DownloadableSubscription && !subscription.lastDownload) - Synchronizer.execute(subscription); - } - - return (subscription.url in FilterStorage.knownSubscriptions); - }, - - /** - * Toggles the pref for the Adblock Plus sync engine. - * @return {Boolean} new state of the sync engine - */ - toggleSync: function() - { - let {Sync} = require("sync"); - let syncEngine = Sync.getEngine(); - if (syncEngine) - { - syncEngine.enabled = !syncEngine.enabled; - return syncEngine.enabled; - } - else - return false; - }, - - /** - * Tests whether blockable items list is currently open. - */ - isBottombarOpen: function(/**Window*/ window) /**Boolean*/ - { - if (detachedBottombar && !detachedBottombar.closed) - return true; - - return !!window.document.getElementById("abp-bottombar"); - }, - - /** - * Called when some pop-up in the application window shows up, initializes - * pop-ups related to Adblock Plus. - */ - onPopupShowing: function(/**Event*/ event) - { - if (event.defaultPrevented) - return; - - let popup = event.originalTarget; - - let {contentContextMenu} = require("appSupport"); - if ((typeof contentContextMenu == "string" && popup.id == contentContextMenu) || - (contentContextMenu instanceof Array && contentContextMenu.indexOf(popup.id) >= 0)) - { - this.fillContentContextMenu(popup); - } - else if (popup.id == "abp-tooltip") - this.fillIconTooltip(event, popup.ownerDocument.defaultView); - else - { - let match = /^(abp-(?:toolbar|status|menuitem)-)popup$/.exec(popup.id); - if (match) - this.fillIconMenu(event, popup.ownerDocument.defaultView, match[1]); - } - }, - - /** - * Handles click on toolbar and status bar icons. - */ - onIconClick: function(/**Event*/ event) - { - if (event.eventPhase != event.AT_TARGET) - return; - - let isToolbar = (event.target.localName != "statusbarpanel"); - let action = 0; - if ((isToolbar && event.type == "command") || (!isToolbar && event.button == 0)) - action = (isToolbar ? Prefs.defaulttoolbaraction : Prefs.defaultstatusbaraction); - else if (event.button == 1) - action = 3; - - let window = event.target.ownerDocument.defaultView; - if (action == 1) - this.toggleBottombar(window); - else if (action == 2) - this.openFiltersDialog(); - else if (action == 3) - { - // If there is a whitelisting rule for current page - remove it (reenable). - // Otherwise flip "enabled" pref. - if (!this.removeWhitelist(window)) - this.togglePref("enabled"); - } - }, - - /** - * Removes/disables the exception rule applying for the current page. - */ - removeWhitelist: function(/**Window*/ window) - { - let location = this.getCurrentLocation(window); - let filter = null; - if (location) - filter = Policy.isWhitelisted(location.spec); - if (filter && filter.subscriptions.length && !filter.disabled) - { - UI.toggleFilter(filter); - return true; - } - return false; - }, - - /** - * Updates state of the icon tooltip. - */ - fillIconTooltip: function(/**Event*/ event, /**Window*/ window) - { - let E = (id) => window.document.getElementById(id); - - let node = window.document.tooltipNode; - if (!node || !node.hasAttribute("tooltip")) - { - event.preventDefault(); - return; - } - - // Prevent tooltip from overlapping menu - for (let id of ["abp-toolbar-popup", "abp-status-popup"]) - { - let element = E(id); - if (element && element.state == "open") - { - event.preventDefault(); - return; - } - } - - let type = (node.id == "abp-toolbarbutton" ? "toolbar" : "statusbar"); - let action = parseInt(Prefs["default" + type + "action"]); - if (isNaN(action)) - action = -1; - - let actionDescr = E("abp-tooltip-action"); - actionDescr.hidden = (action < 0 || action > 3); - if (!actionDescr.hidden) - actionDescr.setAttribute("value", Utils.getString("action" + action + "_tooltip")); - - let statusDescr = E("abp-tooltip-status"); - let state = node.getAttribute("abpstate"); - let statusStr = Utils.getString(state + "_tooltip"); - if (state == "active") - { - let [activeSubscriptions, activeFilters] = FilterStorage.subscriptions.reduce(function([subscriptions, filters], current) - { - if (current instanceof SpecialSubscription) - return [subscriptions, filters + current.filters.filter((filter) => !filter.disabled).length]; - else if (!current.disabled && !(Prefs.subscriptions_exceptionscheckbox && current.url == Prefs.subscriptions_exceptionsurl)) - return [subscriptions + 1, filters]; - else - return [subscriptions, filters] - }, [0, 0]); - - statusStr = statusStr.replace(/\?1\?/, activeSubscriptions).replace(/\?2\?/, activeFilters); - } - statusDescr.setAttribute("value", statusStr); - - let activeFilters = []; - E("abp-tooltip-blocked-label").hidden = (state != "active"); - E("abp-tooltip-blocked").hidden = (state != "active"); - if (state == "active") - { - let {getBrowser} = require("appSupport"); - let stats = RequestNotifier.getWindowStatistics(getBrowser(window).contentWindow); - - let blockedStr = Utils.getString("blocked_count_tooltip"); - blockedStr = blockedStr.replace(/\?1\?/, stats ? stats.blocked : 0).replace(/\?2\?/, stats ? stats.items : 0); - - if (stats && stats.whitelisted + stats.hidden) - { - blockedStr += " " + Utils.getString("blocked_count_addendum"); - blockedStr = blockedStr.replace(/\?1\?/, stats.whitelisted).replace(/\?2\?/, stats.hidden); - } - - E("abp-tooltip-blocked").setAttribute("value", blockedStr); - - if (stats) - { - let filterSort = function(a, b) - { - return stats.filters[b] - stats.filters[a]; - }; - for (let filter in stats.filters) - activeFilters.push(filter); - activeFilters = activeFilters.sort(filterSort); - } - - if (activeFilters.length > 0) - { - let filtersContainer = E("abp-tooltip-filters"); - while (filtersContainer.firstChild) - filtersContainer.removeChild(filtersContainer.firstChild); - - for (let i = 0; i < activeFilters.length && i < 3; i++) - { - let descr = filtersContainer.ownerDocument.createElement("description"); - descr.setAttribute("value", activeFilters[i] + " (" + stats.filters[activeFilters[i]] + ")"); - filtersContainer.appendChild(descr); - } - } - } - - E("abp-tooltip-filters-label").hidden = (activeFilters.length == 0); - E("abp-tooltip-filters").hidden = (activeFilters.length == 0); - E("abp-tooltip-more-filters").hidden = (activeFilters.length <= 3); - }, - - /** - * Updates state of the icon context menu. - */ - fillIconMenu: function(/**Event*/ event, /**Window*/ window, /**String*/ prefix) - { - function hideElement(id, hide) - { - let element = window.document.getElementById(id); - if (element) - element.hidden = hide; - } - function setChecked(id, checked) - { - let element = window.document.getElementById(id); - if (element) - element.setAttribute("checked", checked); - } - function setDisabled(id, disabled) - { - let element = window.document.getElementById(id); - if (element) - element.setAttribute("disabled", disabled); - } - function setDefault(id, isDefault) - { - let element = window.document.getElementById(id); - if (element) - element.setAttribute("default", isDefault); - } - function generateLabel(id, param) - { - let element = window.document.getElementById(id); - if (element) - element.setAttribute("label", element.getAttribute("labeltempl").replace(/\?1\?/, param)); - } - - let bottombarOpen = this.isBottombarOpen(window); - hideElement(prefix + "openbottombar", bottombarOpen); - hideElement(prefix + "closebottombar", !bottombarOpen); - - hideElement(prefix + "whitelistsite", true); - hideElement(prefix + "whitelistpage", true); - - let location = this.getCurrentLocation(window); - if (location && Policy.isBlockableScheme(location)) - { - let host = null; - try - { - host = location.host.replace(/^www\./, ""); - } catch (e) {} - - if (host) - { - let ending = "|"; - location = location.clone(); - if (location instanceof Ci.nsIURL) - location.ref = ""; - if (location instanceof Ci.nsIURL && location.query) - { - location.query = ""; - ending = "?"; - } - - siteWhitelist = Filter.fromText("@@||" + host + "^$document"); - setChecked(prefix + "whitelistsite", siteWhitelist.subscriptions.length && !siteWhitelist.disabled); - generateLabel(prefix + "whitelistsite", host); - hideElement(prefix + "whitelistsite", false); - - pageWhitelist = Filter.fromText("@@|" + location.spec + ending + "$document"); - setChecked(prefix + "whitelistpage", pageWhitelist.subscriptions.length && !pageWhitelist.disabled); - hideElement(prefix + "whitelistpage", false); - } - else - { - siteWhitelist = Filter.fromText("@@|" + location.spec + "|"); - setChecked(prefix + "whitelistsite", siteWhitelist.subscriptions.length && !siteWhitelist.disabled); - generateLabel(prefix + "whitelistsite", location.spec.replace(/^mailto:/, "")); - hideElement(prefix + "whitelistsite", false); - } - } - - setDisabled("abp-command-sendReport", !location || !Policy.isBlockableScheme(location) || location.scheme == "mailto"); - - setChecked(prefix + "disabled", !Prefs.enabled); - setChecked(prefix + "frameobjects", Prefs.frameobjects); - setChecked(prefix + "slowcollapse", !Prefs.fastcollapse); - setChecked(prefix + "savestats", Prefs.savestats); - - let {defaultToolbarPosition, statusbarPosition} = require("appSupport"); - let hasToolbar = defaultToolbarPosition; - let hasStatusBar = statusbarPosition; - hideElement(prefix + "showintoolbar", !hasToolbar || prefix == "abp-toolbar-"); - hideElement(prefix + "showinstatusbar", !hasStatusBar); - hideElement(prefix + "iconSettingsSeparator", (prefix == "abp-toolbar-" || !hasToolbar) && !hasStatusBar); - - setChecked(prefix + "showintoolbar", this.isToolbarIconVisible()); - setChecked(prefix + "showinstatusbar", Prefs.showinstatusbar); - - let {Sync} = require("sync"); - let syncEngine = Sync.getEngine(); - hideElement(prefix + "sync", !syncEngine); - setChecked(prefix + "sync", syncEngine && syncEngine.enabled); - - let defAction = (!window.document.popupNode || window.document.popupNode.id == "abp-toolbarbutton" ? - Prefs.defaulttoolbaraction : - Prefs.defaultstatusbaraction); - setDefault(prefix + "openbottombar", defAction == 1); - setDefault(prefix + "closebottombar", defAction == 1); - setDefault(prefix + "filters", defAction == 2); - setDefault(prefix + "disabled", defAction == 3); - - let popup = window.document.getElementById(prefix + "popup"); - let items = (popup ? popup.querySelectorAll('menuitem[key]') : []); - for (let i = 0; i < items.length; i++) - { - let item = items[i]; - let match = /^abp-key-/.exec(item.getAttribute("key")); - if (!match) - continue; - - let name = match.input.substr(match.index + match[0].length); - if (!this.hotkeys) - this.configureKeys(window); - if (name in this.hotkeys) - { - let text = KeySelector.getTextForKey(this.hotkeys[name]); - if (text) - item.setAttribute("acceltext", text); - else - item.removeAttribute("acceltext"); - } - } - - hideElement(prefix + "contributebutton", Prefs.hideContributeButton); - }, - - /** - * Adds Adblock Plus menu items to the content area context menu when it shows - * up. - */ - fillContentContextMenu: function(/**Element*/ popup) - { - let target = popup.triggerNode; - if (target instanceof Ci.nsIDOMHTMLMapElement || target instanceof Ci.nsIDOMHTMLAreaElement) - { - // HTML image maps will usually receive events when the mouse pointer is - // over a different element, get the real event target. - let rect = target.getClientRects()[0]; - target = target.ownerDocument.elementFromPoint(Math.max(rect.left, 0), Math.max(rect.top, 0)); - } - - if (!target) - return; - - let window = popup.ownerDocument.defaultView; - let menuItems = []; - let addMenuItem = function([node, nodeData]) - { - let type = nodeData.typeDescr.toLowerCase(); - if (type == "background") - { - type = "image"; - node = null; - } - - let label = this.overlay.attributes[type + "contextlabel"]; - if (!label) - return; - - let item = popup.ownerDocument.createElement("menuitem"); - item.setAttribute("label", label); - item.setAttribute("class", "abp-contextmenuitem"); - item.addEventListener("command", this.blockItem.bind(this, window, node, nodeData), false); - popup.appendChild(item); - - menuItems.push(item); - }.bind(this); - - // Look up data that we have for the node - let data = RequestNotifier.getDataForNode(target); - let hadImage = false; - if (data && !data[1].filter) - { - addMenuItem(data); - hadImage = (data[1].typeDescr == "IMAGE"); - } - - // Look for frame data - let wnd = Utils.getWindow(target); - if (wnd.frameElement) - { - let data = RequestNotifier.getDataForNode(wnd.frameElement, true); - if (data && !data[1].filter) - addMenuItem(data); - } - - // Look for a background image - if (!hadImage) - { - let extractImageURL = function(computedStyle, property) - { - let value = computedStyle.getPropertyCSSValue(property); - // CSSValueList - if ("length" in value && value.length >= 1) - value = value[0]; - // CSSValuePrimitiveType - if ("primitiveType" in value && value.primitiveType == value.CSS_URI) - return Utils.unwrapURL(value.getStringValue()).spec; - - return null; - }; - - let node = target; - while (node) - { - if (node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) - { - let style = wnd.getComputedStyle(node, ""); - let bgImage = extractImageURL(style, "background-image") || extractImageURL(style, "list-style-image"); - if (bgImage) - { - let data = RequestNotifier.getDataForNode(wnd.document, true, Policy.type.IMAGE, bgImage); - if (data && !data[1].filter) - { - addMenuItem(data); - break; - } - } - } - - node = node.parentNode; - } - } - - // Add "Remove exception" menu item if necessary - let location = this.getCurrentLocation(window); - let filter = (location ? Policy.isWhitelisted(location.spec) : null); - if (filter && filter.subscriptions.length && !filter.disabled) - { - let label = this.overlay.attributes.whitelistcontextlabel; - if (!label) - return; - - let item = popup.ownerDocument.createElement("menuitem"); - item.setAttribute("label", label); - item.setAttribute("class", "abp-contextmenuitem"); - item.addEventListener("command", this.toggleFilter.bind(this, filter), false); - popup.appendChild(item); - - menuItems.push(item); - } - - // Make sure to clean up everything once the context menu is closed - if (menuItems.length) - { - let cleanUp = function(event) - { - if (event.eventPhase != event.AT_TARGET) - return; - - popup.removeEventListener("popuphidden", cleanUp, false); - for (let i = 0; i < menuItems.length; i++) - if (menuItems[i].parentNode) - menuItems[i].parentNode.removeChild(menuItems[i]); - }.bind(this); - popup.addEventListener("popuphidden", cleanUp, false); - } - }, - - /** - * Called when the user presses a key in the application window, reacts to our - * shortcut keys. - */ - onKeyPress: function(/**Event*/ event) - { - if (!this.hotkeys) - this.configureKeys(event.currentTarget); - - for (let key in this.hotkeys) - { - if (KeySelector.matchesKey(event, this.hotkeys[key])) - { - event.preventDefault(); - let command = event.currentTarget.document.getElementById("abp-command-" + key); - if (command) - command.doCommand(); - } - } - }, - - /** - * Checks whether the toolbar icon is currently displayed. - */ - isToolbarIconVisible: function() /**Boolean*/ - { - if (!CustomizableUI) - return false; - let placement = CustomizableUI.getPlacementOfWidget("abp-toolbarbutton"); - return !!placement; - }, - - /** - * Stores the selected hotkeys, initialized when the user presses a key. - */ - hotkeys: null, - - /** - * Chooses shortcut keys that are available in the window according to - * preferences. - */ - configureKeys: function(/**Window*/ window) - { - let selector = new KeySelector(window); - - this.hotkeys = {}; - for (let name in Prefs) - { - let match = /_key$/.exec(name); - if (match && typeof Prefs[name] == "string") - { - let keyName = match.input.substr(0, match.index); - this.hotkeys[keyName] = selector.selectKey(Prefs[name]); - } - } - }, - - /** - * Toggles open/closed state of the blockable items list. - */ - toggleBottombar: function(/**Window*/ window) - { - if (detachedBottombar && !detachedBottombar.closed) - { - detachedBottombar.close(); - detachedBottombar = null; - } - else - { - let {addBottomBar, removeBottomBar, getBrowser} = require("appSupport"); - let mustDetach = !addBottomBar || !removeBottomBar || !("abp-bottombar-container" in this.overlay); - let detach = mustDetach || Prefs.detachsidebar; - if (!detach && window.document.getElementById("abp-bottombar")) - { - removeBottomBar(window); - - let browser = (getBrowser ? getBrowser(window) : null); - if (browser) - browser.contentWindow.focus(); - } - else if (!detach) - { - addBottomBar(window, this.overlay["abp-bottombar-container"]); - let element = window.document.getElementById("abp-bottombar"); - if (element) - { - element.setAttribute("width", Prefs.blockableItemsSize.width); - element.setAttribute("height", Prefs.blockableItemsSize.height); - - let splitter = window.document.getElementById("abp-bottombar-splitter"); - if (splitter) - { - splitter.addEventListener("command", function() - { - Prefs.blockableItemsSize = {width: element.width, height: element.height}; - }, false); - } - } - } - else - detachedBottombar = window.openDialog("chrome://adblockplus/content/ui/sidebarDetached.xul", "_blank", "chrome,resizable,dependent,dialog=no", mustDetach); - } - }, - - /** - * Hide contribute button and persist this choice. - */ - hideContributeButton: function(/**Window*/ window) - { - Prefs.hideContributeButton = true; - - for (let id of ["abp-status-contributebutton", "abp-toolbar-contributebutton", "abp-menuitem-contributebutton"]) - { - let button = window.document.getElementById(id); - if (button) - button.hidden = true; - } - }, - - showNextNotification: function(url) - { - let window = this.currentWindow; - if (!window) - return; - - let button = window.document.getElementById("abp-toolbarbutton") - || window.document.getElementById("abp-status"); - if (!button) - return; - - let notification = Notification.getNextToShow(url); - if (!notification) - return; - - this._showNotification(window, button, notification); - }, - - _showNotification: function(window, button, notification) - { - let panel = window.document.getElementById("abp-notification"); - if (panel.state !== "closed") - return; - - function insertMessage(element, text, links) - { - let match = /^(.*?)<(a|strong)>(.*?)<\/\2>(.*)$/.exec(text); - if (!match) - { - element.appendChild(window.document.createTextNode(text)); - return; - } - - let [_, before, tagName, value, after] = match; - - insertMessage(element, before, links); - - let newElement = window.document.createElementNS("http://www.w3.org/1999/xhtml", tagName); - if (tagName === "a" && links && links.length) - newElement.setAttribute("href", links.shift()); - insertMessage(newElement, value, links); - element.appendChild(newElement); - - insertMessage(element, after, links); - } - - let texts = Notification.getLocalizedTexts(notification); - let titleElement = window.document.getElementById("abp-notification-title"); - titleElement.textContent = texts.title; - let messageElement = window.document.getElementById("abp-notification-message"); - messageElement.innerHTML = ""; - let docLinks = []; - for (let link of notification.links) - docLinks.push(Utils.getDocLink(link)); - insertMessage(messageElement, texts.message, docLinks); - - messageElement.addEventListener("click", function(event) - { - let link = event.target; - while (link && link !== messageElement && link.localName !== "a") - link = link.parentNode; - if (!link || link.localName !== "a") - return; - event.preventDefault(); - event.stopPropagation(); - this.loadInBrowser(link.href, window); - }.bind(this)); - - if (notification.type === "question") - { - function buttonHandler(approved, event) - { - event.preventDefault(); - event.stopPropagation(); - panel.hidePopup(); - Notification.triggerQuestionListeners(notification.id, approved) - Notification.markAsShown(notification.id); - } - window.document.getElementById("abp-notification-yes").onclick = buttonHandler.bind(null, true); - window.document.getElementById("abp-notification-no").onclick = buttonHandler.bind(null, false); - } - - panel.setAttribute("class", "abp-" + notification.type); - panel.setAttribute("noautohide", notification.type === "question"); - panel.openPopup(button, "bottomcenter topcenter", 0, 0, false, false, null); - } -}; -UI.onPopupShowing = UI.onPopupShowing.bind(UI); -UI.onKeyPress = UI.onKeyPress.bind(UI); -UI.onIconClick = UI.onIconClick.bind(UI); -UI.init(); - -/** - * List of event handers to be registered for each window. For each event - * handler the element ID, event and the actual event handler are listed. - * @type Array - */ -let eventHandlers = [ - ["abp-command-sendReport", "command", UI.openReportDialog.bind(UI)], - ["abp-command-filters", "command", UI.openFiltersDialog.bind(UI)], - ["abp-command-sidebar", "command", UI.toggleBottombar.bind(UI)], - ["abp-command-togglesitewhitelist", "command", function() { UI.toggleFilter(siteWhitelist); }], - ["abp-command-togglepagewhitelist", "command", function() { UI.toggleFilter(pageWhitelist); }], - ["abp-command-toggleobjtabs", "command", UI.togglePref.bind(UI, "frameobjects")], - ["abp-command-togglecollapse", "command", UI.togglePref.bind(UI, "fastcollapse")], - ["abp-command-togglesavestats", "command", UI.toggleSaveStats.bind(UI)], - ["abp-command-togglesync", "command", UI.toggleSync.bind(UI)], - ["abp-command-toggleshowintoolbar", "command", UI.toggleToolbarIcon.bind(UI)], - ["abp-command-toggleshowinstatusbar", "command", UI.togglePref.bind(UI, "showinstatusbar")], - ["abp-command-enable", "command", UI.togglePref.bind(UI, "enabled")], - ["abp-command-contribute", "command", UI.openContributePage.bind(UI)], - ["abp-command-contribute-hide", "command", UI.hideContributeButton.bind(UI)] -]; - -onShutdown.add(function() -{ - for (let window in UI.applicationWindows) - if (UI.isBottombarOpen(window)) - UI.toggleBottombar(window); -}); |