diff options
Diffstat (limited to 'helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib')
27 files changed, 0 insertions, 12382 deletions
diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/Public.jsm b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/Public.jsm deleted file mode 100644 index 0f96bcb..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/Public.jsm +++ /dev/null @@ -1,202 +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/>. - */ - -/** - * @fileOverview Public Adblock Plus API. - */ - -var EXPORTED_SYMBOLS = ["AdblockPlus"]; - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cr = Components.results; -const Cu = Components.utils; - -Cu.import("resource://gre/modules/Services.jsm"); - -function require(module) -{ - let result = {}; - result.wrappedJSObject = result; - Services.obs.notifyObservers(result, "adblockplus-require", module); - return result.exports; -} - -let {FilterStorage} = require("filterStorage"); -let {Filter} = require("filterClasses"); -let {Subscription, SpecialSubscription, RegularSubscription, DownloadableSubscription, ExternalSubscription} = require("subscriptionClasses"); - -const externalPrefix = "~external~"; - -/** - * Class implementing public Adblock Plus API - * @class - */ -var AdblockPlus = -{ - /** - * Returns current subscription count - * @type Integer - */ - get subscriptionCount() - { - return FilterStorage.subscriptions.length; - }, - - /** - * Gets a subscription by its URL - */ - getSubscription: function(/**String*/ id) /**IAdblockPlusSubscription*/ - { - if (id in FilterStorage.knownSubscriptions) - return createSubscriptionWrapper(FilterStorage.knownSubscriptions[id]); - - return null; - }, - - /** - * Gets a subscription by its position in the list - */ - getSubscriptionAt: function(/**Integer*/ index) /**IAdblockPlusSubscription*/ - { - if (index < 0 || index >= FilterStorage.subscriptions.length) - return null; - - return createSubscriptionWrapper(FilterStorage.subscriptions[index]); - }, - - /** - * Updates an external subscription and creates it if necessary - */ - updateExternalSubscription: function(/**String*/ id, /**String*/ title, /**Array of Filter*/ filters) /**String*/ - { - if (id.substr(0, externalPrefix.length) != externalPrefix) - id = externalPrefix + id; - let subscription = Subscription.knownSubscriptions[id]; - if (typeof subscription == "undefined") - subscription = new ExternalSubscription(id, title); - - subscription.lastDownload = parseInt(new Date().getTime() / 1000); - - let newFilters = []; - for (let filter of filters) - { - filter = Filter.fromText(Filter.normalize(filter)); - if (filter) - newFilters.push(filter); - } - - if (id in FilterStorage.knownSubscriptions) - FilterStorage.updateSubscriptionFilters(subscription, newFilters); - else - { - subscription.filters = newFilters; - FilterStorage.addSubscription(subscription); - } - - return id; - }, - - /** - * Removes an external subscription by its identifier - */ - removeExternalSubscription: function(/**String*/ id) /**Boolean*/ - { - if (id.substr(0, externalPrefix.length) != externalPrefix) - id = externalPrefix + id; - if (!(id in FilterStorage.knownSubscriptions)) - return false; - - FilterStorage.removeSubscription(FilterStorage.knownSubscriptions[id]); - return true; - }, - - /** - * Adds user-defined filters to the list - */ - addPatterns: function(/**Array of String*/ filters) - { - for (let filter of filters) - { - filter = Filter.fromText(Filter.normalize(filter)); - if (filter) - { - filter.disabled = false; - FilterStorage.addFilter(filter); - } - } - }, - - /** - * Removes user-defined filters from the list - */ - removePatterns: function(/**Array of String*/ filters) - { - for (let filter of filters) - { - filter = Filter.fromText(Filter.normalize(filter)); - if (filter) - FilterStorage.removeFilter(filter); - } - }, - - /** - * Returns installed Adblock Plus version - */ - getInstalledVersion: function() /**String*/ - { - return require("info").addonVersion; - }, - - /** - * Returns source code revision this Adblock Plus build was created from (if available) - */ - getInstalledBuild: function() /**String*/ - { - return ""; - }, -}; - -/** - * Wraps a subscription into IAdblockPlusSubscription structure. - */ -function createSubscriptionWrapper(/**Subscription*/ subscription) /**IAdblockPlusSubscription*/ -{ - if (!subscription) - return null; - - return { - url: subscription.url, - special: subscription instanceof SpecialSubscription, - title: subscription.title, - autoDownload: true, - disabled: subscription.disabled, - external: subscription instanceof ExternalSubscription, - lastDownload: subscription instanceof RegularSubscription ? subscription.lastDownload : 0, - downloadStatus: subscription instanceof DownloadableSubscription ? subscription.downloadStatus : "synchronize_ok", - lastModified: subscription instanceof DownloadableSubscription ? subscription.lastModified : null, - expires: subscription instanceof DownloadableSubscription ? subscription.expires : 0, - getPatterns: function() - { - let result = subscription.filters.map(function(filter) - { - return filter.text; - }); - return result; - } - }; -} diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/antiadblockInit.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/antiadblockInit.js deleted file mode 100644 index d8b29ca..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/antiadblockInit.js +++ /dev/null @@ -1,78 +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/Services.jsm"); - -let {Utils} = require("utils"); -let {Prefs} = require("prefs"); -let {ActiveFilter} = require("filterClasses"); -let {FilterStorage} = require("filterStorage"); -let {FilterNotifier} = require("filterNotifier"); -let {Subscription} = require("subscriptionClasses"); -let {Notification} = require("notification"); - -exports.initAntiAdblockNotification = function initAntiAdblockNotification() -{ - let notification = { - id: "antiadblock", - type: "question", - title: Utils.getString("notification_antiadblock_title"), - message: Utils.getString("notification_antiadblock_message"), - urlFilters: [] - }; - - function notificationListener(approved) - { - let subscription = Subscription.fromURL(Prefs.subscriptions_antiadblockurl); - if (subscription.url in FilterStorage.knownSubscriptions) - subscription.disabled = !approved; - } - - function addAntiAdblockNotification(subscription) - { - let urlFilters = []; - for (let filter of subscription.filters) - if (filter instanceof ActiveFilter) - for (let domain in filter.domains) - if (domain && urlFilters.indexOf(domain) == -1) - urlFilters.push(domain); - notification.urlFilters = urlFilters; - Notification.addNotification(notification); - Notification.addQuestionListener(notification.id, notificationListener); - } - - function removeAntiAdblockNotification() - { - Notification.removeNotification(notification); - Notification.removeQuestionListener(notification.id, notificationListener); - } - - let subscription = Subscription.fromURL(Prefs.subscriptions_antiadblockurl); - if (subscription.lastDownload && subscription.disabled) - addAntiAdblockNotification(subscription); - - FilterNotifier.addListener(function(action, value, newItem, oldItem) - { - if (!/^subscription\.(updated|removed|disabled)$/.test(action) || value.url != Prefs.subscriptions_antiadblockurl) - return; - - if (action == "subscription.updated") - addAntiAdblockNotification(value); - else if (action == "subscription.removed" || (action == "subscription.disabled" && !value.disabled)) - removeAntiAdblockNotification(); - }); -} diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/appSupport.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/appSupport.js deleted file mode 100644 index 67c6248..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/appSupport.js +++ /dev/null @@ -1,948 +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/>. - */ - -/** - * @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; - } -} diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/contentPolicy.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/contentPolicy.js deleted file mode 100644 index 084ebc5..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/contentPolicy.js +++ /dev/null @@ -1,779 +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/>. - */ - -/** - * @fileOverview Content policy implementation, responsible for blocking things. - */ - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -let {TimeLine} = require("timeline"); -let {Utils} = require("utils"); -let {Prefs} = require("prefs"); -let {FilterStorage} = require("filterStorage"); -let {BlockingFilter, WhitelistFilter} = require("filterClasses"); -let {defaultMatcher} = require("matcher"); -let {objectMouseEventHander} = require("objectTabs"); -let {RequestNotifier} = require("requestNotifier"); -let {ElemHide} = require("elemHide"); - -/** - * List of explicitly supported content types - * @type Array of String - */ -let contentTypes = ["OTHER", "SCRIPT", "IMAGE", "STYLESHEET", "OBJECT", "SUBDOCUMENT", "DOCUMENT", "XMLHTTPREQUEST", "OBJECT_SUBREQUEST", "FONT", "MEDIA"]; - -/** - * List of content types that aren't associated with a visual document area - * @type Array of String - */ -let nonVisualTypes = ["SCRIPT", "STYLESHEET", "XMLHTTPREQUEST", "OBJECT_SUBREQUEST", "FONT"]; - -/** - * Randomly generated class name, to be applied to collapsed nodes. - */ -let collapsedClass = ""; - -/** - * Public policy checking functions and auxiliary objects - * @class - */ -let Policy = exports.Policy = -{ - /** - * Map of content type identifiers by their name. - * @type Object - */ - type: {}, - - /** - * Map of content type names by their identifiers (reverse of type map). - * @type Object - */ - typeDescr: {}, - - /** - * Map of localized content type names by their identifiers. - * @type Object - */ - localizedDescr: {}, - - /** - * Lists the non-visual content types. - * @type Object - */ - nonVisual: {}, - - /** - * Map containing all schemes that should be ignored by content policy. - * @type Object - */ - whitelistSchemes: {}, - - /** - * Called on module startup, initializes various exported properties. - */ - init: function() - { - TimeLine.enter("Entered content policy initialization"); - - // type constant by type description and type description by type constant - let iface = Ci.nsIContentPolicy; - for (let typeName of contentTypes) - { - if ("TYPE_" + typeName in iface) - { - let id = iface["TYPE_" + typeName]; - this.type[typeName] = id; - this.typeDescr[id] = typeName; - this.localizedDescr[id] = Utils.getString("type_label_" + typeName.toLowerCase()); - } - } - - this.type.ELEMHIDE = 0xFFFD; - this.typeDescr[0xFFFD] = "ELEMHIDE"; - this.localizedDescr[0xFFFD] = Utils.getString("type_label_elemhide"); - - this.type.POPUP = 0xFFFE; - this.typeDescr[0xFFFE] = "POPUP"; - this.localizedDescr[0xFFFE] = Utils.getString("type_label_popup"); - - for (let type of nonVisualTypes) - this.nonVisual[this.type[type]] = true; - - // whitelisted URL schemes - for (let scheme of Prefs.whitelistschemes.toLowerCase().split(" ")) - this.whitelistSchemes[scheme] = true; - - TimeLine.log("done initializing types"); - - // Generate class identifier used to collapse node and register corresponding - // stylesheet. - TimeLine.log("registering global stylesheet"); - - let offset = "a".charCodeAt(0); - for (let i = 0; i < 20; i++) - collapsedClass += String.fromCharCode(offset + Math.random() * 26); - - let collapseStyle = Services.io.newURI("data:text/css," + - encodeURIComponent("." + collapsedClass + - "{-moz-binding: url(chrome://global/content/bindings/general.xml#foobarbazdummy) !important;}"), null, null); - Utils.styleService.loadAndRegisterSheet(collapseStyle, Ci.nsIStyleSheetService.USER_SHEET); - onShutdown.add(function() - { - Utils.styleService.unregisterSheet(collapseStyle, Ci.nsIStyleSheetService.USER_SHEET); - }) - TimeLine.log("done registering stylesheet"); - - TimeLine.leave("Done initializing content policy"); - }, - - /** - * Checks whether a node should be blocked, hides it if necessary - * @param wnd {nsIDOMWindow} - * @param node {nsIDOMElement} - * @param contentType {String} - * @param location {nsIURI} - * @param collapse {Boolean} true to force hiding of the node - * @return {Boolean} false if the node should be blocked - */ - processNode: function(wnd, node, contentType, location, collapse) - { - let topWnd = wnd.top; - if (!topWnd || !topWnd.location || !topWnd.location.href) - return true; - - let privatenode=false; - Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); - if (PrivateBrowsingUtils.isWindowPrivate(wnd)) - privatenode=true; - - let originWindow = Utils.getOriginWindow(wnd); - let wndLocation = originWindow.location.href; - let docDomain = getHostname(wndLocation); - let match = null; - if (!match && Prefs.enabled) - { - let testWnd = wnd; - let parentWndLocation = getWindowLocation(testWnd); - while (true) - { - let testWndLocation = parentWndLocation; - parentWndLocation = (testWnd == testWnd.parent ? testWndLocation : getWindowLocation(testWnd.parent)); - match = Policy.isWhitelisted(testWndLocation, parentWndLocation); - - if (!(match instanceof WhitelistFilter)) - { - let keydata = (testWnd.document && testWnd.document.documentElement ? testWnd.document.documentElement.getAttribute("data-adblockkey") : null); - if (keydata && keydata.indexOf("_") >= 0) - { - let [key, signature] = keydata.split("_", 2); - let keyMatch = defaultMatcher.matchesByKey(testWndLocation, key.replace(/=/g, ""), docDomain); - if (keyMatch && Utils.crypto) - { - // Website specifies a key that we know but is the signature valid? - let uri = Services.io.newURI(testWndLocation, null, null); - let params = [ - uri.path.replace(/#.*/, ""), // REQUEST_URI - uri.asciiHost, // HTTP_HOST - Utils.httpProtocol.userAgent // HTTP_USER_AGENT - ]; - if (Utils.verifySignature(key, signature, params.join("\0"))) - match = keyMatch; - } - } - } - - if (match instanceof WhitelistFilter) - { - FilterStorage.increaseHitCount(match, wnd); - RequestNotifier.addNodeData(testWnd.document, topWnd, Policy.type.DOCUMENT, getHostname(parentWndLocation), false, testWndLocation, match); - return true; - } - - if (testWnd.parent == testWnd) - break; - else - testWnd = testWnd.parent; - } - } - - // Data loaded by plugins should be attached to the document - if (contentType == Policy.type.OBJECT_SUBREQUEST && node instanceof Ci.nsIDOMElement) - node = node.ownerDocument; - - // Fix type for objects misrepresented as frames or images - if (contentType != Policy.type.OBJECT && (node instanceof Ci.nsIDOMHTMLObjectElement || node instanceof Ci.nsIDOMHTMLEmbedElement)) - contentType = Policy.type.OBJECT; - - let locationText = location.spec; - if (!match && contentType == Policy.type.ELEMHIDE) - { - let testWnd = wnd; - let parentWndLocation = getWindowLocation(testWnd); - while (true) - { - let testWndLocation = parentWndLocation; - parentWndLocation = (testWnd == testWnd.parent ? testWndLocation : getWindowLocation(testWnd.parent)); - let parentDocDomain = getHostname(parentWndLocation); - match = defaultMatcher.matchesAny(testWndLocation, "ELEMHIDE", parentDocDomain, false); - if (match instanceof WhitelistFilter) - { - FilterStorage.increaseHitCount(match, wnd); - RequestNotifier.addNodeData(testWnd.document, topWnd, contentType, parentDocDomain, false, testWndLocation, match); - return true; - } - - if (testWnd.parent == testWnd) - break; - else - testWnd = testWnd.parent; - } - - match = location; - locationText = match.text.replace(/^.*?#/, '#'); - location = locationText; - - if (!match.isActiveOnDomain(docDomain)) - return true; - - let exception = ElemHide.getException(match, docDomain); - if (exception) - { - FilterStorage.increaseHitCount(exception, wnd); - RequestNotifier.addNodeData(node, topWnd, contentType, docDomain, thirdParty, locationText, exception); - return true; - } - } - - let thirdParty = (contentType == Policy.type.ELEMHIDE ? false : isThirdParty(location, docDomain)); - - if (!match && Prefs.enabled) - { - match = defaultMatcher.matchesAny(locationText, Policy.typeDescr[contentType] || "", docDomain, thirdParty, privatenode); - if (match instanceof BlockingFilter && node.ownerDocument && !(contentType in Policy.nonVisual)) - { - let prefCollapse = (match.collapse != null ? match.collapse : !Prefs.fastcollapse); - if (collapse || prefCollapse) - schedulePostProcess(node); - } - - // Track mouse events for objects - if (!match && contentType == Policy.type.OBJECT && node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) - { - node.addEventListener("mouseover", objectMouseEventHander, true); - node.addEventListener("mouseout", objectMouseEventHander, true); - } - } - - // Store node data - RequestNotifier.addNodeData(node, topWnd, contentType, docDomain, thirdParty, locationText, match); - if (match) - FilterStorage.increaseHitCount(match, wnd); - - return !match || match instanceof WhitelistFilter; - }, - - /** - * Checks whether the location's scheme is blockable. - * @param location {nsIURI} - * @return {Boolean} - */ - isBlockableScheme: function(location) - { - return !(location.scheme in Policy.whitelistSchemes); - }, - - /** - * Checks whether a page is whitelisted. - * @param {String} url - * @param {String} [parentUrl] location of the parent page - * @return {Filter} filter that matched the URL or null if not whitelisted - */ - isWhitelisted: function(url, parentUrl) - { - if (!url) - return null; - - // Do not apply exception rules to schemes on our whitelistschemes list. - let match = /^([\w\-]+):/.exec(url); - if (match && match[1] in Policy.whitelistSchemes) - return null; - - if (!parentUrl) - parentUrl = url; - - // Ignore fragment identifier - let index = url.indexOf("#"); - if (index >= 0) - url = url.substring(0, index); - - let result = defaultMatcher.matchesAny(url, "DOCUMENT", getHostname(parentUrl), false); - return (result instanceof WhitelistFilter ? result : null); - }, - - /** - * Checks whether the page loaded in a window is whitelisted. - * @param wnd {nsIDOMWindow} - * @return {Filter} matching exception rule or null if not whitelisted - */ - isWindowWhitelisted: function(wnd) - { - return Policy.isWhitelisted(getWindowLocation(wnd)); - }, - - - /** - * Asynchronously re-checks filters for given nodes. - */ - refilterNodes: function(/**Node[]*/ nodes, /**RequestEntry*/ entry) - { - // Ignore nodes that have been blocked already - if (entry.filter && !(entry.filter instanceof WhitelistFilter)) - return; - - for (let node of nodes) - Utils.runAsync(refilterNode, this, node, entry); - } -}; -Policy.init(); - -/** - * Actual nsIContentPolicy and nsIChannelEventSink implementation - * @class - */ -let PolicyImplementation = -{ - classDescription: "Adblock Plus content policy", - classID: Components.ID("cfeaabe6-1dd1-11b2-a0c6-cb5c268894c9"), - contractID: "@adblockplus.org/abp/policy;1", - xpcom_categories: ["content-policy", "net-channel-event-sinks"], - - /** - * Registers the content policy on startup. - */ - init: function() - { - let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - try - { - registrar.registerFactory(this.classID, this.classDescription, this.contractID, this); - } - catch (e if e.result == Cr.NS_ERROR_FACTORY_EXISTS) - { - // See bug 924340 - it might be too early to init now, the old version - // we are replacing didn't finish removing itself yet. - Utils.runAsync(this.init.bind(this)); - return; - } - - let catMan = Utils.categoryManager; - for (let category of this.xpcom_categories) - catMan.addCategoryEntry(category, this.contractID, this.contractID, false, true); - - // http-on-opening-request is new in Gecko 18, http-on-modify-request can - // be used in earlier releases. - let httpTopic = "http-on-opening-request"; - if (Services.vc.compare(Utils.platformVersion, "18.0") < 0) - httpTopic = "http-on-modify-request"; - - Services.obs.addObserver(this, httpTopic, true); - Services.obs.addObserver(this, "content-document-global-created", true); - Services.obs.addObserver(this, "xpcom-category-entry-removed", true); - Services.obs.addObserver(this, "xpcom-category-cleared", true); - - onShutdown.add(function() - { - // Our category observers should be removed before changing category - // memberships, just in case. - Services.obs.removeObserver(this, httpTopic); - Services.obs.removeObserver(this, "content-document-global-created"); - Services.obs.removeObserver(this, "xpcom-category-entry-removed"); - Services.obs.removeObserver(this, "xpcom-category-cleared"); - - for (let category of this.xpcom_categories) - catMan.deleteCategoryEntry(category, this.contractID, false); - - // This needs to run asynchronously, see bug 753687 - Utils.runAsync(function() - { - registrar.unregisterFactory(this.classID, this); - }.bind(this)); - - this.previousRequest = null; - }.bind(this)); - }, - - // - // nsISupports interface implementation - // - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy, Ci.nsIObserver, - Ci.nsIChannelEventSink, Ci.nsIFactory, Ci.nsISupportsWeakReference]), - - // - // nsIContentPolicy interface implementation - // - - shouldLoad: function(contentType, contentLocation, requestOrigin, node, mimeTypeGuess, extra) - { - // Ignore requests without context and top-level documents - if (!node || contentType == Policy.type.DOCUMENT) - return Ci.nsIContentPolicy.ACCEPT; - - // Ignore standalone objects - if (contentType == Policy.type.OBJECT && node.ownerDocument && !/^text\/|[+\/]xml$/.test(node.ownerDocument.contentType)) - return Ci.nsIContentPolicy.ACCEPT; - - let wnd = Utils.getWindow(node); - if (!wnd) - return Ci.nsIContentPolicy.ACCEPT; - - // Ignore whitelisted schemes - let location = Utils.unwrapURL(contentLocation); - if (!Policy.isBlockableScheme(location)) - return Ci.nsIContentPolicy.ACCEPT; - - // Interpret unknown types as "other" - if (!(contentType in Policy.typeDescr)) - contentType = Policy.type.OTHER; - - let result = Policy.processNode(wnd, node, contentType, location, false); - if (result) - { - // We didn't block this request so we will probably see it again in - // http-on-opening-request. Keep it so that we can associate it with the - // channel there - will be needed in case of redirect. - this.previousRequest = [location, contentType]; - } - return (result ? Ci.nsIContentPolicy.ACCEPT : Ci.nsIContentPolicy.REJECT_REQUEST); - }, - - shouldProcess: function(contentType, contentLocation, requestOrigin, insecNode, mimeType, extra) - { - return Ci.nsIContentPolicy.ACCEPT; - }, - - // - // nsIObserver interface implementation - // - observe: function(subject, topic, data, additional) - { - switch (topic) - { - case "content-document-global-created": - { - if (!(subject instanceof Ci.nsIDOMWindow) || !subject.opener) - return; - - let uri = additional || Utils.makeURI(subject.location.href); - if (!Policy.processNode(subject.opener, subject.opener.document, Policy.type.POPUP, uri, false)) - { - subject.stop(); - Utils.runAsync(subject.close, subject); - } - else if (uri.spec == "about:blank") - { - // An about:blank pop-up most likely means that a load will be - // initiated synchronously. Set a flag for our "http-on-opening-request" - // handler. - this.expectingPopupLoad = true; - Utils.runAsync(function() - { - this.expectingPopupLoad = false; - }); - } - break; - } - case "http-on-opening-request": - case "http-on-modify-request": - { - if (!(subject instanceof Ci.nsIHttpChannel)) - return; - - if (this.previousRequest && subject.URI == this.previousRequest[0] && - subject instanceof Ci.nsIWritablePropertyBag) - { - // We just handled a content policy call for this request - associate - // the data with the channel so that we can find it in case of a redirect. - subject.setProperty("abpRequestType", this.previousRequest[1]); - this.previousRequest = null; - } - - if (this.expectingPopupLoad) - { - let wnd = Utils.getRequestWindow(subject); - if (wnd && wnd.opener && wnd.location.href == "about:blank") - { - this.observe(wnd, "content-document-global-created", null, subject.URI); - if (subject instanceof Ci.nsIWritablePropertyBag) - subject.setProperty("abpRequestType", Policy.type.POPUP); - } - } - - break; - } - case "xpcom-category-entry-removed": - case "xpcom-category-cleared": - { - let category = data; - if (this.xpcom_categories.indexOf(category) < 0) - return; - - if (topic == "xpcom-category-entry-removed" && - subject instanceof Ci.nsISupportsCString && - subject.data != this.contractID) - { - return; - } - - // Our category entry was removed, make sure to add it back - let catMan = Utils.categoryManager; - catMan.addCategoryEntry(category, this.contractID, this.contractID, false, true); - break; - } - } - }, - - // - // nsIChannelEventSink interface implementation - // - - asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) - { - let result = Cr.NS_OK; - try - { - // Try to retrieve previously stored request data from the channel - let contentType; - if (oldChannel instanceof Ci.nsIWritablePropertyBag) - { - try - { - contentType = oldChannel.getProperty("abpRequestType"); - } - catch(e) - { - // No data attached, ignore this redirect - return; - } - } - - let newLocation = null; - try - { - newLocation = newChannel.URI; - } catch(e2) {} - if (!newLocation) - return; - - let wnd = Utils.getRequestWindow(newChannel); - if (!wnd) - return; - - if (contentType == Policy.type.SUBDOCUMENT && wnd.parent == wnd.top && wnd.opener) - { - // This is a window opened in a new tab miscategorized as frame load, - // see bug 467514. Get the frame as context to be at least consistent. - wnd = wnd.opener; - } - - if (contentType == Policy.type.POPUP && wnd.opener) - { - // Popups are initiated by their opener, not their own window. - wnd = wnd.opener; - } - - if (!Policy.processNode(wnd, wnd.document, contentType, newLocation, false)) - result = Cr.NS_BINDING_ABORTED; - } - catch (e) - { - // We shouldn't throw exceptions here - this will prevent the redirect. - Cu.reportError(e); - } - finally - { - callback.onRedirectVerifyCallback(result); - } - }, - - // - // nsIFactory interface implementation - // - - createInstance: function(outer, iid) - { - if (outer) - throw Cr.NS_ERROR_NO_AGGREGATION; - return this.QueryInterface(iid); - } -}; -PolicyImplementation.init(); - -/** - * Nodes scheduled for post-processing (might be null). - * @type Array of Node - */ -let scheduledNodes = null; - -/** - * Schedules a node for post-processing. - */ -function schedulePostProcess(/**Element*/ node) -{ - if (scheduledNodes) - scheduledNodes.push(node); - else - { - scheduledNodes = [node]; - Utils.runAsync(postProcessNodes); - } -} - -/** - * Processes nodes scheduled for post-processing (typically hides them). - */ -function postProcessNodes() -{ - let nodes = scheduledNodes; - scheduledNodes = null; - - for (let node of nodes) - { - // adjust frameset's cols/rows for frames - let parentNode = node.parentNode; - if (parentNode && parentNode instanceof Ci.nsIDOMHTMLFrameSetElement) - { - let hasCols = (parentNode.cols && parentNode.cols.indexOf(",") > 0); - let hasRows = (parentNode.rows && parentNode.rows.indexOf(",") > 0); - if ((hasCols || hasRows) && !(hasCols && hasRows)) - { - let index = -1; - for (let frame = node; frame; frame = frame.previousSibling) - if (frame instanceof Ci.nsIDOMHTMLFrameElement || frame instanceof Ci.nsIDOMHTMLFrameSetElement) - index++; - - let property = (hasCols ? "cols" : "rows"); - let weights = parentNode[property].split(","); - weights[index] = "0"; - parentNode[property] = weights.join(","); - } - } - else - node.classList.add(collapsedClass); - } -} - -/** - * Extracts the hostname from a URL (might return null). - */ -function getHostname(/**String*/ url) /**String*/ -{ - try - { - return Utils.unwrapURL(url).host; - } - catch(e) - { - return null; - } -} - -/** - * Retrieves the location of a window. - * @param wnd {nsIDOMWindow} - * @return {String} window location or null on failure - */ -function getWindowLocation(wnd) -{ - if ("name" in wnd && wnd.name == "messagepane") - { - // Thunderbird branch - try - { - let mailWnd = wnd.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindow); - - // Typically we get a wrapped mail window here, need to unwrap - try - { - mailWnd = mailWnd.wrappedJSObject; - } catch(e) {} - - if ("currentHeaderData" in mailWnd && "content-base" in mailWnd.currentHeaderData) - { - return mailWnd.currentHeaderData["content-base"].headerValue; - } - else if ("currentHeaderData" in mailWnd && "from" in mailWnd.currentHeaderData) - { - let emailAddress = Utils.headerParser.extractHeaderAddressMailboxes(mailWnd.currentHeaderData.from.headerValue); - if (emailAddress) - return 'mailto:' + emailAddress.replace(/^[\s"]+/, "").replace(/[\s"]+$/, "").replace(/\s/g, '%20'); - } - } catch(e) {} - } - - // Firefox branch - return wnd.location.href; -} - -/** - * Checks whether the location's origin is different from document's origin. - */ -function isThirdParty(/**nsIURI*/location, /**String*/ docDomain) /**Boolean*/ -{ - if (!location || !docDomain) - return true; - - try - { - return Utils.effectiveTLD.getBaseDomain(location) != Utils.effectiveTLD.getBaseDomainFromHost(docDomain); - } - catch (e) - { - // EffectiveTLDService throws on IP addresses, just compare the host name - let host = ""; - try - { - host = location.host; - } catch (e) {} - return host != docDomain; - } -} - -/** - * Re-checks filters on an element. - */ -function refilterNode(/**Node*/ node, /**RequestEntry*/ entry) -{ - let wnd = Utils.getWindow(node); - if (!wnd || wnd.closed) - return; - - if (entry.type == Policy.type.OBJECT) - { - node.removeEventListener("mouseover", objectMouseEventHander, true); - node.removeEventListener("mouseout", objectMouseEventHander, true); - } - Policy.processNode(wnd, node, entry.type, Utils.makeURI(entry.location), true); -} diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/customizableUI.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/customizableUI.js deleted file mode 100644 index 7db7425..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/customizableUI.js +++ /dev/null @@ -1,320 +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/>. - */ - -/** - * @fileOverview This emulates a subset of the CustomizableUI API from Firefox 28. - */ - -let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", null); - -let {Utils} = require("utils"); - -// UI module has to be referenced lazily to avoid circular references -XPCOMUtils.defineLazyGetter(this, "UI", () => require("ui").UI); - -let widgets = Map(); - -function getToolbox(/**Window*/ window, /**Widget*/ widget) /**Element*/ -{ - if (!("defaultArea" in widget) || !widget.defaultArea) - return null; - - let toolbar = UI.findElement(window, widget.defaultArea); - if (!toolbar) - return null; - - let toolbox = toolbar.toolbox; - if (toolbox && ("palette" in toolbox) && toolbox.palette) - return toolbox; - else - return null; -} - -function getToolbar(/**Element*/ element) /**Element*/ -{ - for (let parent = element.parentNode; parent; parent = parent.parentNode) - if (parent.localName == "toolbar") - return parent; - return null; -} - -function getPaletteItem(/**Element*/ toolbox, /**String*/ id) /**Element*/ -{ - for (let child of toolbox.palette.children) - if (child.id == id) - return child; - - return null; -} - -function restoreWidget(/**Element*/ toolbox, /**Widget*/ widget) -{ - // Create node - let node = widget.onBuild(toolbox.ownerDocument); - - // Insert into the palette first - toolbox.palette.insertBefore(node, toolbox.palette.firstChild); - - // Now find out where we should put it - let position = toolbox.getAttribute(widget.positionAttribute); - if (!/^\S*,\S*,\S*$/.test(position)) - position = null; - - if (position == null) - { - // No explicitly saved position but maybe we can find it in a currentset - // attribute somewhere. - let toolbars = toolbox.externalToolbars.slice(); - for (let child of toolbox.children) - if (child.localName == "toolbar") - toolbars.push(child); - for (let toolbar of toolbars) - { - let currentSet = toolbar.getAttribute("currentset"); - if (currentSet) - { - let items = currentSet.split(","); - let index = items.indexOf(widget.id); - if (index >= 0) - { - let before = (index + 1 < items.length ? items[index + 1] : ""); - position = "visible," + toolbar.id + "," + before; - toolbox.setAttribute(widget.positionAttribute, position); - toolbox.ownerDocument.persist(toolbox.id, widget.positionAttribute); - break; - } - } - } - } - - showWidget(toolbox, widget, position); -} - -function showWidget(/**Element*/ toolbox, /**Widget*/ widget, /**String*/ position) -{ - let visible = "visible", parent = null, before = null; - if (position) - { - [visible, parent, before] = position.split(",", 3); - parent = toolbox.ownerDocument.getElementById(parent); - if (before == "") - before = null; - else - before = toolbox.ownerDocument.getElementById(before); - if (before && before.parentNode != parent) - before = null; - } - - if (visible == "visible" && !parent) - { - let insertionPoint = { - parent: widget.defaultArea - }; - if (typeof widget.defaultBefore != "undefined") - insertionPoint.before = widget.defaultBefore; - if (typeof widget.defaultAfter != "undefined") - insertionPoint.after = widget.defaultAfter; - - [parent, before] = UI.resolveInsertionPoint(toolbox.ownerDocument.defaultView, insertionPoint); - } - - if (parent && parent.localName != "toolbar") - parent = null; - - if (visible != "visible") - { - // Move to palette if the item is currently visible - let node = toolbox.ownerDocument.getElementById(widget.id); - if (node) - toolbox.palette.appendChild(node); - } - else if (parent) - { - // Add the item to the toolbar - let items = parent.currentSet.split(","); - let index = (before ? items.indexOf(before.id) : -1); - if (index < 0) - before = null; - parent.insertItem(widget.id, before, null, false); - } - - saveState(toolbox, widget); -} - -function removeWidget(/**Window*/ window, /**Widget*/ widget) -{ - let element = window.document.getElementById(widget.id); - if (element) - element.parentNode.removeChild(element); - - let toolbox = getToolbox(window, widget); - if (toolbox) - { - let paletteItem = getPaletteItem(toolbox, widget.id); - if (paletteItem) - paletteItem.parentNode.removeChild(paletteItem); - } -} - -function onToolbarCustomization(/**Event*/ event) -{ - let toolbox = event.currentTarget; - for (let [id, widget] of widgets) - saveState(toolbox, widget); -} - -function saveState(/**Element*/ toolbox, /**Widget*/ widget) -{ - let node = toolbox.ownerDocument.getElementById(widget.id); - - let position = toolbox.getAttribute(widget.positionAttribute) || "hidden,,"; - if (node && node.parentNode.localName != "toolbarpalette") - { - if (typeof widget.onAdded == "function") - widget.onAdded(node) - - let toolbar = getToolbar(node); - position = "visible," + toolbar.id + "," + (node.nextSibling ? node.nextSibling.id : ""); - } - else - position = position.replace(/^visible,/, "hidden,") - - toolbox.setAttribute(widget.positionAttribute, position); - toolbox.ownerDocument.persist(toolbox.id, widget.positionAttribute); -} - -let CustomizableUI = exports.CustomizableUI = -{ - createWidget: function(widget) - { - if (typeof widget.id == "undefined" || - typeof widget.defaultArea == "undefined" || - typeof widget.positionAttribute == "undefined") - { - throw new Error("Unexpected: required property missing from the widget data"); - } - widgets.set(widget.id, widget); - - // Show widget in any existing windows - for (let window of UI.applicationWindows) - { - let toolbox = getToolbox(window, widget); - if (toolbox) - { - toolbox.addEventListener("aftercustomization", onToolbarCustomization, false); - restoreWidget(toolbox, widget); - } - } - }, - - destroyWidget: function(id) - { - // Don't do anything here. This function is called on shutdown, - // removeFromWindow will take care of cleaning up already. - }, - - getPlacementOfWidget: function(id) - { - let window = UI.currentWindow; - if (!window) - return null; - - let widget = window.document.getElementById(id); - if (!widget) - return null; - - let toolbar = getToolbar(widget); - if (!toolbar) - return null; - - return {area: toolbar.id}; - }, - - addWidgetToArea: function(id) - { - // Note: the official API function also has area and position parameters. - // We ignore those here and simply restore the previous position instead. - let widget = widgets.get(id); - for (let window of UI.applicationWindows) - { - let toolbox = getToolbox(window, widget); - if (!toolbox) - continue; - - let position = toolbox.getAttribute(widget.positionAttribute); - if (position) - position = position.replace(/^hidden,/, "visible,"); - showWidget(toolbox, widget, position); - } - }, - - removeWidgetFromArea: function(id) - { - let widget = widgets.get(id); - for (let window of UI.applicationWindows) - { - let toolbox = getToolbox(window, widget); - if (!toolbox) - continue; - - let position = toolbox.getAttribute(widget.positionAttribute); - if (position) - position = position.replace(/^visible,/, "hidden,"); - else - position = "hidden,,"; - showWidget(toolbox, widget, position); - } - } -}; - -let {WindowObserver} = require("windowObserver"); -new WindowObserver({ - applyToWindow: function(window) - { - let {isKnownWindow} = require("appSupport"); - if (!isKnownWindow(window)) - return; - - for (let [id, widget] of widgets) - { - let toolbox = getToolbox(window, widget); - if (toolbox) - { - toolbox.addEventListener("aftercustomization", onToolbarCustomization, false); - - // Restore widget asynchronously to allow the stylesheet to load - Utils.runAsync(restoreWidget.bind(null, toolbox, widget)); - } - } - }, - - removeFromWindow: function(window) - { - let {isKnownWindow} = require("appSupport"); - if (!isKnownWindow(window)) - return; - - for (let [id, widget] of widgets) - { - let toolbox = getToolbox(window, widget); - if (toolbox) - toolbox.removeEventListener("aftercustomization", onToolbarCustomization, false); - - removeWidget(window, widget); - } - } -}); diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/downloader.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/downloader.js deleted file mode 100644 index d1ef209..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/downloader.js +++ /dev/null @@ -1,381 +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/>. - */ - -/** - * @fileOverview Downloads a set of URLs in regular time intervals. - */ - -let {Utils} = require("utils"); - -let MILLIS_IN_SECOND = exports.MILLIS_IN_SECOND = 1000; -let MILLIS_IN_MINUTE = exports.MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND; -let MILLIS_IN_HOUR = exports.MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE; -let MILLIS_IN_DAY = exports.MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR; - -/** - * Creates a new downloader instance. - * @param {Function} dataSource Function that will yield downloadable objects on each check - * @param {Integer} initialDelay Number of milliseconds to wait before the first check - * @param {Integer} checkInterval Interval between the checks - * @constructor - */ -let Downloader = exports.Downloader = function Downloader(dataSource, initialDelay, checkInterval) -{ - this.dataSource = dataSource; - this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this._timer.initWithCallback(function() - { - this._timer.delay = checkInterval; - this._doCheck(); - }.bind(this), initialDelay, Ci.nsITimer.TYPE_REPEATING_SLACK); - this._downloading = Object.create(null); -} -Downloader.prototype = -{ - /** - * Timer triggering the downloads. - * @type nsITimer - */ - _timer: null, - - /** - * Map containing the URLs of objects currently being downloaded as its keys. - */ - _downloading: null, - - /** - * Function that will yield downloadable objects on each check. - * @type Function - */ - dataSource: null, - - /** - * Maximal time interval that the checks can be left out until the soft - * expiration interval increases. - * @type Integer - */ - maxAbsenceInterval: 1 * MILLIS_IN_DAY, - - /** - * Minimal time interval before retrying a download after an error. - * @type Integer - */ - minRetryInterval: 1 * MILLIS_IN_DAY, - - /** - * Maximal allowed expiration interval, larger expiration intervals will be - * corrected. - * @type Integer - */ - maxExpirationInterval: 14 * MILLIS_IN_DAY, - - /** - * Maximal number of redirects before the download is considered as failed. - * @type Integer - */ - maxRedirects: 5, - - /** - * Called whenever expiration intervals for an object need to be adapted. - * @type Function - */ - onExpirationChange: null, - - /** - * Callback to be triggered whenever a download starts. - * @type Function - */ - onDownloadStarted: null, - - /** - * Callback to be triggered whenever a download finishes successfully. The - * callback can return an error code to indicate that the data is wrong. - * @type Function - */ - onDownloadSuccess: null, - - /** - * Callback to be triggered whenever a download fails. - * @type Function - */ - onDownloadError: null, - - /** - * Checks whether anything needs downloading. - */ - _doCheck: function() - { - let now = Date.now(); - for (let downloadable of this.dataSource()) - { - if (downloadable.lastCheck && now - downloadable.lastCheck > this.maxAbsenceInterval) - { - // No checks for a long time interval - user must have been offline, e.g. - // during a weekend. Increase soft expiration to prevent load peaks on the - // server. - downloadable.softExpiration += now - downloadable.lastCheck; - } - downloadable.lastCheck = now; - - // Sanity check: do expiration times make sense? Make sure people changing - // system clock don't get stuck with outdated subscriptions. - if (downloadable.hardExpiration - now > this.maxExpirationInterval) - downloadable.hardExpiration = now + this.maxExpirationInterval; - if (downloadable.softExpiration - now > this.maxExpirationInterval) - downloadable.softExpiration = now + this.maxExpirationInterval; - - // Notify the caller about changes to expiration parameters - if (this.onExpirationChange) - this.onExpirationChange(downloadable); - - // Does that object need downloading? - if (downloadable.softExpiration > now && downloadable.hardExpiration > now) - continue; - - // Do not retry downloads too often - if (downloadable.lastError && now - downloadable.lastError < this.minRetryInterval) - continue; - - this._download(downloadable, 0); - } - }, - - /** - * Stops the periodic checks. - */ - cancel: function() - { - this._timer.cancel(); - }, - - /** - * Checks whether an address is currently being downloaded. - */ - isDownloading: function(/**String*/ url) /**Boolean*/ - { - return url in this._downloading; - }, - - /** - * Starts downloading for an object. - */ - download: function(/**Downloadable*/ downloadable) - { - // Make sure to detach download from the current execution context - Utils.runAsync(this._download.bind(this, downloadable, 0)); - }, - - /** - * Generates the real download URL for an object by appending various - * parameters. - */ - getDownloadUrl: function(/**Downloadable*/ downloadable) /** String*/ - { - let {addonName, addonVersion, application, applicationVersion, platform, platformVersion} = require("info"); - let url = downloadable.redirectURL || downloadable.url; - if (url.indexOf("?") >= 0) - url += "&"; - else - url += "?"; - url += "addonName=" + encodeURIComponent(addonName) + - "&addonVersion=" + encodeURIComponent(addonVersion) + - "&application=" + encodeURIComponent(application) + - "&applicationVersion=" + encodeURIComponent(applicationVersion) + - "&platform=" + encodeURIComponent(platform) + - "&platformVersion=" + encodeURIComponent(platformVersion) + - "&lastVersion=" + encodeURIComponent(downloadable.lastVersion); - return url; - }, - - _download: function(downloadable, redirects) - { - if (this.isDownloading(downloadable.url)) - return; - - let downloadUrl = this.getDownloadUrl(downloadable); - let request = null; - - let errorCallback = function errorCallback(error) - { - let channelStatus = -1; - try - { - channelStatus = request.channel.status; - } catch (e) {} - - let responseStatus = request.status; - - Cu.reportError("Adblock Plus: Downloading URL " + downloadable.url + " failed (" + error + ")\n" + - "Download address: " + downloadUrl + "\n" + - "Channel status: " + channelStatus + "\n" + - "Server response: " + responseStatus); - - if (this.onDownloadError) - { - // Allow one extra redirect if the error handler gives us a redirect URL - let redirectCallback = null; - if (redirects <= this.maxRedirects) - { - redirectCallback = function redirectCallback(url) - { - downloadable.redirectURL = url; - this._download(downloadable, redirects + 1); - }.bind(this); - } - - this.onDownloadError(downloadable, downloadUrl, error, channelStatus, responseStatus, redirectCallback); - } - }.bind(this); - - try - { - request = new XMLHttpRequest(); - request.mozBackgroundRequest = true; - request.open("GET", downloadUrl); - } - catch (e) - { - errorCallback("synchronize_invalid_url"); - return; - } - - try { - request.overrideMimeType("text/plain"); - request.channel.loadFlags = request.channel.loadFlags | - request.channel.INHIBIT_CACHING | - request.channel.VALIDATE_ALWAYS; - - // Override redirect limit from preferences, user might have set it to 1 - if (request.channel instanceof Ci.nsIHttpChannel) - request.channel.redirectionLimit = this.maxRedirects; - } - catch (e) - { - Cu.reportError(e) - } - - request.addEventListener("error", function(event) - { - if (onShutdown.done) - return; - - delete this._downloading[downloadable.url]; - errorCallback("synchronize_connection_error"); - }.bind(this), false); - - request.addEventListener("load", function(event) - { - if (onShutdown.done) - return; - - delete this._downloading[downloadable.url]; - - // Status will be 0 for non-HTTP requests - if (request.status && request.status != 200) - { - errorCallback("synchronize_connection_error"); - return; - } - - this.onDownloadSuccess(downloadable, request.responseText, errorCallback, function redirectCallback(url) - { - if (redirects >= this.maxRedirects) - errorCallback("synchronize_connection_error"); - else - { - downloadable.redirectURL = url; - this._download(downloadable, redirects + 1); - } - }.bind(this)); - }.bind(this), false); - - request.send(null); - - this._downloading[downloadable.url] = true; - if (this.onDownloadStarted) - this.onDownloadStarted(downloadable); - }, - - /** - * Produces a soft and a hard expiration interval for a given supplied - * expiration interval. - * @return {Array} soft and hard expiration interval - */ - processExpirationInterval: function(/**Integer*/ interval) - { - interval = Math.min(Math.max(interval, 0), this.maxExpirationInterval); - let soft = Math.round(interval * (Math.random() * 0.4 + 0.8)); - let hard = interval * 2; - let now = Date.now(); - return [now + soft, now + hard]; - } -}; - -/** - * An object that can be downloaded by the downloadable - * @param {String} url URL that has to be requested for the object - * @constructor - */ -let Downloadable = exports.Downloadable = function Downloadable(url) -{ - this.url = url; -} -Downloadable.prototype = -{ - /** - * URL that has to be requested for the object. - * @type String - */ - url: null, - - /** - * URL that the download was redirected to if any. - * @type String - */ - redirectURL: null, - - /** - * Time of last download error or 0 if the last download was successful. - * @type Integer - */ - lastError: 0, - - /** - * Time of last check whether the object needs downloading. - * @type Integer - */ - lastCheck: 0, - - /** - * Object version corresponding to the last successful download. - * @type Integer - */ - lastVersion: 0, - - /** - * Soft expiration interval, will increase if no checks are performed for a - * while. - * @type Integer - */ - softExpiration: 0, - - /** - * Hard expiration interval, this is fixed. - * @type Integer - */ - hardExpiration: 0, -}; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/elemHide.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/elemHide.js deleted file mode 100644 index df17a0f..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/elemHide.js +++ /dev/null @@ -1,419 +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/>. - */ - -/** - * @fileOverview Element hiding implementation. - */ - -Cu.import("resource://gre/modules/Services.jsm"); - -let {Utils} = require("utils"); -let {IO} = require("io"); -let {Prefs} = require("prefs"); -let {ElemHideException} = require("filterClasses"); -let {FilterNotifier} = require("filterNotifier"); -let {AboutHandler} = require("elemHideHitRegistration"); -let {TimeLine} = require("timeline"); - -/** - * Lookup table, filters by their associated key - * @type Object - */ -let filterByKey = {__proto__: null}; - -/** - * Lookup table, keys of the filters by filter text - * @type Object - */ -let keyByFilter = {__proto__: null}; - -/** - * Lookup table, keys are known element hiding exceptions - * @type Object - */ -let knownExceptions = {__proto__: null}; - -/** - * Lookup table, lists of element hiding exceptions by selector - * @type Object - */ -let exceptions = {__proto__: null}; - -/** - * Currently applied stylesheet URL - * @type nsIURI - */ -let styleURL = null; - -/** - * Element hiding component - * @class - */ -let ElemHide = exports.ElemHide = -{ - /** - * Indicates whether filters have been added or removed since the last apply() call. - * @type Boolean - */ - isDirty: false, - - /** - * Inidicates whether the element hiding stylesheet is currently applied. - * @type Boolean - */ - applied: false, - - /** - * Called on module startup. - */ - init: function() - { - TimeLine.enter("Entered ElemHide.init()"); - Prefs.addListener(function(name) - { - if (name == "enabled") - ElemHide.apply(); - }); - onShutdown.add(function() - { - ElemHide.unapply(); - }); - - TimeLine.log("done adding prefs listener"); - - let styleFile = IO.resolveFilePath(Prefs.data_directory); - styleFile.append("elemhide.css"); - styleURL = Services.io.newFileURI(styleFile).QueryInterface(Ci.nsIFileURL); - TimeLine.log("done determining stylesheet URL"); - - TimeLine.leave("ElemHide.init() done"); - }, - - /** - * Removes all known filters - */ - clear: function() - { - filterByKey = {__proto__: null}; - keyByFilter = {__proto__: null}; - knownExceptions = {__proto__: null}; - exceptions = {__proto__: null}; - ElemHide.isDirty = false; - ElemHide.unapply(); - }, - - /** - * Add a new element hiding filter - * @param {ElemHideFilter} filter - */ - add: function(filter) - { - if (filter instanceof ElemHideException) - { - if (filter.text in knownExceptions) - return; - - let selector = filter.selector; - if (!(selector in exceptions)) - exceptions[selector] = []; - exceptions[selector].push(filter); - knownExceptions[filter.text] = true; - } - else - { - if (filter.text in keyByFilter) - return; - - let key; - do { - key = Math.random().toFixed(15).substr(5); - } while (key in filterByKey); - - filterByKey[key] = filter; - keyByFilter[filter.text] = key; - ElemHide.isDirty = true; - } - }, - - /** - * Removes an element hiding filter - * @param {ElemHideFilter} filter - */ - remove: function(filter) - { - if (filter instanceof ElemHideException) - { - if (!(filter.text in knownExceptions)) - return; - - let list = exceptions[filter.selector]; - let index = list.indexOf(filter); - if (index >= 0) - list.splice(index, 1); - delete knownExceptions[filter.text]; - } - else - { - if (!(filter.text in keyByFilter)) - return; - - let key = keyByFilter[filter.text]; - delete filterByKey[key]; - delete keyByFilter[filter.text]; - ElemHide.isDirty = true; - } - }, - - /** - * Checks whether an exception rule is registered for a filter on a particular - * domain. - */ - getException: function(/**Filter*/ filter, /**String*/ docDomain) /**ElemHideException*/ - { - let selector = filter.selector; - if (!(filter.selector in exceptions)) - return null; - - let list = exceptions[filter.selector]; - for (let i = list.length - 1; i >= 0; i--) - if (list[i].isActiveOnDomain(docDomain)) - return list[i]; - - return null; - }, - - /** - * Will be set to true if apply() is running (reentrance protection). - * @type Boolean - */ - _applying: false, - - /** - * Will be set to true if an apply() call arrives while apply() is already - * running (delayed execution). - * @type Boolean - */ - _needsApply: false, - - /** - * Generates stylesheet URL and applies it globally - */ - apply: function() - { - if (this._applying) - { - this._needsApply = true; - return; - } - - TimeLine.enter("Entered ElemHide.apply()"); - - if (!ElemHide.isDirty || !Prefs.enabled) - { - // Nothing changed, looks like we merely got enabled/disabled - if (Prefs.enabled && !ElemHide.applied) - { - try - { - Utils.styleService.loadAndRegisterSheet(styleURL, Ci.nsIStyleSheetService.USER_SHEET); - ElemHide.applied = true; - } - catch (e) - { - Cu.reportError(e); - } - TimeLine.log("Applying existing stylesheet finished"); - } - else if (!Prefs.enabled && ElemHide.applied) - { - ElemHide.unapply(); - TimeLine.log("ElemHide.unapply() finished"); - } - - TimeLine.leave("ElemHide.apply() done (no file changes)"); - return; - } - - IO.writeToFile(styleURL.file, this._generateCSSContent(), function(e) - { - TimeLine.enter("ElemHide.apply() write callback"); - this._applying = false; - - // _generateCSSContent is throwing NS_ERROR_NOT_AVAILABLE to indicate that - // there are no filters. If that exception is passed through XPCOM we will - // see a proper exception here, otherwise a number. - let noFilters = (e == Cr.NS_ERROR_NOT_AVAILABLE || (e && e.result == Cr.NS_ERROR_NOT_AVAILABLE)); - if (noFilters) - { - e = null; - IO.removeFile(styleURL.file, function(e) {}); - } - else if (e) - Cu.reportError(e); - - if (this._needsApply) - { - this._needsApply = false; - this.apply(); - } - else if (!e) - { - ElemHide.isDirty = false; - - ElemHide.unapply(); - TimeLine.log("ElemHide.unapply() finished"); - - if (!noFilters) - { - try - { - Utils.styleService.loadAndRegisterSheet(styleURL, Ci.nsIStyleSheetService.USER_SHEET); - ElemHide.applied = true; - } - catch (e) - { - Cu.reportError(e); - } - TimeLine.log("Applying stylesheet finished"); - } - - FilterNotifier.triggerListeners("elemhideupdate"); - } - TimeLine.leave("ElemHide.apply() write callback done"); - }.bind(this), "ElemHideWrite"); - - this._applying = true; - - TimeLine.leave("ElemHide.apply() done", "ElemHideWrite"); - }, - - _generateCSSContent: function() - { - // Grouping selectors by domains - TimeLine.log("start grouping selectors"); - let domains = {__proto__: null}; - let hasFilters = false; - for (let key in filterByKey) - { - let filter = filterByKey[key]; - let domain = filter.selectorDomain || ""; - - let list; - if (domain in domains) - list = domains[domain]; - else - { - list = {__proto__: null}; - domains[domain] = list; - } - list[filter.selector] = key; - hasFilters = true; - } - TimeLine.log("done grouping selectors"); - - if (!hasFilters) - throw Cr.NS_ERROR_NOT_AVAILABLE; - - function escapeChar(match) - { - return "\\" + match.charCodeAt(0).toString(16) + " "; - } - - // Return CSS data - let cssTemplate = "-moz-binding: url(about:" + AboutHandler.aboutPrefix + "?%ID%#dummy) !important;"; - for (let domain in domains) - { - let rules = []; - let list = domains[domain]; - - if (domain) - yield ('@-moz-document domain("' + domain.split(",").join('"),domain("') + '"){').replace(/[^\x01-\x7F]/g, escapeChar); - else - { - // Only allow unqualified rules on a few protocols to prevent them from blocking chrome - yield '@-moz-document url-prefix("http://"),url-prefix("https://"),' - + 'url-prefix("mailbox://"),url-prefix("imap://"),' - + 'url-prefix("news://"),url-prefix("snews://"){'; - } - - for (let selector in list) - yield selector.replace(/[^\x01-\x7F]/g, escapeChar) + "{" + cssTemplate.replace("%ID%", list[selector]) + "}"; - yield '}'; - } - }, - - /** - * Unapplies current stylesheet URL - */ - unapply: function() - { - if (ElemHide.applied) - { - try - { - Utils.styleService.unregisterSheet(styleURL, Ci.nsIStyleSheetService.USER_SHEET); - } - catch (e) - { - Cu.reportError(e); - } - ElemHide.applied = false; - } - }, - - /** - * Retrieves the currently applied stylesheet URL - * @type String - */ - get styleURL() - { - return ElemHide.applied ? styleURL.spec : null; - }, - - /** - * Retrieves an element hiding filter by the corresponding protocol key - */ - getFilterByKey: function(/**String*/ key) /**Filter*/ - { - return (key in filterByKey ? filterByKey[key] : null); - }, - - /** - * Returns a list of all selectors active on a particular domain (currently - * used only in Chrome, Opera and Safari). - */ - getSelectorsForDomain: function(/**String*/ domain, /**Boolean*/ specificOnly) - { - let result = []; - for (let key in filterByKey) - { - let filter = filterByKey[key]; - - // it is important to always access filter.domains - // here, even if it isn't used, in order to - // workaround WebKit bug 132872, also see #419 - let domains = filter.domains; - - if (specificOnly && (!domains || domains[""])) - continue; - - if (filter.isActiveOnDomain(domain) && !this.getException(filter, domain)) - result.push(filter.selector); - } - return result; - } -}; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/elemHideHitRegistration.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/elemHideHitRegistration.js deleted file mode 100644 index a05f6df..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/elemHideHitRegistration.js +++ /dev/null @@ -1,160 +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/>. - */ - -/** - * @fileOverview Hit counts for element hiding. - */ - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -let {Utils} = require("utils"); - -/** - * about: URL module used to count hits. - * @class - */ -let AboutHandler = exports.AboutHandler = -{ - classID: Components.ID("{55fb7be0-1dd2-11b2-98e6-9e97caf8ba67}"), - classDescription: "Element hiding hit registration protocol handler", - aboutPrefix: "abp-elemhidehit", - - /** - * Registers handler on startup. - */ - init: function() - { - let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - registrar.registerFactory(this.classID, this.classDescription, - "@mozilla.org/network/protocol/about;1?what=" + this.aboutPrefix, this); - onShutdown.add(function() - { - registrar.unregisterFactory(this.classID, this); - }.bind(this)); - }, - - // - // Factory implementation - // - - createInstance: function(outer, iid) - { - if (outer != null) - throw Cr.NS_ERROR_NO_AGGREGATION; - - return this.QueryInterface(iid); - }, - - // - // About module implementation - // - - getURIFlags: function(uri) - { - return ("HIDE_FROM_ABOUTABOUT" in Ci.nsIAboutModule ? Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT : 0); - }, - - newChannel: function(uri) - { - let match = /\?(\d+)/.exec(uri.path) - if (!match) - throw Cr.NS_ERROR_FAILURE; - - return new HitRegistrationChannel(uri, match[1]); - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory, Ci.nsIAboutModule]) -}; -AboutHandler.init(); - -/** - * Channel returning data for element hiding hits. - * @constructor - */ -function HitRegistrationChannel(uri, key) -{ - this.key = key; - this.URI = this.originalURI = uri; -} -HitRegistrationChannel.prototype = { - key: null, - URI: null, - originalURI: null, - contentCharset: "utf-8", - contentLength: 0, - contentType: "text/xml", - owner: Utils.systemPrincipal, - securityInfo: null, - notificationCallbacks: null, - loadFlags: 0, - loadGroup: null, - name: null, - status: Cr.NS_OK, - - asyncOpen: function(listener, context) - { - let stream = this.open(); - Utils.runAsync(function() - { - try { - listener.onStartRequest(this, context); - } catch(e) {} - try { - listener.onDataAvailable(this, context, stream, 0, stream.available()); - } catch(e) {} - try { - listener.onStopRequest(this, context, Cr.NS_OK); - } catch(e) {} - }, this); - }, - - open: function() - { - let {Policy} = require("contentPolicy"); - let {ElemHide} = require("elemHide"); - let data = "<bindings xmlns='http://www.mozilla.org/xbl'><binding id='dummy'/></bindings>"; - let filter = ElemHide.getFilterByKey(this.key); - if (filter) - { - let wnd = Utils.getRequestWindow(this); - if (wnd && wnd.document && !Policy.processNode(wnd, wnd.document, Policy.type.ELEMHIDE, filter)) - data = "<bindings xmlns='http://www.mozilla.org/xbl'/>"; - } - - let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream); - stream.setData(data, data.length); - return stream; - }, - isPending: function() - { - return false; - }, - cancel: function() - { - throw Cr.NS_ERROR_NOT_IMPLEMENTED; - }, - suspend: function() - { - throw Cr.NS_ERROR_NOT_IMPLEMENTED; - }, - resume: function() - { - throw Cr.NS_ERROR_NOT_IMPLEMENTED; - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel, Ci.nsIRequest]) -}; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterClasses.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterClasses.js deleted file mode 100644 index cb3a5b1..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterClasses.js +++ /dev/null @@ -1,906 +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/>. - */ - -/** - * @fileOverview Definition of Filter class and its subclasses. - */ - -let {FilterNotifier} = require("filterNotifier"); - -/** - * Abstract base class for filters - * - * @param {String} text string representation of the filter - * @constructor - */ -function Filter(text) -{ - this.text = text; - this.subscriptions = []; -} -exports.Filter = Filter; - -Filter.prototype = -{ - /** - * String representation of the filter - * @type String - */ - text: null, - - /** - * Filter subscriptions the filter belongs to - * @type Array of Subscription - */ - subscriptions: null, - - /** - * Serializes the filter to an array of strings for writing out on the disk. - * @param {Array of String} buffer buffer to push the serialization results into - */ - serialize: function(buffer) - { - buffer.push("[Filter]"); - buffer.push("text=" + this.text); - }, - - toString: function() - { - return this.text; - } -}; - -/** - * Cache for known filters, maps string representation to filter objects. - * @type Object - */ -Filter.knownFilters = {__proto__: null}; - -/** - * Regular expression that element hiding filters should match - * @type RegExp - */ -Filter.elemhideRegExp = /^([^\/\*\|\@"!]*?)#(\@)?(?:([\w\-]+|\*)((?:\([\w\-]+(?:[$^*]?=[^\(\)"]*)?\))*)|#([^{}]+))$/; -/** - * Regular expression that RegExp filters specified as RegExps should match - * @type RegExp - */ -Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)?$/; -/** - * Regular expression that options on a RegExp filter should match - * @type RegExp - */ -Filter.optionsRegExp = /\$(~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)$/; - -/** - * Creates a filter of correct type from its text representation - does the basic parsing and - * calls the right constructor then. - * - * @param {String} text as in Filter() - * @return {Filter} - */ -Filter.fromText = function(text) -{ - if (text in Filter.knownFilters) - return Filter.knownFilters[text]; - - let ret; - let match = (text.indexOf("#") >= 0 ? Filter.elemhideRegExp.exec(text) : null); - if (match) - ret = ElemHideBase.fromText(text, match[1], match[2], match[3], match[4], match[5]); - else if (text[0] == "!") - ret = new CommentFilter(text); - else - ret = RegExpFilter.fromText(text); - - Filter.knownFilters[ret.text] = ret; - return ret; -} - -/** - * Deserializes a filter - * - * @param {Object} obj map of serialized properties and their values - * @return {Filter} filter or null if the filter couldn't be created - */ -Filter.fromObject = function(obj) -{ - let ret = Filter.fromText(obj.text); - if (ret instanceof ActiveFilter) - { - if ("disabled" in obj) - ret._disabled = (obj.disabled == "true"); - if ("hitCount" in obj) - ret._hitCount = parseInt(obj.hitCount) || 0; - if ("lastHit" in obj) - ret._lastHit = parseInt(obj.lastHit) || 0; - } - return ret; -} - -/** - * Removes unnecessary whitespaces from filter text, will only return null if - * the input parameter is null. - */ -Filter.normalize = function(/**String*/ text) /**String*/ -{ - if (!text) - return text; - - // Remove line breaks and such - text = text.replace(/[^\S ]/g, ""); - - if (/^\s*!/.test(text)) - { - // Don't remove spaces inside comments - return text.replace(/^\s+/, "").replace(/\s+$/, ""); - } - else if (Filter.elemhideRegExp.test(text)) - { - // Special treatment for element hiding filters, right side is allowed to contain spaces - let [, domain, separator, selector] = /^(.*?)(#\@?#?)(.*)$/.exec(text); - return domain.replace(/\s/g, "") + separator + selector.replace(/^\s+/, "").replace(/\s+$/, ""); - } - else - return text.replace(/\s/g, ""); -} - -/** - * Class for invalid filters - * @param {String} text see Filter() - * @param {String} reason Reason why this filter is invalid - * @constructor - * @augments Filter - */ -function InvalidFilter(text, reason) -{ - Filter.call(this, text); - - this.reason = reason; -} -exports.InvalidFilter = InvalidFilter; - -InvalidFilter.prototype = -{ - __proto__: Filter.prototype, - - /** - * Reason why this filter is invalid - * @type String - */ - reason: null, - - /** - * See Filter.serialize() - */ - serialize: function(buffer) {} -}; - -/** - * Class for comments - * @param {String} text see Filter() - * @constructor - * @augments Filter - */ -function CommentFilter(text) -{ - Filter.call(this, text); -} -exports.CommentFilter = CommentFilter; - -CommentFilter.prototype = -{ - __proto__: Filter.prototype, - - /** - * See Filter.serialize() - */ - serialize: function(buffer) {} -}; - -/** - * Abstract base class for filters that can get hits - * @param {String} text see Filter() - * @param {String} domains (optional) Domains that the filter is restricted to separated by domainSeparator e.g. "foo.com|bar.com|~baz.com" - * @constructor - * @augments Filter - */ -function ActiveFilter(text, domains) -{ - Filter.call(this, text); - - this.domainSource = domains; -} -exports.ActiveFilter = ActiveFilter; - -ActiveFilter.prototype = -{ - __proto__: Filter.prototype, - - _disabled: false, - _hitCount: 0, - _lastHit: 0, - - /** - * Defines whether the filter is disabled - * @type Boolean - */ - get disabled() - { - return this._disabled; - }, - set disabled(value) - { - if (value != this._disabled) - { - let oldValue = this._disabled; - this._disabled = value; - FilterNotifier.triggerListeners("filter.disabled", this, value, oldValue); - } - return this._disabled; - }, - - /** - * Number of hits on the filter since the last reset - * @type Number - */ - get hitCount() - { - return this._hitCount; - }, - set hitCount(value) - { - if (value != this._hitCount) - { - let oldValue = this._hitCount; - this._hitCount = value; - FilterNotifier.triggerListeners("filter.hitCount", this, value, oldValue); - } - return this._hitCount; - }, - - /** - * Last time the filter had a hit (in milliseconds since the beginning of the epoch) - * @type Number - */ - get lastHit() - { - return this._lastHit; - }, - set lastHit(value) - { - if (value != this._lastHit) - { - let oldValue = this._lastHit; - this._lastHit = value; - FilterNotifier.triggerListeners("filter.lastHit", this, value, oldValue); - } - return this._lastHit; - }, - - /** - * String that the domains property should be generated from - * @type String - */ - domainSource: null, - - /** - * Separator character used in domainSource property, must be overridden by subclasses - * @type String - */ - domainSeparator: null, - - /** - * Determines whether the trailing dot in domain names isn't important and - * should be ignored, must be overridden by subclasses. - * @type Boolean - */ - ignoreTrailingDot: true, - - /** - * Determines whether domainSource is already upper-case, - * can be overridden by subclasses. - * @type Boolean - */ - domainSourceIsUpperCase: false, - - /** - * Map containing domains that this filter should match on/not match on or null if the filter should match on all domains - * @type Object - */ - get domains() - { - let domains = null; - - if (this.domainSource) - { - let source = this.domainSource; - if (!this.domainSourceIsUpperCase) { - // RegExpFilter already have uppercase domains - source = source.toUpperCase(); - } - let list = source.split(this.domainSeparator); - if (list.length == 1 && list[0][0] != "~") - { - // Fast track for the common one-domain scenario - domains = {__proto__: null, "": false}; - if (this.ignoreTrailingDot) - list[0] = list[0].replace(/\.+$/, ""); - domains[list[0]] = true; - } - else - { - let hasIncludes = false; - for (let i = 0; i < list.length; i++) - { - let domain = list[i]; - if (this.ignoreTrailingDot) - domain = domain.replace(/\.+$/, ""); - if (domain == "") - continue; - - let include; - if (domain[0] == "~") - { - include = false; - domain = domain.substr(1); - } - else - { - include = true; - hasIncludes = true; - } - - if (!domains) - domains = {__proto__: null}; - - domains[domain] = include; - } - domains[""] = !hasIncludes; - } - - this.domainSource = null; - } - - Object.defineProperty(this, "domains", {value: domains, enumerable: true}); - return this.domains; - }, - - /** - * Checks whether this filter is active on a domain. - */ - isActiveOnDomain: function(/**String*/ docDomain) /**Boolean*/ - { - // If no domains are set the rule matches everywhere - if (!this.domains) - return true; - - // If the document has no host name, match only if the filter isn't restricted to specific domains - if (!docDomain) - return this.domains[""]; - - if (this.ignoreTrailingDot) - docDomain = docDomain.replace(/\.+$/, ""); - docDomain = docDomain.toUpperCase(); - - while (true) - { - if (docDomain in this.domains) - return this.domains[docDomain]; - - let nextDot = docDomain.indexOf("."); - if (nextDot < 0) - break; - docDomain = docDomain.substr(nextDot + 1); - } - return this.domains[""]; - }, - - /** - * Checks whether this filter is active only on a domain and its subdomains. - */ - isActiveOnlyOnDomain: function(/**String*/ docDomain) /**Boolean*/ - { - if (!docDomain || !this.domains || this.domains[""]) - return false; - - if (this.ignoreTrailingDot) - docDomain = docDomain.replace(/\.+$/, ""); - docDomain = docDomain.toUpperCase(); - - for (let domain in this.domains) - if (this.domains[domain] && domain != docDomain && (domain.length <= docDomain.length || domain.indexOf("." + docDomain) != domain.length - docDomain.length - 1)) - return false; - - return true; - }, - - /** - * See Filter.serialize() - */ - serialize: function(buffer) - { - if (this._disabled || this._hitCount || this._lastHit) - { - Filter.prototype.serialize.call(this, buffer); - if (this._disabled) - buffer.push("disabled=true"); - if (this._hitCount) - buffer.push("hitCount=" + this._hitCount); - if (this._lastHit) - buffer.push("lastHit=" + this._lastHit); - } - } -}; - -/** - * Abstract base class for RegExp-based filters - * @param {String} text see Filter() - * @param {String} regexpSource filter part that the regular expression should be build from - * @param {Number} contentType (optional) Content types the filter applies to, combination of values from RegExpFilter.typeMap - * @param {Boolean} matchCase (optional) Defines whether the filter should distinguish between lower and upper case letters - * @param {String} domains (optional) Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com" - * @param {Boolean} thirdParty (optional) Defines whether the filter should apply to third-party or first-party content only - * @constructor - * @augments ActiveFilter - */ -function RegExpFilter(text, regexpSource, contentType, matchCase, domains, thirdParty) -{ - ActiveFilter.call(this, text, domains); - - if (contentType != null) - this.contentType = contentType; - if (matchCase) - this.matchCase = matchCase; - if (thirdParty != null) - this.thirdParty = thirdParty; - - if (regexpSource.length >= 2 && regexpSource[0] == "/" && regexpSource[regexpSource.length - 1] == "/") - { - // The filter is a regular expression - convert it immediately to catch syntax errors - let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), this.matchCase ? "" : "i"); - this.__defineGetter__("regexp", () => regexp); - } - else - { - // No need to convert this filter to regular expression yet, do it on demand - this.regexpSource = regexpSource; - } -} -exports.RegExpFilter = RegExpFilter; - -RegExpFilter.prototype = -{ - __proto__: ActiveFilter.prototype, - - /** - * @see ActiveFilter.domainSourceIsUpperCase - */ - domainSourceIsUpperCase: true, - - /** - * Number of filters contained, will always be 1 (required to optimize Matcher). - * @type Integer - */ - length: 1, - - /** - * @see ActiveFilter.domainSeparator - */ - domainSeparator: "|", - - /** - * Expression from which a regular expression should be generated - for delayed creation of the regexp property - * @type String - */ - regexpSource: null, - /** - * Regular expression to be used when testing against this filter - * @type RegExp - */ - get regexp() - { - // Remove multiple wildcards - let source = this.regexpSource - .replace(/\*+/g, "*") // remove multiple wildcards - .replace(/\^\|$/, "^") // remove anchors following separator placeholder - .replace(/\W/g, "\\$&") // escape special symbols - .replace(/\\\*/g, ".*") // replace wildcards by .* - // process separator placeholders (all ANSI characters but alphanumeric characters and _%.-) - .replace(/\\\^/g, "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\\x60\\x7B-\\x7F]|$)") - .replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?") // process extended anchor at expression start - .replace(/^\\\|/, "^") // process anchor at expression start - .replace(/\\\|$/, "$") // process anchor at expression end - .replace(/^(\.\*)/, "") // remove leading wildcards - .replace(/(\.\*)$/, ""); // remove trailing wildcards - - let regexp = new RegExp(source, this.matchCase ? "" : "i"); - - delete this.regexpSource; - this.__defineGetter__("regexp", () => regexp); - return this.regexp; - }, - /** - * Content types the filter applies to, combination of values from RegExpFilter.typeMap - * @type Number - */ - contentType: 0x7FFFFFFF, - /** - * Defines whether the filter should distinguish between lower and upper case letters - * @type Boolean - */ - matchCase: false, - /** - * Defines whether the filter should apply to third-party or first-party content only. Can be null (apply to all content). - * @type Boolean - */ - thirdParty: null, - - /** - * Tests whether the URL matches this filter - * @param {String} location URL to be tested - * @param {String} contentType content type identifier of the URL - * @param {String} docDomain domain name of the document that loads the URL - * @param {Boolean} thirdParty should be true if the URL is a third-party request - * @return {Boolean} true in case of a match - */ - matches: function(location, contentType, docDomain, thirdParty, privatenode) - { - - if(this.subscriptions[0]) - if (this.subscriptions[0].privateMode) - if (privatenode==false) - return false; - - if (this.regexp.test(location) && - (RegExpFilter.typeMap[contentType] & this.contentType) != 0 && - (this.thirdParty == null || this.thirdParty == thirdParty) && - this.isActiveOnDomain(docDomain)) - { - return true; - } - - return false; - } -}; - -RegExpFilter.prototype.__defineGetter__("0", function() -{ - return this; -}); - -/** - * Creates a RegExp filter from its text representation - * @param {String} text same as in Filter() - */ -RegExpFilter.fromText = function(text) -{ - let blocking = true; - let origText = text; - if (text.indexOf("@@") == 0) - { - blocking = false; - text = text.substr(2); - } - - let contentType = null; - let matchCase = null; - let domains = null; - let siteKeys = null; - let thirdParty = null; - let collapse = null; - let options; - let match = (text.indexOf("$") >= 0 ? Filter.optionsRegExp.exec(text) : null); - if (match) - { - options = match[1].toUpperCase().split(","); - text = match.input.substr(0, match.index); - for (let option of options) - { - let value = null; - let separatorIndex = option.indexOf("="); - if (separatorIndex >= 0) - { - value = option.substr(separatorIndex + 1); - option = option.substr(0, separatorIndex); - } - option = option.replace(/-/, "_"); - if (option in RegExpFilter.typeMap) - { - if (contentType == null) - contentType = 0; - contentType |= RegExpFilter.typeMap[option]; - } - else if (option[0] == "~" && option.substr(1) in RegExpFilter.typeMap) - { - if (contentType == null) - contentType = RegExpFilter.prototype.contentType; - contentType &= ~RegExpFilter.typeMap[option.substr(1)]; - } - else if (option == "MATCH_CASE") - matchCase = true; - else if (option == "~MATCH_CASE") - matchCase = false; - else if (option == "DOMAIN" && typeof value != "undefined") - domains = value; - else if (option == "THIRD_PARTY") - thirdParty = true; - else if (option == "~THIRD_PARTY") - thirdParty = false; - else if (option == "COLLAPSE") - collapse = true; - else if (option == "~COLLAPSE") - collapse = false; - else if (option == "SITEKEY" && typeof value != "undefined") - siteKeys = value.split(/\|/); - else - return new InvalidFilter(origText, "Unknown option " + option.toLowerCase()); - } - } - - if (!blocking && (contentType == null || (contentType & RegExpFilter.typeMap.DOCUMENT)) && - (!options || options.indexOf("DOCUMENT") < 0) && !/^\|?[\w\-]+:/.test(text)) - { - // Exception filters shouldn't apply to pages by default unless they start with a protocol name - if (contentType == null) - contentType = RegExpFilter.prototype.contentType; - contentType &= ~RegExpFilter.typeMap.DOCUMENT; - } - if (!blocking && siteKeys) - contentType = RegExpFilter.typeMap.DOCUMENT; - - try - { - if (blocking) - return new BlockingFilter(origText, text, contentType, matchCase, domains, thirdParty, collapse); - else - return new WhitelistFilter(origText, text, contentType, matchCase, domains, thirdParty, siteKeys); - } - catch (e) - { - return new InvalidFilter(origText, e); - } -} - -/** - * Maps type strings like "SCRIPT" or "OBJECT" to bit masks - */ -RegExpFilter.typeMap = { - OTHER: 1, - SCRIPT: 2, - IMAGE: 4, - STYLESHEET: 8, - OBJECT: 16, - SUBDOCUMENT: 32, - DOCUMENT: 64, - XBL: 1, - PING: 1, - XMLHTTPREQUEST: 2048, - OBJECT_SUBREQUEST: 4096, - DTD: 1, - MEDIA: 16384, - FONT: 32768, - - BACKGROUND: 4, // Backwards compat, same as IMAGE - - POPUP: 0x10000000, - ELEMHIDE: 0x40000000 -}; - -// ELEMHIDE, POPUP option shouldn't be there by default -RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.ELEMHIDE | RegExpFilter.typeMap.POPUP); - -/** - * Class for blocking filters - * @param {String} text see Filter() - * @param {String} regexpSource see RegExpFilter() - * @param {Number} contentType see RegExpFilter() - * @param {Boolean} matchCase see RegExpFilter() - * @param {String} domains see RegExpFilter() - * @param {Boolean} thirdParty see RegExpFilter() - * @param {Boolean} collapse defines whether the filter should collapse blocked content, can be null - * @constructor - * @augments RegExpFilter - */ -function BlockingFilter(text, regexpSource, contentType, matchCase, domains, thirdParty, collapse) -{ - RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, thirdParty); - - this.collapse = collapse; -} -exports.BlockingFilter = BlockingFilter; - -BlockingFilter.prototype = -{ - __proto__: RegExpFilter.prototype, - - /** - * Defines whether the filter should collapse blocked content. Can be null (use the global preference). - * @type Boolean - */ - collapse: null -}; - -/** - * Class for whitelist filters - * @param {String} text see Filter() - * @param {String} regexpSource see RegExpFilter() - * @param {Number} contentType see RegExpFilter() - * @param {Boolean} matchCase see RegExpFilter() - * @param {String} domains see RegExpFilter() - * @param {Boolean} thirdParty see RegExpFilter() - * @param {String[]} siteKeys public keys of websites that this filter should apply to - * @constructor - * @augments RegExpFilter - */ -function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, thirdParty, siteKeys) -{ - RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, thirdParty); - - if (siteKeys != null) - this.siteKeys = siteKeys; -} -exports.WhitelistFilter = WhitelistFilter; - -WhitelistFilter.prototype = -{ - __proto__: RegExpFilter.prototype, - - /** - * List of public keys of websites that this filter should apply to - * @type String[] - */ - siteKeys: null -} - -/** - * Base class for element hiding filters - * @param {String} text see Filter() - * @param {String} domains (optional) Host names or domains the filter should be restricted to - * @param {String} selector CSS selector for the HTML elements that should be hidden - * @constructor - * @augments ActiveFilter - */ -function ElemHideBase(text, domains, selector) -{ - ActiveFilter.call(this, text, domains || null); - - if (domains) - this.selectorDomain = domains.replace(/,~[^,]+/g, "").replace(/^~[^,]+,?/, "").toLowerCase(); - this.selector = selector; -} -exports.ElemHideBase = ElemHideBase; - -ElemHideBase.prototype = -{ - __proto__: ActiveFilter.prototype, - - /** - * @see ActiveFilter.domainSeparator - */ - domainSeparator: ",", - - /** - * @see ActiveFilter.ignoreTrailingDot - */ - ignoreTrailingDot: false, - - /** - * Host name or domain the filter should be restricted to (can be null for no restriction) - * @type String - */ - selectorDomain: null, - /** - * CSS selector for the HTML elements that should be hidden - * @type String - */ - selector: null -}; - -/** - * Creates an element hiding filter from a pre-parsed text representation - * - * @param {String} text same as in Filter() - * @param {String} domain domain part of the text representation (can be empty) - * @param {String} tagName tag name part (can be empty) - * @param {String} attrRules attribute matching rules (can be empty) - * @param {String} selector raw CSS selector (can be empty) - * @return {ElemHideFilter|ElemHideException|InvalidFilter} - */ -ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules, selector) -{ - if (!selector) - { - if (tagName == "*") - tagName = ""; - - let id = null; - let additional = ""; - if (attrRules) { - attrRules = attrRules.match(/\([\w\-]+(?:[$^*]?=[^\(\)"]*)?\)/g); - for (let rule of attrRules) { - rule = rule.substr(1, rule.length - 2); - let separatorPos = rule.indexOf("="); - if (separatorPos > 0) { - rule = rule.replace(/=/, '="') + '"'; - additional += "[" + rule + "]"; - } - else { - if (id) - { - let {Utils} = require("utils"); - return new InvalidFilter(text, Utils.getString("filter_elemhide_duplicate_id")); - } - else - id = rule; - } - } - } - - if (id) - selector = tagName + "." + id + additional + "," + tagName + "#" + id + additional; - else if (tagName || additional) - selector = tagName + additional; - else - { - let {Utils} = require("utils"); - return new InvalidFilter(text, Utils.getString("filter_elemhide_nocriteria")); - } - } - if (isException) - return new ElemHideException(text, domain, selector); - else - return new ElemHideFilter(text, domain, selector); -} - -/** - * Class for element hiding filters - * @param {String} text see Filter() - * @param {String} domains see ElemHideBase() - * @param {String} selector see ElemHideBase() - * @constructor - * @augments ElemHideBase - */ -function ElemHideFilter(text, domains, selector) -{ - ElemHideBase.call(this, text, domains, selector); -} -exports.ElemHideFilter = ElemHideFilter; - -ElemHideFilter.prototype = -{ - __proto__: ElemHideBase.prototype -}; - -/** - * Class for element hiding exceptions - * @param {String} text see Filter() - * @param {String} domains see ElemHideBase() - * @param {String} selector see ElemHideBase() - * @constructor - * @augments ElemHideBase - */ -function ElemHideException(text, domains, selector) -{ - ElemHideBase.call(this, text, domains, selector); -} -exports.ElemHideException = ElemHideException; - -ElemHideException.prototype = -{ - __proto__: ElemHideBase.prototype -}; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterListener.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterListener.js deleted file mode 100644 index 1687a26..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterListener.js +++ /dev/null @@ -1,282 +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/>. - */ - -/** - * @fileOverview Component synchronizing filter storage with Matcher instances and ElemHide. - */ - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -let {TimeLine} = require("timeline"); -let {FilterStorage} = require("filterStorage"); -let {FilterNotifier} = require("filterNotifier"); -let {ElemHide} = require("elemHide"); -let {defaultMatcher} = require("matcher"); -let {ActiveFilter, RegExpFilter, ElemHideBase} = require("filterClasses"); -let {Prefs} = require("prefs"); - -/** - * Value of the FilterListener.batchMode property. - * @type Boolean - */ -let batchMode = false; - -/** - * Increases on filter changes, filters will be saved if it exceeds 1. - * @type Integer - */ -let isDirty = 0; - -/** - * This object can be used to change properties of the filter change listeners. - * @class - */ -let FilterListener = -{ - /** - * Set to true when executing many changes, changes will only be fully applied after this variable is set to false again. - * @type Boolean - */ - get batchMode() - { - return batchMode; - }, - set batchMode(value) - { - batchMode = value; - flushElemHide(); - }, - - /** - * Increases "dirty factor" of the filters and calls FilterStorage.saveToDisk() - * if it becomes 1 or more. Save is executed delayed to prevent multiple - * subsequent calls. If the parameter is 0 it forces saving filters if any - * changes were recorded after the previous save. - */ - setDirty: function(/**Integer*/ factor) - { - if (factor == 0 && isDirty > 0) - isDirty = 1; - else - isDirty += factor; - if (isDirty >= 1) - FilterStorage.saveToDisk(); - } -}; - -/** - * Observer listening to history purge actions. - * @class - */ -let HistoryPurgeObserver = -{ - observe: function(subject, topic, data) - { - if (topic == "browser:purge-session-history" && Prefs.clearStatsOnHistoryPurge) - { - FilterStorage.resetHitCounts(); - FilterListener.setDirty(0); // Force saving to disk - - Prefs.recentReports = []; - } - }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObserver]) -}; - -/** - * Initializes filter listener on startup, registers the necessary hooks. - */ -function init() -{ - TimeLine.enter("Entered filter listener initialization()"); - - FilterNotifier.addListener(function(action, item, newValue, oldValue) - { - let match = /^(\w+)\.(.*)/.exec(action); - if (match && match[1] == "filter") - onFilterChange(match[2], item, newValue, oldValue); - else if (match && match[1] == "subscription") - onSubscriptionChange(match[2], item, newValue, oldValue); - else - onGenericChange(action, item); - }); - - if ("nsIStyleSheetService" in Ci) - ElemHide.init(); - else - flushElemHide = function() {}; // No global stylesheet in Chrome & Co. - FilterStorage.loadFromDisk(); - - TimeLine.log("done initializing data structures"); - - Services.obs.addObserver(HistoryPurgeObserver, "browser:purge-session-history", true); - onShutdown.add(function() - { - Services.obs.removeObserver(HistoryPurgeObserver, "browser:purge-session-history"); - }); - TimeLine.log("done adding observers"); - - TimeLine.leave("Filter listener initialization done"); -} -init(); - -/** - * Calls ElemHide.apply() if necessary. - */ -function flushElemHide() -{ - if (!batchMode && ElemHide.isDirty) - ElemHide.apply(); -} - -/** - * Notifies Matcher instances or ElemHide object about a new filter - * if necessary. - * @param {Filter} filter filter that has been added - */ -function addFilter(filter) -{ - if (!(filter instanceof ActiveFilter) || filter.disabled) - return; - - let hasEnabled = false; - for (let i = 0; i < filter.subscriptions.length; i++) - if (!filter.subscriptions[i].disabled) - hasEnabled = true; - if (!hasEnabled) - return; - - if (filter instanceof RegExpFilter) - defaultMatcher.add(filter); - else if (filter instanceof ElemHideBase) - ElemHide.add(filter); -} - -/** - * Notifies Matcher instances or ElemHide object about removal of a filter - * if necessary. - * @param {Filter} filter filter that has been removed - */ -function removeFilter(filter) -{ - if (!(filter instanceof ActiveFilter)) - return; - - if (!filter.disabled) - { - let hasEnabled = false; - for (let i = 0; i < filter.subscriptions.length; i++) - if (!filter.subscriptions[i].disabled) - hasEnabled = true; - if (hasEnabled) - return; - } - - if (filter instanceof RegExpFilter) - defaultMatcher.remove(filter); - else if (filter instanceof ElemHideBase) - ElemHide.remove(filter); -} - -/** - * Subscription change listener - */ -function onSubscriptionChange(action, subscription, newValue, oldValue) -{ - FilterListener.setDirty(1); - - if (action != "added" && action != "removed" && action != "disabled" && action != "updated") - return; - - if (action != "removed" && !(subscription.url in FilterStorage.knownSubscriptions)) - { - // Ignore updates for subscriptions not in the list - return; - } - - if ((action == "added" || action == "removed" || action == "updated") && subscription.disabled) - { - // Ignore adding/removing/updating of disabled subscriptions - return; - } - - if (action == "added" || action == "removed" || action == "disabled") - { - let method = (action == "added" || (action == "disabled" && newValue == false) ? addFilter : removeFilter); - if (subscription.filters) - subscription.filters.forEach(method); - } - else if (action == "updated") - { - subscription.oldFilters.forEach(removeFilter); - subscription.filters.forEach(addFilter); - } - - flushElemHide(); -} - -/** - * Filter change listener - */ -function onFilterChange(action, filter, newValue, oldValue) -{ - if (action == "hitCount" && newValue == 0) - { - // Filter hits are being reset, make sure these changes are saved. - FilterListener.setDirty(0); - } - else if (action == "hitCount" || action == "lastHit") - FilterListener.setDirty(0.002); - else - FilterListener.setDirty(1); - - if (action != "added" && action != "removed" && action != "disabled") - return; - - if ((action == "added" || action == "removed") && filter.disabled) - { - // Ignore adding/removing of disabled filters - return; - } - - if (action == "added" || (action == "disabled" && newValue == false)) - addFilter(filter); - else - removeFilter(filter); - flushElemHide(); -} - -/** - * Generic notification listener - */ -function onGenericChange(action) -{ - if (action == "load") - { - isDirty = 0; - - defaultMatcher.clear(); - ElemHide.clear(); - for (let subscription of FilterStorage.subscriptions) - if (!subscription.disabled) - subscription.filters.forEach(addFilter); - flushElemHide(); - } - else if (action == "save") - isDirty = 0; -} diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterNotifier.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterNotifier.js deleted file mode 100644 index 010081e..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterNotifier.js +++ /dev/null @@ -1,73 +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/>. - */ - -/** - * @fileOverview This component manages listeners and calls them to distributes - * messages about filter changes. - */ - -/** - * List of registered listeners - * @type Array of function(action, item, newValue, oldValue) - */ -let listeners = []; - -/** - * This class allows registering and triggering listeners for filter events. - * @class - */ -let FilterNotifier = exports.FilterNotifier = -{ - /** - * Adds a listener - */ - addListener: function(/**function(action, item, newValue, oldValue)*/ listener) - { - if (listeners.indexOf(listener) >= 0) - return; - - listeners.push(listener); - }, - - /** - * Removes a listener that was previosly added via addListener - */ - removeListener: function(/**function(action, item, newValue, oldValue)*/ listener) - { - let index = listeners.indexOf(listener); - if (index >= 0) - listeners.splice(index, 1); - }, - - /** - * Notifies listeners about an event - * @param {String} action event code ("load", "save", "elemhideupdate", - * "subscription.added", "subscription.removed", - * "subscription.disabled", "subscription.title", - * "subscription.lastDownload", "subscription.downloadStatus", - * "subscription.homepage", "subscription.updated", - * "filter.added", "filter.removed", "filter.moved", - * "filter.disabled", "filter.hitCount", "filter.lastHit") - * @param {Subscription|Filter} item item that the change applies to - */ - triggerListeners: function(action, item, param1, param2, param3) - { - let list = listeners.slice(); - for (let listener of list) - listener(action, item, param1, param2, param3); - } -}; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterStorage.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterStorage.js deleted file mode 100644 index 546f788..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/filterStorage.js +++ /dev/null @@ -1,897 +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/>. - */ - -/** - * @fileOverview FilterStorage class responsible for managing user's subscriptions and filters. - */ - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/FileUtils.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -let {IO} = require("io"); -let {Prefs} = require("prefs"); -let {Filter, ActiveFilter} = require("filterClasses"); -let {Subscription, SpecialSubscription, ExternalSubscription} = require("subscriptionClasses"); -let {FilterNotifier} = require("filterNotifier"); -let {Utils} = require("utils"); -let {TimeLine} = require("timeline"); - -/** - * Version number of the filter storage file format. - * @type Integer - */ -let formatVersion = 4; - -/** - * This class reads user's filters from disk, manages them in memory and writes them back. - * @class - */ -let FilterStorage = exports.FilterStorage = -{ - /** - * Version number of the patterns.ini format used. - * @type Integer - */ - get formatVersion() - { - return formatVersion; - }, - - /** - * File that the filter list has been loaded from and should be saved to - * @type nsIFile - */ - get sourceFile() - { - let file = null; - if (Prefs.patternsfile) - { - // Override in place, use it instead of placing the file in the regular data dir - file = IO.resolveFilePath(Prefs.patternsfile); - } - if (!file) - { - // Place the file in the data dir - file = IO.resolveFilePath(Prefs.data_directory); - if (file) - file.append("patterns.ini"); - } - if (!file) - { - // Data directory pref misconfigured? Try the default value - try - { - file = IO.resolveFilePath(Services.prefs.getDefaultBranch("extensions.adblockplus.").getCharPref("data_directory")); - if (file) - file.append("patterns.ini"); - } catch(e) {} - } - - if (!file) - Cu.reportError("Adblock Plus: Failed to resolve filter file location from extensions.adblockplus.patternsfile preference"); - - this.__defineGetter__("sourceFile", () => file); - return this.sourceFile; - }, - - /** - * Will be set to true if no patterns.ini file exists. - * @type Boolean - */ - firstRun: false, - - /** - * Map of properties listed in the filter storage file before the sections - * start. Right now this should be only the format version. - */ - fileProperties: {__proto__: null}, - - /** - * List of filter subscriptions containing all filters - * @type Array of Subscription - */ - subscriptions: [], - - /** - * Map of subscriptions already on the list, by their URL/identifier - * @type Object - */ - knownSubscriptions: {__proto__: null}, - - /** - * Finds the filter group that a filter should be added to by default. Will - * return null if this group doesn't exist yet. - */ - getGroupForFilter: function(/**Filter*/ filter) /**SpecialSubscription*/ - { - let generalSubscription = null; - for (let subscription of FilterStorage.subscriptions) - { - if (subscription instanceof SpecialSubscription && !subscription.disabled) - { - // Always prefer specialized subscriptions - if (subscription.isDefaultFor(filter)) - return subscription; - - // If this is a general subscription - store it as fallback - if (!generalSubscription && (!subscription.defaults || !subscription.defaults.length)) - generalSubscription = subscription; - } - } - return generalSubscription; - }, - - /** - * Adds a filter subscription to the list - * @param {Subscription} subscription filter subscription to be added - * @param {Boolean} silent if true, no listeners will be triggered (to be used when filter list is reloaded) - */ - addSubscription: function(subscription, silent) - { - if (subscription.url in FilterStorage.knownSubscriptions) - return; - - FilterStorage.subscriptions.push(subscription); - FilterStorage.knownSubscriptions[subscription.url] = subscription; - addSubscriptionFilters(subscription); - - if (!silent) - FilterNotifier.triggerListeners("subscription.added", subscription); - }, - - /** - * Removes a filter subscription from the list - * @param {Subscription} subscription filter subscription to be removed - * @param {Boolean} silent if true, no listeners will be triggered (to be used when filter list is reloaded) - */ - removeSubscription: function(subscription, silent) - { - for (let i = 0; i < FilterStorage.subscriptions.length; i++) - { - if (FilterStorage.subscriptions[i].url == subscription.url) - { - removeSubscriptionFilters(subscription); - - FilterStorage.subscriptions.splice(i--, 1); - delete FilterStorage.knownSubscriptions[subscription.url]; - if (!silent) - FilterNotifier.triggerListeners("subscription.removed", subscription); - return; - } - } - }, - - /** - * Moves a subscription in the list to a new position. - * @param {Subscription} subscription filter subscription to be moved - * @param {Subscription} [insertBefore] filter subscription to insert before - * (if omitted the subscription will be put at the end of the list) - */ - moveSubscription: function(subscription, insertBefore) - { - let currentPos = FilterStorage.subscriptions.indexOf(subscription); - if (currentPos < 0) - return; - - let newPos = insertBefore ? FilterStorage.subscriptions.indexOf(insertBefore) : -1; - if (newPos < 0) - newPos = FilterStorage.subscriptions.length; - - if (currentPos < newPos) - newPos--; - if (currentPos == newPos) - return; - - FilterStorage.subscriptions.splice(currentPos, 1); - FilterStorage.subscriptions.splice(newPos, 0, subscription); - FilterNotifier.triggerListeners("subscription.moved", subscription); - }, - - /** - * Replaces the list of filters in a subscription by a new list - * @param {Subscription} subscription filter subscription to be updated - * @param {Array of Filter} filters new filter lsit - */ - updateSubscriptionFilters: function(subscription, filters) - { - removeSubscriptionFilters(subscription); - subscription.oldFilters = subscription.filters; - subscription.filters = filters; - addSubscriptionFilters(subscription); - FilterNotifier.triggerListeners("subscription.updated", subscription); - delete subscription.oldFilters; - }, - - /** - * Adds a user-defined filter to the list - * @param {Filter} filter - * @param {SpecialSubscription} [subscription] particular group that the filter should be added to - * @param {Integer} [position] position within the subscription at which the filter should be added - * @param {Boolean} silent if true, no listeners will be triggered (to be used when filter list is reloaded) - */ - addFilter: function(filter, subscription, position, silent) - { - if (!subscription) - { - if (filter.subscriptions.some(s => s instanceof SpecialSubscription && !s.disabled)) - return; // No need to add - subscription = FilterStorage.getGroupForFilter(filter); - } - if (!subscription) - { - // No group for this filter exists, create one - subscription = SpecialSubscription.createForFilter(filter); - this.addSubscription(subscription); - return; - } - - if (typeof position == "undefined") - position = subscription.filters.length; - - if (filter.subscriptions.indexOf(subscription) < 0) - filter.subscriptions.push(subscription); - subscription.filters.splice(position, 0, filter); - if (!silent) - FilterNotifier.triggerListeners("filter.added", filter, subscription, position); - }, - - /** - * Removes a user-defined filter from the list - * @param {Filter} filter - * @param {SpecialSubscription} [subscription] a particular filter group that - * the filter should be removed from (if ommited will be removed from all subscriptions) - * @param {Integer} [position] position inside the filter group at which the - * filter should be removed (if ommited all instances will be removed) - */ - removeFilter: function(filter, subscription, position) - { - let subscriptions = (subscription ? [subscription] : filter.subscriptions.slice()); - for (let i = 0; i < subscriptions.length; i++) - { - let subscription = subscriptions[i]; - if (subscription instanceof SpecialSubscription) - { - let positions = []; - if (typeof position == "undefined") - { - let index = -1; - do - { - index = subscription.filters.indexOf(filter, index + 1); - if (index >= 0) - positions.push(index); - } while (index >= 0); - } - else - positions.push(position); - - for (let j = positions.length - 1; j >= 0; j--) - { - let position = positions[j]; - if (subscription.filters[position] == filter) - { - subscription.filters.splice(position, 1); - if (subscription.filters.indexOf(filter) < 0) - { - let index = filter.subscriptions.indexOf(subscription); - if (index >= 0) - filter.subscriptions.splice(index, 1); - } - FilterNotifier.triggerListeners("filter.removed", filter, subscription, position); - } - } - } - } - }, - - /** - * Moves a user-defined filter to a new position - * @param {Filter} filter - * @param {SpecialSubscription} subscription filter group where the filter is located - * @param {Integer} oldPosition current position of the filter - * @param {Integer} newPosition new position of the filter - */ - moveFilter: function(filter, subscription, oldPosition, newPosition) - { - if (!(subscription instanceof SpecialSubscription) || subscription.filters[oldPosition] != filter) - return; - - newPosition = Math.min(Math.max(newPosition, 0), subscription.filters.length - 1); - if (oldPosition == newPosition) - return; - - subscription.filters.splice(oldPosition, 1); - subscription.filters.splice(newPosition, 0, filter); - FilterNotifier.triggerListeners("filter.moved", filter, subscription, oldPosition, newPosition); - }, - - /** - * Increases the hit count for a filter by one - * @param {Filter} filter - * @param {Window} window Window that the match originated in (required - * to recognize private browsing mode) - */ - increaseHitCount: function(filter, wnd) - { - if (!Prefs.savestats || PrivateBrowsing.enabledForWindow(wnd) || - PrivateBrowsing.enabled || !(filter instanceof ActiveFilter)) - { - return; - } - - filter.hitCount++; - filter.lastHit = Date.now(); - }, - - /** - * Resets hit count for some filters - * @param {Array of Filter} filters filters to be reset, if null all filters will be reset - */ - resetHitCounts: function(filters) - { - if (!filters) - { - filters = []; - for (let text in Filter.knownFilters) - filters.push(Filter.knownFilters[text]); - } - for (let filter of filters) - { - filter.hitCount = 0; - filter.lastHit = 0; - } - }, - - _loading: false, - - /** - * Loads all subscriptions from the disk - * @param {nsIFile} [sourceFile] File to read from - */ - loadFromDisk: function(sourceFile) - { - if (this._loading) - return; - - TimeLine.enter("Entered FilterStorage.loadFromDisk()"); - this._loading = true; - - let readFile = function(sourceFile, backupIndex) - { - TimeLine.enter("FilterStorage.loadFromDisk() -> readFile()"); - - let parser = new INIParser(); - IO.readFromFile(sourceFile, parser, function(e) - { - TimeLine.enter("FilterStorage.loadFromDisk() read callback"); - if (!e && parser.subscriptions.length == 0) - { - // No filter subscriptions in the file, this isn't right. - e = new Error("No data in the file"); - } - - if (e) - Cu.reportError(e); - - if (e && !explicitFile) - { - // Attempt to load a backup - sourceFile = this.sourceFile; - if (sourceFile) - { - let [, part1, part2] = /^(.*)(\.\w+)$/.exec(sourceFile.leafName) || [null, sourceFile.leafName, ""]; - - sourceFile = sourceFile.clone(); - sourceFile.leafName = part1 + "-backup" + (++backupIndex) + part2; - - IO.statFile(sourceFile, function(e, statData) - { - if (!e && statData.exists) - readFile(sourceFile, backupIndex); - else - doneReading(parser); - }); - TimeLine.leave("FilterStorage.loadFromDisk() read callback done"); - return; - } - } - doneReading(parser); - }.bind(this), "FilterStorageRead"); - - TimeLine.leave("FilterStorage.loadFromDisk() <- readFile()", "FilterStorageRead"); - }.bind(this); - - var doneReading = function(parser) - { - // Old special groups might have been converted, remove them if they are empty - let specialMap = {"~il~": true, "~wl~": true, "~fl~": true, "~eh~": true}; - let knownSubscriptions = {__proto__: null}; - for (let i = 0; i < parser.subscriptions.length; i++) - { - let subscription = parser.subscriptions[i]; - if (subscription instanceof SpecialSubscription && subscription.filters.length == 0 && subscription.url in specialMap) - parser.subscriptions.splice(i--, 1); - else - knownSubscriptions[subscription.url] = subscription; - } - - this.fileProperties = parser.fileProperties; - this.subscriptions = parser.subscriptions; - this.knownSubscriptions = knownSubscriptions; - Filter.knownFilters = parser.knownFilters; - Subscription.knownSubscriptions = parser.knownSubscriptions; - - if (parser.userFilters) - { - for (let i = 0; i < parser.userFilters.length; i++) - { - let filter = Filter.fromText(parser.userFilters[i]); - this.addFilter(filter, null, undefined, true); - } - } - TimeLine.log("Initializing data done, triggering observers") - - this._loading = false; - FilterNotifier.triggerListeners("load"); - - if (sourceFile != this.sourceFile) - this.saveToDisk(); - - TimeLine.leave("FilterStorage.loadFromDisk() read callback done"); - }.bind(this); - - let explicitFile; - if (sourceFile) - { - explicitFile = true; - readFile(sourceFile, 0); - } - else - { - explicitFile = false; - sourceFile = FilterStorage.sourceFile; - - let callback = function(e, statData) - { - if (e || !statData.exists) - { - this.firstRun = true; - this._loading = false; - FilterNotifier.triggerListeners("load"); - - TimeLine.leave("FilterStorage.loadFromDisk() read callback done"); - } - else - readFile(sourceFile, 0); - }.bind(this); - - if (sourceFile) - IO.statFile(sourceFile, callback); - else - callback(true); - } - - TimeLine.leave("FilterStorage.loadFromDisk() done"); - }, - - _generateFilterData: function(subscriptions) - { - yield "# Adblock Plus preferences"; - yield "version=" + formatVersion; - - let saved = {__proto__: null}; - let buf = []; - - // Save filter data - for (let i = 0; i < subscriptions.length; i++) - { - let subscription = subscriptions[i]; - for (let j = 0; j < subscription.filters.length; j++) - { - let filter = subscription.filters[j]; - if (!(filter.text in saved)) - { - filter.serialize(buf); - saved[filter.text] = filter; - for (let k = 0; k < buf.length; k++) - yield buf[k]; - buf.splice(0); - } - } - } - - // Save subscriptions - for (let i = 0; i < subscriptions.length; i++) - { - let subscription = subscriptions[i]; - - yield ""; - - subscription.serialize(buf); - if (subscription.filters.length) - { - buf.push("", "[Subscription filters]") - subscription.serializeFilters(buf); - } - for (let k = 0; k < buf.length; k++) - yield buf[k]; - buf.splice(0); - } - }, - - /** - * Will be set to true if saveToDisk() is running (reentrance protection). - * @type Boolean - */ - _saving: false, - - /** - * Will be set to true if a saveToDisk() call arrives while saveToDisk() is - * already running (delayed execution). - * @type Boolean - */ - _needsSave: false, - - /** - * Saves all subscriptions back to disk - * @param {nsIFile} [targetFile] File to be written - */ - saveToDisk: function(targetFile) - { - let explicitFile = true; - if (!targetFile) - { - targetFile = FilterStorage.sourceFile; - explicitFile = false; - } - if (!targetFile) - return; - - if (!explicitFile && this._saving) - { - this._needsSave = true; - return; - } - - TimeLine.enter("Entered FilterStorage.saveToDisk()"); - - // Make sure the file's parent directory exists - try { - targetFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - } catch (e) {} - - let writeFilters = function() - { - TimeLine.enter("FilterStorage.saveToDisk() -> writeFilters()"); - IO.writeToFile(targetFile, this._generateFilterData(subscriptions), function(e) - { - TimeLine.enter("FilterStorage.saveToDisk() write callback"); - if (!explicitFile) - this._saving = false; - - if (e) - Cu.reportError(e); - - if (!explicitFile && this._needsSave) - { - this._needsSave = false; - this.saveToDisk(); - } - else - FilterNotifier.triggerListeners("save"); - TimeLine.leave("FilterStorage.saveToDisk() write callback done"); - }.bind(this), "FilterStorageWrite"); - TimeLine.leave("FilterStorage.saveToDisk() -> writeFilters()", "FilterStorageWrite"); - }.bind(this); - - let checkBackupRequired = function(callbackNotRequired, callbackRequired) - { - if (explicitFile || Prefs.patternsbackups <= 0) - callbackNotRequired(); - else - { - IO.statFile(targetFile, function(e, statData) - { - if (e || !statData.exists) - callbackNotRequired(); - else - { - let [, part1, part2] = /^(.*)(\.\w+)$/.exec(targetFile.leafName) || [null, targetFile.leafName, ""]; - let newestBackup = targetFile.clone(); - newestBackup.leafName = part1 + "-backup1" + part2; - IO.statFile(newestBackup, function(e, statData) - { - if (!e && (!statData.exists || (Date.now() - statData.lastModified) / 3600000 >= Prefs.patternsbackupinterval)) - callbackRequired(part1, part2) - else - callbackNotRequired(); - }); - } - }); - } - }.bind(this); - - let removeLastBackup = function(part1, part2) - { - TimeLine.enter("FilterStorage.saveToDisk() -> removeLastBackup()"); - let file = targetFile.clone(); - file.leafName = part1 + "-backup" + Prefs.patternsbackups + part2; - IO.removeFile(file, (e) => renameBackup(part1, part2, Prefs.patternsbackups - 1)); - TimeLine.leave("FilterStorage.saveToDisk() <- removeLastBackup()"); - }.bind(this); - - let renameBackup = function(part1, part2, index) - { - TimeLine.enter("FilterStorage.saveToDisk() -> renameBackup()"); - if (index > 0) - { - let fromFile = targetFile.clone(); - fromFile.leafName = part1 + "-backup" + index + part2; - - let toName = part1 + "-backup" + (index + 1) + part2; - - IO.renameFile(fromFile, toName, (e) => renameBackup(part1, part2, index - 1)); - } - else - { - let toFile = targetFile.clone(); - toFile.leafName = part1 + "-backup" + (index + 1) + part2; - - IO.copyFile(targetFile, toFile, writeFilters); - } - TimeLine.leave("FilterStorage.saveToDisk() <- renameBackup()"); - }.bind(this); - - // Do not persist external subscriptions - let subscriptions = this.subscriptions.filter((s) => !(s instanceof ExternalSubscription)); - if (!explicitFile) - this._saving = true; - - checkBackupRequired(writeFilters, removeLastBackup); - - TimeLine.leave("FilterStorage.saveToDisk() done"); - }, - - /** - * Returns the list of existing backup files. - */ - getBackupFiles: function() /**nsIFile[]*/ - { - // TODO: This method should be asynchronous - let result = []; - - let [, part1, part2] = /^(.*)(\.\w+)$/.exec(FilterStorage.sourceFile.leafName) || [null, FilterStorage.sourceFile.leafName, ""]; - for (let i = 1; ; i++) - { - let file = FilterStorage.sourceFile.clone(); - file.leafName = part1 + "-backup" + i + part2; - if (file.exists()) - result.push(file); - else - break; - } - return result; - } -}; - -/** - * Joins subscription's filters to the subscription without any notifications. - * @param {Subscription} subscription filter subscription that should be connected to its filters - */ -function addSubscriptionFilters(subscription) -{ - if (!(subscription.url in FilterStorage.knownSubscriptions)) - return; - - for (let filter of subscription.filters) - filter.subscriptions.push(subscription); -} - -/** - * Removes subscription's filters from the subscription without any notifications. - * @param {Subscription} subscription filter subscription to be removed - */ -function removeSubscriptionFilters(subscription) -{ - if (!(subscription.url in FilterStorage.knownSubscriptions)) - return; - - for (let filter of subscription.filters) - { - let i = filter.subscriptions.indexOf(subscription); - if (i >= 0) - filter.subscriptions.splice(i, 1); - } -} - -/** - * Observer listening to private browsing mode changes. - * @class - */ -let PrivateBrowsing = exports.PrivateBrowsing = -{ - /** - * Will be set to true when the private browsing mode is switched on globally. - * @type Boolean - */ - enabled: false, - - /** - * Checks whether private browsing is enabled for a particular window. - */ - enabledForWindow: function(/**Window*/ wnd) /**Boolean*/ - { - try - { - return wnd.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsILoadContext) - .usePrivateBrowsing; - } - catch (e) - { - // Gecko 19 and below will throw NS_NOINTERFACE, this is expected - if (e.result != Cr.NS_NOINTERFACE) - Cu.reportError(e); - return false; - } - }, - - init: function() - { - if ("@mozilla.org/privatebrowsing;1" in Cc) - { - try - { - this.enabled = Cc["@mozilla.org/privatebrowsing;1"].getService(Ci.nsIPrivateBrowsingService).privateBrowsingEnabled; - Services.obs.addObserver(this, "private-browsing", true); - onShutdown.add(function() - { - Services.obs.removeObserver(this, "private-browsing"); - }.bind(this)); - } - catch(e) - { - Cu.reportError(e); - } - } - }, - - observe: function(subject, topic, data) - { - if (topic == "private-browsing") - { - if (data == "enter") - this.enabled = true; - else if (data == "exit") - this.enabled = false; - } - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObserver]) -}; -PrivateBrowsing.init(); - -/** - * IO.readFromFile() listener to parse filter data. - * @constructor - */ -function INIParser() -{ - this.fileProperties = this.curObj = {}; - this.subscriptions = []; - this.knownFilters = {__proto__: null}; - this.knownSubscriptions = {__proto__: null}; -} -INIParser.prototype = -{ - linesProcessed: 0, - subscriptions: null, - knownFilters: null, - knownSubscriptions : null, - wantObj: true, - fileProperties: null, - curObj: null, - curSection: null, - userFilters: null, - - process: function(val) - { - let origKnownFilters = Filter.knownFilters; - Filter.knownFilters = this.knownFilters; - let origKnownSubscriptions = Subscription.knownSubscriptions; - Subscription.knownSubscriptions = this.knownSubscriptions; - let match; - try - { - if (this.wantObj === true && (match = /^(\w+)=(.*)$/.exec(val))) - this.curObj[match[1]] = match[2]; - else if (val === null || (match = /^\s*\[(.+)\]\s*$/.exec(val))) - { - if (this.curObj) - { - // Process current object before going to next section - switch (this.curSection) - { - case "filter": - case "pattern": - if ("text" in this.curObj) - Filter.fromObject(this.curObj); - break; - case "subscription": - let subscription = Subscription.fromObject(this.curObj); - if (subscription) - this.subscriptions.push(subscription); - break; - case "subscription filters": - case "subscription patterns": - if (this.subscriptions.length) - { - let subscription = this.subscriptions[this.subscriptions.length - 1]; - for (let text of this.curObj) - { - let filter = Filter.fromText(text); - subscription.filters.push(filter); - filter.subscriptions.push(subscription); - } - } - break; - case "user patterns": - this.userFilters = this.curObj; - break; - } - } - - if (val === null) - return; - - this.curSection = match[1].toLowerCase(); - switch (this.curSection) - { - case "filter": - case "pattern": - case "subscription": - this.wantObj = true; - this.curObj = {}; - break; - case "subscription filters": - case "subscription patterns": - case "user patterns": - this.wantObj = false; - this.curObj = []; - break; - default: - this.wantObj = undefined; - this.curObj = null; - } - } - else if (this.wantObj === false && val) - this.curObj.push(val.replace(/\\\[/g, "[")); - } - finally - { - Filter.knownFilters = origKnownFilters; - Subscription.knownSubscriptions = origKnownSubscriptions; - } - - // Allow events to be processed every now and then. - // Note: IO.readFromFile() will deal with the potential reentrance here. - this.linesProcessed++; - if (this.linesProcessed % 1000 == 0) - Utils.yield(); - } -}; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/io.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/io.js deleted file mode 100644 index ea362b7..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/io.js +++ /dev/null @@ -1,365 +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/>. - */ - -/** - * @fileOverview Module containing file I/O helpers. - */ - -let {Services} = Cu.import("resource://gre/modules/Services.jsm", null); -let {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", null); -let {OS} = Cu.import("resource://gre/modules/osfile.jsm", null); -let {Task} = Cu.import("resource://gre/modules/Task.jsm", null); - -let {TimeLine} = require("timeline"); -let {Prefs} = require("prefs"); -let {Utils} = require("utils"); - -let firstRead = true; -const BUFFER_SIZE = 0x8000; // 32kB - -let IO = exports.IO = -{ - /** - * Retrieves the platform-dependent line break string. - */ - get lineBreak() - { - let lineBreak = (Services.appinfo.OS == "WINNT" ? "\r\n" : "\n"); - delete IO.lineBreak; - IO.__defineGetter__("lineBreak", () => lineBreak); - return IO.lineBreak; - }, - - /** - * Tries to interpret a file path as an absolute path or a path relative to - * user's profile. Returns a file or null on failure. - */ - resolveFilePath: function(/**String*/ path) /**nsIFile*/ - { - if (!path) - return null; - - try { - // Assume an absolute path first - return new FileUtils.File(path); - } catch (e) {} - - try { - // Try relative path now - return FileUtils.getFile("ProfD", path.split("/")); - } catch (e) {} - - return null; - }, - - /** - * Reads strings from a file asynchronously, calls listener.process() with - * each line read and with a null parameter once the read operation is done. - * The callback will be called when the operation is done. - */ - readFromFile: function(/**nsIFile*/ file, /**Object*/ listener, /**Function*/ callback, /**String*/ timeLineID) - { - try - { - let processing = false; - let buffer = ""; - let loaded = false; - let error = null; - - let onProgress = function(data) - { - if (timeLineID) - { - TimeLine.asyncStart(timeLineID); - } - - let index = (processing ? -1 : Math.max(data.lastIndexOf("\n"), data.lastIndexOf("\r"))); - if (index >= 0) - { - // Protect against reentrance in case the listener processes events. - processing = true; - try - { - let oldBuffer = buffer; - buffer = data.substr(index + 1); - data = data.substr(0, index + 1); - let lines = data.split(/[\r\n]+/); - lines.pop(); - lines[0] = oldBuffer + lines[0]; - for (let i = 0; i < lines.length; i++) - listener.process(lines[i]); - } - finally - { - processing = false; - data = buffer; - buffer = ""; - onProgress(data); - - if (loaded) - { - loaded = false; - onSuccess(); - } - - if (error) - { - let param = error; - error = null; - onError(param); - } - } - } - else - buffer += data; - - if (timeLineID) - { - TimeLine.asyncEnd(timeLineID); - } - }; - - let onSuccess = function() - { - if (processing) - { - // Still processing data, delay processing this event. - loaded = true; - return; - } - - if (timeLineID) - { - TimeLine.asyncStart(timeLineID); - } - - if (buffer !== "") - listener.process(buffer); - listener.process(null); - - if (timeLineID) - { - TimeLine.asyncEnd(timeLineID); - TimeLine.asyncDone(timeLineID); - } - - callback(null); - }; - - let onError = function(e) - { - if (processing) - { - // Still processing data, delay processing this event. - error = e; - return; - } - - callback(e); - - if (timeLineID) - { - TimeLine.asyncDone(timeLineID); - } - }; - - let decoder = new TextDecoder(); - let array = new Uint8Array(BUFFER_SIZE); - Task.spawn(function() - { - if (firstRead && Services.vc.compare(Utils.platformVersion, "23.0a1") <= 0) - { - // See https://issues.adblockplus.org/ticket/530 - the first file - // opened cannot be closed due to Gecko bug 858723. Make sure that - // our patterns.ini file doesn't stay locked by opening a dummy file - // first. - try - { - let dummyPath = IO.resolveFilePath(Prefs.data_directory + "/dummy").path; - let dummy = yield OS.File.open(dummyPath, {write: true, truncate: true}); - yield dummy.close(); - } - catch (e) - { - // Dummy might be locked already, we don't care - } - } - firstRead = false; - - let f = yield OS.File.open(file.path, {read: true}); - let numBytes; - do - { - numBytes = yield f.readTo(array); - if (numBytes) - { - let data = decoder.decode(numBytes == BUFFER_SIZE ? - array : - array.subarray(0, numBytes), {stream: true}); - onProgress(data); - } - } while (numBytes); - - yield f.close(); - }.bind(this)).then(onSuccess, onError); - } - catch (e) - { - callback(e); - } - }, - - /** - * Writes string data to a file in UTF-8 format asynchronously. The callback - * will be called when the write operation is done. - */ - writeToFile: function(/**nsIFile*/ file, /**Iterator*/ data, /**Function*/ callback, /**String*/ timeLineID) - { - try - { - let encoder = new TextEncoder(); - - Task.spawn(function() - { - // This mimics OS.File.writeAtomic() but writes in chunks. - let tmpPath = file.path + ".tmp"; - let f = yield OS.File.open(tmpPath, {write: true, truncate: true}); - - let buf = []; - let bufLen = 0; - let lineBreak = this.lineBreak; - - function writeChunk() - { - let array = encoder.encode(buf.join(lineBreak) + lineBreak); - buf = []; - bufLen = 0; - return f.write(array); - } - - for (let line in data) - { - buf.push(line); - bufLen += line.length; - if (bufLen >= BUFFER_SIZE) - yield writeChunk(); - } - - if (bufLen) - yield writeChunk(); - - // OS.File.flush() isn't exposed prior to Gecko 27, see bug 912457. - if (typeof f.flush == "function") - yield f.flush(); - yield f.close(); - yield OS.File.move(tmpPath, file.path, {noCopy: true}); - }.bind(this)).then(callback.bind(null, null), callback); - } - catch (e) - { - callback(e); - } - }, - - /** - * Copies a file asynchronously. The callback will be called when the copy - * operation is done. - */ - copyFile: function(/**nsIFile*/ fromFile, /**nsIFile*/ toFile, /**Function*/ callback) - { - try - { - let promise = OS.File.copy(fromFile.path, toFile.path); - promise.then(callback.bind(null, null), callback); - } - catch (e) - { - callback(e); - } - }, - - /** - * Renames a file within the same directory, will call callback when done. - */ - renameFile: function(/**nsIFile*/ fromFile, /**String*/ newName, /**Function*/ callback) - { - try - { - toFile = fromFile.clone(); - toFile.leafName = newName; - let promise = OS.File.move(fromFile.path, toFile.path); - promise.then(callback.bind(null, null), callback); - } - catch(e) - { - callback(e); - } - }, - - /** - * Removes a file, will call callback when done. - */ - removeFile: function(/**nsIFile*/ file, /**Function*/ callback) - { - try - { - let promise = OS.File.remove(file.path); - promise.then(callback.bind(null, null), callback); - } - catch(e) - { - callback(e); - } - }, - - /** - * Gets file information such as whether the file exists. - */ - statFile: function(/**nsIFile*/ file, /**Function*/ callback) - { - try - { - let promise = OS.File.stat(file.path); - promise.then(function onSuccess(info) - { - callback(null, { - exists: true, - isDirectory: info.isDir, - isFile: !info.isDir, - lastModified: info.lastModificationDate.getTime() - }); - }, function onError(e) - { - if (e.becauseNoSuchFile) - { - callback(null, { - exists: false, - isDirectory: false, - isFile: false, - lastModified: 0 - }); - } - else - callback(e); - }); - } - catch(e) - { - callback(e); - } - } -} diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/keySelector.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/keySelector.js deleted file mode 100644 index 20847d9..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/keySelector.js +++ /dev/null @@ -1,228 +0,0 @@ -/* - * This file is part of the Adblock Plus build tools, - * 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/Services.jsm"); - -let validModifiers = -{ - ACCEL: null, - CTRL: "control", - CONTROL: "control", - SHIFT: "shift", - ALT: "alt", - META: "meta", - __proto__: null -}; - -/** - * Sets the correct value of validModifiers.ACCEL. - */ -function initAccelKey() -{ - validModifiers.ACCEL = "control"; - try - { - let accelKey = Services.prefs.getIntPref("ui.key.accelKey"); - if (accelKey == Ci.nsIDOMKeyEvent.DOM_VK_CONTROL) - validModifiers.ACCEL = "control"; - else if (accelKey == Ci.nsIDOMKeyEvent.DOM_VK_ALT) - validModifiers.ACCEL = "alt"; - else if (accelKey == Ci.nsIDOMKeyEvent.DOM_VK_META) - validModifiers.ACCEL = "meta"; - } - catch(e) - { - Cu.reportError(e); - } -} - -exports.KeySelector = KeySelector; - -/** - * This class provides capabilities to find and use available keyboard shortcut - * keys. - * @param {ChromeWindow} window the window where to look up existing shortcut - * keys - * @constructor - */ -function KeySelector(window) -{ - this._initExistingShortcuts(window); -} -KeySelector.prototype = -{ - /** - * Map listing existing shortcut keys as its keys. - * @type Object - */ - _existingShortcuts: null, - - /** - * Sets up _existingShortcuts property for a window. - */ - _initExistingShortcuts: function(/**ChromeWindow*/ window) - { - if (!validModifiers.ACCEL) - initAccelKey(); - - this._existingShortcuts = {__proto__: null}; - - let keys = window.document.getElementsByTagName("key"); - for (let i = 0; i < keys.length; i++) - { - let key = keys[i]; - let keyData = - { - shift: false, - meta: false, - alt: false, - control: false, - char: null, - code: null - }; - - let keyChar = key.getAttribute("key"); - if (keyChar && keyChar.length == 1) - keyData.char = keyChar.toUpperCase(); - - let keyCode = key.getAttribute("keycode"); - if (keyCode && "DOM_" + keyCode.toUpperCase() in Ci.nsIDOMKeyEvent) - keyData.code = Ci.nsIDOMKeyEvent["DOM_" + keyCode.toUpperCase()]; - - if (!keyData.char && !keyData.code) - continue; - - let keyModifiers = key.getAttribute("modifiers"); - if (keyModifiers) - for each (let modifier in keyModifiers.toUpperCase().match(/\w+/g)) - if (modifier in validModifiers) - keyData[validModifiers[modifier]] = true; - - let canonical = [keyData.shift, keyData.meta, keyData.alt, keyData.control, keyData.char || keyData.code].join(" "); - this._existingShortcuts[canonical] = true; - } - }, - - /** - * Selects a keyboard shortcut variant that isn't already taken, - * parses it into an object. - */ - selectKey: function(/**String*/ variants) /**Object*/ - { - for each (let variant in variants.split(/\s*,\s*/)) - { - if (!variant) - continue; - - let keyData = - { - shift: false, - meta: false, - alt: false, - control: false, - char: null, - code: null, - codeName: null - }; - for each (let part in variant.toUpperCase().split(/\s+/)) - { - if (part in validModifiers) - keyData[validModifiers[part]] = true; - else if (part.length == 1) - keyData.char = part; - else if ("DOM_VK_" + part in Ci.nsIDOMKeyEvent) - { - keyData.code = Ci.nsIDOMKeyEvent["DOM_VK_" + part]; - keyData.codeName = "VK_" + part; - } - } - - if (!keyData.char && !keyData.code) - continue; - - let canonical = [keyData.shift, keyData.meta, keyData.alt, keyData.control, keyData.char || keyData.code].join(" "); - if (canonical in this._existingShortcuts) - continue; - - return keyData; - } - - return null; - } -}; - -/** - * Creates the text representation for a key. - * @static - */ -KeySelector.getTextForKey = function (/**Object*/ key) /**String*/ -{ - if (!key) - return null; - - if (!("text" in key)) - { - key.text = null; - try - { - let stringBundle = Services.strings.createBundle("chrome://global-platform/locale/platformKeys.properties"); - let parts = []; - if (key.control) - parts.push(stringBundle.GetStringFromName("VK_CONTROL")); - if (key.alt) - parts.push(stringBundle.GetStringFromName("VK_ALT")); - if (key.meta) - parts.push(stringBundle.GetStringFromName("VK_META")); - if (key.shift) - parts.push(stringBundle.GetStringFromName("VK_SHIFT")); - if (key.char) - parts.push(key.char.toUpperCase()); - else - { - let stringBundle2 = Services.strings.createBundle("chrome://global/locale/keys.properties"); - parts.push(stringBundle2.GetStringFromName(key.codeName)); - } - key.text = parts.join(stringBundle.GetStringFromName("MODIFIER_SEPARATOR")); - } - catch (e) - { - Cu.reportError(e); - return null; - } - } - return key.text; -}; - -/** - * Tests whether a keypress event matches the given key. - * @static - */ -KeySelector.matchesKey = function(/**Event*/ event, /**Object*/ key) /**Boolean*/ -{ - if (event.defaultPrevented || !key) - return false; - if (key.shift != event.shiftKey || key.alt != event.altKey) - return false; - if (key.meta != event.metaKey || key.control != event.ctrlKey) - return false; - - if (key.char && event.charCode && String.fromCharCode(event.charCode).toUpperCase() == key.char) - return true; - if (key.code && event.keyCode && event.keyCode == key.code) - return true; - return false; -}; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/main.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/main.js deleted file mode 100644 index f18cc05..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/main.js +++ /dev/null @@ -1,73 +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/>. - */ - -/** - * @fileOverview Starts up Adblock Plus - */ - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -let {TimeLine} = require("timeline"); - -TimeLine.enter("Adblock Plus startup"); -registerPublicAPI(); -TimeLine.log("Done registering public API"); -require("filterListener"); -TimeLine.log("Done loading filter listener"); -require("contentPolicy"); -TimeLine.log("Done loading content policy"); -require("synchronizer"); -TimeLine.log("Done loading subscription synchronizer"); -require("notification"); -TimeLine.log("Done loading notification downloader"); -require("sync"); -TimeLine.log("Done loading sync support"); -require("ui"); -TimeLine.log("Done loading UI integration code"); -TimeLine.leave("Started up"); - -function registerPublicAPI() -{ - let {addonRoot} = require("info"); - - let uri = Services.io.newURI(addonRoot + "lib/Public.jsm", null, null); - if (uri instanceof Ci.nsIMutable) - uri.mutable = false; - - let classID = Components.ID("5e447bce-1dd2-11b2-b151-ec21c2b6a135"); - let contractID = "@adblockplus.org/abp/public;1"; - let factory = - { - createInstance: function(outer, iid) - { - if (outer) - throw Cr.NS_ERROR_NO_AGGREGATION; - return uri.QueryInterface(iid); - }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) - }; - - let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - registrar.registerFactory(classID, "Adblock Plus public API URL", contractID, factory); - - onShutdown.add(function() - { - registrar.unregisterFactory(classID, factory); - Cu.unload(uri.spec); - }); -} diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/matcher.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/matcher.js deleted file mode 100644 index 908b0b8..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/matcher.js +++ /dev/null @@ -1,446 +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/>. - */ - -/** - * @fileOverview Matcher class implementing matching addresses against a list of filters. - */ - -let {Filter, RegExpFilter, WhitelistFilter} = require("filterClasses"); - -/** - * Blacklist/whitelist filter matching - * @constructor - */ -function Matcher() -{ - this.clear(); -} -exports.Matcher = Matcher; - -Matcher.prototype = { - /** - * Lookup table for filters by their associated keyword - * @type Object - */ - filterByKeyword: null, - - /** - * Lookup table for keywords by the filter text - * @type Object - */ - keywordByFilter: null, - - /** - * Removes all known filters - */ - clear: function() - { - this.filterByKeyword = {__proto__: null}; - this.keywordByFilter = {__proto__: null}; - }, - - /** - * Adds a filter to the matcher - * @param {RegExpFilter} filter - */ - add: function(filter) - { - if (filter.text in this.keywordByFilter) - return; - - // Look for a suitable keyword - let keyword = this.findKeyword(filter); - let oldEntry = this.filterByKeyword[keyword]; - if (typeof oldEntry == "undefined") - this.filterByKeyword[keyword] = filter; - else if (oldEntry.length == 1) - this.filterByKeyword[keyword] = [oldEntry, filter]; - else - oldEntry.push(filter); - this.keywordByFilter[filter.text] = keyword; - }, - - /** - * Removes a filter from the matcher - * @param {RegExpFilter} filter - */ - remove: function(filter) - { - if (!(filter.text in this.keywordByFilter)) - return; - - let keyword = this.keywordByFilter[filter.text]; - let list = this.filterByKeyword[keyword]; - if (list.length <= 1) - delete this.filterByKeyword[keyword]; - else - { - let index = list.indexOf(filter); - if (index >= 0) - { - list.splice(index, 1); - if (list.length == 1) - this.filterByKeyword[keyword] = list[0]; - } - } - - delete this.keywordByFilter[filter.text]; - }, - - /** - * Chooses a keyword to be associated with the filter - * @param {String} text text representation of the filter - * @return {String} keyword (might be empty string) - */ - findKeyword: function(filter) - { - let result = ""; - let text = filter.text; - if (Filter.regexpRegExp.test(text)) - return result; - - // Remove options - let match = Filter.optionsRegExp.exec(text); - if (match) - text = match.input.substr(0, match.index); - - // Remove whitelist marker - if (text.substr(0, 2) == "@@") - text = text.substr(2); - - let candidates = text.toLowerCase().match(/[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])/g); - if (!candidates) - return result; - - let hash = this.filterByKeyword; - let resultCount = 0xFFFFFF; - let resultLength = 0; - for (let i = 0, l = candidates.length; i < l; i++) - { - let candidate = candidates[i].substr(1); - let count = (candidate in hash ? hash[candidate].length : 0); - if (count < resultCount || (count == resultCount && candidate.length > resultLength)) - { - result = candidate; - resultCount = count; - resultLength = candidate.length; - } - } - return result; - }, - - /** - * Checks whether a particular filter is being matched against. - */ - hasFilter: function(/**RegExpFilter*/ filter) /**Boolean*/ - { - return (filter.text in this.keywordByFilter); - }, - - /** - * Returns the keyword used for a filter, null for unknown filters. - */ - getKeywordForFilter: function(/**RegExpFilter*/ filter) /**String*/ - { - if (filter.text in this.keywordByFilter) - return this.keywordByFilter[filter.text]; - else - return null; - }, - - /** - * Checks whether the entries for a particular keyword match a URL - */ - _checkEntryMatch: function(keyword, location, contentType, docDomain, thirdParty, privatenode) - { - let list = this.filterByKeyword[keyword]; - for (let i = 0; i < list.length; i++) - { - let filter = list[i]; - if (filter.matches(location, contentType, docDomain, thirdParty,privatenode)) - return filter; - } - return null; - }, - - /** - * Tests whether the URL matches any of the known filters - * @param {String} location URL to be tested - * @param {String} contentType content type identifier of the URL - * @param {String} docDomain domain name of the document that loads the URL - * @param {Boolean} thirdParty should be true if the URL is a third-party request - * @return {RegExpFilter} matching filter or null - */ - matchesAny: function(location, contentType, docDomain, thirdParty) - { - let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); - if (candidates === null) - candidates = []; - candidates.push(""); - for (let i = 0, l = candidates.length; i < l; i++) - { - let substr = candidates[i]; - if (substr in this.filterByKeyword) - { - let result = this._checkEntryMatch(substr, location, contentType, docDomain, thirdParty); - if (result) - return result; - } - } - - return null; - } -}; - -/** - * Combines a matcher for blocking and exception rules, automatically sorts - * rules into two Matcher instances. - * @constructor - */ -function CombinedMatcher() -{ - this.blacklist = new Matcher(); - this.whitelist = new Matcher(); - this.keys = {__proto__: null}; - this.resultCache = {__proto__: null}; -} -exports.CombinedMatcher = CombinedMatcher; - -/** - * Maximal number of matching cache entries to be kept - * @type Number - */ -CombinedMatcher.maxCacheEntries = 1000; - -CombinedMatcher.prototype = -{ - /** - * Matcher for blocking rules. - * @type Matcher - */ - blacklist: null, - - /** - * Matcher for exception rules. - * @type Matcher - */ - whitelist: null, - - /** - * Exception rules that are limited by public keys, mapped by the corresponding keys. - * @type Object - */ - keys: null, - - /** - * Lookup table of previous matchesAny results - * @type Object - */ - resultCache: null, - - /** - * Number of entries in resultCache - * @type Number - */ - cacheEntries: 0, - - /** - * @see Matcher#clear - */ - clear: function() - { - this.blacklist.clear(); - this.whitelist.clear(); - this.keys = {__proto__: null}; - this.resultCache = {__proto__: null}; - this.cacheEntries = 0; - }, - - /** - * @see Matcher#add - */ - add: function(filter) - { - if (filter instanceof WhitelistFilter) - { - if (filter.siteKeys) - { - for (let i = 0; i < filter.siteKeys.length; i++) - this.keys[filter.siteKeys[i]] = filter.text; - } - else - this.whitelist.add(filter); - } - else - this.blacklist.add(filter); - - if (this.cacheEntries > 0) - { - this.resultCache = {__proto__: null}; - this.cacheEntries = 0; - } - }, - - /** - * @see Matcher#remove - */ - remove: function(filter) - { - if (filter instanceof WhitelistFilter) - { - if (filter.siteKeys) - { - for (let i = 0; i < filter.siteKeys.length; i++) - delete this.keys[filter.siteKeys[i]]; - } - else - this.whitelist.remove(filter); - } - else - this.blacklist.remove(filter); - - if (this.cacheEntries > 0) - { - this.resultCache = {__proto__: null}; - this.cacheEntries = 0; - } - }, - - /** - * @see Matcher#findKeyword - */ - findKeyword: function(filter) - { - if (filter instanceof WhitelistFilter) - return this.whitelist.findKeyword(filter); - else - return this.blacklist.findKeyword(filter); - }, - - /** - * @see Matcher#hasFilter - */ - hasFilter: function(filter) - { - if (filter instanceof WhitelistFilter) - return this.whitelist.hasFilter(filter); - else - return this.blacklist.hasFilter(filter); - }, - - /** - * @see Matcher#getKeywordForFilter - */ - getKeywordForFilter: function(filter) - { - if (filter instanceof WhitelistFilter) - return this.whitelist.getKeywordForFilter(filter); - else - return this.blacklist.getKeywordForFilter(filter); - }, - - /** - * Checks whether a particular filter is slow - */ - isSlowFilter: function(/**RegExpFilter*/ filter) /**Boolean*/ - { - let matcher = (filter instanceof WhitelistFilter ? this.whitelist : this.blacklist); - if (matcher.hasFilter(filter)) - return !matcher.getKeywordForFilter(filter); - else - return !matcher.findKeyword(filter); - }, - - /** - * Optimized filter matching testing both whitelist and blacklist matchers - * simultaneously. For parameters see Matcher.matchesAny(). - * @see Matcher#matchesAny - */ - matchesAnyInternal: function(location, contentType, docDomain, thirdParty, privatenode) - { - let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); - if (candidates === null) - candidates = []; - candidates.push(""); - - let blacklistHit = null; - for (let i = 0, l = candidates.length; i < l; i++) - { - let substr = candidates[i]; - if (substr in this.whitelist.filterByKeyword) - { - let result = this.whitelist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, privatenode); - if (result) - return result; - } - if (substr in this.blacklist.filterByKeyword && blacklistHit === null) - blacklistHit = this.blacklist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, privatenode); - } - return blacklistHit; - }, - - /** - * @see Matcher#matchesAny - */ - matchesAny: function(location, contentType, docDomain, thirdParty, privatenode) - { - let key = location + " " + contentType + " " + docDomain + " " + thirdParty; - if (!privatenode){ - if (key in this.resultCache) - return this.resultCache[key]; - } - - let result = this.matchesAnyInternal(location, contentType, docDomain, thirdParty, privatenode); - - if (this.cacheEntries >= CombinedMatcher.maxCacheEntries) - { - this.resultCache = {__proto__: null}; - this.cacheEntries = 0; - } - - if (!privatenode){ - this.resultCache[key] = result; - this.cacheEntries++; - } - - return result; - }, - - /** - * Looks up whether any filters match the given website key. - */ - matchesByKey: function(/**String*/ location, /**String*/ key, /**String*/ docDomain) - { - key = key.toUpperCase(); - if (key in this.keys) - { - let filter = Filter.knownFilters[this.keys[key]]; - if (filter && filter.matches(location, "DOCUMENT", docDomain, false)) - return filter; - else - return null; - } - else - return null; - } -} - -/** - * Shared CombinedMatcher instance that should usually be used. - * @type CombinedMatcher - */ -let defaultMatcher = exports.defaultMatcher = new CombinedMatcher(); diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/notification.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/notification.js deleted file mode 100644 index 06e949e..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/notification.js +++ /dev/null @@ -1,339 +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/>. - */ - -/** - * @fileOverview Handles notifications. - */ - -Cu.import("resource://gre/modules/Services.jsm"); - -let {TimeLine} = require("timeline"); -let {Prefs} = require("prefs"); -let {Downloader, Downloadable, MILLIS_IN_MINUTE, MILLIS_IN_HOUR, MILLIS_IN_DAY} = require("downloader"); -let {Utils} = require("utils"); -let {Matcher} = require("matcher"); -let {Filter} = require("filterClasses"); - -let INITIAL_DELAY = 12 * MILLIS_IN_MINUTE; -let CHECK_INTERVAL = 1 * MILLIS_IN_HOUR; -let EXPIRATION_INTERVAL = 1 * MILLIS_IN_DAY; -let TYPE = { - information: 0, - question: 1, - critical: 2 -}; - -let listeners = {}; - -function getNumericalSeverity(notification) -{ - return (notification.type in TYPE ? TYPE[notification.type] : TYPE.information); -} - -function saveNotificationData() -{ - // HACK: JSON values aren't saved unless they are assigned a different object. - Prefs.notificationdata = JSON.parse(JSON.stringify(Prefs.notificationdata)); -} - -function localize(translations, locale) -{ - if (locale in translations) - return translations[locale]; - - let languagePart = locale.substring(0, locale.indexOf("-")); - if (languagePart && languagePart in translations) - return translations[languagePart]; - - let defaultLocale = "en-US"; - return translations[defaultLocale]; -} - -/** - * The object providing actual downloading functionality. - * @type Downloader - */ -let downloader = null; -let localData = []; - -/** - * Regularly fetches notifications and decides which to show. - * @class - */ -let Notification = exports.Notification = -{ - /** - * Called on module startup. - */ - init: function() - { - TimeLine.enter("Entered Notification.init()"); - - downloader = new Downloader(this._getDownloadables.bind(this), INITIAL_DELAY, CHECK_INTERVAL); - onShutdown.add(function() - { - downloader.cancel(); - }); - - downloader.onExpirationChange = this._onExpirationChange.bind(this); - downloader.onDownloadSuccess = this._onDownloadSuccess.bind(this); - downloader.onDownloadError = this._onDownloadError.bind(this); - - TimeLine.leave("Notification.init() done"); - }, - - /** - * Yields a Downloadable instances for the notifications download. - */ - _getDownloadables: function() - { - let downloadable = new Downloadable(Prefs.notificationurl); - if (typeof Prefs.notificationdata.lastError === "number") - downloadable.lastError = Prefs.notificationdata.lastError; - if (typeof Prefs.notificationdata.lastCheck === "number") - downloadable.lastCheck = Prefs.notificationdata.lastCheck; - if (typeof Prefs.notificationdata.data === "object" && "version" in Prefs.notificationdata.data) - downloadable.lastVersion = Prefs.notificationdata.data.version; - if (typeof Prefs.notificationdata.softExpiration === "number") - downloadable.softExpiration = Prefs.notificationdata.softExpiration; - if (typeof Prefs.notificationdata.hardExpiration === "number") - downloadable.hardExpiration = Prefs.notificationdata.hardExpiration; - yield downloadable; - }, - - _onExpirationChange: function(downloadable) - { - Prefs.notificationdata.lastCheck = downloadable.lastCheck; - Prefs.notificationdata.softExpiration = downloadable.softExpiration; - Prefs.notificationdata.hardExpiration = downloadable.hardExpiration; - saveNotificationData(); - }, - - _onDownloadSuccess: function(downloadable, responseText, errorCallback, redirectCallback) - { - try - { - let data = JSON.parse(responseText); - for (let notification of data.notifications) - { - if ("severity" in notification) - { - if (!("type" in notification)) - notification.type = notification.severity; - delete notification.severity; - } - } - Prefs.notificationdata.data = data; - } - catch (e) - { - Cu.reportError(e); - errorCallback("synchronize_invalid_data"); - return; - } - - Prefs.notificationdata.lastError = 0; - Prefs.notificationdata.downloadStatus = "synchronize_ok"; - [Prefs.notificationdata.softExpiration, Prefs.notificationdata.hardExpiration] = downloader.processExpirationInterval(EXPIRATION_INTERVAL); - saveNotificationData(); - }, - - _onDownloadError: function(downloadable, downloadURL, error, channelStatus, responseStatus, redirectCallback) - { - Prefs.notificationdata.lastError = Date.now(); - Prefs.notificationdata.downloadStatus = error; - saveNotificationData(); - }, - - /** - * Determines which notification is to be shown next. - * @param {String} url URL to match notifications to (optional) - * @return {Object} notification to be shown, or null if there is none - */ - getNextToShow: function(url) - { - function checkTarget(target, parameter, name, version) - { - let minVersionKey = parameter + "MinVersion"; - let maxVersionKey = parameter + "MaxVersion"; - return !((parameter in target && target[parameter] != name) || - (minVersionKey in target && Services.vc.compare(version, target[minVersionKey]) < 0) || - (maxVersionKey in target && Services.vc.compare(version, target[maxVersionKey]) > 0)); - } - - let remoteData = []; - if (typeof Prefs.notificationdata.data == "object" && Prefs.notificationdata.data.notifications instanceof Array) - remoteData = Prefs.notificationdata.data.notifications; - - if (!(Prefs.notificationdata.shown instanceof Array)) - { - Prefs.notificationdata.shown = []; - saveNotificationData(); - } - - let notifications = localData.concat(remoteData); - if (notifications.length === 0) - return null; - - let {addonName, addonVersion, application, applicationVersion, platform, platformVersion} = require("info"); - let notificationToShow = null; - for (let notification of notifications) - { - if ((typeof notification.type === "undefined" || notification.type !== "critical") - && Prefs.notificationdata.shown.indexOf(notification.id) !== -1) - continue; - - if (typeof url === "string" || notification.urlFilters instanceof Array) - { - if (typeof url === "string" && notification.urlFilters instanceof Array) - { - let matcher = new Matcher(); - for (let urlFilter of notification.urlFilters) - matcher.add(Filter.fromText(urlFilter)); - if (!matcher.matchesAny(url, "DOCUMENT", url)) - continue; - } - else - continue; - } - - if (notification.targets instanceof Array) - { - let match = false; - for (let target of notification.targets) - { - if (checkTarget(target, "extension", addonName, addonVersion) && - checkTarget(target, "application", application, applicationVersion) && - checkTarget(target, "platform", platform, platformVersion)) - { - match = true; - break; - } - } - if (!match) - continue; - } - - if (!notificationToShow - || getNumericalSeverity(notification) > getNumericalSeverity(notificationToShow)) - notificationToShow = notification; - } - - if (notificationToShow && "id" in notificationToShow) - { - if (notificationToShow.type !== "question") - this.markAsShown(notificationToShow.id); - } - - return notificationToShow; - }, - - markAsShown: function(id) - { - if (Prefs.notificationdata.shown.indexOf(id) > -1) - return; - - Prefs.notificationdata.shown.push(id); - saveNotificationData(); - }, - - /** - * Localizes the texts of the supplied notification. - * @param {Object} notification notification to translate - * @param {String} locale the target locale (optional, defaults to the - * application locale) - * @return {Object} the translated texts - */ - getLocalizedTexts: function(notification, locale) - { - locale = locale || Utils.appLocale; - let textKeys = ["title", "message"]; - let localizedTexts = []; - for (let key of textKeys) - { - if (key in notification) - { - if (typeof notification[key] == "string") - localizedTexts[key] = notification[key]; - else - localizedTexts[key] = localize(notification[key], locale); - } - } - return localizedTexts; - }, - - /** - * Adds a local notification. - * @param {Object} notification notification to add - */ - addNotification: function(notification) - { - if (localData.indexOf(notification) == -1) - localData.push(notification); - }, - - /** - * Removes an existing local notification. - * @param {Object} notification notification to remove - */ - removeNotification: function(notification) - { - let index = localData.indexOf(notification); - if (index > -1) - localData.splice(index, 1); - }, - - /** - * Adds a listener for question-type notifications - */ - addQuestionListener: function(/**string*/ id, /**function(approved)*/ listener) - { - if (!(id in listeners)) - listeners[id] = []; - if (listeners[id].indexOf(listener) === -1) - listeners[id].push(listener); - }, - - /** - * Removes a listener that was previously added via addQuestionListener - */ - removeQuestionListener: function(/**string*/ id, /**function(approved)*/ listener) - { - if (!(id in listeners)) - return; - let index = listeners[id].indexOf(listener); - if (index > -1) - listeners[id].splice(index, 1); - if (listeners[id].length === 0) - delete listeners[id]; - }, - - /** - * Notifies listeners about interactions with a notification - * @param {String} id notification ID - * @param {Boolean} approved indicator whether notification has been approved or not - */ - triggerQuestionListeners: function(id, approved) - { - if (!(id in listeners)) - return; - let questionListeners = listeners[id]; - for (let listener of questionListeners) - listener(approved); - } -}; -Notification.init(); diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/objectTabs.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/objectTabs.js deleted file mode 100644 index 1227490..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/objectTabs.js +++ /dev/null @@ -1,492 +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/>. - */ - -/** - * @fileOverview Code responsible for showing and hiding object tabs. - */ - -/** - * Class responsible for showing and hiding object tabs. - * @class - */ -var objTabs = -{ - /** - * Number of milliseconds to wait until hiding tab after the mouse moves away. - * @type Integer - */ - HIDE_DELAY: 1000, - - /** - * Flag used to trigger object tabs initialization first time object tabs are - * used. - * @type Boolean - */ - initialized: false, - - /** - * Will be set to true while initialization is in progress. - * @type Boolean - */ - initializing: false, - - /** - * Parameters for _showTab, to be called once initialization is complete. - */ - delayedShowParams: null, - - /** - * Randomly generated class to be used for visible object tabs on top of object. - * @type String - */ - objTabClassVisibleTop: null, - - /** - * Randomly generated class to be used for visible object tabs at the bottom of the object. - * @type String - */ - objTabClassVisibleBottom: null, - - /** - * Randomly generated class to be used for invisible object tabs. - * @type String - */ - objTabClassHidden: null, - - /** - * Document element the object tab is currently being displayed for. - * @type Element - */ - currentElement: null, - - /** - * Windows that the window event handler is currently registered for. - * @type Array of Window - */ - windowListeners: null, - - /** - * Panel element currently used as object tab. - * @type Element - */ - objtabElement: null, - - /** - * Time of previous position update. - * @type Integer - */ - prevPositionUpdate: 0, - - /** - * Timer used to update position of the object tab. - * @type nsITimer - */ - positionTimer: null, - - /** - * Timer used to delay hiding of the object tab. - * @type nsITimer - */ - hideTimer: null, - - /** - * Used when hideTimer is running, time when the tab should be hidden. - * @type Integer - */ - hideTargetTime: 0, - - /** - * Initializes object tabs (generates random classes and registers stylesheet). - */ - _initCSS: function() - { - function processCSSData(request) - { - if (onShutdown.done) - return; - - let data = request.responseText; - - let rnd = []; - let offset = "a".charCodeAt(0); - for (let i = 0; i < 60; i++) - rnd.push(offset + Math.random() * 26); - - this.objTabClassVisibleTop = String.fromCharCode.apply(String, rnd.slice(0, 20)); - this.objTabClassVisibleBottom = String.fromCharCode.apply(String, rnd.slice(20, 40)); - this.objTabClassHidden = String.fromCharCode.apply(String, rnd.slice(40, 60)); - - let {Utils} = require("utils"); - let url = Utils.makeURI("data:text/css," + encodeURIComponent(data.replace(/%%CLASSVISIBLETOP%%/g, this.objTabClassVisibleTop) - .replace(/%%CLASSVISIBLEBOTTOM%%/g, this.objTabClassVisibleBottom) - .replace(/%%CLASSHIDDEN%%/g, this.objTabClassHidden))); - Utils.styleService.loadAndRegisterSheet(url, Ci.nsIStyleSheetService.USER_SHEET); - onShutdown.add(function() - { - Utils.styleService.unregisterSheet(url, Ci.nsIStyleSheetService.USER_SHEET); - }); - - this.initializing = false; - this.initialized = true; - - if (this.delayedShowParams) - this._showTab.apply(this, this.delayedShowParams); - } - - this.delayedShowParams = arguments; - - if (!this.initializing) - { - this.initializing = true; - - // Load CSS asynchronously - try { - let request = new XMLHttpRequest(); - request.mozBackgroundRequest = true; - request.open("GET", "chrome://adblockplus/content/objtabs.css"); - request.overrideMimeType("text/plain"); - - request.addEventListener("load", processCSSData.bind(this, request), false); - request.send(null); - } - catch (e) - { - Cu.reportError(e); - this.initializing = false; - } - } - }, - - /** - * Called to show object tab for an element. - */ - showTabFor: function(/**Element*/ element) - { - // Object tabs aren't usable in Fennec - let {application} = require("info"); - if (application == "fennec" || application == "fennec2") - return; - - let {Prefs} = require("prefs"); - if (!Prefs.frameobjects) - return; - - if (this.hideTimer) - { - this.hideTimer.cancel(); - this.hideTimer = null; - } - - if (this.objtabElement) - this.objtabElement.style.setProperty("opacity", "1", "important"); - - if (this.currentElement != element) - { - this._hideTab(); - - let {Policy} = require("contentPolicy"); - let {RequestNotifier} = require("requestNotifier"); - let data = RequestNotifier.getDataForNode(element, true, Policy.type.OBJECT); - if (data) - { - if (this.initialized) - this._showTab(element, data[1]); - else - this._initCSS(element, data[1]); - } - } - }, - - /** - * Called to hide object tab for an element (actual hiding happens delayed). - */ - hideTabFor: function(/**Element*/ element) - { - if (element != this.currentElement || this.hideTimer) - return; - - this.hideTargetTime = Date.now() + this.HIDE_DELAY; - this.hideTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this.hideTimer.init(this, 40, Ci.nsITimer.TYPE_REPEATING_SLACK); - }, - - /** - * Makes the tab element visible. - */ - _showTab: function(/**Element*/ element, /**RequestEntry*/ data) - { - let {UI} = require("ui"); - if (!UI.overlay) - return; - - let doc = element.ownerDocument.defaultView.top.document; - - this.objtabElement = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"); - this.objtabElement.textContent = UI.overlay.attributes.objtabtext; - this.objtabElement.setAttribute("title", UI.overlay.attributes.objtabtooltip); - this.objtabElement.setAttribute("href", data.location); - this.objtabElement.setAttribute("class", this.objTabClassHidden); - this.objtabElement.style.setProperty("opacity", "1", "important"); - this.objtabElement.nodeData = data; - - this.currentElement = element; - - // Register paint listeners for the relevant windows - this.windowListeners = []; - let wnd = element.ownerDocument.defaultView; - while (wnd) - { - wnd.addEventListener("MozAfterPaint", objectWindowEventHandler, false); - this.windowListeners.push(wnd); - wnd = (wnd.parent != wnd ? wnd.parent : null); - } - - // Register mouse listeners on the object tab - this.objtabElement.addEventListener("mouseover", objectTabEventHander, false); - this.objtabElement.addEventListener("mouseout", objectTabEventHander, false); - this.objtabElement.addEventListener("click", objectTabEventHander, true); - - // Insert the tab into the document and adjust its position - doc.documentElement.appendChild(this.objtabElement); - if (!this.positionTimer) - { - this.positionTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this.positionTimer.init(this, 200, Ci.nsITimer.TYPE_REPEATING_SLACK); - } - this._positionTab(); - }, - - /** - * Hides the tab element. - */ - _hideTab: function() - { - this.delayedShowParams = null; - - if (this.objtabElement) - { - // Prevent recursive calls via popuphidden handler - let objtab = this.objtabElement; - this.objtabElement = null; - this.currentElement = null; - - if (this.hideTimer) - { - this.hideTimer.cancel(); - this.hideTimer = null; - } - - if (this.positionTimer) - { - this.positionTimer.cancel(); - this.positionTimer = null; - } - - try { - objtab.parentNode.removeChild(objtab); - } catch (e) {} - objtab.removeEventListener("mouseover", objectTabEventHander, false); - objtab.removeEventListener("mouseout", objectTabEventHander, false); - objtab.nodeData = null; - - for (let wnd of this.windowListeners) - wnd.removeEventListener("MozAfterPaint", objectWindowEventHandler, false); - this.windowListeners = null; - } - }, - - /** - * Updates position of the tab element. - */ - _positionTab: function() - { - // Test whether element is still in document - let elementDoc = null; - try - { - elementDoc = this.currentElement.ownerDocument; - } catch (e) {} // Ignore "can't access dead object" error - if (!elementDoc || !this.currentElement.offsetWidth || !this.currentElement.offsetHeight || - !elementDoc.defaultView || !elementDoc.documentElement) - { - this._hideTab(); - return; - } - - let objRect = this._getElementPosition(this.currentElement); - - let className = this.objTabClassVisibleTop; - let left = objRect.right - this.objtabElement.offsetWidth; - let top = objRect.top - this.objtabElement.offsetHeight; - if (top < 0) - { - top = objRect.bottom; - className = this.objTabClassVisibleBottom; - } - - if (this.objtabElement.style.left != left + "px") - this.objtabElement.style.setProperty("left", left + "px", "important"); - if (this.objtabElement.style.top != top + "px") - this.objtabElement.style.setProperty("top", top + "px", "important"); - - if (this.objtabElement.getAttribute("class") != className) - this.objtabElement.setAttribute("class", className); - - this.prevPositionUpdate = Date.now(); - }, - - /** - * Calculates element's position relative to the top frame and considering - * clipping due to scrolling. - * @return {left: Number, top: Number, right: Number, bottom: Number} - */ - _getElementPosition: function(/**Element*/ element) - { - // Restrict rectangle coordinates by the boundaries of a window's client area - function intersectRect(rect, wnd) - { - // Cannot use wnd.innerWidth/Height because they won't account for scrollbars - let doc = wnd.document; - let wndWidth = doc.documentElement.clientWidth; - let wndHeight = doc.documentElement.clientHeight; - if (doc.compatMode == "BackCompat") // clientHeight will be bogus in quirks mode - wndHeight = Math.max(doc.documentElement.offsetHeight, doc.body.offsetHeight) - wnd.scrollMaxY - 1; - - rect.left = Math.max(rect.left, 0); - rect.top = Math.max(rect.top, 0); - rect.right = Math.min(rect.right, wndWidth); - rect.bottom = Math.min(rect.bottom, wndHeight); - } - - let rect = element.getBoundingClientRect(); - let wnd = element.ownerDocument.defaultView; - - let style = wnd.getComputedStyle(element, null); - let offsets = [ - parseFloat(style.borderLeftWidth) + parseFloat(style.paddingLeft), - parseFloat(style.borderTopWidth) + parseFloat(style.paddingTop), - parseFloat(style.borderRightWidth) + parseFloat(style.paddingRight), - parseFloat(style.borderBottomWidth) + parseFloat(style.paddingBottom) - ]; - - rect = {left: rect.left + offsets[0], top: rect.top + offsets[1], - right: rect.right - offsets[2], bottom: rect.bottom - offsets[3]}; - while (true) - { - intersectRect(rect, wnd); - - if (!wnd.frameElement) - break; - - // Recalculate coordinates to be relative to frame's parent window - let frameElement = wnd.frameElement; - wnd = frameElement.ownerDocument.defaultView; - - let frameRect = frameElement.getBoundingClientRect(); - let frameStyle = wnd.getComputedStyle(frameElement, null); - let relLeft = frameRect.left + parseFloat(frameStyle.borderLeftWidth) + parseFloat(frameStyle.paddingLeft); - let relTop = frameRect.top + parseFloat(frameStyle.borderTopWidth) + parseFloat(frameStyle.paddingTop); - - rect.left += relLeft; - rect.right += relLeft; - rect.top += relTop; - rect.bottom += relTop; - } - - return rect; - }, - - doBlock: function() - { - let {UI} = require("ui"); - let {Utils} = require("utils"); - let chromeWindow = Utils.getChromeWindow(this.currentElement.ownerDocument.defaultView); - UI.blockItem(chromeWindow, this.currentElement, this.objtabElement.nodeData); - }, - - /** - * Called whenever a timer fires. - */ - observe: function(/**nsISupport*/ subject, /**String*/ topic, /**String*/ data) - { - if (subject == this.positionTimer) - { - // Don't update position if it was already updated recently (via MozAfterPaint) - if (Date.now() - this.prevPositionUpdate > 100) - this._positionTab(); - } - else if (subject == this.hideTimer) - { - let now = Date.now(); - if (now >= this.hideTargetTime) - this._hideTab(); - else if (this.hideTargetTime - now < this.HIDE_DELAY / 2) - this.objtabElement.style.setProperty("opacity", (this.hideTargetTime - now) * 2 / this.HIDE_DELAY, "important"); - } - } -}; - -onShutdown.add(objTabs._hideTab.bind(objTabs)); - -/** - * Function called whenever the mouse enters or leaves an object. - */ -function objectMouseEventHander(/**Event*/ event) -{ - if (!event.isTrusted) - return; - - if (event.type == "mouseover") - objTabs.showTabFor(event.target); - else if (event.type == "mouseout") - objTabs.hideTabFor(event.target); -} - -/** - * Function called for paint events of the object tab window. - */ -function objectWindowEventHandler(/**Event*/ event) -{ - if (!event.isTrusted) - return; - - // Don't trigger update too often, avoid overusing CPU on frequent page updates - if (event.type == "MozAfterPaint" && Date.now() - objTabs.prevPositionUpdate > 20) - objTabs._positionTab(); -} - -/** - * Function called whenever the mouse enters or leaves an object tab. - */ -function objectTabEventHander(/**Event*/ event) -{ - if (onShutdown.done || !event.isTrusted) - return; - - if (event.type == "click" && event.button == 0) - { - event.preventDefault(); - event.stopPropagation(); - - objTabs.doBlock(); - } - else if (event.type == "mouseover") - objTabs.showTabFor(objTabs.currentElement); - else if (event.type == "mouseout") - objTabs.hideTabFor(objTabs.currentElement); -} -exports.objectMouseEventHander = objectMouseEventHander; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/prefs.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/prefs.js deleted file mode 100644 index e1b6ae0..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/prefs.js +++ /dev/null @@ -1,203 +0,0 @@ -/* - * This file is part of the Adblock Plus build tools, - * 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/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -let {addonRoot, addonName} = require("info"); -let branchName = "extensions." + addonName + "."; -let branch = Services.prefs.getBranch(branchName); -let ignorePrefChanges = false; - -function init() -{ - // Load default preferences and set up properties for them - let defaultBranch = Services.prefs.getDefaultBranch(branchName); - let scope = - { - pref: function(pref, value) - { - if (pref.substr(0, branchName.length) != branchName) - { - Cu.reportError(new Error("Ignoring default preference " + pref + ", wrong branch.")); - return; - } - pref = pref.substr(branchName.length); - - let [getter, setter] = typeMap[typeof value]; - setter(defaultBranch, pref, value); - defineProperty(pref, false, getter, setter); - } - }; - Services.scriptloader.loadSubScript(addonRoot + "defaults/prefs.js", scope); - - // Add preference change observer - try - { - branch.QueryInterface(Ci.nsIPrefBranch2).addObserver("", Prefs, true); - onShutdown.add(function() branch.removeObserver("", Prefs)); - } - catch (e) - { - Cu.reportError(e); - } -} - -/** - * Sets up getter/setter on Prefs object for preference. - */ -function defineProperty(/**String*/ name, defaultValue, /**Function*/ readFunc, /**Function*/ writeFunc) -{ - let value = defaultValue; - Prefs["_update_" + name] = function() - { - try - { - value = readFunc(branch, name); - triggerListeners(name); - } - catch(e) - { - Cu.reportError(e); - } - }; - Prefs.__defineGetter__(name, function() value); - Prefs.__defineSetter__(name, function(newValue) - { - if (value == newValue) - return value; - - try - { - ignorePrefChanges = true; - writeFunc(branch, name, newValue); - value = newValue; - Services.prefs.savePrefFile(null); - triggerListeners(name); - } - catch(e) - { - Cu.reportError(e); - } - finally - { - ignorePrefChanges = false; - } - return value; - }); - Prefs["_update_" + name](); -} - -let listeners = []; -function triggerListeners(/**String*/ name) -{ - for (let i = 0; i < listeners.length; i++) - { - try - { - listeners[i](name); - } - catch(e) - { - Cu.reportError(e); - } - } -} - -/** - * Manages the preferences for an extension, object properties corresponding - * to extension's preferences are added automatically. Setting the property - * will automatically change the preference, external preference changes are - * also recognized automatically. - */ -let Prefs = exports.Prefs = -{ - /** - * Migrates an old preference to a new name. - */ - migrate: function(/**String*/ oldName, /**String*/ newName) - { - if (newName in this && Services.prefs.prefHasUserValue(oldName)) - { - let [getter, setter] = typeMap[typeof this[newName]]; - try - { - this[newName] = getter(Services.prefs, oldName); - } catch(e) {} - Services.prefs.clearUserPref(oldName); - } - }, - - /** - * Adds a preferences listener that will be fired whenever a preference - * changes. - */ - addListener: function(/**Function*/ listener) - { - if (listeners.indexOf(listener) < 0) - listeners.push(listener); - }, - - /** - * Removes a preferences listener. - */ - removeListener: function(/**Function*/ listener) - { - let index = listeners.indexOf(listener); - if (index >= 0) - listeners.splice(index, 1); - }, - - observe: function(subject, topic, data) - { - if (ignorePrefChanges || topic != "nsPref:changed") - return; - - if ("_update_" + data in this) - this["_update_" + data](); - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObserver]) -}; - -// Getter/setter functions for difference preference types -let typeMap = -{ - boolean: [getBoolPref, setBoolPref], - number: [getIntPref, setIntPref], - string: [getCharPref, setCharPref], - object: [getJSONPref, setJSONPref] -}; - -function getIntPref(branch, pref) branch.getIntPref(pref) -function setIntPref(branch, pref, newValue) branch.setIntPref(pref, newValue) - -function getBoolPref(branch, pref) branch.getBoolPref(pref) -function setBoolPref(branch, pref, newValue) branch.setBoolPref(pref, newValue) - -function getCharPref(branch, pref) branch.getComplexValue(pref, Ci.nsISupportsString).data -function setCharPref(branch, pref, newValue) -{ - let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString); - str.data = newValue; - branch.setComplexValue(pref, Ci.nsISupportsString, str); -} - -function getJSONPref(branch, pref) JSON.parse(getCharPref(branch, pref)) -function setJSONPref(branch, pref, newValue) setCharPref(branch, pref, JSON.stringify(newValue)) - -init(); diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/requestNotifier.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/requestNotifier.js deleted file mode 100644 index 2ee9ec3..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/requestNotifier.js +++ /dev/null @@ -1,378 +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/>. - */ - -/** - * @fileOverview Stores Adblock Plus data to be attached to a window. - */ - -Cu.import("resource://gre/modules/Services.jsm"); - -let {Utils} = require("utils"); -let {BlockingFilter, WhitelistFilter, ElemHideBase, ElemHideFilter, ElemHideException} = require("filterClasses"); - -let nodeData = new WeakMap(); -let windowStats = new WeakMap(); -let windowSelection = new WeakMap(); - -let setEntry, hasEntry, getEntry; -// Last issue(Bug 982561) preventing us from using WeakMap fixed for FF version 32 -if (Services.vc.compare(Utils.platformVersion, "32.0a1") >= 0) -{ - setEntry = (map, key, value) => map.set(key, value); - hasEntry = (map, key) => map.has(key); - getEntry = (map, key) => map.get(key); -} -else -{ - // Fall back to user data - let dataSeed = Math.random(); - let nodeDataProp = "abpNodeData" + dataSeed; - let windowStatsProp = "abpWindowStats" + dataSeed; - let windowSelectionProp = "abpWindowSelection" + dataSeed; - let getProp = function(map) - { - switch (map) - { - case nodeData: - return nodeDataProp; - case windowStats: - return windowStatsProp; - case windowSelection: - return windowSelectionProp; - default: - return null; - } - }; - - setEntry = (map, key, value) => key.setUserData(getProp(map), value, null); - hasEntry = (map, key) => key.getUserData(getProp(map)); - getEntry = (map, key) => key.getUserData(getProp(map)) || undefined; -} - -/** - * List of notifiers in use - these notifiers need to receive notifications on - * new requests. - * @type RequestNotifier[] - */ -let activeNotifiers = []; - -/** - * Creates a notifier object for a particular window. After creation the window - * will first be scanned for previously saved requests. Once that scan is - * complete only new requests for this window will be reported. - * @param {Window} wnd window to attach the notifier to - * @param {Function} listener listener to be called whenever a new request is found - * @param {Object} [listenerObj] "this" pointer to be used when calling the listener - */ -function RequestNotifier(wnd, listener, listenerObj) -{ - this.window = wnd; - this.listener = listener; - this.listenerObj = listenerObj || null; - activeNotifiers.push(this); - if (wnd) - this.startScan(wnd); - else - this.scanComplete = true; -} -exports.RequestNotifier = RequestNotifier; - -RequestNotifier.prototype = -{ - /** - * The window this notifier is associated with. - * @type Window - */ - window: null, - - /** - * The listener to be called when a new request is found. - * @type Function - */ - listener: null, - - /** - * "this" pointer to be used when calling the listener. - * @type Object - */ - listenerObj: null, - - /** - * Will be set to true once the initial window scan is complete. - * @type Boolean - */ - scanComplete: false, - - /** - * Shuts down the notifier once it is no longer used. The listener - * will no longer be called after that. - */ - shutdown: function() - { - delete this.window; - delete this.listener; - delete this.listenerObj; - - for (let i = activeNotifiers.length - 1; i >= 0; i--) - if (activeNotifiers[i] == this) - activeNotifiers.splice(i, 1); - }, - - /** - * Notifies listener about a new request. - */ - notifyListener: function(/**Window*/ wnd, /**Node*/ node, /**RequestEntry*/ entry) - { - this.listener.call(this.listenerObj, wnd, node, entry, this.scanComplete); - }, - - /** - * Number of currently posted scan events (will be 0 when the scan finishes - * running). - */ - eventsPosted: 0, - - /** - * Starts the initial scan of the window (will recurse into frames). - * @param {Window} wnd the window to be scanned - */ - startScan: function(wnd) - { - let doc = wnd.document; - let walker = doc.createTreeWalker(doc, Ci.nsIDOMNodeFilter.SHOW_ELEMENT, null, false); - - let process = function() - { - if (!this.listener) - return; - - let node = walker.currentNode; - let data = getEntry(nodeData, node); - if (typeof data != "undefined") - for (let k in data) - this.notifyListener(wnd, node, data[k]); - - if (walker.nextNode()) - Utils.runAsync(process); - else - { - // Done with the current window, start the scan for its frames - for (let i = 0; i < wnd.frames.length; i++) - this.startScan(wnd.frames[i]); - - this.eventsPosted--; - if (!this.eventsPosted) - { - this.scanComplete = true; - this.notifyListener(wnd, null, null); - } - } - }.bind(this); - - // Process each node in a separate event to allow other events to process - this.eventsPosted++; - Utils.runAsync(process); - } -}; - -RequestNotifier.storeSelection = function(/**Window*/ wnd, /**String*/ selection) -{ - setEntry(windowSelection, wnd.document, selection); -}; -RequestNotifier.getSelection = function(/**Window*/ wnd) /**String*/ -{ - if (hasEntry(windowSelection, wnd.document)) - return getEntry(windowSelection, wnd.document); - else - return null; -}; - -/** - * Attaches request data to a DOM node. - * @param {Node} node node to attach data to - * @param {Window} topWnd top-level window the node belongs to - * @param {Integer} contentType request type, one of the Policy.type.* constants - * @param {String} docDomain domain of the document that initiated the request - * @param {Boolean} thirdParty will be true if a third-party server has been requested - * @param {String} location the address that has been requested - * @param {Filter} filter filter applied to the request or null if none - */ -RequestNotifier.addNodeData = function(/**Node*/ node, /**Window*/ topWnd, /**Integer*/ contentType, /**String*/ docDomain, /**Boolean*/ thirdParty, /**String*/ location, /**Filter*/ filter) -{ - return new RequestEntry(node, topWnd, contentType, docDomain, thirdParty, location, filter); -} - -/** - * Retrieves the statistics for a window. - * @result {Object} Object with the properties items, blocked, whitelisted, hidden, filters containing statistics for the window (might be null) - */ -RequestNotifier.getWindowStatistics = function(/**Window*/ wnd) -{ - if (hasEntry(windowStats, wnd.document)) - return getEntry(windowStats, wnd.document); - else - return null; -} - -/** - * Retrieves the request entry associated with a DOM node. - * @param {Node} node - * @param {Boolean} noParent if missing or false, the search will extend to the parent nodes until one is found that has data associated with it - * @param {Integer} [type] request type to be looking for - * @param {String} [location] request location to be looking for - * @result {[Node, RequestEntry]} - * @static - */ -RequestNotifier.getDataForNode = function(node, noParent, type, location) -{ - while (node) - { - let data = getEntry(nodeData, node); - if (typeof data != "undefined") - { - // Look for matching entry - for (let k in data) - { - let entry = data[k]; - if ((typeof type == "undefined" || entry.type == type) && - (typeof location == "undefined" || entry.location == location)) - { - return [node, entry]; - } - } - } - - // If we don't have any match on this node then maybe its parent will do - if ((typeof noParent != "boolean" || !noParent) && - node.parentNode instanceof Ci.nsIDOMElement) - { - node = node.parentNode; - } - else - { - node = null; - } - } - - return null; -}; - -function RequestEntry(node, topWnd, contentType, docDomain, thirdParty, location, filter) -{ - this.type = contentType; - this.docDomain = docDomain; - this.thirdParty = thirdParty; - this.location = location; - this.filter = filter; - - this.attachToNode(node); - - // Update window statistics - if (!hasEntry(windowStats, topWnd.document)) - { - setEntry(windowStats, topWnd.document, { - items: 0, - hidden: 0, - blocked: 0, - whitelisted: 0, - filters: {} - }); - } - - let stats = getEntry(windowStats, topWnd.document); - if (!filter || !(filter instanceof ElemHideBase)) - stats.items++; - if (filter) - { - if (filter instanceof BlockingFilter) - stats.blocked++; - else if (filter instanceof WhitelistFilter || filter instanceof ElemHideException) - stats.whitelisted++; - else if (filter instanceof ElemHideFilter) - stats.hidden++; - - if (filter.text in stats.filters) - stats.filters[filter.text]++; - else - stats.filters[filter.text] = 1; - } - - // Notify listeners - for (let notifier of activeNotifiers) - if (!notifier.window || notifier.window == topWnd) - notifier.notifyListener(topWnd, node, this); -} -RequestEntry.prototype = -{ - /** - * Content type of the request (one of the nsIContentPolicy constants) - * @type Integer - */ - type: null, - /** - * Domain name of the requesting document - * @type String - */ - docDomain: null, - /** - * True if the request goes to a different domain than the domain of the containing document - * @type Boolean - */ - thirdParty: false, - /** - * Address being requested - * @type String - */ - location: null, - /** - * Filter that was applied to this request (if any) - * @type Filter - */ - filter: null, - /** - * String representation of the content type, e.g. "subdocument" - * @type String - */ - get typeDescr() - { - return require("contentPolicy").Policy.typeDescr[this.type]; - }, - /** - * User-visible localized representation of the content type, e.g. "frame" - * @type String - */ - get localizedDescr() - { - return require("contentPolicy").Policy.localizedDescr[this.type]; - }, - - /** - * Attaches this request object to a DOM node. - */ - attachToNode: function(/**Node*/ node) - { - let existingData = getEntry(nodeData, node); - if (typeof existingData == "undefined") - { - existingData = {}; - setEntry(nodeData, node, existingData); - } - - // Add this request to the node data - existingData[this.type + " " + this.location] = this; - } -}; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/subscriptionClasses.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/subscriptionClasses.js deleted file mode 100644 index 13dceaf..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/subscriptionClasses.js +++ /dev/null @@ -1,597 +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/>. - */ - -/** - * @fileOverview Definition of Subscription class and its subclasses. - */ - -Cu.import("resource://gre/modules/Services.jsm"); - -let {ActiveFilter, BlockingFilter, WhitelistFilter, ElemHideBase} = require("filterClasses"); -let {FilterNotifier} = require("filterNotifier"); - -/** - * Abstract base class for filter subscriptions - * - * @param {String} url download location of the subscription - * @param {String} [title] title of the filter subscription - * @constructor - */ -function Subscription(url, title) -{ - this.url = url; - this.filters = []; - if (title) - this._title = title; - else - { - let {Utils} = require("utils"); - this._title = Utils.getString("newGroup_title"); - } - Subscription.knownSubscriptions[url] = this; -} -exports.Subscription = Subscription; - -Subscription.prototype = -{ - /** - * Download location of the subscription - * @type String - */ - url: null, - - /** - * Filters contained in the filter subscription - * @type Array of Filter - */ - filters: null, - - _title: null, - _fixedTitle: false, - _disabled: false, - - /** - * Title of the filter subscription - * @type String - */ - get title() - { - return this._title; - }, - set title(value) - { - if (value != this._title) - { - let oldValue = this._title; - this._title = value; - FilterNotifier.triggerListeners("subscription.title", this, value, oldValue); - } - return this._title; - }, - - /** - * Determines whether the title should be editable - * @type Boolean - */ - get fixedTitle() - { - return this._fixedTitle; - }, - set fixedTitle(value) - { - if (value != this._fixedTitle) - { - let oldValue = this._fixedTitle; - this._fixedTitle = value; - FilterNotifier.triggerListeners("subscription.fixedTitle", this, value, oldValue); - } - return this._fixedTitle; - }, - - /** - * Defines whether the filters in the subscription should be disabled - * @type Boolean - */ - get disabled() - { - return this._disabled; - }, - set disabled(value) - { - if (value != this._disabled) - { - let oldValue = this._disabled; - this._disabled = value; - FilterNotifier.triggerListeners("subscription.disabled", this, value, oldValue); - } - return this._disabled; - }, - - /** - * Serializes the filter to an array of strings for writing out on the disk. - * @param {Array of String} buffer buffer to push the serialization results into - */ - serialize: function(buffer) - { - buffer.push("[Subscription]"); - buffer.push("url=" + this.url); - buffer.push("title=" + this._title); - if (this._fixedTitle) - buffer.push("fixedTitle=true"); - if (this._disabled) - buffer.push("disabled=true"); - }, - - serializeFilters: function(buffer) - { - for (let filter of this.filters) - buffer.push(filter.text.replace(/\[/g, "\\[")); - }, - - toString: function() - { - let buffer = []; - this.serialize(buffer); - return buffer.join("\n"); - } -}; - -/** - * Cache for known filter subscriptions, maps URL to subscription objects. - * @type Object - */ -Subscription.knownSubscriptions = {__proto__: null}; - -/** - * Returns a subscription from its URL, creates a new one if necessary. - * @param {String} url URL of the subscription - * @return {Subscription} subscription or null if the subscription couldn't be created - */ -Subscription.fromURL = function(url) -{ - if (url in Subscription.knownSubscriptions) - return Subscription.knownSubscriptions[url]; - - try - { - // Test URL for validity - url = Services.io.newURI(url, null, null).spec; - return new DownloadableSubscription(url, null); - } - catch (e) - { - return new SpecialSubscription(url); - } -} - -/** - * Deserializes a subscription - * - * @param {Object} obj map of serialized properties and their values - * @return {Subscription} subscription or null if the subscription couldn't be created - */ -Subscription.fromObject = function(obj) -{ - let result; - try - { - obj.url = Services.io.newURI(obj.url, null, null).spec; - - // URL is valid - this is a downloadable subscription - result = new DownloadableSubscription(obj.url, obj.title); - if ("downloadStatus" in obj) - result._downloadStatus = obj.downloadStatus; - if ("lastSuccess" in obj) - result.lastSuccess = parseInt(obj.lastSuccess) || 0; - if ("lastCheck" in obj) - result._lastCheck = parseInt(obj.lastCheck) || 0; - if ("expires" in obj) - result.expires = parseInt(obj.expires) || 0; - if ("softExpiration" in obj) - result.softExpiration = parseInt(obj.softExpiration) || 0; - if ("errors" in obj) - result._errors = parseInt(obj.errors) || 0; - if ("version" in obj) - result.version = parseInt(obj.version) || 0; - if ("requiredVersion" in obj) - { - let {addonVersion} = require("info"); - result.requiredVersion = obj.requiredVersion; - if (Services.vc.compare(result.requiredVersion, addonVersion) > 0) - result.upgradeRequired = true; - } - if ("homepage" in obj) - result._homepage = obj.homepage; - if ("lastDownload" in obj) - result._lastDownload = parseInt(obj.lastDownload) || 0; - } - catch (e) - { - // Invalid URL - custom filter group - if (!("title" in obj)) - { - // Backwards compatibility - titles and filter types were originally - // determined by group identifier. - if (obj.url == "~wl~") - obj.defaults = "whitelist"; - else if (obj.url == "~fl~") - obj.defaults = "blocking"; - else if (obj.url == "~eh~") - obj.defaults = "elemhide"; - if ("defaults" in obj) - { - let {Utils} = require("utils"); - obj.title = Utils.getString(obj.defaults + "Group_title"); - } - } - result = new SpecialSubscription(obj.url, obj.title); - if ("defaults" in obj) - result.defaults = obj.defaults.split(" "); - } - if ("fixedTitle" in obj) - result._fixedTitle = (obj.fixedTitle == "true"); - if ("privateMode" in obj) - result.privateMode = (obj.privateMode == "true"); - if ("disabled" in obj) - result._disabled = (obj.disabled == "true"); - - return result; -} - -/** - * Class for special filter subscriptions (user's filters) - * @param {String} url see Subscription() - * @param {String} [title] see Subscription() - * @constructor - * @augments Subscription - */ -function SpecialSubscription(url, title) -{ - Subscription.call(this, url, title); -} -exports.SpecialSubscription = SpecialSubscription; - -SpecialSubscription.prototype = -{ - __proto__: Subscription.prototype, - - /** - * Filter types that should be added to this subscription by default - * (entries should correspond to keys in SpecialSubscription.defaultsMap). - * @type Array of String - */ - defaults: null, - - /** - * Tests whether a filter should be added to this group by default - * @param {Filter} filter filter to be tested - * @return {Boolean} - */ - isDefaultFor: function(filter) - { - if (this.defaults && this.defaults.length) - { - for (let type of this.defaults) - { - if (filter instanceof SpecialSubscription.defaultsMap[type]) - return true; - if (!(filter instanceof ActiveFilter) && type == "blacklist") - return true; - } - } - - return false; - }, - - /** - * See Subscription.serialize() - */ - serialize: function(buffer) - { - Subscription.prototype.serialize.call(this, buffer); - if (this.defaults && this.defaults.length) - buffer.push("defaults=" + this.defaults.filter((type) => type in SpecialSubscription.defaultsMap).join(" ")); - if (this._lastDownload) - buffer.push("lastDownload=" + this._lastDownload); - } -}; - -SpecialSubscription.defaultsMap = { - __proto__: null, - "whitelist": WhitelistFilter, - "blocking": BlockingFilter, - "elemhide": ElemHideBase -}; - -/** - * Creates a new user-defined filter group. - * @param {String} [title] title of the new filter group - * @result {SpecialSubscription} - */ -SpecialSubscription.create = function(title) -{ - let url; - do - { - url = "~user~" + Math.round(Math.random()*1000000); - } while (url in Subscription.knownSubscriptions); - return new SpecialSubscription(url, title) -}; - -/** - * Creates a new user-defined filter group and adds the given filter to it. - * This group will act as the default group for this filter type. - */ -SpecialSubscription.createForFilter = function(/**Filter*/ filter) /**SpecialSubscription*/ -{ - let subscription = SpecialSubscription.create(); - subscription.filters.push(filter); - for (let type in SpecialSubscription.defaultsMap) - { - if (filter instanceof SpecialSubscription.defaultsMap[type]) - subscription.defaults = [type]; - } - if (!subscription.defaults) - subscription.defaults = ["blocking"]; - - let {Utils} = require("utils"); - subscription.title = Utils.getString(subscription.defaults[0] + "Group_title"); - return subscription; -}; - -/** - * Abstract base class for regular filter subscriptions (both internally and externally updated) - * @param {String} url see Subscription() - * @param {String} [title] see Subscription() - * @constructor - * @augments Subscription - */ -function RegularSubscription(url, title) -{ - Subscription.call(this, url, title || url); -} -exports.RegularSubscription = RegularSubscription; - -RegularSubscription.prototype = -{ - __proto__: Subscription.prototype, - - _homepage: null, - _lastDownload: 0, - - /** - * Filter subscription homepage if known - * @type String - */ - get homepage() - { - return this._homepage; - }, - set homepage(value) - { - if (value != this._homepage) - { - let oldValue = this._homepage; - this._homepage = value; - FilterNotifier.triggerListeners("subscription.homepage", this, value, oldValue); - } - return this._homepage; - }, - - /** - * Time of the last subscription download (in seconds since the beginning of the epoch) - * @type Number - */ - get lastDownload() - { - return this._lastDownload; - }, - set lastDownload(value) - { - if (value != this._lastDownload) - { - let oldValue = this._lastDownload; - this._lastDownload = value; - FilterNotifier.triggerListeners("subscription.lastDownload", this, value, oldValue); - } - return this._lastDownload; - }, - - /** - * See Subscription.serialize() - */ - serialize: function(buffer) - { - Subscription.prototype.serialize.call(this, buffer); - if (this._homepage) - buffer.push("homepage=" + this._homepage); - if (this._lastDownload) - buffer.push("lastDownload=" + this._lastDownload); - } -}; - -/** - * Class for filter subscriptions updated by externally (by other extension) - * @param {String} url see Subscription() - * @param {String} [title] see Subscription() - * @constructor - * @augments RegularSubscription - */ -function ExternalSubscription(url, title) -{ - RegularSubscription.call(this, url, title); -} -exports.ExternalSubscription = ExternalSubscription; - -ExternalSubscription.prototype = -{ - __proto__: RegularSubscription.prototype, - - /** - * See Subscription.serialize() - */ - serialize: function(buffer) - { - throw new Error("Unexpected call, external subscriptions should not be serialized"); - } -}; - -/** - * Class for filter subscriptions updated by externally (by other extension) - * @param {String} url see Subscription() - * @param {String} [title] see Subscription() - * @constructor - * @augments RegularSubscription - */ -function DownloadableSubscription(url, title) -{ - RegularSubscription.call(this, url, title); -} -exports.DownloadableSubscription = DownloadableSubscription; - -DownloadableSubscription.prototype = -{ - __proto__: RegularSubscription.prototype, - - _downloadStatus: null, - _lastCheck: 0, - _errors: 0, - - /** - * Status of the last download (ID of a string) - * @type String - */ - get downloadStatus() - { - return this._downloadStatus; - }, - set downloadStatus(value) - { - let oldValue = this._downloadStatus; - this._downloadStatus = value; - FilterNotifier.triggerListeners("subscription.downloadStatus", this, value, oldValue); - return this._downloadStatus; - }, - - /** - * Time of the last successful download (in seconds since the beginning of the - * epoch). - */ - lastSuccess: 0, - - /** - * Time when the subscription was considered for an update last time (in seconds - * since the beginning of the epoch). This will be used to increase softExpiration - * if the user doesn't use Adblock Plus for some time. - * @type Number - */ - get lastCheck() - { - return this._lastCheck; - }, - set lastCheck(value) - { - if (value != this._lastCheck) - { - let oldValue = this._lastCheck; - this._lastCheck = value; - FilterNotifier.triggerListeners("subscription.lastCheck", this, value, oldValue); - } - return this._lastCheck; - }, - - /** - * Hard expiration time of the filter subscription (in seconds since the beginning of the epoch) - * @type Number - */ - expires: 0, - - /** - * Soft expiration time of the filter subscription (in seconds since the beginning of the epoch) - * @type Number - */ - softExpiration: 0, - - /** - * Number of download failures since last success - * @type Number - */ - get errors() - { - return this._errors; - }, - set errors(value) - { - if (value != this._errors) - { - let oldValue = this._errors; - this._errors = value; - FilterNotifier.triggerListeners("subscription.errors", this, value, oldValue); - } - return this._errors; - }, - - /** - * Version of the subscription data retrieved on last successful download - * @type Number - */ - version: 0, - - /** - * Minimal Adblock Plus version required for this subscription - * @type String - */ - requiredVersion: null, - - /** - * Should be true if requiredVersion is higher than current Adblock Plus version - * @type Boolean - */ - upgradeRequired: false, - - /** - * Should be true if the Privatemode: header is set to true in the subscription - * @type Boolean - */ - privateMode: false, - - /** - * See Subscription.serialize() - */ - serialize: function(buffer) - { - RegularSubscription.prototype.serialize.call(this, buffer); - if (this.downloadStatus) - buffer.push("downloadStatus=" + this.downloadStatus); - if (this.lastSuccess) - buffer.push("lastSuccess=" + this.lastSuccess); - if (this.lastCheck) - buffer.push("lastCheck=" + this.lastCheck); - if (this.expires) - buffer.push("expires=" + this.expires); - if (this.softExpiration) - buffer.push("softExpiration=" + this.softExpiration); - if (this.errors) - buffer.push("errors=" + this.errors); - if (this.version) - buffer.push("version=" + this.version); - if (this.requiredVersion) - buffer.push("requiredVersion=" + this.requiredVersion); - if (this.privateMode) - buffer.push("privateMode=" + this.privateMode); - } -}; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/sync.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/sync.js deleted file mode 100644 index 05eeced..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/sync.js +++ /dev/null @@ -1,459 +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/>. - */ - -/** - * @fileOverview Firefox Sync integration - */ - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -let {FilterStorage} = require("filterStorage"); -let {FilterNotifier} = require("filterNotifier"); -let {Synchronizer} = require("synchronizer"); -let {Subscription, SpecialSubscription, DownloadableSubscription, ExternalSubscription} = require("subscriptionClasses"); -let {Filter, ActiveFilter} = require("filterClasses"); - -// Firefox Sync classes are set later in initEngine() -let Service, Engines, SyncEngine, Store, Tracker; - -/** - * ID of the only record stored - * @type String - */ -let filtersRecordID = "6fad6286-8207-46b6-aa39-8e0ce0bd7c49"; - -let Sync = exports.Sync = -{ - /** - * Will be set to true if/when Weave starts up. - * @type Boolean - */ - initialized: false, - - /** - * Whether Weave requested us to track changes. - * @type Boolean - */ - trackingEnabled: false, - - /** - * Returns Adblock Plus sync engine. - * @result Engine - */ - getEngine: function() - { - if (this.initialized) - return Engines.get("adblockplus"); - else - return null; - } -}; - -/** - * Listens to notifications from Sync service. - */ -let SyncServiceObserver = -{ - init: function() - { - try - { - let {Status, STATUS_DISABLED, CLIENT_NOT_CONFIGURED} = Cu.import("resource://services-sync/status.js", null); - Sync.initialized = Status.ready; - Sync.trackingEnabled = (Status.service != STATUS_DISABLED && Status.service != CLIENT_NOT_CONFIGURED); - } - catch (e) - { - return; - } - - if (Sync.initialized) - this.initEngine(); - else - Services.obs.addObserver(this, "weave:service:ready", true); - Services.obs.addObserver(this, "weave:engine:start-tracking", true); - Services.obs.addObserver(this, "weave:engine:stop-tracking", true); - - onShutdown.add(function() - { - try - { - Services.obs.removeObserver(this, "weave:service:ready"); - } catch (e) {} - Services.obs.removeObserver(this, "weave:engine:start-tracking"); - Services.obs.removeObserver(this, "weave:engine:stop-tracking"); - }.bind(this)); - }, - - initEngine: function() - { - ({Engines, SyncEngine, Store, Tracker} = Cu.import("resource://services-sync/engines.js")); - if (typeof Engines == "undefined") - { - ({Service} = Cu.import("resource://services-sync/service.js")); - Engines = Service.engineManager; - } - - ABPEngine.prototype.__proto__ = SyncEngine.prototype; - ABPStore.prototype.__proto__ = Store.prototype; - ABPTracker.prototype.__proto__ = Tracker.prototype; - - Engines.register(ABPEngine); - onShutdown.add(function() - { - Engines.unregister("adblockplus"); - }); - }, - - observe: function(subject, topic, data) - { - switch (topic) - { - case "weave:service:ready": - if (Sync.initialized) - return; - - this.initEngine(); - Sync.initialized = true; - break; - case "weave:engine:start-tracking": - Sync.trackingEnabled = true; - if (trackerInstance) - trackerInstance.startTracking(); - break; - case "weave:engine:stop-tracking": - Sync.trackingEnabled = false; - if (trackerInstance) - trackerInstance.stopTracking(); - break; - } - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), -}; - -function ABPEngine() -{ - SyncEngine.call(this, "AdblockPlus", Service); -} -ABPEngine.prototype = -{ - _storeObj: ABPStore, - _trackerObj: ABPTracker, - version: 1, - - _reconcile: function(item) - { - // Always process server data, we will do the merging ourselves - return true; - } -}; - -function ABPStore(name, engine) -{ - Store.call(this, name, engine); -} -ABPStore.prototype = -{ - getAllIDs: function() - { - let result = {} - result[filtersRecordID] = true; - return result; - }, - - changeItemID: function(oldId, newId) - { - // This should not be called, our engine doesn't implement _findDupe - throw Cr.NS_ERROR_UNEXPECTED; - }, - - itemExists: function(id) - { - // Only one id exists so far - return (id == filtersRecordID); - }, - - createRecord: function(id, collection) - { - let record = new ABPEngine.prototype._recordObj(collection, id); - if (id == filtersRecordID) - { - record.cleartext = { - id: id, - subscriptions: [], - }; - for (let subscription of FilterStorage.subscriptions) - { - if (subscription instanceof ExternalSubscription) - continue; - - let subscriptionEntry = - { - url: subscription.url, - disabled: subscription.disabled - }; - if (subscription instanceof SpecialSubscription) - { - subscriptionEntry.filters = []; - for (let filter of subscription.filters) - { - let filterEntry = {text: filter.text}; - if (filter instanceof ActiveFilter) - filterEntry.disabled = filter.disabled; - subscriptionEntry.filters.push(filterEntry); - } - } - else - subscriptionEntry.title = subscription.title; - record.cleartext.subscriptions.push(subscriptionEntry); - } - - // Data sent, forget about local changes now - trackerInstance.clearPrivateChanges() - } - else - record.deleted = true; - - return record; - }, - - create: function(record) - { - // This should not be called because our record list doesn't change but - // call update just in case. - this.update(record); - }, - - update: function(record) - { - if (record.id != filtersRecordID) - return; - - this._log.trace("Merging in remote data"); - - let data = record.cleartext.subscriptions; - - // First make sure we have the same subscriptions on both sides - let seenSubscription = {__proto__: null}; - for (let remoteSubscription of data) - { - seenSubscription[remoteSubscription.url] = true; - if (remoteSubscription.url in FilterStorage.knownSubscriptions) - { - let subscription = FilterStorage.knownSubscriptions[remoteSubscription.url]; - if (!trackerInstance.didSubscriptionChange(remoteSubscription)) - { - // Only change local subscription if there were no changes, otherwise dismiss remote changes - subscription.disabled = remoteSubscription.disabled; - if (subscription instanceof DownloadableSubscription) - subscription.title = remoteSubscription.title; - } - } - else if (!trackerInstance.didSubscriptionChange(remoteSubscription)) - { - // Subscription was added remotely, add it locally as well - let subscription = Subscription.fromURL(remoteSubscription.url); - if (!subscription) - continue; - - subscription.disabled = remoteSubscription.disabled; - if (subscription instanceof DownloadableSubscription) - { - subscription.title = remoteSubscription.title; - FilterStorage.addSubscription(subscription); - Synchronizer.execute(subscription); - } - } - } - - for (let subscription of FilterStorage.subscriptions.slice()) - { - if (!(subscription.url in seenSubscription) && subscription instanceof DownloadableSubscription && !trackerInstance.didSubscriptionChange(subscription)) - { - // Subscription was removed remotely, remove it locally as well - FilterStorage.removeSubscription(subscription); - } - } - - // Now sync the custom filters - let seenFilter = {__proto__: null}; - for (let remoteSubscription of data) - { - if (!("filters" in remoteSubscription)) - continue; - - for (let remoteFilter of remoteSubscription.filters) - { - seenFilter[remoteFilter.text] = true; - - let filter = Filter.fromText(remoteFilter.text); - if (trackerInstance.didFilterChange(filter)) - continue; - - if (filter.subscriptions.some((subscription) => subscription instanceof SpecialSubscription)) - { - // Filter might have been changed remotely - if (filter instanceof ActiveFilter) - filter.disabled = remoteFilter.disabled; - } - else - { - // Filter was added remotely, add it locally as well - FilterStorage.addFilter(filter); - } - } - } - - for (let subscription of FilterStorage.subscriptions) - { - if (!(subscription instanceof SpecialSubscription)) - continue; - - for (let filter of subscription.filters.slice()) - { - if (!(filter.text in seenFilter) && !trackerInstance.didFilterChange(filter)) - { - // Filter was removed remotely, remove it locally as well - FilterStorage.removeFilter(filter); - } - } - } - - // Merge done, forget about local changes now - trackerInstance.clearPrivateChanges() - }, - - remove: function(record) - { - // Shouldn't be called but if it is - ignore - }, - - wipe: function() - { - this._log.trace("Got wipe command, removing all data"); - - for (let subscription of FilterStorage.subscriptions.slice()) - { - if (subscription instanceof DownloadableSubscription) - FilterStorage.removeSubscription(subscription); - else if (subscription instanceof SpecialSubscription) - { - for (let filter of subscription.filters.slice()) - FilterStorage.removeFilter(filter); - } - } - - // Data wiped, forget about local changes now - trackerInstance.clearPrivateChanges() - } -}; - -/** - * Hack to allow store to use the tracker - store tracker pointer globally. - */ -let trackerInstance = null; - -function ABPTracker(name, engine) -{ - Tracker.call(this, name, engine); - - this.privateTracker = new Tracker(name + ".private", engine); - trackerInstance = this; - - this.onChange = this.onChange.bind(this); - - if (Sync.trackingEnabled) - this.startTracking(); -} -ABPTracker.prototype = -{ - privateTracker: null, - - startTracking: function() - { - FilterNotifier.addListener(this.onChange); - }, - - stopTracking: function() - { - FilterNotifier.removeListener(this.onChange); - }, - - clearPrivateChanges: function() - { - this.privateTracker.clearChangedIDs(); - }, - - addPrivateChange: function(id) - { - // Ignore changes during syncing - if (this.ignoreAll) - return; - - this.addChangedID(filtersRecordID); - this.privateTracker.addChangedID(id); - this.score += 10; - }, - - didSubscriptionChange: function(subscription) - { - return ("subscription " + subscription.url) in this.privateTracker.changedIDs; - }, - - didFilterChange: function(filter) - { - return ("filter " + filter.text) in this.privateTracker.changedIDs; - }, - - onChange: function(action, item) - { - switch (action) - { - case "subscription.updated": - if ("oldSubscription" in item) - { - // Subscription moved to a new address - this.addPrivateChange("subscription " + item.url); - this.addPrivateChange("subscription " + item.oldSubscription.url); - } - else if (item instanceof SpecialSubscription) - { - // User's filters changed via Preferences window - for (let filter of item.filters) - this.addPrivateChange("filter " + filter.text); - for (let filter of item.oldFilters) - this.addPrivateChange("filter " + filter.text); - } - break; - case "subscription.added": - case "subscription.removed": - case "subscription.disabled": - case "subscription.title": - this.addPrivateChange("subscription " + item.url); - break; - case "filter.added": - case "filter.removed": - case "filter.disabled": - this.addPrivateChange("filter " + item.text); - break; - } - } -}; - -SyncServiceObserver.init(); diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/synchronizer.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/synchronizer.js deleted file mode 100644 index b9f9e29..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/synchronizer.js +++ /dev/null @@ -1,330 +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/>. - */ - -/** - * @fileOverview Manages synchronization of filter subscriptions. - */ - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -let {TimeLine} = require("timeline"); -let {Downloader, Downloadable, - MILLIS_IN_SECOND, MILLIS_IN_MINUTE, MILLIS_IN_HOUR, MILLIS_IN_DAY} = require("downloader"); -let {Filter, CommentFilter} = require("filterClasses"); -let {FilterStorage} = require("filterStorage"); -let {FilterNotifier} = require("filterNotifier"); -let {Prefs} = require("prefs"); -let {Subscription, DownloadableSubscription} = require("subscriptionClasses"); -let {Utils} = require("utils"); - -let INITIAL_DELAY = 6 * MILLIS_IN_MINUTE; -let CHECK_INTERVAL = 1 * MILLIS_IN_HOUR; -let DEFAULT_EXPIRATION_INTERVAL = 5 * MILLIS_IN_DAY; - -/** - * The object providing actual downloading functionality. - * @type Downloader - */ -let downloader = null; - -/** - * This object is responsible for downloading filter subscriptions whenever - * necessary. - * @class - */ -let Synchronizer = exports.Synchronizer = -{ - /** - * Called on module startup. - */ - init: function() - { - TimeLine.enter("Entered Synchronizer.init()"); - - downloader = new Downloader(this._getDownloadables.bind(this), INITIAL_DELAY, CHECK_INTERVAL); - onShutdown.add(function() - { - downloader.cancel(); - }); - - downloader.onExpirationChange = this._onExpirationChange.bind(this); - downloader.onDownloadStarted = this._onDownloadStarted.bind(this); - downloader.onDownloadSuccess = this._onDownloadSuccess.bind(this); - downloader.onDownloadError = this._onDownloadError.bind(this); - - TimeLine.leave("Synchronizer.init() done"); - }, - - /** - * Checks whether a subscription is currently being downloaded. - * @param {String} url URL of the subscription - * @return {Boolean} - */ - isExecuting: function(url) - { - return downloader.isDownloading(url); - }, - - /** - * Starts the download of a subscription. - * @param {DownloadableSubscription} subscription Subscription to be downloaded - * @param {Boolean} manual true for a manually started download (should not trigger fallback requests) - */ - execute: function(subscription, manual) - { - downloader.download(this._getDownloadable(subscription, manual)); - }, - - /** - * Yields Downloadable instances for all subscriptions that can be downloaded. - */ - _getDownloadables: function() - { - if (!Prefs.subscriptions_autoupdate) - return; - - for (let subscription of FilterStorage.subscriptions) - { - if (subscription instanceof DownloadableSubscription) - yield this._getDownloadable(subscription, false); - } - }, - - /** - * Creates a Downloadable instance for a subscription. - */ - _getDownloadable: function(/**Subscription*/ subscription, /**Boolean*/ manual) /**Downloadable*/ - { - let result = new Downloadable(subscription.url); - if (subscription.lastDownload != subscription.lastSuccess) - result.lastError = subscription.lastDownload * MILLIS_IN_SECOND; - result.lastCheck = subscription.lastCheck * MILLIS_IN_SECOND; - result.lastVersion = subscription.version; - result.softExpiration = subscription.softExpiration * MILLIS_IN_SECOND; - result.hardExpiration = subscription.expires * MILLIS_IN_SECOND; - result.manual = manual; - result.privateMode = subscription.privateMode; - return result; - }, - - _onExpirationChange: function(downloadable) - { - let subscription = Subscription.fromURL(downloadable.url); - subscription.lastCheck = Math.round(downloadable.lastCheck / MILLIS_IN_SECOND); - subscription.softExpiration = Math.round(downloadable.softExpiration / MILLIS_IN_SECOND); - subscription.expires = Math.round(downloadable.hardExpiration / MILLIS_IN_SECOND); - }, - - _onDownloadStarted: function(downloadable) - { - let subscription = Subscription.fromURL(downloadable.url); - FilterNotifier.triggerListeners("subscription.downloadStatus", subscription); - }, - - _onDownloadSuccess: function(downloadable, responseText, errorCallback, redirectCallback) - { - let lines = responseText.split(/[\r\n]+/); - let match = /\[Adblock(?:\s*Plus\s*([\d\.]+)?)?\]/i.exec(lines[0]); - if (!match) - return errorCallback("synchronize_invalid_data"); - let minVersion = match[1]; - - // Don't remove parameter comments immediately but add them to a list first, - // they need to be considered in the checksum calculation. - let remove = []; - let params = { - redirect: null, - homepage: null, - title: null, - version: null, - privatemode: null, - expires: null - }; - for (let i = 0; i < lines.length; i++) - { - let match = /^\s*!\s*(\w+)\s*:\s*(.*)/.exec(lines[i]); - if (match) - { - let keyword = match[1].toLowerCase(); - let value = match[2]; - if (keyword in params) - { - params[keyword] = value; - remove.push(i); - } - else if (keyword == "checksum") - { - lines.splice(i--, 1); - let checksum = Utils.generateChecksum(lines); - if (checksum && checksum != value.replace(/=+$/, "")) - return errorCallback("synchronize_checksum_mismatch"); - } - } - } - - if (params.redirect) - return redirectCallback(params.redirect); - - // Handle redirects - let subscription = Subscription.fromURL(downloadable.redirectURL || downloadable.url); - if (downloadable.redirectURL && downloadable.redirectURL != downloadable.url) - { - let oldSubscription = Subscription.fromURL(downloadable.url); - subscription.title = oldSubscription.title; - subscription.disabled = oldSubscription.disabled; - subscription.lastCheck = oldSubscription.lastCheck; - - let listed = (oldSubscription.url in FilterStorage.knownSubscriptions); - if (listed) - FilterStorage.removeSubscription(oldSubscription); - - delete Subscription.knownSubscriptions[oldSubscription.url]; - - if (listed) - FilterStorage.addSubscription(subscription); - } - - // The download actually succeeded - subscription.lastSuccess = subscription.lastDownload = Math.round(Date.now() / MILLIS_IN_SECOND); - subscription.downloadStatus = "synchronize_ok"; - subscription.errors = 0; - - // Remove lines containing parameters - for (let i = remove.length - 1; i >= 0; i--) - lines.splice(remove[i], 1); - - // Process parameters - if (params.homepage) - { - let uri = Utils.makeURI(params.homepage); - if (uri && (uri.scheme == "http" || uri.scheme == "https")) - subscription.homepage = uri.spec; - } - - if (params.privatemode) - { - subscription.privateMode = (params.privatemode == "true"); - } - - if (params.title) - { - subscription.title = params.title; - subscription.fixedTitle = true; - } - else - subscription.fixedTitle = false; - - subscription.version = (params.version ? parseInt(params.version, 10) : 0); - - let expirationInterval = DEFAULT_EXPIRATION_INTERVAL; - if (params.expires) - { - let match = /^(\d+)\s*(h)?/.exec(params.expires); - if (match) - { - let interval = parseInt(match[1], 10); - if (match[2]) - expirationInterval = interval * MILLIS_IN_HOUR; - else - expirationInterval = interval * MILLIS_IN_DAY; - } - } - - let [softExpiration, hardExpiration] = downloader.processExpirationInterval(expirationInterval); - subscription.softExpiration = Math.round(softExpiration / MILLIS_IN_SECOND); - subscription.expires = Math.round(hardExpiration / MILLIS_IN_SECOND); - - delete subscription.requiredVersion; - delete subscription.upgradeRequired; - if (minVersion) - { - let {addonVersion} = require("info"); - subscription.requiredVersion = minVersion; - if (Services.vc.compare(minVersion, addonVersion) > 0) - subscription.upgradeRequired = true; - } - - // Process filters - lines.shift(); - let filters = []; - for (let line of lines) - { - line = Filter.normalize(line); - if (line) - filters.push(Filter.fromText(line)); - } - - FilterStorage.updateSubscriptionFilters(subscription, filters); - - return undefined; - }, - - _onDownloadError: function(downloadable, downloadURL, error, channelStatus, responseStatus, redirectCallback) - { - let subscription = Subscription.fromURL(downloadable.url); - subscription.lastDownload = Math.round(Date.now() / MILLIS_IN_SECOND); - subscription.downloadStatus = error; - - // Request fallback URL if necessary - for automatic updates only - if (!downloadable.manual) - { - subscription.errors++; - - if (redirectCallback && subscription.errors >= Prefs.subscriptions_fallbackerrors && /^https?:\/\//i.test(subscription.url)) - { - subscription.errors = 0; - - let fallbackURL = Prefs.subscriptions_fallbackurl; - let {addonVersion} = require("info"); - fallbackURL = fallbackURL.replace(/%VERSION%/g, encodeURIComponent(addonVersion)); - fallbackURL = fallbackURL.replace(/%SUBSCRIPTION%/g, encodeURIComponent(subscription.url)); - fallbackURL = fallbackURL.replace(/%URL%/g, encodeURIComponent(downloadURL)); - fallbackURL = fallbackURL.replace(/%ERROR%/g, encodeURIComponent(error)); - fallbackURL = fallbackURL.replace(/%CHANNELSTATUS%/g, encodeURIComponent(channelStatus)); - fallbackURL = fallbackURL.replace(/%RESPONSESTATUS%/g, encodeURIComponent(responseStatus)); - - let request = new XMLHttpRequest(); - request.mozBackgroundRequest = true; - request.open("GET", fallbackURL); - request.overrideMimeType("text/plain"); - request.channel.loadFlags = request.channel.loadFlags | - request.channel.INHIBIT_CACHING | - request.channel.VALIDATE_ALWAYS; - request.addEventListener("load", function(ev) - { - if (onShutdown.done) - return; - - if (!(subscription.url in FilterStorage.knownSubscriptions)) - return; - - let match = /^(\d+)(?:\s+(\S+))?$/.exec(request.responseText); - if (match && match[1] == "301" && match[2] && /^https?:\/\//i.test(match[2])) // Moved permanently - redirectCallback(match[2]); - else if (match && match[1] == "410") // Gone - { - let data = "[Adblock]\n" + subscription.filters.map((f) => f.text).join("\n"); - redirectCallback("data:text/plain," + encodeURIComponent(data)); - } - }, false); - request.send(null); - } - } - }, -}; -Synchronizer.init(); diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/timeline.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/timeline.js deleted file mode 100644 index 18c10fb..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/timeline.js +++ /dev/null @@ -1,155 +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/>. - */ - -/** - * @fileOverview Debugging module used for load time measurements. - */ - -let nestingCounter = 0; -let firstTimeStamp = null; -let lastTimeStamp = null; - -let asyncActions = {__proto__: null}; - -/** - * Time logging module, used to measure startup time of Adblock Plus (development builds only). - * @class - */ -let TimeLine = exports.TimeLine = { - /** - * Logs an event to console together with the time it took to get there. - */ - log: function(/**String*/ message, /**Boolean*/ _forceDisplay) - { - if (!_forceDisplay && nestingCounter <= 0) - return; - - let now = Date.now(); - let diff = lastTimeStamp ? Math.round(now - lastTimeStamp) : "first event"; - lastTimeStamp = now; - - // Indent message depending on current nesting level - for (let i = 0; i < nestingCounter; i++) - message = "* " + message; - - // Pad message with spaces - let padding = []; - for (let i = message.toString().length; i < 80; i++) - padding.push(" "); - dump("[" + now + "] ABP timeline: " + message + padding.join("") + "\t (" + diff + ")\n"); - }, - - /** - * Called to indicate that application entered a block that needs to be timed. - */ - enter: function(/**String*/ message) - { - if (nestingCounter <= 0) - firstTimeStamp = Date.now(); - - this.log(message, true); - nestingCounter = (nestingCounter <= 0 ? 1 : nestingCounter + 1); - }, - - /** - * Called when application exited a block that TimeLine.enter() was called for. - * @param {String} message message to be logged - * @param {String} [asyncAction] identifier of a pending async action - */ - leave: function(message, asyncAction) - { - if (typeof asyncAction != "undefined") - message += " (async action pending)"; - - nestingCounter--; - this.log(message, true); - - if (nestingCounter <= 0) - { - if (firstTimeStamp !== null) - dump("ABP timeline: Total time elapsed: " + Math.round(Date.now() - firstTimeStamp) + "\n"); - firstTimeStamp = null; - lastTimeStamp = null; - } - - if (typeof asyncAction != "undefined") - { - if (asyncAction in asyncActions) - dump("ABP timeline: Warning: Async action " + asyncAction + " already executing\n"); - asyncActions[asyncAction] = {start: Date.now(), total: 0}; - } - }, - - /** - * Called when the application starts processing of an async action. - */ - asyncStart: function(/**String*/ asyncAction) - { - if (asyncAction in asyncActions) - { - let action = asyncActions[asyncAction]; - if ("currentStart" in action) - dump("ABP timeline: Warning: Processing reentered for async action " + asyncAction + "\n"); - action.currentStart = Date.now(); - } - else - dump("ABP timeline: Warning: Async action " + asyncAction + " is unknown\n"); - }, - - /** - * Called when the application finishes processing of an async action. - */ - asyncEnd: function(/**String*/ asyncAction) - { - if (asyncAction in asyncActions) - { - let action = asyncActions[asyncAction]; - if ("currentStart" in action) - { - action.total += Date.now() - action.currentStart; - delete action.currentStart; - } - else - dump("ABP timeline: Warning: Processing not entered for async action " + asyncAction + "\n"); - } - else - dump("ABP timeline: Warning: Async action " + asyncAction + " is unknown\n"); - }, - - /** - * Called when an async action is done and its time can be logged. - */ - asyncDone: function(/**String*/ asyncAction) - { - if (asyncAction in asyncActions) - { - let action = asyncActions[asyncAction]; - let now = Date.now(); - let diff = now - action.start; - if ("currentStart" in action) - dump("ABP timeline: Warning: Still processing for async action " + asyncAction + "\n"); - - let message = "Async action " + asyncAction + " done"; - let padding = []; - for (let i = message.toString().length; i < 80; i++) - padding.push(" "); - dump("[" + now + "] ABP timeline: " + message + padding.join("") + "\t (" + action.total + "/" + diff + ")\n"); - } - else - dump("ABP timeline: Warning: Async action " + asyncAction + " is unknown\n"); - } -}; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/ui.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/ui.js deleted file mode 100644 index 668e356..0000000 --- a/helpers/DATA/firefox/gnu/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); -}); diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/utils.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/utils.js deleted file mode 100644 index 8fbdf3e..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/utils.js +++ /dev/null @@ -1,787 +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/>. - */ - -/** - * @fileOverview Module containing a bunch of utility functions. - */ - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -let sidebarParams = null; - -/** - * Provides a bunch of utility functions. - * @class - */ -let Utils = exports.Utils = -{ - /** - * Returns the add-on ID used by Adblock Plus - */ - get addonID() - { - let {addonID} = require("info"); - return addonID; - }, - - /** - * Returns the installed Adblock Plus version - */ - get addonVersion() - { - let {addonVersion} = require("info"); - return addonVersion; - }, - - /** - * Returns whether we are running in Fennec, for Fennec-specific hacks - * @type Boolean - */ - get isFennec() - { - let {application} = require("info"); - let result = (application == "fennec" || application == "fennec2"); - Utils.__defineGetter__("isFennec", () => result); - return result; - }, - - /** - * Returns the user interface locale selected for adblockplus chrome package. - */ - get appLocale() - { - let locale = "en-US"; - try - { - locale = Utils.chromeRegistry.getSelectedLocale("adblockplus"); - } - catch (e) - { - Cu.reportError(e); - } - Utils.__defineGetter__("appLocale", () => locale); - return Utils.appLocale; - }, - - /** - * Returns version of the Gecko platform - */ - get platformVersion() - { - let platformVersion = Services.appinfo.platformVersion; - Utils.__defineGetter__("platformVersion", () => platformVersion); - return Utils.platformVersion; - }, - - /** - * Retrieves a string from global.properties string bundle, will throw if string isn't found. - * - * @param {String} name string name - * @return {String} - */ - getString: function(name) - { - // Randomize URI to work around bug 719376 - let stringBundle = Services.strings.createBundle("chrome://adblockplus/locale/global.properties?" + Math.random()); - Utils.getString = function(name) - { - return stringBundle.GetStringFromName(name); - } - return Utils.getString(name); - }, - - /** - * Shows an alert message like window.alert() but with a custom title. - * - * @param {Window} parentWindow parent window of the dialog (can be null) - * @param {String} message message to be displayed - * @param {String} [title] dialog title, default title will be used if omitted - */ - alert: function(parentWindow, message, title) - { - if (!title) - title = Utils.getString("default_dialog_title"); - Utils.promptService.alert(parentWindow, title, message); - }, - - /** - * Asks the user for a confirmation like window.confirm() but with a custom title. - * - * @param {Window} parentWindow parent window of the dialog (can be null) - * @param {String} message message to be displayed - * @param {String} [title] dialog title, default title will be used if omitted - * @return {Bool} - */ - confirm: function(parentWindow, message, title) - { - if (!title) - title = Utils.getString("default_dialog_title"); - return Utils.promptService.confirm(parentWindow, title, message); - }, - - /** - * Retrieves the window for a document node. - * @return {Window} will be null if the node isn't associated with a window - */ - getWindow: function(/**Node*/ node) - { - if ("ownerDocument" in node && node.ownerDocument) - node = node.ownerDocument; - - if ("defaultView" in node) - return node.defaultView; - - return null; - }, - - /** - * Retrieves the top-level chrome window for a content window. - */ - getChromeWindow: function(/**Window*/ window) /**Window*/ - { - return window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindow); - }, - - /** - * If the window doesn't have its own security context (e.g. about:blank or - * data: URL) walks up the parent chain until a window is found that has a - * security context. - */ - getOriginWindow: function(/**Window*/ wnd) /**Window*/ - { - while (wnd != wnd.parent) - { - let uri = Utils.makeURI(wnd.location.href); - if (uri.spec != "about:blank" && uri.spec != "moz-safe-about:blank" && - !Utils.netUtils.URIChainHasFlags(uri, Ci.nsIProtocolHandler.URI_INHERITS_SECURITY_CONTEXT)) - { - break; - } - wnd = wnd.parent; - } - return wnd; - }, - - /** - * If a protocol using nested URIs like jar: is used - retrieves innermost - * nested URI. - */ - unwrapURL: function(/**nsIURI or String*/ url) /**nsIURI*/ - { - if (!(url instanceof Ci.nsIURI)) - url = Utils.makeURI(url); - - if (url instanceof Ci.nsINestedURI) - return url.innermostURI; - else - return url; - }, - - /** - * Translates a string URI into its nsIURI representation, will return null for - * invalid URIs. - */ - makeURI: function(/**String*/ url) /**nsIURI*/ - { - try - { - return Utils.ioService.newURI(url, null, null); - } - catch (e) { - return null; - } - }, - - /** - * Posts an action to the event queue of the current thread to run it - * asynchronously. Any additional parameters to this function are passed - * as parameters to the callback. - */ - runAsync: function(/**Function*/ callback, /**Object*/ thisPtr) - { - let params = Array.prototype.slice.call(arguments, 2); - let runnable = { - run: function() - { - callback.apply(thisPtr, params); - } - }; - Services.tm.currentThread.dispatch(runnable, Ci.nsIEventTarget.DISPATCH_NORMAL); - }, - - /** - * Gets the DOM window associated with a particular request (if any). - */ - getRequestWindow: function(/**nsIChannel*/ channel) /**nsIDOMWindow*/ - { - try - { - if (channel.notificationCallbacks) - return channel.notificationCallbacks.getInterface(Ci.nsILoadContext).associatedWindow; - } catch(e) {} - - try - { - if (channel.loadGroup && channel.loadGroup.notificationCallbacks) - return channel.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext).associatedWindow; - } catch(e) {} - - return null; - }, - - /** - * Generates filter subscription checksum. - * - * @param {Array of String} lines filter subscription lines (with checksum line removed) - * @return {String} checksum or null - */ - generateChecksum: function(lines) - { - let stream = null; - try - { - // Checksum is an MD5 checksum (base64-encoded without the trailing "=") of - // all lines in UTF-8 without the checksum line, joined with "\n". - - let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); - converter.charset = "UTF-8"; - stream = converter.convertToInputStream(lines.join("\n")); - - let hashEngine = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash); - hashEngine.init(hashEngine.MD5); - hashEngine.updateFromStream(stream, stream.available()); - return hashEngine.finish(true).replace(/=+$/, ""); - } - catch (e) - { - return null; - } - finally - { - if (stream) - stream.close(); - } - }, - - /** - * Formats a unix time according to user's locale. - * @param {Integer} time unix time in milliseconds - * @return {String} formatted date and time - */ - formatTime: function(time) - { - try - { - let date = new Date(time); - return Utils.dateFormatter.FormatDateTime("", Ci.nsIScriptableDateFormat.dateFormatShort, - Ci.nsIScriptableDateFormat.timeFormatNoSeconds, - date.getFullYear(), date.getMonth() + 1, date.getDate(), - date.getHours(), date.getMinutes(), date.getSeconds()); - } - catch(e) - { - // Make sure to return even on errors - Cu.reportError(e); - return ""; - } - }, - - /** - * Checks whether any of the prefixes listed match the application locale, - * returns matching prefix if any. - */ - checkLocalePrefixMatch: function(/**String*/ prefixes) /**String*/ - { - if (!prefixes) - return null; - - let appLocale = Utils.appLocale; - for (let prefix of prefixes.split(/,/)) - if (new RegExp("^" + prefix + "\\b").test(appLocale)) - return prefix; - - return null; - }, - - /** - * Chooses the best filter subscription for user's language. - */ - chooseFilterSubscription: function(/**NodeList*/ subscriptions) /**Node*/ - { - let selectedItem = null; - let selectedPrefix = null; - let matchCount = 0; - for (let i = 0; i < subscriptions.length; i++) - { - let subscription = subscriptions[i]; - if (!selectedItem) - selectedItem = subscription; - - let prefix = Utils.checkLocalePrefixMatch(subscription.getAttribute("prefixes")); - if (prefix) - { - if (!selectedPrefix || selectedPrefix.length < prefix.length) - { - selectedItem = subscription; - selectedPrefix = prefix; - matchCount = 1; - } - else if (selectedPrefix && selectedPrefix.length == prefix.length) - { - matchCount++; - - // If multiple items have a matching prefix of the same length: - // Select one of the items randomly, probability should be the same - // for all items. So we replace the previous match here with - // probability 1/N (N being the number of matches). - if (Math.random() * matchCount < 1) - { - selectedItem = subscription; - selectedPrefix = prefix; - } - } - } - } - return selectedItem; - }, - - /** - * Pauses code execution and allows events to be processed. Warning: - * other extension code might execute, the extension might even shut down. - */ - yield: function() - { - let {Prefs} = require("prefs"); - if (Prefs.please_kill_startup_performance) - { - this.yield = function() {}; - return; - } - let thread = Services.tm.currentThread; - while (thread.processNextEvent(false)); - }, - - /** - * Saves sidebar state before detaching/reattaching - */ - setParams: function(params) - { - sidebarParams = params; - }, - - /** - * Retrieves and removes sidebar state after detaching/reattaching - */ - getParams: function() - { - let ret = sidebarParams; - sidebarParams = null; - return ret; - }, - - /** - * Verifies RSA signature. The public key and signature should be base64-encoded. - */ - verifySignature: function(/**String*/ key, /**String*/ signature, /**String*/ data) /**Boolean*/ - { - if (!Utils.crypto) - return false; - - // Maybe we did the same check recently, look it up in the cache - if (!("_cache" in Utils.verifySignature)) - Utils.verifySignature._cache = new Cache(5); - let cache = Utils.verifySignature._cache; - let cacheKey = key + " " + signature + " " + data; - if (cacheKey in cache.data) - return cache.data[cacheKey]; - else - cache.add(cacheKey, false); - - let keyInfo, pubKey, context; - try - { - let keyItem = Utils.crypto.getSECItem(atob(key)); - keyInfo = Utils.crypto.SECKEY_DecodeDERSubjectPublicKeyInfo(keyItem.address()); - if (keyInfo.isNull()) - throw new Error("SECKEY_DecodeDERSubjectPublicKeyInfo failed"); - - pubKey = Utils.crypto.SECKEY_ExtractPublicKey(keyInfo); - if (pubKey.isNull()) - throw new Error("SECKEY_ExtractPublicKey failed"); - - let signatureItem = Utils.crypto.getSECItem(atob(signature)); - - context = Utils.crypto.VFY_CreateContext(pubKey, signatureItem.address(), Utils.crypto.SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, null); - if (context.isNull()) - return false; // This could happen if the signature is invalid - - let error = Utils.crypto.VFY_Begin(context); - if (error < 0) - throw new Error("VFY_Begin failed"); - - error = Utils.crypto.VFY_Update(context, data, data.length); - if (error < 0) - throw new Error("VFY_Update failed"); - - error = Utils.crypto.VFY_End(context); - if (error < 0) - return false; - - cache.data[cacheKey] = true; - return true; - } - catch (e) - { - Cu.reportError(e); - return false; - } - finally - { - if (keyInfo && !keyInfo.isNull()) - Utils.crypto.SECKEY_DestroySubjectPublicKeyInfo(keyInfo); - if (pubKey && !pubKey.isNull()) - Utils.crypto.SECKEY_DestroyPublicKey(pubKey); - if (context && !context.isNull()) - Utils.crypto.VFY_DestroyContext(context, true); - } - }, - - /** - * Returns the documentation link from the preferences. - */ - getDocLink: function(/**String*/ linkID) - { - let {Prefs} = require("prefs"); - let docLink = Prefs.documentation_link; - return docLink.replace(/%LINK%/g, linkID).replace(/%LANG%/g, Utils.appLocale); - }, - - /** - * Splits up a combined label into the label and access key components. - * - * @return {Array} An array with two strings: label and access key - */ - splitLabel: function(/**String*/ label) - { - let match = /^(.*)\s*\(&(.)\)\s*(\u2026?)$/.exec(label); - if (match) - { - // Access key not part of the label - return [match[1] + match[3], match[2]]; - } - else - { - // Access key part of the label - let pos = label.indexOf("&"); - if (pos >= 0 && pos < label.length - 1) - return [label.substr(0, pos) + label.substr(pos + 1), label[pos + 1]]; - else - return [label, ""]; - } - }, - - /** - * Split all labels starting from a particular DOM node. - */ - splitAllLabels: function(/**DOMNode*/ root) - { - let attrMap = { - __proto__: null, - "label": "value", - "setting": "title" - }; - - let elements = root.querySelectorAll("*[label], label[value], setting[title]"); - for (let i = 0; i < elements.length; i++) - { - let element = elements[i]; - let attr = (element.localName in attrMap ? attrMap[element.localName] : "label"); - let origLabel = element.getAttribute(attr); - - let [label, accesskey] = this.splitLabel(origLabel); - if (label != origLabel) - element.setAttribute(attr, label); - if (accesskey != "") - element.setAttribute("accesskey", accesskey); - - // Labels forward changes of the accessKey property to their control, only - // set it for actual controls. - if (element.localName != "label") - element.accessKey = accesskey; - } - } -}; - -/** - * A cache with a fixed capacity, newer entries replace entries that have been - * stored first. - * @constructor - */ -function Cache(/**Integer*/ size) -{ - this._ringBuffer = new Array(size); - this.data = {__proto__: null}; -} -exports.Cache = Cache; - -Cache.prototype = -{ - /** - * Ring buffer storing hash keys, allows determining which keys need to be - * evicted. - * @type Array - */ - _ringBuffer: null, - - /** - * Index in the ring buffer to be written next. - * @type Integer - */ - _bufferIndex: 0, - - /** - * Cache data, maps values to the keys. Read-only access, for writing use - * add() method. - * @type Object - */ - data: null, - - /** - * Adds a key and the corresponding value to the cache. - */ - add: function(/**String*/ key, value) - { - if (!(key in this.data)) - { - // This is a new key - we need to add it to the ring buffer and evict - // another entry instead. - let oldKey = this._ringBuffer[this._bufferIndex]; - if (typeof oldKey != "undefined") - delete this.data[oldKey]; - this._ringBuffer[this._bufferIndex] = key; - - this._bufferIndex++; - if (this._bufferIndex >= this._ringBuffer.length) - this._bufferIndex = 0; - } - - this.data[key] = value; - }, - - /** - * Clears cache contents. - */ - clear: function() - { - this._ringBuffer = new Array(this._ringBuffer.length); - this.data = {__proto__: null}; - } -} - -// Getters for common services, this should be replaced by Services.jsm in future - -XPCOMUtils.defineLazyServiceGetter(Utils, "categoryManager", "@mozilla.org/categorymanager;1", "nsICategoryManager"); -XPCOMUtils.defineLazyServiceGetter(Utils, "ioService", "@mozilla.org/network/io-service;1", "nsIIOService"); -XPCOMUtils.defineLazyServiceGetter(Utils, "promptService", "@mozilla.org/embedcomp/prompt-service;1", "nsIPromptService"); -XPCOMUtils.defineLazyServiceGetter(Utils, "effectiveTLD", "@mozilla.org/network/effective-tld-service;1", "nsIEffectiveTLDService"); -XPCOMUtils.defineLazyServiceGetter(Utils, "netUtils", "@mozilla.org/network/util;1", "nsINetUtil"); -XPCOMUtils.defineLazyServiceGetter(Utils, "styleService", "@mozilla.org/content/style-sheet-service;1", "nsIStyleSheetService"); -XPCOMUtils.defineLazyServiceGetter(Utils, "prefService", "@mozilla.org/preferences-service;1", "nsIPrefService"); -XPCOMUtils.defineLazyServiceGetter(Utils, "versionComparator", "@mozilla.org/xpcom/version-comparator;1", "nsIVersionComparator"); -XPCOMUtils.defineLazyServiceGetter(Utils, "windowMediator", "@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator"); -XPCOMUtils.defineLazyServiceGetter(Utils, "windowWatcher", "@mozilla.org/embedcomp/window-watcher;1", "nsIWindowWatcher"); -XPCOMUtils.defineLazyServiceGetter(Utils, "chromeRegistry", "@mozilla.org/chrome/chrome-registry;1", "nsIXULChromeRegistry"); -XPCOMUtils.defineLazyServiceGetter(Utils, "systemPrincipal", "@mozilla.org/systemprincipal;1", "nsIPrincipal"); -XPCOMUtils.defineLazyServiceGetter(Utils, "dateFormatter", "@mozilla.org/intl/scriptabledateformat;1", "nsIScriptableDateFormat"); -XPCOMUtils.defineLazyServiceGetter(Utils, "childMessageManager", "@mozilla.org/childprocessmessagemanager;1", "nsISyncMessageSender"); -XPCOMUtils.defineLazyServiceGetter(Utils, "parentMessageManager", "@mozilla.org/parentprocessmessagemanager;1", "nsIFrameMessageManager"); -XPCOMUtils.defineLazyServiceGetter(Utils, "httpProtocol", "@mozilla.org/network/protocol;1?name=http", "nsIHttpProtocolHandler"); -XPCOMUtils.defineLazyServiceGetter(Utils, "clipboard", "@mozilla.org/widget/clipboard;1", "nsIClipboard"); -XPCOMUtils.defineLazyServiceGetter(Utils, "clipboardHelper", "@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper"); -XPCOMUtils.defineLazyGetter(Utils, "crypto", function() -{ - try - { - let ctypes = Components.utils.import("resource://gre/modules/ctypes.jsm", null).ctypes; - - let nsslib; - try - { - nsslib = ctypes.open(ctypes.libraryName("nss3")); - } - catch (e) - { - // It seems that on Mac OS X the full path name needs to be specified - let file = Services.dirsvc.get("GreD", Ci.nsILocalFile); - file.append(ctypes.libraryName("nss3")); - nsslib = ctypes.open(file.path); - } - - let result = {}; - - // seccomon.h - result.siUTF8String = 14; - - // secoidt.h - result.SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE = 15; - - // The following types are opaque to us - result.VFYContext = ctypes.void_t; - result.SECKEYPublicKey = ctypes.void_t; - result.CERTSubjectPublicKeyInfo = ctypes.void_t; - - /* - * seccomon.h - * struct SECItemStr { - * SECItemType type; - * unsigned char *data; - * unsigned int len; - * }; - */ - result.SECItem = ctypes.StructType("SECItem", [ - {type: ctypes.int}, - {data: ctypes.unsigned_char.ptr}, - {len: ctypes.int} - ]); - - /* - * cryptohi.h - * extern VFYContext *VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, - * SECOidTag sigAlg, void *wincx); - */ - result.VFY_CreateContext = nsslib.declare( - "VFY_CreateContext", - ctypes.default_abi, result.VFYContext.ptr, - result.SECKEYPublicKey.ptr, - result.SECItem.ptr, - ctypes.int, - ctypes.voidptr_t - ); - - /* - * cryptohi.h - * extern void VFY_DestroyContext(VFYContext *cx, PRBool freeit); - */ - result.VFY_DestroyContext = nsslib.declare( - "VFY_DestroyContext", - ctypes.default_abi, ctypes.void_t, - result.VFYContext.ptr, - ctypes.bool - ); - - /* - * cryptohi.h - * extern SECStatus VFY_Begin(VFYContext *cx); - */ - result.VFY_Begin = nsslib.declare("VFY_Begin", - ctypes.default_abi, ctypes.int, - result.VFYContext.ptr - ); - - /* - * cryptohi.h - * extern SECStatus VFY_Update(VFYContext *cx, const unsigned char *input, - * unsigned int inputLen); - */ - result.VFY_Update = nsslib.declare( - "VFY_Update", - ctypes.default_abi, ctypes.int, - result.VFYContext.ptr, - ctypes.unsigned_char.ptr, - ctypes.int - ); - - /* - * cryptohi.h - * extern SECStatus VFY_End(VFYContext *cx); - */ - result.VFY_End = nsslib.declare( - "VFY_End", - ctypes.default_abi, ctypes.int, - result.VFYContext.ptr - ); - - /* - * keyhi.h - * extern CERTSubjectPublicKeyInfo * - * SECKEY_DecodeDERSubjectPublicKeyInfo(SECItem *spkider); - */ - result.SECKEY_DecodeDERSubjectPublicKeyInfo = nsslib.declare( - "SECKEY_DecodeDERSubjectPublicKeyInfo", - ctypes.default_abi, result.CERTSubjectPublicKeyInfo.ptr, - result.SECItem.ptr - ); - - /* - * keyhi.h - * extern void SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki); - */ - result.SECKEY_DestroySubjectPublicKeyInfo = nsslib.declare( - "SECKEY_DestroySubjectPublicKeyInfo", - ctypes.default_abi, ctypes.void_t, - result.CERTSubjectPublicKeyInfo.ptr - ); - - /* - * keyhi.h - * extern SECKEYPublicKey * - * SECKEY_ExtractPublicKey(CERTSubjectPublicKeyInfo *); - */ - result.SECKEY_ExtractPublicKey = nsslib.declare( - "SECKEY_ExtractPublicKey", - ctypes.default_abi, result.SECKEYPublicKey.ptr, - result.CERTSubjectPublicKeyInfo.ptr - ); - - /* - * keyhi.h - * extern void SECKEY_DestroyPublicKey(SECKEYPublicKey *key); - */ - result.SECKEY_DestroyPublicKey = nsslib.declare( - "SECKEY_DestroyPublicKey", - ctypes.default_abi, ctypes.void_t, - result.SECKEYPublicKey.ptr - ); - - // Convenience method - result.getSECItem = function(data) - { - var dataArray = new ctypes.ArrayType(ctypes.unsigned_char, data.length)(); - for (let i = 0; i < data.length; i++) - dataArray[i] = data.charCodeAt(i) % 256; - return new result.SECItem(result.siUTF8String, dataArray, dataArray.length); - }; - - return result; - } - catch (e) - { - Cu.reportError(e); - // Expected, ctypes isn't supported in Gecko 1.9.2 - return null; - } -}); - -if ("@mozilla.org/messenger/headerparser;1" in Cc) - XPCOMUtils.defineLazyServiceGetter(Utils, "headerParser", "@mozilla.org/messenger/headerparser;1", "nsIMsgHeaderParser"); -else - Utils.headerParser = null; diff --git a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/windowObserver.js b/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/windowObserver.js deleted file mode 100644 index eb0b13a..0000000 --- a/helpers/DATA/firefox/gnu/extensions/spyblock@gnu.org/lib/windowObserver.js +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This file is part of the Adblock Plus build tools, - * 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/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -exports.WindowObserver = WindowObserver; - -/** - * This class will call listener's method applyToWindow() for all new chrome - * windows being opened. It will also call listener's method removeFromWindow() - * for all windows still open when the extension is shut down. - * @param {Object} listener - * @param {String} [when] when to execute applyToWindow(). "start" means immediately - * when the window opens, "ready" when its contents are available - * and "end" (default) means to wait until the "load" event. - * @constructor - */ -function WindowObserver(listener, when) -{ - this._listener = listener; - this._when = when; - - let windows = []; - let e = Services.wm.getZOrderDOMWindowEnumerator(null, true); - while (e.hasMoreElements()) - windows.push(e.getNext()); - - // Check if there are any windows that we missed - let eAll = Services.ww.getWindowEnumerator(); - while (eAll.hasMoreElements()) - { - let element = eAll.getNext(); - if (windows.indexOf(element) < 0) - windows.push(element); - } - - for (let i = 0; i < windows.length; i++) - { - let window = windows[i].QueryInterface(Ci.nsIDOMWindow); - if (when == "start" || window.document.readyState == "complete") - this._listener.applyToWindow(window); - else - this.observe(window, "chrome-document-global-created", null); - } - - Services.obs.addObserver(this, "chrome-document-global-created", true); - - this._shutdownHandler = function() - { - let e = Services.ww.getWindowEnumerator(); - while (e.hasMoreElements()) - this._listener.removeFromWindow(e.getNext().QueryInterface(Ci.nsIDOMWindow)); - - Services.obs.removeObserver(this, "chrome-document-global-created"); - }.bind(this); - onShutdown.add(this._shutdownHandler); -} -WindowObserver.prototype = -{ - _listener: null, - _when: null, - _shutdownHandler: null, - - shutdown: function() - { - if (!this._shutdownHandler) - return; - - onShutdown.remove(this._shutdownHandler); - this._shutdownHandler(); - this._shutdownHandler = null; - }, - - observe: function(subject, topic, data) - { - if (topic == "chrome-document-global-created") - { - let window = subject.QueryInterface(Ci.nsIDOMWindow); - if (this._when == "start") - { - this._listener.applyToWindow(window); - return; - } - - let event = (this._when == "ready" ? "DOMContentLoaded" : "load"); - let listener = function() - { - window.removeEventListener(event, listener, false); - if (this._shutdownHandler) - this._listener.applyToWindow(window); - }.bind(this); - window.addEventListener(event, listener, false); - } - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObserver]) -}; |