diff options
Diffstat (limited to 'data/extensions/spyblock@gnu.org/lib/contentPolicy.js')
-rw-r--r-- | data/extensions/spyblock@gnu.org/lib/contentPolicy.js | 415 |
1 files changed, 0 insertions, 415 deletions
diff --git a/data/extensions/spyblock@gnu.org/lib/contentPolicy.js b/data/extensions/spyblock@gnu.org/lib/contentPolicy.js deleted file mode 100644 index ad36655..0000000 --- a/data/extensions/spyblock@gnu.org/lib/contentPolicy.js +++ /dev/null @@ -1,415 +0,0 @@ -/* - * This file is part of Adblock Plus <https://adblockplus.org/>, - * 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 <http://www.gnu.org/licenses/>. - */ - -/** - * @fileOverview Content policy implementation, responsible for blocking things. - */ - -"use strict"; - -let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {}); -let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); - -let {Utils} = require("utils"); -let {port} = require("messaging"); -let {Prefs} = require("prefs"); -let {FilterStorage} = require("filterStorage"); -let {BlockingFilter, WhitelistFilter, RegExpFilter} = require("filterClasses"); -let {defaultMatcher} = require("matcher"); - -/** - * Public policy checking functions and auxiliary objects - * @class - */ -var Policy = exports.Policy = -{ - /** - * Map of content types reported by Firefox to the respecitve content types - * used by Adblock Plus. Other content types are simply mapped to OTHER. - * @type Map.<string,string> - */ - contentTypes: new Map(function* () - { - // Treat navigator.sendBeacon() the same as <a ping>, - // it's essentially the same concept - merely generalized. - yield ["BEACON", "PING"]; - - // Treat <img srcset> and <picture> the same as other images. - yield ["IMAGESET", "IMAGE"]; - - // Treat fetch() the same as XMLHttpRequest, - // it's essentially the same - merely a more modern API. - yield ["FETCH", "XMLHTTPREQUEST"]; - - // Everything else is mapped to itself - for (let contentType of ["OTHER", "SCRIPT", "IMAGE", "STYLESHEET", "OBJECT", - "SUBDOCUMENT", "DOCUMENT", "XMLHTTPREQUEST", - "OBJECT_SUBREQUEST", "FONT", "MEDIA", "PING", - "WEBSOCKET", "ELEMHIDE", "POPUP", "GENERICHIDE", - "GENERICBLOCK"]) - yield [contentType, contentType]; - }()), - - /** - * Set of content types that aren't associated with a visual document area - * @type Set.<string> - */ - nonVisualTypes: new Set([ - "SCRIPT", "STYLESHEET", "XMLHTTPREQUEST", "OBJECT_SUBREQUEST", "FONT", - "PING", "WEBSOCKET", "ELEMHIDE", "POPUP", "GENERICHIDE", "GENERICBLOCK" - ]), - - /** - * Map containing all schemes that should be ignored by content policy. - * @type Set.<string> - */ - whitelistSchemes: new Set(), - - /** - * Called on module startup, initializes various exported properties. - */ - init: function() - { - // whitelisted URL schemes - for (let scheme of Prefs.whitelistschemes.toLowerCase().split(" ")) - this.whitelistSchemes.add(scheme); - - port.on("shouldAllow", (message, sender) => this.shouldAllow(message)); - - // Generate class identifier used to collapse nodes and register - // corresponding stylesheet. - let collapsedClass = ""; - let offset = "a".charCodeAt(0); - for (let i = 0; i < 20; i++) - collapsedClass += String.fromCharCode(offset + Math.random() * 26); - port.on("getCollapsedClass", (message, sender) => collapsedClass); - - 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(() => - { - Utils.styleService.unregisterSheet(collapseStyle, Ci.nsIStyleSheetService.USER_SHEET); - }); - }, - - /** - * Checks whether a node should be blocked, hides it if necessary - * @param {Object} data request data - * @param {String} data.contentType - * @param {String} data.location location of the request - * @param {Object[]} data.frames - * @param {Boolean} data.isPrivate true if the request belongs to a private browsing window - * @return {Object} An object containing properties allow, collapse and hits - * indicating how this request should be handled. - */ - shouldAllow: function({contentType, location, frames, isPrivate}) - { - let hits = []; - - function addHit(frameIndex, contentType, docDomain, thirdParty, location, filter) - { - if (filter && !isPrivate) - FilterStorage.increaseHitCount(filter); - hits.push({ - frameIndex, contentType, docDomain, thirdParty, location, - filter: filter ? filter.text : null, - filterType: filter ? filter.type : null - }); - } - - function response(allow, collapse) - { - return {allow, collapse, hits}; - } - - // Ignore whitelisted schemes - if (contentType != "POPUP" && !this.isBlockableScheme(location)) - return response(true, false); - - // Interpret unknown types as "other" - contentType = this.contentTypes.get(contentType) || "OTHER"; - - let nogeneric = false; - if (Prefs.enabled) - { - let whitelistHit = - this.isFrameWhitelisted(frames, false); - if (whitelistHit) - { - let [frameIndex, matchType, docDomain, thirdParty, location, filter] = whitelistHit; - addHit(frameIndex, matchType, docDomain, thirdParty, location, filter); - if (matchType == "DOCUMENT") - return response(true, false); - else - nogeneric = true; - } - } - - let match = null; - let wndLocation = frames[0].location; - let docDomain = getHostname(wndLocation); - let [sitekey, sitekeyFrame] = getSitekey(frames); - - let thirdParty = isThirdParty(location, docDomain); - let collapse = false; - - if (!match && Prefs.enabled && RegExpFilter.typeMap.hasOwnProperty(contentType)) - { - match = defaultMatcher.matchesAny(location, RegExpFilter.typeMap[contentType], - docDomain, thirdParty, sitekey, nogeneric, isPrivate); - if (match instanceof BlockingFilter && !this.nonVisualTypes.has(contentType)) - collapse = (match.collapse != null ? match.collapse : !Prefs.fastcollapse); - } - addHit(null, contentType, docDomain, thirdParty, location, match); - - return response(!match || match instanceof WhitelistFilter, collapse); - }, - - /** - * Checks whether the location's scheme is blockable. - * @param location {nsIURI|String} - * @return {Boolean} - */ - isBlockableScheme: function(location) - { - let scheme; - if (typeof location == "string") - { - let match = /^([\w\-]+):/.exec(location); - scheme = match ? match[1] : null; - } - else - scheme = location.scheme; - return !this.whitelistSchemes.has(scheme); - }, - - /** - * Checks whether a top-level window is whitelisted. - * @param {String} url - * URL of the document loaded into the window - * @return {?WhitelistFilter} - * exception rule that matched the URL if any - */ - isWhitelisted: function(url) - { - if (!url) - return null; - - // Do not apply exception rules to schemes on our whitelistschemes list. - if (!this.isBlockableScheme(url)) - return null; - - // Ignore fragment identifier - let index = url.indexOf("#"); - if (index >= 0) - url = url.substring(0, index); - - let result = defaultMatcher.matchesAny(url, RegExpFilter.typeMap.DOCUMENT, - getHostname(url), false, null); - return (result instanceof WhitelistFilter ? result : null); - }, - - /** - * Checks whether a frame is whitelisted. - * @param {Array} frames - * frame structure as returned by getFrames() in child/utils module. - * @param {boolean} isElemHide - * true if element hiding whitelisting should be considered - * @return {?Array} - * An array with the hit parameters: frameIndex, contentType, docDomain, - * thirdParty, location, filter. Note that the filter could be a - * genericblock/generichide exception rule. If nothing matched null is - * returned. - */ - isFrameWhitelisted: function(frames, isElemHide) - { - let [sitekey, sitekeyFrame] = getSitekey(frames); - let nogenericHit = null; - - let typeMap = RegExpFilter.typeMap.DOCUMENT; - if (isElemHide) - typeMap = typeMap | RegExpFilter.typeMap.ELEMHIDE; - let genericType = (isElemHide ? "GENERICHIDE" : "GENERICBLOCK"); - - for (let i = 0; i < frames.length; i++) - { - let frame = frames[i]; - let wndLocation = frame.location; - let parentWndLocation = frames[Math.min(i + 1, frames.length - 1)].location; - let parentDocDomain = getHostname(parentWndLocation); - - let match = defaultMatcher.matchesAny(wndLocation, typeMap, parentDocDomain, false, sitekey); - if (match instanceof WhitelistFilter) - { - let whitelistType = (match.contentType & RegExpFilter.typeMap.DOCUMENT) ? "DOCUMENT" : "ELEMHIDE"; - return [i, whitelistType, parentDocDomain, false, wndLocation, match]; - } - - if (!nogenericHit) - { - match = defaultMatcher.matchesAny(wndLocation, - RegExpFilter.typeMap[genericType], parentDocDomain, false, sitekey); - if (match instanceof WhitelistFilter) - nogenericHit = [i, genericType, parentDocDomain, false, wndLocation, match]; - } - - if (frame == sitekeyFrame) - [sitekey, sitekeyFrame] = getSitekey(frames.slice(i + 1)); - } - - return nogenericHit; - }, - - /** - * Deletes nodes that were previously stored with a - * RequestNotifier.storeNodesForEntries() call or similar. - * @param {string} id unique ID of the nodes - */ - deleteNodes: function(id) - { - port.emit("deleteNodes", id); - }, - - /** - * Asynchronously re-checks filters for nodes given by an ID previously - * returned by a RequestNotifier.storeNodesForEntries() call or similar. - * @param {string} id unique ID of the nodes - * @param {RequestEntry} entry - */ - refilterNodes: function(id, entry) - { - port.emit("refilterNodes", { - nodesID: id, - entry: entry - }); - } -}; -Policy.init(); - -/** - * 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 and validates the sitekey for a frame structure. - */ -function getSitekey(frames) -{ - for (let frame of frames) - { - if (frame.sitekey && frame.sitekey.indexOf("_") >= 0) - { - let [key, signature] = frame.sitekey.split("_", 2); - key = key.replace(/=/g, ""); - - // Website specifies a key but is the signature valid? - let uri = Services.io.newURI(frame.location, null, null); - let host = uri.asciiHost; - if (uri.port > 0) - host += ":" + uri.port; - let params = [ - uri.path.replace(/#.*/, ""), // REQUEST_URI - host, // HTTP_HOST - Utils.httpProtocol.userAgent // HTTP_USER_AGENT - ]; - if (Utils.verifySignature(key, signature, params.join("\0"))) - return [key, frame]; - } - } - - return [null, 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(/**String*/location, /**String*/ docDomain) /**Boolean*/ -{ - if (!location || !docDomain) - return true; - - let uri = Utils.makeURI(location); - try - { - return Utils.effectiveTLD.getBaseDomain(uri) != Utils.effectiveTLD.getBaseDomainFromHost(docDomain); - } - catch (e) - { - // EffectiveTLDService throws on IP addresses, just compare the host name - let host = ""; - try - { - host = uri.host; - } catch (e) {} - return host != docDomain; - } -} |