summaryrefslogtreecommitdiff
path: root/data/extensions/spyblock@gnu.org/lib/appSupport.js
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/spyblock@gnu.org/lib/appSupport.js')
-rw-r--r--data/extensions/spyblock@gnu.org/lib/appSupport.js948
1 files changed, 948 insertions, 0 deletions
diff --git a/data/extensions/spyblock@gnu.org/lib/appSupport.js b/data/extensions/spyblock@gnu.org/lib/appSupport.js
new file mode 100644
index 0000000..67c6248
--- /dev/null
+++ b/data/extensions/spyblock@gnu.org/lib/appSupport.js
@@ -0,0 +1,948 @@
+/*
+ * 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/>.
+ */
+
+/**
+ * @fileOverview Various application-specific functions.
+ */
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/AddonManager.jsm");
+
+/**
+ * Checks whether an application window is known and should get Adblock Plus
+ * user interface elements.
+ * @result Boolean
+ */
+exports.isKnownWindow = (/**Window*/ window) => false;
+
+/**
+ * HACK: In some applications the window finishes initialization during load
+ * event processing which makes an additional delay necessary. This flag
+ * indicates that.
+ * @type Boolean
+ */
+exports.delayInitialization = false;
+
+/**
+ * Retrieves the browser element for an application window.
+ * @type function(window)
+ */
+exports.getBrowser = null;
+
+/**
+ * Adds a new browser tab in the given application window.
+ * @type function(window, url, event)
+ */
+exports.addTab = null;
+
+/**
+ * Retrieves the current browser location for an application window.
+ */
+exports.getCurrentLocation = function getCurrentLocation(/**Window*/ window) /**nsIURI|String*/
+{
+ let browser = (exports.getBrowser ? exports.getBrowser(window) : null);
+ return (browser ? browser.currentURI : null);
+}
+
+
+/**
+ * The ID (or a list of possible IDs) of the content area context menu.
+ * @type String|String[]
+ */
+exports.contentContextMenu = null;
+
+/**
+ * Determines the default placement of the toolbar icon via object properties
+ * parent, before and after.
+ * @type Object
+ */
+exports.defaultToolbarPosition = null;
+
+/**
+ * The properties parent, before, after determine the placement of the status
+ * bar icon.
+ * @type Object
+ */
+exports.statusbarPosition = null;
+
+/**
+ * The properties parent, before, after determine the placement of the Tools
+ * submenu.
+ * @type Object
+ */
+exports.toolsMenu = null;
+
+/**
+ * Maps windows to their bottom bar info.
+ */
+let bottomBars = new WeakMap();
+
+/**
+ * Adds a bottom bar to the application window.
+ * @type function(window, element)
+ */
+exports.addBottomBar = null;
+
+function _addBottomBar(window, parent, element)
+{
+ if (bottomBars.has(window) || !parent)
+ return null;
+
+ let bar = {elements: []};
+ for (let child = element.firstElementChild; child; child = child.nextElementSibling)
+ {
+ let clone = child.cloneNode(true);
+ parent.appendChild(clone);
+ bar.elements.push(clone);
+ }
+
+ bottomBars.set(window, bar);
+ return bar;
+};
+
+/**
+ * Removes the bottom bar from the application window.
+ * @type function(window)
+ */
+exports.removeBottomBar = null;
+
+function _removeBottomBar(window)
+{
+ if (!bottomBars.has(window))
+ return null;
+
+ let bar = bottomBars.get(window);
+ for (let i = 0; i < bar.elements.length; i++)
+ if (bar.elements[i].parentNode)
+ bar.elements[i].parentNode.removeChild(bar.elements[i]);
+
+ bottomBars.delete(window);
+ return bar;
+};
+
+/**
+ * Maps windows to a list of progress listeners.
+ */
+let progressListeners = new WeakMap();
+
+/**
+ * Makes sure that a function is called whenever the displayed browser location changes.
+ */
+exports.addBrowserLocationListener = function addBrowserLocationListener(/**Window*/ window, /**Function*/ callback, /**Boolean*/ ignoreSameDoc)
+{
+ let browser = (exports.getBrowser ? exports.getBrowser(window) : null);
+ if (browser)
+ {
+ let dummy = function() {};
+ let progressListener =
+ {
+ callback: callback,
+ onLocationChange: function(progress, request, uri, flags)
+ {
+ if (!ignoreSameDoc || !flags || !(flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT))
+ this.callback();
+ },
+ onProgressChange: dummy,
+ onSecurityChange: dummy,
+ onStateChange: dummy,
+ onStatusChange: dummy,
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference])
+ };
+ browser.addProgressListener(progressListener);
+
+ if (progressListeners.has(window))
+ progressListeners.get(window).push(progressListener);
+ else
+ progressListeners.set(window, [progressListener]);
+ }
+};
+
+/**
+ * Removes a location listener registered for a window.
+ */
+exports.removeBrowserLocationListener = function removeBrowserLocationListener(/**Window*/ window, /**Function*/ callback)
+{
+ if (!progressListeners.has(window))
+ return;
+
+ let browser = (exports.getBrowser ? exports.getBrowser(window) : null);
+ let listeners = progressListeners.get(window);
+ for (let i = 0; i < listeners.length; i++)
+ {
+ if (listeners[i].callback == callback)
+ {
+ if (browser)
+ browser.removeProgressListener(listeners[i]);
+ listeners.splice(i--, 1);
+ }
+ }
+};
+
+/**
+ * Removes all location listeners registered for a window, to be called on
+ * cleanup.
+ */
+exports.removeBrowserLocationListeners = function removeBrowserLocationListeners(/**Window*/ window)
+{
+ if (!progressListeners.has(window))
+ return;
+
+ let browser = (exports.getBrowser ? exports.getBrowser(window) : null);
+ if (browser)
+ {
+ let listeners = progressListeners.get(window);
+ for (let i = 0; i < listeners.length; i++)
+ browser.removeProgressListener(listeners[i]);
+ }
+ progressListeners.delete(window);
+};
+
+/**
+ * Maps windows to a list of click listeners.
+ */
+let clickListeners = new WeakMap();
+
+/**
+ * Makes sure that a function is called whenever the user clicks inside the
+ * browser's content area.
+ */
+exports.addBrowserClickListener = function addBrowserClickListener(/**Window*/ window, /**Function*/ callback)
+{
+ let browser = (exports.getBrowser ? exports.getBrowser(window) : null);
+ if (browser)
+ {
+ browser.addEventListener("click", callback, true);
+
+ if (clickListeners.has(window))
+ clickListeners.get(window).push(callback);
+ else
+ clickListeners.set(window, [callback]);
+ }
+};
+
+/**
+ * Removes all click listeners registered for a window, to be called on
+ * cleanup.
+ */
+exports.removeBrowserClickListeners = function removeBrowserClickListeners(/**Window*/ window)
+{
+ if (!clickListeners.has(window))
+ return;
+
+ let browser = (exports.getBrowser ? exports.getBrowser(window) : null);
+ if (browser)
+ {
+ let listeners = clickListeners.get(window);
+ for (let i = 0; i < listeners.length; i++)
+ browser.removeEventListener("click", listeners[i], true);
+ }
+ clickListeners.delete(window);
+};
+
+let {application} = require("info");
+switch (application)
+{
+ case "firefox":
+ {
+ exports.isKnownWindow = function ff_isKnownWindow(window)
+ {
+ return (window.document.documentElement.getAttribute("windowtype") == "navigator:browser");
+ };
+
+ exports.getBrowser = (window) => window.gBrowser;
+
+ exports.addTab = function ff_addTab(window, url, event)
+ {
+ if (event)
+ window.openNewTabWith(url, exports.getBrowser(window).contentDocument, null, event, false);
+ else
+ window.gBrowser.loadOneTab(url, {inBackground: false});
+ };
+
+ exports.contentContextMenu = "contentAreaContextMenu";
+
+ exports.defaultToolbarPosition = {
+ parent: "nav-bar"
+ };
+
+ exports.toolsMenu = {
+ parent: "menu_ToolsPopup"
+ };
+
+ exports.addBottomBar = function fx_addBottomBar(window, element)
+ {
+ let bar = _addBottomBar(window, window.document.getElementById("appcontent"), element);
+ if (bar)
+ {
+ let display = window.document.getElementById("statusbar-display");
+ bar.changedFixed = display && !display.hasAttribute("fixed");
+ if (bar.changedFixed)
+ display.setAttribute("fixed", "true");
+ }
+ };
+
+ exports.removeBottomBar = function fx_removeBottomBar(window)
+ {
+ let bar = _removeBottomBar(window);
+ if (bar && bar.changedFixed)
+ window.document.getElementById("statusbar-display").removeAttribute("fixed");
+ };
+
+ break;
+ }
+
+ case "seamonkey":
+ {
+ exports.isKnownWindow = function sm_isKnownWindow(window)
+ {
+ let type = window.document.documentElement.getAttribute("windowtype");
+ return (type == "navigator:browser" || type == "mail:3pane" || type == "mail:messageWindow");
+ };
+
+ exports.addTab = function sm_addTab(window, url, event)
+ {
+ if (event || !("gBrowser" in window))
+ window.openNewTabWith(url, ("gBrowser" in window ? window.gBrowser.contentDocument : null), null, event, false);
+ else
+ window.gBrowser.loadOneTab(url, {inBackground: false});
+ };
+
+ exports.getBrowser = function sm_getBrowser(window)
+ {
+ if ("gBrowser" in window)
+ return window.gBrowser;
+ else if ("getMessageBrowser" in window)
+ return window.getMessageBrowser();
+ else
+ return null;
+ };
+
+ exports.getCurrentLocation = function sm_getCurrentLocation(window)
+ {
+ if ("currentHeaderData" in window && "content-base" in window.currentHeaderData)
+ {
+ // This is a blog entry
+ return window.currentHeaderData["content-base"].headerValue;
+ }
+ else if ("currentHeaderData" in window && "from" in window.currentHeaderData)
+ {
+ // This is a mail/newsgroup entry
+ try
+ {
+ let headerParser = Cc["@mozilla.org/messenger/headerparser;1"].getService(Ci.nsIMsgHeaderParser);
+ let emailAddress = headerParser.extractHeaderAddressMailboxes(window.currentHeaderData.from.headerValue);
+ return "mailto:" + emailAddress.replace(/^[\s"]+/, "").replace(/[\s"]+$/, "").replace(/\s/g, "%20");
+ }
+ catch(e)
+ {
+ return null;
+ }
+ }
+ else
+ {
+ let browser = exports.getBrowser(window);
+ return (browser ? browser.currentURI : null);
+ }
+ };
+
+ exports.contentContextMenu = ["contentAreaContextMenu", "mailContext"];
+
+ exports.defaultToolbarPosition = {
+ parent: ["PersonalToolbar", "msgToolbar"],
+ before: ["bookmarks-button", "button-junk"]
+ };
+
+ exports.statusbarPosition = {
+ parent: "status-bar"
+ };
+
+ exports.toolsMenu = {
+ parent: "taskPopup",
+ after: "downloadmgr"
+ };
+
+ exports.addBottomBar = function sm_addBottomBar(window, element)
+ {
+ _addBottomBar(window, window.document.getElementById("appcontent") || window.document.getElementById("messagepanebox"), element);
+ };
+
+ exports.removeBottomBar = _removeBottomBar;
+
+ break;
+ }
+
+ case "thunderbird":
+ {
+ exports.isKnownWindow = function tb_isKnownWindow(window)
+ {
+ let type = window.document.documentElement.getAttribute("windowtype");
+ return (type == "mail:3pane" || type == "mail:messageWindow");
+ };
+
+ exports.delayInitialization = true;
+
+ exports.getBrowser = (window) => window.getBrowser();
+
+ exports.addTab = function tb_addTab(window, url, event)
+ {
+ let tabmail = window.document.getElementById("tabmail");
+ if (!tabmail)
+ {
+ let wnd = Services.wm.getMostRecentWindow("mail:3pane");
+ if (window)
+ tabmail = wnd.document.getElementById("tabmail");
+ }
+
+ if (tabmail)
+ tabmail.openTab("contentTab", {contentPage: url});
+ else
+ {
+ window.openDialog("chrome://messenger/content/", "_blank",
+ "chrome,dialog=no,all", null,
+ {
+ tabType: "contentTab",
+ tabParams: {contentPage: url}
+ });
+ }
+ };
+
+ exports.contentContextMenu = ["mailContext", "pageContextMenu"];
+
+ exports.defaultToolbarPosition = {
+ parent: "header-view-toolbar",
+ before: "hdrReplyButton",
+ addClass: "msgHeaderView-button"
+ };
+
+ exports.statusbarPosition = {
+ parent: "status-bar"
+ };
+
+ exports.toolsMenu = {
+ parent: "taskPopup",
+ after: "javaScriptConsole"
+ };
+
+ exports.getCurrentLocation = function getCurrentLocation(window)
+ {
+ let browser = exports.getBrowser(window);
+ if (!browser)
+ return null;
+
+ if (browser.id == "messagepane" && "currentHeaderData" in window && "content-base" in window.currentHeaderData)
+ {
+ // This is a blog entry
+ return window.currentHeaderData["content-base"].headerValue;
+ }
+ else if (browser.id == "messagepane" && "currentHeaderData" in window && "from" in window.currentHeaderData)
+ {
+ // This is a mail/newsgroup entry
+ try
+ {
+ let headerParser = Cc["@mozilla.org/messenger/headerparser;1"].getService(Ci.nsIMsgHeaderParser);
+ let emailAddress = headerParser.extractHeaderAddressMailboxes(window.currentHeaderData.from.headerValue);
+ return "mailto:" + emailAddress.replace(/^[\s"]+/, "").replace(/[\s"]+$/, "").replace(/\s/g, "%20");
+ }
+ catch(e)
+ {
+ return null;
+ }
+ }
+ else
+ return browser.currentURI;
+ }
+
+ exports.addBottomBar = function tb_addBottomBar(window, element)
+ {
+ let browser = exports.getBrowser(window);
+ if (!browser)
+ return;
+
+ let parent = window.document.getElementById("messagepanebox");
+ if (!parent || !(parent.compareDocumentPosition(browser) & Ci.nsIDOMNode.DOCUMENT_POSITION_CONTAINED_BY))
+ parent = browser.parentNode;
+
+ _addBottomBar(window, parent, element);
+ };
+
+ exports.removeBottomBar = _removeBottomBar;
+
+ let BrowserChangeListener = function(window, callback)
+ {
+ this.window = window;
+ this.callback = callback;
+ this.onSelect = this.onSelect.bind(this);
+ this.attach();
+ };
+ BrowserChangeListener.prototype = {
+ window: null,
+ callback: null,
+ currentBrowser: null,
+
+ setBrowser: function(browser)
+ {
+ if (browser != this.currentBrowser)
+ {
+ let oldBrowser = this.currentBrowser;
+ this.currentBrowser = browser;
+ this.callback(oldBrowser, browser);
+ }
+ },
+
+ onSelect: function()
+ {
+ this.setBrowser(exports.getBrowser(this.window));
+ },
+
+ attach: function()
+ {
+ this.onSelect();
+
+ let tabmail = this.window.document.getElementById("tabmail");
+ if (tabmail)
+ tabmail.tabContainer.addEventListener("select", this.onSelect, false);
+ },
+ detach: function()
+ {
+ let tabmail = this.window.document.getElementById("tabmail");
+ if (tabmail)
+ tabmail.tabContainer.removeEventListener("select", this.onSelect, false);
+
+ this.setBrowser(null);
+ }
+ };
+
+ exports.addBrowserLocationListener = function(/**Window*/ window, /**Function*/ callback, /**Boolean*/ ignoreSameDoc)
+ {
+ if (progressListeners.has(window))
+ {
+ progressListeners.get(window).locationCallbacks.push(callback);
+ return;
+ }
+
+ let callbacks = [callback];
+ let dummy = function() {};
+ let progressListener =
+ {
+ onLocationChange: function(progress, request, uri, flags)
+ {
+ if (!ignoreSameDoc || !flags || !(flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT))
+ for (let i = 0; i < callbacks.length; i++)
+ callbacks[i]();
+ },
+ onProgressChange: dummy,
+ onSecurityChange: dummy,
+ onStateChange: dummy,
+ onStatusChange: dummy,
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference])
+ };
+ let messageListener =
+ {
+ onStartHeaders: dummy,
+ onEndHeaders: function()
+ {
+ let browser = exports.getBrowser(window);
+ if (browser.id == "messagepane")
+ for (let i = 0; i < callbacks.length; i++)
+ callbacks[i]();
+ },
+ onEndAttachments: dummy,
+ onBeforeShowHeaderPane: dummy
+ };
+
+ let listener = new BrowserChangeListener(window, function(oldBrowser, newBrowser)
+ {
+ if (oldBrowser)
+ oldBrowser.removeProgressListener(progressListener);
+ if (newBrowser)
+ newBrowser.addProgressListener(progressListener);
+ progressListener.onLocationChange();
+ });
+ listener.locationCallbacks = callbacks;
+
+ if ("gMessageListeners" in window)
+ window.gMessageListeners.push(messageListener);
+ listener.messageListener = messageListener;
+
+ progressListeners.set(window, listener);
+ };
+
+ exports.removeBrowserLocationListener = function(/**Window*/ window, /**Function*/ callback)
+ {
+ if (!progressListeners.has(window))
+ return;
+
+ let callbacks = progressListeners.get(window).locationCallbacks;
+ for (let i = 0; i < callbacks.length; i++)
+ if (callbacks[i] == callback)
+ callbacks.splice(i--, 1);
+ };
+
+ exports.removeBrowserLocationListeners = function(/**Window*/ window)
+ {
+ if (!progressListeners.has(window))
+ return;
+
+ let listener = progressListeners.get(window);
+
+ let messageListener = listener.messageListener;
+ let index = ("gMessageListeners" in window ? window.gMessageListeners.indexOf(messageListener) : -1);
+ if (index >= 0)
+ window.gMessageListeners.splice(index, 1);
+
+ listener.detach();
+ progressListeners.delete(window);
+ };
+
+ exports.addBrowserClickListener = function addBrowserClickListener(/**Window*/ window, /**Function*/ callback)
+ {
+ if (clickListeners.has(window))
+ {
+ clickListeners.get(window).callbacks.push(callback);
+ return;
+ }
+
+ let callbacks = [callback];
+ let listener = new BrowserChangeListener(window, function(oldBrowser, newBrowser)
+ {
+ if (oldBrowser)
+ for (let i = 0; i < callbacks.length; i++)
+ oldBrowser.removeEventListener("click", callbacks[i], true);
+ if (newBrowser)
+ for (let i = 0; i < callbacks.length; i++)
+ newBrowser.addEventListener("click", callbacks[i], true);
+ });
+ listener.callbacks = callbacks;
+
+ clickListeners.set(window, listener);
+ };
+
+ exports.removeBrowserClickListeners = function removeBrowserClickListeners(/**Window*/ window)
+ {
+ if (!clickListeners.has(window))
+ return;
+
+ let listener = clickListeners.get(window);
+ listener.detach();
+
+ clickListeners.delete(window);
+ };
+
+ // Make sure to close/reopen list of blockable items when the user changes tabs
+ let {WindowObserver} = require("windowObserver");
+ new WindowObserver({
+ listeners: new WeakMap(),
+ applyToWindow: function(window)
+ {
+ if (!exports.isKnownWindow(window) || this.listeners.has(window))
+ return;
+
+ let {Utils} = require("utils");
+ Utils.runAsync(function()
+ {
+ let listener = new BrowserChangeListener(window, function(oldBrowser, newBrowser)
+ {
+ if (bottomBars.has(window))
+ {
+ let {UI} = require("ui")
+ UI.toggleBottombar(window);
+ UI.toggleBottombar(window);
+ }
+ });
+ this.listeners.set(window, listener);
+ }.bind(this));
+ },
+ removeFromWindow: function(window)
+ {
+ if (!this.listeners.has(window))
+ return;
+
+ let listener = this.listeners.get(window);
+ listener.detach();
+ this.listeners.delete(window);
+ }
+ });
+
+ break;
+ }
+
+ case "fennec2":
+ {
+ exports.isKnownWindow = (window) => window.document.documentElement.id == "main-window";
+
+ exports.getBrowser = (window) => window.BrowserApp.selectedBrowser;
+
+ exports.addTab = (window, url, event) => window.BrowserApp.addTab(url, {selected: true});
+
+ let BrowserChangeListener = function(window, callback)
+ {
+ this.window = window;
+ this.callback = callback;
+ this.onSelect = this.onSelect.bind(this);
+ this.attach();
+ };
+ BrowserChangeListener.prototype = {
+ window: null,
+ callback: null,
+ currentBrowser: null,
+
+ setBrowser: function(browser)
+ {
+ if (browser != this.currentBrowser)
+ {
+ let oldBrowser = this.currentBrowser;
+ this.currentBrowser = browser;
+ this.callback(oldBrowser, browser);
+ }
+ },
+
+ onSelect: function()
+ {
+ let {Utils} = require("utils");
+ Utils.runAsync(function()
+ {
+ this.setBrowser(exports.getBrowser(this.window));
+ }.bind(this));
+ },
+
+ attach: function()
+ {
+ this.onSelect();
+
+ this.window.BrowserApp.deck.addEventListener("TabSelect", this.onSelect, false);
+ },
+ detach: function()
+ {
+ this.window.BrowserApp.deck.removeEventListener("TabSelect", this.onSelect, false);
+
+ this.setBrowser(null);
+ }
+ };
+
+ exports.addBrowserLocationListener = function ffn_addBrowserLocationListener(/**Window*/ window, /**Function*/ callback, /**Boolean*/ ignoreSameDoc)
+ {
+ if (progressListeners.has(window))
+ {
+ progressListeners.get(window).locationCallbacks.push(callback);
+ return;
+ }
+
+ let callbacks = [callback];
+ let dummy = function() {};
+ let progressListener =
+ {
+ onLocationChange: function(progress, request, uri, flags)
+ {
+ if (!ignoreSameDoc || !flags || !(flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT))
+ for (let i = 0; i < callbacks.length; i++)
+ callbacks[i]();
+ },
+ onProgressChange: dummy,
+ onSecurityChange: dummy,
+ onStateChange: dummy,
+ onStatusChange: dummy,
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference])
+ };
+
+ let listener = new BrowserChangeListener(window, function(oldBrowser, newBrowser)
+ {
+ if (oldBrowser && typeof oldBrowser.removeProgressListener == "function")
+ oldBrowser.removeProgressListener(progressListener);
+ if (newBrowser && typeof newBrowser.removeProgressListener == "function")
+ newBrowser.addProgressListener(progressListener);
+ progressListener.onLocationChange();
+ });
+ listener.locationCallbacks = callbacks;
+
+ progressListeners.set(window, listener);
+ };
+
+ exports.removeBrowserLocationListener = function ffn_removeBrowserLocationListener(/**Window*/ window, /**Function*/ callback)
+ {
+ if (!progressListeners.has(window))
+ return;
+
+ let callbacks = progressListeners.get(window).locationCallbacks;
+ for (let i = 0; i < callbacks.length; i++)
+ if (callbacks[i] == callback)
+ callbacks.splice(i--, 1);
+ };
+
+ exports.removeBrowserLocationListeners = function ffn_removeBrowserLocationListeners(/**Window*/ window)
+ {
+ if (!progressListeners.has(window))
+ return;
+
+ let listener = progressListeners.get(window);
+ listener.detach();
+ progressListeners.delete(window);
+ };
+
+ exports.addBrowserClickListener = function ffn_addBrowserClickListener(/**Window*/ window, /**Function*/ callback)
+ {
+ if (clickListeners.has(window))
+ {
+ clickListeners.get(window).callbacks.push(callback);
+ return;
+ }
+
+ let callbacks = [callback];
+ let listener = new BrowserChangeListener(window, function(oldBrowser, newBrowser)
+ {
+ if (oldBrowser)
+ for (let i = 0; i < callbacks.length; i++)
+ oldBrowser.removeEventListener("click", callbacks[i], true);
+ if (newBrowser)
+ for (let i = 0; i < callbacks.length; i++)
+ newBrowser.addEventListener("click", callbacks[i], true);
+ });
+ listener.callbacks = callbacks;
+
+ clickListeners.set(window, listener);
+ };
+
+ exports.removeBrowserClickListeners = function ffn_removeBrowserClickListeners(/**Window*/ window)
+ {
+ if (!clickListeners.has(window))
+ return;
+
+ let listener = clickListeners.get(window);
+ listener.detach();
+
+ clickListeners.delete(window);
+ };
+
+ let {Filter} = require("filterClasses");
+ let {Prefs} = require("prefs");
+ let {Policy} = require("contentPolicy");
+ let {UI} = require("ui");
+ let {Utils} = require("utils");
+
+ let toggleWhitelist = function(window)
+ {
+ if (!Prefs.enabled)
+ {
+ Prefs.enabled = true;
+ return;
+ }
+
+ let location = exports.getCurrentLocation(window);
+ let host = null;
+ if (location instanceof Ci.nsIURL && Policy.isBlockableScheme(location))
+ {
+ try
+ {
+ host = location.host.replace(/^www\./, "");
+ } catch (e) {}
+ }
+
+ if (!host)
+ return;
+
+ if (Policy.isWhitelisted(location.spec))
+ UI.removeWhitelist(window);
+ else
+ UI.toggleFilter(Filter.fromText("@@||" + host + "^$document"));
+ };
+
+ let menuItem = null;
+ onShutdown.add(function()
+ {
+ let window = null;
+ for (window in UI.applicationWindows)
+ break;
+
+ if (window && menuItem)
+ window.NativeWindow.menu.remove(menuItem);
+ });
+
+ UI.updateIconState = function fmn_updateIconState(window, icon)
+ {
+ if (menuItem !== null)
+ {
+ window.NativeWindow.menu.remove(menuItem);
+ menuItem = null;
+ }
+
+ let action;
+ let host = null;
+ if (Prefs.enabled)
+ {
+ let location = exports.getCurrentLocation(window);
+ if (location instanceof Ci.nsIURL && Policy.isBlockableScheme(location))
+ {
+ try
+ {
+ host = location.host.replace(/^www\./, "");
+ } catch (e) {}
+ }
+ if (!host)
+ return;
+
+ if (host && Policy.isWhitelisted(location.spec))
+ action = "enable_site";
+ else if (host)
+ action = "disable_site";
+ }
+ else
+ action = "enable";
+
+ let actionText = Utils.getString("mobile_menu_" + action);
+ if (host)
+ actionText = actionText.replace(/\?1\?/g, host);
+
+ let iconUrl = require("info").addonRoot + "icon64.png";
+ menuItem = window.NativeWindow.menu.add(actionText, iconUrl, toggleWhitelist.bind(null, window));
+ };
+
+ UI.openSubscriptionDialog = function(window, url, title, mainURL, mainTitle)
+ {
+ let dialogTitle = this.overlay.attributes.subscriptionDialogTitle;
+ let dialogMessage = this.overlay.attributes.subscriptionDialogMessage.replace(/\?1\?/, title).replace(/\?2\?/, url);
+ if (Utils.confirm(window, dialogMessage, dialogTitle))
+ this.setSubscription(url, title);
+ };
+
+ UI.openFiltersDialog = function()
+ {
+ let window = UI.currentWindow;
+ if (!window)
+ return
+
+ let browser = exports.addTab(window, "about:addons").browser;
+ browser.addEventListener("load", function openAddonPrefs(event)
+ {
+ browser.removeEventListener("load", openAddonPrefs, true);
+ Utils.runAsync(function()
+ {
+ // The page won't be ready until the add-on manager data is loaded so we call this method
+ // to know when the data will be ready.
+ AddonManager.getAddonsByTypes(["extension", "theme", "locale"], function()
+ {
+ let event = new Event("Event");
+ event.initEvent("popstate", true, false);
+ event.state = {id: require("info").addonID};
+ browser._contentWindow.dispatchEvent(event);
+ });
+ });
+ }, true);
+ };
+
+ break;
+ }
+}