From d26b319fd6f98517cc3421f10bf18698b953e4d2 Mon Sep 17 00:00:00 2001 From: Ruben Rodriguez Date: Thu, 13 Sep 2018 20:39:48 -0400 Subject: Updated extensions list for v60 --- .../spyblock@gnu.org/lib/child/bootstrap.js | 97 ---- .../spyblock@gnu.org/lib/child/contentPolicy.js | 518 --------------------- .../spyblock@gnu.org/lib/child/contextMenu.js | 137 ------ .../spyblock@gnu.org/lib/child/dataCollector.js | 108 ----- .../spyblock@gnu.org/lib/child/elemHide.js | 403 ---------------- .../lib/child/elemHideEmulation.js | 118 ----- .../spyblock@gnu.org/lib/child/flasher.js | 99 ---- data/extensions/spyblock@gnu.org/lib/child/main.js | 31 -- .../spyblock@gnu.org/lib/child/objectTabs.js | 405 ---------------- .../spyblock@gnu.org/lib/child/requestNotifier.js | 444 ------------------ .../spyblock@gnu.org/lib/child/subscribeLinks.js | 118 ----- .../extensions/spyblock@gnu.org/lib/child/utils.js | 141 ------ 12 files changed, 2619 deletions(-) delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/bootstrap.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/contentPolicy.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/contextMenu.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/dataCollector.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/elemHide.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/elemHideEmulation.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/flasher.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/main.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/objectTabs.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/requestNotifier.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/subscribeLinks.js delete mode 100644 data/extensions/spyblock@gnu.org/lib/child/utils.js (limited to 'data/extensions/spyblock@gnu.org/lib/child') diff --git a/data/extensions/spyblock@gnu.org/lib/child/bootstrap.js b/data/extensions/spyblock@gnu.org/lib/child/bootstrap.js deleted file mode 100644 index 477ca44..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/bootstrap.js +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -(function() -{ - const Cc = Components.classes; - const Ci = Components.interfaces; - const Cr = Components.results; - const Cu = Components.utils; - - let {Loader, main, unload} = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {}); - let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); - - Cu.importGlobalProperties(["atob", "btoa", "File", "URL", "URLSearchParams", - "TextDecoder", "TextEncoder"]); - - let shutdownHandlers = []; - let onShutdown = - { - done: false, - add: function(handler) - { - if (shutdownHandlers.indexOf(handler) < 0) - shutdownHandlers.push(handler); - }, - remove: function(handler) - { - let index = shutdownHandlers.indexOf(handler); - if (index >= 0) - shutdownHandlers.splice(index, 1); - } - }; - - function init() - { - let url = new URL(Components.stack.filename); - let params = new URLSearchParams(url.search.substr(1)); - let info = JSON.parse(params.get("info")); - - let loader = Loader({ - paths: { - "": info.addonRoot + "lib/" - }, - globals: { - Components, Cc, Ci, Cu, Cr, atob, btoa, File, URL, URLSearchParams, - TextDecoder, TextEncoder, onShutdown - }, - modules: {"info": info, "messageManager": this}, - id: info.addonID - }); - onShutdown.add(() => unload(loader, "disable")) - - main(loader, "child/main"); - } - - function shutdown(message) - { - if (message.data == Components.stack.filename) - { - onShutdown.done = true; - for (let i = shutdownHandlers.length - 1; i >= 0; i --) - { - try - { - shutdownHandlers[i](); - } - catch (e) - { - Cu.reportError(e); - } - } - shutdownHandlers = null; - } - } - - addMessageListener("AdblockPlus:Shutdown", shutdown); - onShutdown.add(() => - { - removeMessageListener("AdblockPlus:Shutdown", shutdown); - }); - - init(); -})(); diff --git a/data/extensions/spyblock@gnu.org/lib/child/contentPolicy.js b/data/extensions/spyblock@gnu.org/lib/child/contentPolicy.js deleted file mode 100644 index 97ea7b1..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/contentPolicy.js +++ /dev/null @@ -1,518 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -/** - * @fileOverview Content policy implementation, responsible for blocking things. - */ - -"use strict"; - -try -{ - // Hack: SDK loader masks our Components object with a getter. - let proto = Object.getPrototypeOf(this); - let property = Object.getOwnPropertyDescriptor(proto, "Components"); - if (property && property.get) - delete proto.Components; -} -catch (e) -{ - Cu.reportError(e); -} - -let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {}); -let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); - -let {port} = require("messaging"); -let {Utils} = require("utils"); -let {getFrames, isPrivate, getRequestWindow} = require("child/utils"); -let {objectMouseEventHander} = require("child/objectTabs"); -let {RequestNotifier} = require("child/requestNotifier"); - -/** - * Randomly generated class name, to be applied to collapsed nodes. - * @type Promise. - */ -let collapsedClass = port.emitWithResponse("getCollapsedClass"); - -/** - * Maps numerical content type IDs to strings. - * @type Map. - */ -let types = new Map(); - -/** - * Contains nodes stored by storeNodes() mapped by their IDs. - * @type Map. - */ -let storedNodes = new Map(); - -/** - * Process-dependent prefix to be used for unique nodes identifiers returned - * by storeNodes(). - * @type string - */ -let nodesIDPrefix = Services.appinfo.processID + " "; - -/** - * Counter used to generate unique nodes identifiers in storeNodes(). - * @type number - */ -let maxNodesID = 0; - -port.on("deleteNodes", onDeleteNodes); -port.on("refilterNodes", onRefilterNodes); - -/** - * Processes parent's response to the ShouldAllow message. - * @param {nsIDOMWindow} window window that the request is associated with - * @param {nsIDOMElement} node DOM element that the request is associated with - * @param {Object|undefined} response object received as response - * @return {Boolean} false if the request should be blocked - */ -function processPolicyResponse(window, node, response) -{ - if (typeof response == "undefined") - return true; - - let {allow, collapse, hits} = response; - let isObject = false; - for (let hit of hits) - { - if (hit.contentType == "OBJECT") - isObject = true; - - let context = node; - if (typeof hit.frameIndex == "number") - { - context = window; - for (let i = 0; i < hit.frameIndex; i++) - context = context.parent; - context = context.document; - } - RequestNotifier.addNodeData(context, window.top, hit); - } - - if (node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) - { - // Track mouse events for objects - if (allow && isObject) - { - node.addEventListener("mouseover", objectMouseEventHander, true); - node.addEventListener("mouseout", objectMouseEventHander, true); - } - - if (collapse) - schedulePostProcess(node); - } - return allow; -} - -/** - * Checks whether a request should be allowed, hides it if necessary - * @param {nsIDOMWindow} window - * @param {nsIDOMElement} node - * @param {String} contentType - * @param {String} location location of the request, filter key if contentType is ELEMHIDE - * @return {Boolean} false if the request should be blocked - */ -let shouldAllow = exports.shouldAllow = function(window, node, contentType, location) -{ - return processPolicyResponse(window, node, port.emitSync("shouldAllow", { - contentType, - location, - frames: getFrames(window), - isPrivate: isPrivate(window) - })); -}; - -/** - * Asynchronously checks whether a request should be allowed. - * @param {nsIDOMWindow} window - * @param {nsIDOMElement} node - * @param {String} contentType - * @param {String} location location of the request, filter key if contentType is ELEMHIDE - * @param {Function} callback callback to be called with a boolean value, if - * false the request should be blocked - */ -let shouldAllowAsync = exports.shouldAllowAsync = function(window, node, contentType, location, callback) -{ - port.emitWithResponse("shouldAllow", { - contentType, - location, - frames: getFrames(window), - isPrivate: isPrivate(window) - }).then(response => - { - callback(processPolicyResponse(window, node, response)); - }); -}; - -/** - * Stores nodes and generates a unique ID for them that can be used for - * Policy.refilterNodes() later. It's important that Policy.deleteNodes() is - * called later, otherwise the nodes will be leaked. - * @param {DOMNode[]} nodes list of nodes to be stored - * @return {string} unique ID for the nodes - */ -let storeNodes = exports.storeNodes = function(nodes) -{ - let id = nodesIDPrefix + (++maxNodesID); - storedNodes.set(id, nodes); - return id; -}; - -/** - * Called via message whenever Policy.deleteNodes() is called in the parent. - */ -function onDeleteNodes(id, sender) -{ - storedNodes.delete(id); -} - -/** - * Called via message whenever Policy.refilterNodes() is called in the parent. - */ -function onRefilterNodes({nodesID, entry}, sender) -{ - let nodes = storedNodes.get(nodesID); - if (nodes) - for (let node of nodes) - if (node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) - Utils.runAsync(refilterNode.bind(this, node, entry)); -} - -/** - * Re-checks filters on an element. - */ -function refilterNode(/**Node*/ node, /**Object*/ entry) -{ - let wnd = Utils.getWindow(node); - if (!wnd || wnd.closed) - return; - - if (entry.type == "OBJECT") - { - node.removeEventListener("mouseover", objectMouseEventHander, true); - node.removeEventListener("mouseout", objectMouseEventHander, true); - } - - shouldAllow(wnd, node, entry.type, entry.location, (allow) => { - // Force node to be collapsed - if (!allow) - schedulePostProcess(node) - }); -} - -/** - * Actual nsIContentPolicy and nsIChannelEventSink implementation - * @class - */ -var 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() - { - // Populate types map - let iface = Ci.nsIContentPolicy; - for (let name in iface) - if (name.indexOf("TYPE_") == 0 && name != "TYPE_DATAREQUEST") - types.set(iface[name], name.substr(5)); - - let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - registrar.registerFactory(this.classID, this.classDescription, this.contractID, this); - - let catMan = Utils.categoryManager; - for (let category of this.xpcom_categories) - catMan.addCategoryEntry(category, this.contractID, this.contractID, false, true); - - Services.obs.addObserver(this, "document-element-inserted", true); - - onShutdown.add(() => - { - Services.obs.removeObserver(this, "document-element-inserted"); - - for (let category of this.xpcom_categories) - catMan.deleteCategoryEntry(category, this.contractID, false); - - registrar.unregisterFactory(this.classID, 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 == Ci.nsIContentPolicy.TYPE_DOCUMENT) - return Ci.nsIContentPolicy.ACCEPT; - - // Bail out early for chrome: an resource: URLs, this is a work-around for - // https://bugzil.la/1127744 and https://bugzil.la/1247640 - let location = Utils.unwrapURL(contentLocation); - if (location.schemeIs("chrome") || location.schemeIs("resource")) - return Ci.nsIContentPolicy.ACCEPT; - - // Ignore standalone objects - if (contentType == Ci.nsIContentPolicy.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; - - // Data loaded by plugins should be associated with the document - if (contentType == Ci.nsIContentPolicy.TYPE_OBJECT_SUBREQUEST && node instanceof Ci.nsIDOMElement) - node = node.ownerDocument; - - // Fix type for objects misrepresented as frames or images - if (contentType != Ci.nsIContentPolicy.TYPE_OBJECT && (node instanceof Ci.nsIDOMHTMLObjectElement || node instanceof Ci.nsIDOMHTMLEmbedElement)) - contentType = Ci.nsIContentPolicy.TYPE_OBJECT; - - let result = shouldAllow(wnd, node, types.get(contentType), location.spec); - return (result ? Ci.nsIContentPolicy.ACCEPT : Ci.nsIContentPolicy.REJECT_REQUEST); - }, - - shouldProcess: function(contentType, contentLocation, requestOrigin, insecNode, mimeType, extra) - { - return Ci.nsIContentPolicy.ACCEPT; - }, - - // - // nsIObserver interface implementation - // - _openers: new WeakMap(), - _alreadyLoaded: Symbol(), - - observe: function(subject, topic, data, uri) - { - switch (topic) - { - case "document-element-inserted": - { - let window = subject.defaultView; - if (!window) - return; - - let type = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .itemType; - if (type != Ci.nsIDocShellTreeItem.typeContent) - return; - - let opener = this._openers.get(window); - if (opener == this._alreadyLoaded) - { - // This window has loaded already, ignore it regardless of whether - // window.opener is still set. - return; - } - - if (opener && Cu.isDeadWrapper(opener)) - opener = null; - - if (!opener) - { - // We don't know the opener for this window yet, try to find it - opener = window.opener; - if (!opener) - return; - - // The opener might be an intermediate window, get the real one - while (opener.location == "about:blank" && opener.opener) - opener = opener.opener; - - this._openers.set(window, opener); - - let forgetPopup = event => - { - subject.removeEventListener("DOMContentLoaded", forgetPopup); - this._openers.set(window, this._alreadyLoaded); - }; - subject.addEventListener("DOMContentLoaded", forgetPopup); - } - - if (!uri) - uri = window.location.href; - if (!shouldAllow(opener, opener.document, "POPUP", uri)) - { - window.stop(); - Utils.runAsync(() => window.close()); - } - else if (uri == "about:blank") - { - // An about:blank pop-up most likely means that a load will be - // initiated asynchronously. Wait for that. - Utils.runAsync(() => - { - let channel = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDocShell) - .QueryInterface(Ci.nsIDocumentLoader) - .documentChannel; - if (channel) - this.observe(subject, topic, data, channel.URI.spec); - }); - } - break; - } - } - }, - - // - // nsIChannelEventSink interface implementation - // - - asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) - { - let async = false; - try - { - // nsILoadInfo.contentPolicyType was introduced in Gecko 35, then - // renamed to nsILoadInfo.externalContentPolicyType in Gecko 44. - let loadInfo = oldChannel.loadInfo; - let contentType = ("externalContentPolicyType" in loadInfo ? - loadInfo.externalContentPolicyType : loadInfo.contentPolicyType); - if (!contentType) - return; - - let wnd = getRequestWindow(newChannel); - if (!wnd) - return; - - if (contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT) - { - if (wnd.history.length <= 1 && wnd.opener) - { - // Special treatment for pop-up windows - this will close the window - // rather than preventing the redirect. Note that we might not have - // seen the original channel yet because the redirect happened before - // the async code in observe() had a chance to run. - this.observe(wnd.document, "document-element-inserted", null, oldChannel.URI.spec); - this.observe(wnd.document, "document-element-inserted", null, newChannel.URI.spec); - } - return; - } - - shouldAllowAsync(wnd, wnd.document, types.get(contentType), newChannel.URI.spec, function(allow) - { - callback.onRedirectVerifyCallback(allow ? Cr.NS_OK : Cr.NS_BINDING_ABORTED); - }); - async = true; - } - catch (e) - { - // We shouldn't throw exceptions here - this will prevent the redirect. - Cu.reportError(e); - } - finally - { - if (!async) - callback.onRedirectVerifyCallback(Cr.NS_OK); - } - }, - - // - // 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 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() -{ - collapsedClass.then(cls => - { - let nodes = scheduledNodes; - scheduledNodes = null; - - // Resolving class is async initially so the nodes might have already been - // processed in the meantime. - if (!nodes) - return; - - 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(cls); - } - }); -} diff --git a/data/extensions/spyblock@gnu.org/lib/child/contextMenu.js b/data/extensions/spyblock@gnu.org/lib/child/contextMenu.js deleted file mode 100644 index 297ef3e..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/contextMenu.js +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -"use strict"; - -let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); -let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {}); - -let {Utils} = require("utils"); -let {RequestNotifier} = require("child/requestNotifier"); -let {storeNodes} = require("child/contentPolicy"); - -/** - * Determines the context menu entries to be shown for a contextmenu event. - * @param {Event} event - * @return {Array} - */ -function getContextInfo(event) -{ - let items = []; - let target = event.target; - if (target.localName == "menupopup" && target.triggerNode) - { - // SeaMonkey gives us the context menu's popupshowing event - target = target.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 items; - - let addMenuItem = function([node, nodeData]) - { - let nodeID = null; - if (node && node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) - nodeID = storeNodes([node]); - items.push([nodeID, nodeData]); - }.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].type == "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, "IMAGE", bgImage); - if (data && !data[1].filter) - { - addMenuItem(data); - break; - } - } - } - - node = node.parentNode; - } - } - - return items; -}; - -let ContextMenuObserver = -{ - observe: function(subject, topic, data) - { - if (subject.wrappedJSObject) - subject = subject.wrappedJSObject; - - if (subject.addonInfo) - subject.addonInfo.adblockplus = getContextInfo(subject.event); - }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObserver]) -}; - -Services.obs.addObserver(ContextMenuObserver, "content-contextmenu", true); -Services.obs.addObserver(ContextMenuObserver, "AdblockPlus:content-contextmenu", true); -onShutdown.add(() => { - Services.obs.removeObserver(ContextMenuObserver, "content-contextmenu"); - Services.obs.removeObserver(ContextMenuObserver, "AdblockPlus:content-contextmenu"); -}); diff --git a/data/extensions/spyblock@gnu.org/lib/child/dataCollector.js b/data/extensions/spyblock@gnu.org/lib/child/dataCollector.js deleted file mode 100644 index 09c334a..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/dataCollector.js +++ /dev/null @@ -1,108 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -/** - * @fileOverview Collects some data for a content window, to be attached to - * issue reports. - */ - -"use strict"; - -let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); -let {Task} = Cu.import("resource://gre/modules/Task.jsm", {}); -let {PrivateBrowsingUtils} = Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm", {}); - -let {port} = require("messaging"); -let {Utils} = require("utils"); - -port.on("collectData", onCollectData); - -function onCollectData({outerWindowID, screenshotWidth}, sender) -{ - let window = Services.wm.getOuterWindowWithId(outerWindowID); - if (window) - { - return Task.spawn(function*() - { - let data = {}; - data.isPrivate = PrivateBrowsingUtils.isContentWindowPrivate(window); - data.opener = window.opener ? window.opener.location.href : null; - data.referrer = window.document.referrer; - data.frames = yield scanFrames(window); - data.screenshot = yield createScreenshot(window, screenshotWidth); - return data; - }); - } -} - -function scanFrames(window) -{ - let frames = []; - for (let i = 0; i < window.frames.length; i++) - { - let frame = window.frames[i]; - frames.push({ - url: frame.location.href, - frames: scanFrames(frame) - }); - } - return frames; -} - -function* createScreenshot(window, screenshotWidth) -{ - let canvas = window.document.createElement("canvas"); - canvas.width = screenshotWidth; - - let context = canvas.getContext("2d"); - let wndWidth = window.document.documentElement.scrollWidth; - let wndHeight = window.document.documentElement.scrollHeight; - - // Copy scaled screenshot of the webpage, according to the specified width. - - // Gecko doesn't like sizes more than 64k, restrict to 30k to be on the safe side. - // Also, make sure height is at most five times the width to keep image size down. - let copyWidth = Math.min(wndWidth, 30000); - let copyHeight = Math.min(wndHeight, 30000, copyWidth * 5); - let copyX = Math.max(Math.min(window.scrollX - copyWidth / 2, wndWidth - copyWidth), 0); - let copyY = Math.max(Math.min(window.scrollY - copyHeight / 2, wndHeight - copyHeight), 0); - - let scalingFactor = screenshotWidth / copyWidth; - canvas.height = copyHeight * scalingFactor; - - context.save(); - context.scale(scalingFactor, scalingFactor); - context.drawWindow(window, copyX, copyY, copyWidth, copyHeight, "rgb(255,255,255)"); - context.restore(); - - // Reduce colors - let pixelData = context.getImageData(0, 0, canvas.width, canvas.height); - let data = pixelData.data; - let mapping = [0x00, 0x55, 0xAA, 0xFF]; - for (let i = 0; i < data.length; i++) - { - data[i] = mapping[data[i] >> 6]; - - if (i % 5000 == 0) - { - // Take a break every 5000 bytes to prevent browser hangs - yield new Promise((resolve, reject) => Utils.runAsync(resolve)); - } - } - - return pixelData; -} diff --git a/data/extensions/spyblock@gnu.org/lib/child/elemHide.js b/data/extensions/spyblock@gnu.org/lib/child/elemHide.js deleted file mode 100644 index 988adee..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/elemHide.js +++ /dev/null @@ -1,403 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -/** - * @fileOverview Serves CSS for element hiding and processes hits. - */ - -try -{ - // Hack: SDK loader masks our Components object with a getter. - let proto = Object.getPrototypeOf(this); - let property = Object.getOwnPropertyDescriptor(proto, "Components"); - if (property && property.get) - delete proto.Components; -} -catch (e) -{ - Cu.reportError(e); -} - -let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {}); -let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); - -let {shouldAllowAsync} = require("child/contentPolicy"); -let {getFrames, isPrivate, getRequestWindow} = require("child/utils"); -let {RequestNotifier} = require("child/requestNotifier"); -let {port} = require("messaging"); -let {Utils} = require("utils"); - -const notImplemented = () => Cr.NS_ERROR_NOT_IMPLEMENTED; - -/** - * about: URL module used to count hits. - * @class - */ -let AboutHandler = -{ - classID: Components.ID("{55fb7be0-1dd2-11b2-98e6-9e97caf8ba67}"), - classDescription: "Element hiding hit registration protocol handler", - aboutPrefix: "abp-elemhide", - - /** - * 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 Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT; - }, - - newChannel: function(uri, loadInfo) - { - let match = /\?hit(\d+)$/.exec(uri.path); - if (match) - return new HitRegistrationChannel(uri, loadInfo, match[1]); - - match = /\?css(?:=(.*?))?(&specificonly)?$/.exec(uri.path); - if (match) - { - return new StyleDataChannel(uri, loadInfo, - match[1] ? decodeURIComponent(match[1]) : null, !!match[2]); - } - - throw Cr.NS_ERROR_FAILURE; - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory, Ci.nsIAboutModule]) -}; -AboutHandler.init(); - -/** - * Base class for channel implementations, subclasses usually only need to - * override BaseChannel._getResponse() method. - * @constructor - */ -function BaseChannel(uri, loadInfo) -{ - this.URI = this.originalURI = uri; - this.loadInfo = loadInfo; -} -BaseChannel.prototype = { - URI: null, - originalURI: null, - contentCharset: "utf-8", - contentLength: 0, - contentType: null, - owner: Utils.systemPrincipal, - securityInfo: null, - notificationCallbacks: null, - loadFlags: 0, - loadGroup: null, - name: null, - status: Cr.NS_OK, - - _getResponse: notImplemented, - - _checkSecurity: function() - { - if (!this.loadInfo.triggeringPrincipal.equals(Utils.systemPrincipal)) - throw Cr.NS_ERROR_FAILURE; - }, - - asyncOpen: function(listener, context) - { - Promise.resolve(this._getResponse()).then(data => - { - let stream = Cc["@mozilla.org/io/string-input-stream;1"] - .createInstance(Ci.nsIStringInputStream); - stream.setData(data, data.length); - - try - { - listener.onStartRequest(this, context); - } - catch(e) - { - // Listener failing isn't our problem - } - - try - { - listener.onDataAvailable(this, context, stream, 0, stream.available()); - } - catch(e) - { - // Listener failing isn't our problem - } - - try - { - listener.onStopRequest(this, context, Cr.NS_OK); - } - catch(e) - { - // Listener failing isn't our problem - } - }); - }, - - asyncOpen2: function(listener) - { - this._checkSecurity(); - this.asyncOpen(listener, null); - }, - - open: function() - { - let data = this._getResponse(); - if (typeof data.then == "function") - throw Cr.NS_ERROR_NOT_IMPLEMENTED; - - let stream = Cc["@mozilla.org/io/string-input-stream;1"] - .createInstance(Ci.nsIStringInputStream); - stream.setData(data, data.length); - return stream; - }, - - open2: function() - { - this._checkSecurity(); - return this.open(); - }, - - isPending: () => false, - cancel: notImplemented, - suspend: notImplemented, - resume: notImplemented, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel, Ci.nsIRequest]) -}; - -/** - * Channel returning CSS data for the global as well as site-specific stylesheet. - * @constructor - */ -function StyleDataChannel(uri, loadInfo, domain, specificOnly) -{ - BaseChannel.call(this, uri, loadInfo); - this._domain = domain; - this._specificOnly = specificOnly; -} -StyleDataChannel.prototype = { - __proto__: BaseChannel.prototype, - contentType: "text/css", - _domain: null, - - _getResponse: function() - { - function escapeChar(match) - { - return "\\" + match.charCodeAt(0).toString(16) + " "; - } - - // Would be great to avoid sync messaging here but nsIStyleSheetService - // insists on opening channels synchronously. - let [selectors, keys] = (this._domain ? - port.emitSync("getSelectorsForDomain", [this._domain, this._specificOnly]) : - port.emitSync("getUnconditionalSelectors")); - - let cssPrefix = "{-moz-binding: url(about:abp-elemhide?hit"; - let cssSuffix = "#dummy) !important;}\n"; - let result = []; - - for (let i = 0; i < selectors.length; i++) - { - let selector = selectors[i]; - let key = keys[i]; - result.push(selector.replace(/[^\x01-\x7F]/g, escapeChar), - cssPrefix, key, cssSuffix); - } - - return result.join(""); - } -}; - -/** - * Channel returning data for element hiding hits. - * @constructor - */ -function HitRegistrationChannel(uri, loadInfo, key) -{ - BaseChannel.call(this, uri, loadInfo); - this.key = key; -} -HitRegistrationChannel.prototype = { - __proto__: BaseChannel.prototype, - key: null, - contentType: "text/xml", - - _getResponse: function() - { - let window = getRequestWindow(this); - port.emitWithResponse("registerElemHideHit", { - key: this.key, - frames: getFrames(window), - isPrivate: isPrivate(window) - }).then(hit => - { - if (hit) - RequestNotifier.addNodeData(window.document, window.top, hit); - }); - return ""; - } -}; - -let observer = { - QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIObserver, Ci.nsISupportsWeakReference - ]), - - topic: "document-element-inserted", - styleURL: Utils.makeURI("about:abp-elemhide?css"), - sheet: null, - - init: function() - { - Services.obs.addObserver(this, this.topic, true); - onShutdown.add(() => - { - Services.obs.removeObserver(this, this.topic); - }); - - port.on("elemhideupdate", () => - { - this.sheet = null; - }); - }, - - observe: function(subject, topic, data) - { - if (topic != this.topic) - return; - - let window = subject.defaultView; - if (!window) - { - // This is typically XBL bindings and SVG images, but also real - // documents occasionally - probably due to speculative loading? - return; - } - let type = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .itemType; - if (type != Ci.nsIDocShellTreeItem.typeContent) - return; - - port.emitWithResponse("elemhideEnabled", { - frames: getFrames(window), - isPrivate: isPrivate(window) - }).then(({ - enabled, contentType, docDomain, thirdParty, location, filter, - filterType - }) => - { - if (Cu.isDeadWrapper(window)) - { - // We are too late, the window is gone already. - return; - } - - if (enabled) - { - let utils = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - - // If we have a filter hit at this point then it must be a $generichide - // filter - apply only specific element hiding filters. - let specificOnly = !!filter; - if (!specificOnly) - { - if (!this.sheet) - { - this.sheet = Utils.styleService.preloadSheet(this.styleURL, - Ci.nsIStyleSheetService.USER_SHEET); - } - - try - { - utils.addSheet(this.sheet, Ci.nsIStyleSheetService.USER_SHEET); - } - catch (e) - { - // Ignore NS_ERROR_ILLEGAL_VALUE - it will be thrown if we try to add - // the stylesheet multiple times to the same document (the observer - // will be notified twice for some documents). - if (e.result != Cr.NS_ERROR_ILLEGAL_VALUE) - throw e; - } - } - - let host = window.location.hostname; - if (host) - { - try - { - let suffix = "=" + encodeURIComponent(host); - if (specificOnly) - suffix += "&specificonly"; - utils.loadSheetUsingURIString(this.styleURL.spec + suffix, - Ci.nsIStyleSheetService.USER_SHEET); - } - catch (e) - { - // Ignore NS_ERROR_ILLEGAL_VALUE - it will be thrown if we try to add - // the stylesheet multiple times to the same document (the observer - // will be notified twice for some documents). - if (e.result != Cr.NS_ERROR_ILLEGAL_VALUE) - throw e; - } - } - } - - if (filter) - { - RequestNotifier.addNodeData(window.document, window.top, { - contentType, docDomain, thirdParty, location, filter, filterType - }); - } - }); - } -}; -observer.init(); diff --git a/data/extensions/spyblock@gnu.org/lib/child/elemHideEmulation.js b/data/extensions/spyblock@gnu.org/lib/child/elemHideEmulation.js deleted file mode 100644 index 7c4ee17..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/elemHideEmulation.js +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -"use strict"; - -(function() -{ - let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); - - let {port} = require("messaging"); - let {getFrames, isPrivate} = require("child/utils"); - let {RequestNotifier} = require("child/requestNotifier"); - - function getFilters(window, callback) - { - let message = { - frames: getFrames(window), - payload: { - type: "filters.get", - what: "elemhideemulation" - } - }; - port.emitWithResponse("ext_message", message).then(callback); - } - - function addUserCSS(window, cssCode) - { - let uri = Services.io.newURI("data:text/css," + encodeURIComponent(cssCode), - null, null); - let utils = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - utils.loadSheet(uri, Ci.nsIDOMWindowUtils.USER_SHEET); - } - - function initElemHideEmulation() - { - let scope = Object.assign({}, require("common")); - Services.scriptloader.loadSubScript( - "chrome://adblockplus/content/elemHideEmulation.js", scope); - - let onContentWindow = (subject, topic, data) => - { - if (!(subject instanceof Ci.nsIDOMWindow)) - return; - - let onReady = event => - { - subject.removeEventListener("load", onReady); - let handler = new scope.ElemHideEmulation( - subject, getFilters.bind(null, subject), (selectors, filters) => - { - if (selectors.length == 0) - return; - - addUserCSS(subject, selectors.map( - selector => selector + "{display: none !important;}" - ).join("\n")); - - if (!isPrivate(subject)) - port.emit("addHits", filters); - - let docDomain = null; - try - { - // We are calling getFrames() here because it will consider - // "inheritance" for about:blank and data: frames. - docDomain = new URL(getFrames(subject)[0].location).hostname; - } - catch (e) - { - // Invalid URL? - } - - for (let i = 0; i < filters.length; i++) - { - RequestNotifier.addNodeData(subject.document, subject.top, { - contentType: "ELEMHIDE", - docDomain: docDomain, - thirdParty: false, - location: "##" + selectors[i], - filter: filters[i], - filterType: "elemhideemulation" - }); - } - } - ); - - handler.apply(); - }; - - subject.addEventListener("load", onReady); - }; - - Services.obs.addObserver(onContentWindow, "content-document-global-created", - false); - onShutdown.add(() => - { - Services.obs.removeObserver(onContentWindow, - "content-document-global-created"); - }); - } - - initElemHideEmulation(); -})(); diff --git a/data/extensions/spyblock@gnu.org/lib/child/flasher.js b/data/extensions/spyblock@gnu.org/lib/child/flasher.js deleted file mode 100644 index 492f4e0..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/flasher.js +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -/** - * @fileOverview Draws a blinking border for a list of matching elements. - */ - -function Flasher(elements, scrollToItem) -{ - if (scrollToItem && elements[0].ownerDocument) - { - // Ensure that at least one element is visible when flashing - elements[0].scrollIntoView(); - } - - this.elements = elements; - this.count = 0; - - this.doFlash(); - -} -Flasher.prototype = -{ - elements: null, - count: 0, - timer: null, - - doFlash: function() - { - if (this.count >= 12) - { - this.stop(); - return; - } - - if (this.count % 2) - this.switchOff(); - else - this.switchOn(); - - this.count++; - - this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this.timer.initWithCallback(() => this.doFlash(), 300, Ci.nsITimer.TYPE_ONE_SHOT); - }, - - stop: function() - { - if (this.timer) - { - this.timer.cancel(); - this.timer = null; - } - - if (this.elements) - { - this.switchOff(); - this.elements = null; - } - }, - - setOutline: function(outline, offset) - { - for (let element of this.elements) - { - if (!Cu.isDeadWrapper(element) && "style" in element) - { - element.style.outline = outline; - element.style.outlineOffset = offset; - } - } - }, - - switchOn: function() - { - this.setOutline("#CC0000 dotted 2px", "-2px"); - }, - - switchOff: function() - { - this.setOutline("", ""); - } -}; - -exports.Flasher = Flasher; diff --git a/data/extensions/spyblock@gnu.org/lib/child/main.js b/data/extensions/spyblock@gnu.org/lib/child/main.js deleted file mode 100644 index bc21e9a..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/main.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -let {port} = require("messaging"); - -// Only initialize after receiving a "response" to a dummy message - this makes -// sure that on update the old version has enough time to receive and process -// the shutdown message. -port.emitWithResponse("ping").then(() => -{ - require("child/elemHide"); - require("child/contentPolicy"); - require("child/contextMenu"); - require("child/dataCollector"); - require("child/elemHideEmulation"); - require("child/subscribeLinks"); -}).catch(e => Cu.reportError(e)); diff --git a/data/extensions/spyblock@gnu.org/lib/child/objectTabs.js b/data/extensions/spyblock@gnu.org/lib/child/objectTabs.js deleted file mode 100644 index 74e7387..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/objectTabs.js +++ /dev/null @@ -1,405 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -/** - * @fileOverview Code responsible for showing and hiding object tabs. - */ - -let {port} = require("messaging"); - -/** - * 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, - - /** - * 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 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, - - /** - * Localized texts and class names to be used for the tab. This will be set - * when showTabFor is called for the first time. - * @type Object - */ - texts: null, - - /** - * 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" || - application == "adblockbrowser") - return; - - if (!this.texts) - this.texts = port.emitWithResponse("getObjectTabsTexts"); - Promise.all([port.emitWithResponse("getObjectTabsStatus"), this.texts]) - .then(([status, texts]) => - { - this.texts = texts; - if (!status) - 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 {RequestNotifier} = require("child/requestNotifier"); - let data = RequestNotifier.getDataForNode(element, true, "OBJECT"); - if (data) - this._showTab(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. - * @param {Element} element - * @param {RequestEntry} data - */ - _showTab: function(element, data) - { - let doc = element.ownerDocument.defaultView.top.document; - - this.objtabElement = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"); - this.objtabElement.textContent = this.texts.label; - this.objtabElement.setAttribute("title", this.texts.tooltip); - this.objtabElement.setAttribute("href", data.location); - this.objtabElement.setAttribute("class", this.texts.classHidden); - 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() - { - 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.texts.classVisibleTop; - let left = objRect.right - this.objtabElement.offsetWidth; - let top = objRect.top - this.objtabElement.offsetHeight; - if (top < 0) - { - top = objRect.bottom; - className = this.texts.classVisibleBottom; - } - - 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 {storeNodes} = require("child/contentPolicy"); - let nodesID = storeNodes([this.currentElement]); - port.emit("blockItem", { - request: this.objtabElement.nodeData, - nodesID - }); - }, - - /** - * Called whenever a timer fires. - * @param {nsISupport} subject - * @param {string} topic - * @param {string} data - */ - observe: function(subject, topic, 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/data/extensions/spyblock@gnu.org/lib/child/requestNotifier.js b/data/extensions/spyblock@gnu.org/lib/child/requestNotifier.js deleted file mode 100644 index fc6d314..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/requestNotifier.js +++ /dev/null @@ -1,444 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -/** - * @fileOverview Stores Adblock Plus data to be attached to a window. - */ -let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); - -let {port} = require("messaging"); -let {Utils} = require("utils"); -let {Flasher} = require("child/flasher"); - -let nodeData = new WeakMap(); -let windowStats = new WeakMap(); -let windowData = new WeakMap(); -let requestEntryMaxId = 0; - -/** - * Active RequestNotifier instances by their ID - * @type Map. - */ -let notifiers = new Map(); - -port.on("startWindowScan", onStartScan); -port.on("shutdownNotifier", onNotifierShutdown); -port.on("flashNodes", onFlashNodes); -port.on("retrieveNodeSize", onRetrieveNodeSize); -port.on("storeNodesForEntries", onStoreNodes); -port.on("retrieveWindowStats", onRetrieveWindowStats); -port.on("storeWindowData", onStoreWindowData); -port.on("retrieveWindowData", onRetrieveWindowData); - -function onStartScan({notifierID, outerWindowID}) -{ - let window = Services.wm.getOuterWindowWithId(outerWindowID); - if (window) - new RequestNotifier(window, notifierID); -} - -function onNotifierShutdown(notifierID) -{ - let notifier = notifiers.get(notifierID); - if (notifier) - notifier.shutdown(); -} - -function onFlashNodes({notifierID, requests, scrollToItem}) -{ - let notifier = notifiers.get(notifierID); - if (notifier) - notifier.flashNodes(requests, scrollToItem); -} - -function onRetrieveNodeSize({notifierID, requests}) -{ - let notifier = notifiers.get(notifierID); - if (notifier) - return notifier.retrieveNodeSize(requests); -} - -function onStoreNodes({notifierID, requests}) -{ - let notifier = notifiers.get(notifierID); - if (notifier) - return notifier.storeNodesForEntries(requests); -} - -function onRetrieveWindowStats(outerWindowID) -{ - let window = Services.wm.getOuterWindowWithId(outerWindowID); - if (window) - return RequestNotifier.getWindowStatistics(window); -} - -function onStoreWindowData({outerWindowID, data}) -{ - let window = Services.wm.getOuterWindowWithId(outerWindowID); - if (window) - windowData.set(window.document, data); -}; - -function onRetrieveWindowData(outerWindowID) -{ - let window = Services.wm.getOuterWindowWithId(outerWindowID); - if (window) - return windowData.get(window.document) || null; -}; - -/** - * 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} window window to attach the notifier to - * @param {Integer} notifierID Parent notifier ID to be messaged - */ -function RequestNotifier(window, notifierID) -{ - this.window = window; - this.id = notifierID; - notifiers.set(this.id, this); - this.nodes = new Map(); - this.startScan(window); -} -exports.RequestNotifier = RequestNotifier; - -RequestNotifier.prototype = -{ - /** - * Parent notifier ID to be messaged - * @type Integer - */ - id: null, - - /** - * The window this notifier is associated with. - * @type Window - */ - window: null, - - /** - * Nodes associated with a particular request ID. - * @type Map. - */ - nodes: null, - - /** - * 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.nodes; - this.stopFlashing(); - notifiers.delete(this.id); - }, - - /** - * Notifies the parent about a new request. - * @param {Node} node DOM node that the request is associated with - * @param {Object} entry - */ - notifyListener: function(node, entry) - { - if (this.nodes) - this.nodes.set(entry.id, node); - port.emit("foundNodeData", { - notifierID: this.id, - data: entry - }); - }, - - onComplete: function() - { - port.emit("scanComplete", this.id); - }, - - /** - * 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() - { - // Don't do anything if the notifier was shut down already. - if (!this.window) - return; - - let node = walker.currentNode; - let data = nodeData.get(node); - if (typeof data != "undefined") - for (let k in data) - this.notifyListener(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.onComplete(); - } - } - }.bind(this); - - // Process each node in a separate event to allow other events to process - this.eventsPosted++; - Utils.runAsync(process); - }, - - /** - * Makes the nodes associated with the given requests blink. - * @param {number[]} requests list of request IDs that were previously - * reported by this notifier. - * @param {boolean} scrollToItem if true, scroll to first node - */ - flashNodes: function(requests, scrollToItem) - { - this.stopFlashing(); - - let nodes = []; - for (let id of requests) - { - if (!this.nodes.has(id)) - continue; - - let node = this.nodes.get(id); - if (Cu.isDeadWrapper(node)) - this.nodes.delete(node); - else if (node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) - nodes.push(node); - } - if (nodes.length) - this.flasher = new Flasher(nodes, scrollToItem); - }, - - /** - * Stops flashing nodes after a previous flashNodes() call. - */ - stopFlashing: function() - { - if (this.flasher) - this.flasher.stop(); - this.flasher = null; - }, - - /** - * Attempts to calculate the size of the nodes associated with the requests. - * @param {number[]} requests list of request IDs that were previously - * reported by this notifier. - * @return {number[]|null} either an array containing width and height or - * null if the size could not be calculated. - */ - retrieveNodeSize: function(requests) - { - function getNodeSize(node) - { - if (node instanceof Ci.nsIDOMHTMLImageElement && (node.naturalWidth || node.naturalHeight)) - return [node.naturalWidth, node.naturalHeight]; - else if (node instanceof Ci.nsIDOMHTMLElement && (node.offsetWidth || node.offsetHeight)) - return [node.offsetWidth, node.offsetHeight]; - else - return null; - } - - let size = null; - for (let id of requests) - { - if (!this.nodes.has(id)) - continue; - - let node = this.nodes.get(id); - if (Cu.isDeadWrapper(node)) - this.nodes.delete(node); - else - { - size = getNodeSize(node); - if (size) - break; - } - } - return size; - }, - - /** - * Stores the nodes associated with the requests and generates a unique ID - * for them that can be used with Policy.refilterNodes(). - * @param {number[]} requests list of request IDs that were previously - * reported by this notifier. - * @return {string} unique identifiers associated with the nodes. - */ - storeNodesForEntries: function(requests) - { - let nodes = []; - for (let id of requests) - { - if (!this.nodes.has(id)) - continue; - - let node = this.nodes.get(id); - if (Cu.isDeadWrapper(node)) - this.nodes.delete(node); - else - nodes.push(node); - } - - let {storeNodes} = require("child/contentPolicy"); - return storeNodes(nodes); - } -}; - -/** - * 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 {Object} hitData - * @param {String} hitData.contentType request type, e.g. "IMAGE" - * @param {String} hitData.docDomain domain of the document that initiated the request - * @param {Boolean} hitData.thirdParty will be true if a third-party server has been requested - * @param {String} hitData.location the address that has been requested - * @param {String} hitData.filter filter applied to the request or null if none - * @param {String} hitData.filterType type of filter applied to the request - */ -RequestNotifier.addNodeData = function(node, topWnd, {contentType, docDomain, thirdParty, location, filter, filterType}) -{ - let entry = { - id: ++requestEntryMaxId, - type: contentType, - docDomain, thirdParty, location, filter - }; - - let existingData = nodeData.get(node); - if (typeof existingData == "undefined") - { - existingData = {}; - nodeData.set(node, existingData); - } - - // Add this request to the node data - existingData[contentType + " " + location] = entry; - - // Update window statistics - if (!windowStats.has(topWnd.document)) - { - windowStats.set(topWnd.document, { - items: 0, - hidden: 0, - blocked: 0, - whitelisted: 0, - filters: {} - }); - } - - let stats = windowStats.get(topWnd.document); - if (filterType != "elemhide" && filterType != "elemhideexception" && filterType != "elemhideemulation") - stats.items++; - if (filter) - { - if (filterType == "blocking") - stats.blocked++; - else if (filterType == "whitelist" || filterType == "elemhideexception") - stats.whitelisted++; - else if (filterType == "elemhide" || filterType == "elemhideemulation") - stats.hidden++; - - if (filter in stats.filters) - stats.filters[filter]++; - else - stats.filters[filter] = 1; - } - - // Notify listeners - for (let notifier of notifiers.values()) - if (!notifier.window || notifier.window == topWnd) - notifier.notifyListener(node, entry); -} - -/** - * Retrieves the statistics for a window. - * @return {Object} Object with the properties items, blocked, whitelisted, hidden, filters containing statistics for the window (might be null) - */ -RequestNotifier.getWindowStatistics = function(/**Window*/ wnd) -{ - if (windowStats.has(wnd.document)) - return windowStats.get(wnd.document); - else - return null; -} - -/** - * Retrieves the request data 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, Object]} - * @static - */ -RequestNotifier.getDataForNode = function(node, noParent, type, location) -{ - while (node) - { - let data = nodeData.get(node); - if (typeof data != "undefined") - { - let entry = null; - // Look for matching entry - for (let k in data) - { - if ((!entry || entry.id < data[k].id) && - (typeof type == "undefined" || data[k].type == type) && - (typeof location == "undefined" || data[k].location == location)) - { - entry = data[k]; - } - } - if (entry) - 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; -}; diff --git a/data/extensions/spyblock@gnu.org/lib/child/subscribeLinks.js b/data/extensions/spyblock@gnu.org/lib/child/subscribeLinks.js deleted file mode 100644 index a2e729d..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/subscribeLinks.js +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); - -let {port} = require("messaging"); - -Services.obs.addObserver(onContentWindow, "content-document-global-created", - false); -onShutdown.add(() => -{ - Services.obs.removeObserver(onContentWindow, - "content-document-global-created"); -}); - -function onContentWindow(subject, topic, data) -{ - if (subject instanceof Ci.nsIDOMWindow && subject.top == subject) - { - let eventTarget = subject.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell) - .chromeEventHandler; - if (eventTarget) - eventTarget.addEventListener("click", onClick, true); - } -} - -function onClick(event) -{ - if (onShutdown.done) - return; - - // Ignore right-clicks - if (event.button == 2) - return; - - // Search the link associated with the click - let link = event.target; - while (!(link instanceof Ci.nsIDOMHTMLAnchorElement)) - { - link = link.parentNode; - - if (!link) - return; - } - - let queryString = null; - if (link.protocol == "http:" || link.protocol == "https:") - { - if (link.host == "subscribe.adblockplus.org" && link.pathname == "/") - queryString = link.search.substr(1); - } - else - { - // Firefox doesn't populate the "search" property for links with - // non-standard URL schemes so we need to extract the query string - // manually - let match = /^abp:\/*subscribe\/*\?(.*)/i.exec(link.href); - if (match) - queryString = match[1]; - } - - if (!queryString) - return; - - // This is our link - make sure the browser doesn't handle it - event.preventDefault(); - event.stopPropagation(); - - // Decode URL parameters - let title = null; - let url = null; - let mainSubscriptionTitle = null; - let mainSubscriptionURL = null; - for (let param of queryString.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; - } - } - - port.emit("subscribeLinkClick", { - title: title, - url: url, - mainSubscriptionTitle: mainSubscriptionTitle, - mainSubscriptionURL: mainSubscriptionURL - }); -} diff --git a/data/extensions/spyblock@gnu.org/lib/child/utils.js b/data/extensions/spyblock@gnu.org/lib/child/utils.js deleted file mode 100644 index fde649f..0000000 --- a/data/extensions/spyblock@gnu.org/lib/child/utils.js +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is part of Adblock Plus , - * Copyright (C) 2006-2017 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 . - */ - -"use strict"; - -let {PrivateBrowsingUtils} = Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm", {}); - -let {Utils} = require("utils"); - -/** - * Retrieves the effective location of a window. - */ -let getWindowLocation = exports.getWindowLocation = function(/**Window*/ window) /**String*/ -{ - let result = null; - - // Crazy Thunderbird stuff - if ("name" in window && window.name == "messagepane") - { - try - { - let mailWnd = window.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) - { - result = 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) - result = 'mailto:' + emailAddress.replace(/^[\s"]+/, "").replace(/[\s"]+$/, "").replace(/\s/g, '%20'); - } - } catch(e) {} - } - - // Sane branch - if (!result) - result = window.location.href; - - // Remove the anchor if any - let index = result.indexOf("#"); - if (index >= 0) - result = result.substring(0, index); - - return result; -} - -/** - * Retrieves the frame hierarchy for a window. Returns an array containing - * the information for all frames, starting with the window itself up to its - * top-level window. Each entry has a location and a sitekey entry. - * @return {Array} - */ -let getFrames = exports.getFrames = function(/**Window*/ window) -{ - let frames = []; - while (window) - { - let frame = { - location: getWindowLocation(window), - sitekey: null - }; - - let documentElement = window.document && window.document.documentElement; - if (documentElement) - frame.sitekey = documentElement.getAttribute("data-adblockkey") - - frames.push(frame); - window = (window != window.parent ? window.parent : null); - } - - // URLs like about:blank inherit their security context from upper-level - // frames, resolve their URLs accordingly. - for (let i = frames.length - 2; i >= 0; i--) - { - let frame = frames[i]; - if (frame.location == "about:blank" || frame.location == "moz-safe-about:blank" || - frame.location == "about:srcdoc" || - Utils.netUtils.URIChainHasFlags(Utils.makeURI(frame.location), Ci.nsIProtocolHandler.URI_INHERITS_SECURITY_CONTEXT)) - { - frame.location = frames[i + 1].location; - } - } - - return frames; -}; - -/** - * Checks whether Private Browsing mode is enabled for a content window. - * @return {Boolean} - */ -let isPrivate = exports.isPrivate = function(/**Window*/ window) -{ - return PrivateBrowsingUtils.isContentWindowPrivate(window); -}; - -/** - * Gets the DOM window associated with a particular request (if any). - */ -let getRequestWindow = exports.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; -}; -- cgit v1.2.3