[Pkg-mozext-commits] [adblock-plus] 49/87: Issue 2401 - Integrate CSS property rule handling in Firefox

David Prévot taffit at moszumanska.debian.org
Sat Apr 30 17:59:07 UTC 2016


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository adblock-plus.

commit 284f8b9868ac06944ac71a35235bcec95d9af15d
Author: Wladimir Palant <trev at adblockplus.org>
Date:   Wed Mar 30 20:38:48 2016 +0200

    Issue 2401 - Integrate CSS property rule handling in Firefox
---
 lib/child/cssProperties.js |  97 +++++++++++++++++++++++++++++++++++++
 lib/child/main.js          |   1 +
 lib/contentPolicy.js       | 116 +++++++++++++++++++++++++++------------------
 lib/cssProperties.js       |  47 ++++++++++++++++++
 lib/main.js                |   1 +
 lib/whitelisting.js        |  46 ++++++++++++++++++
 6 files changed, 263 insertions(+), 45 deletions(-)

diff --git a/lib/child/cssProperties.js b/lib/child/cssProperties.js
new file mode 100644
index 0000000..2a27655
--- /dev/null
+++ b/lib/child/cssProperties.js
@@ -0,0 +1,97 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2016 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/>.
+ */
+
+"use strict";
+
+(function()
+{
+  let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
+
+  let {port} = require("messaging");
+  let {getFrames} = require("child/utils");
+
+  let senderWindow = null;
+
+  let scope = {
+    ext: {
+      backgroundPage: {
+        sendMessage: function(data, callback)
+        {
+          data = {payload: data, frames: getFrames(senderWindow)};
+          if (typeof callback == "function")
+            port.emitWithResponse("cssPropertiesRequest", data).then(callback);
+          else
+            port.emit("cssPropertiesRequest", data);
+        }
+      }
+    }
+  };
+
+  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 initCSSPropertyFilters()
+  {
+    Services.scriptloader.loadSubScript(
+        "chrome://adblockplus/content/cssProperties.js", scope);
+
+    let onContentWindow = (subject, topic, data) =>
+    {
+      if (!(subject instanceof Ci.nsIDOMWindow))
+        return;
+
+      let onReady = event =>
+      {
+        subject.removeEventListener("DOMContentLoaded", onReady);
+        let handler = new scope.CSSPropertyFilters(subject, selectors =>
+        {
+          if (selectors.length == 0)
+            return;
+
+          addUserCSS(subject, selectors.map(
+            selector => selector + "{display: none !important;}"
+          ).join("\n"));
+        });
+
+        // HACK: The content script just calls ext.backgroundPage.sendMessage
+        // without indicating which window this is about. We'll store the window
+        // here because we know that messaging happens synchronously.
+        senderWindow = subject;
+        handler.load(() => handler.apply());
+        senderWindow = null;
+      };
+
+      subject.addEventListener("DOMContentLoaded", onReady);
+    };
+
+    Services.obs.addObserver(onContentWindow, "content-document-global-created",
+        false);
+    onShutdown.add(() =>
+    {
+      Services.obs.removeObserver(onContentWindow,
+          "content-document-global-created");
+    });
+  }
+
+  initCSSPropertyFilters();
+})();
diff --git a/lib/child/main.js b/lib/child/main.js
index 7065464..f971968 100644
--- a/lib/child/main.js
+++ b/lib/child/main.js
@@ -19,3 +19,4 @@ require("child/elemHide");
 require("child/contentPolicy");
 require("child/contextMenu");
 require("child/dataCollector");
+require("child/cssProperties");
diff --git a/lib/contentPolicy.js b/lib/contentPolicy.js
index e416634..b5e506a 100644
--- a/lib/contentPolicy.js
+++ b/lib/contentPolicy.js
@@ -145,50 +145,27 @@ var Policy = exports.Policy =
     // Interpret unknown types as "other"
     contentType = this.contentTypes.get(contentType) || "OTHER";
 
-    let wndLocation = frames[0].location;
-    let docDomain = getHostname(wndLocation);
-    let match = null;
-    let [sitekey, sitekeyFrame] = getSitekey(frames);
     let nogeneric = false;
-    if (!match && Prefs.enabled)
+    if (Prefs.enabled)
     {
-      let testSitekey = sitekey;
-      let testSitekeyFrame = sitekeyFrame;
-      for (let i = 0; i < frames.length; i++)
+      let whitelistHit =
+          this.isFrameWhitelisted(frames, contentType == "ELEMHIDE");
+      if (whitelistHit)
       {
-        let frame = frames[i];
-        let testWndLocation = frame.location;
-        let parentWndLocation = frames[Math.min(i + 1, frames.length - 1)].location;
-        let parentDocDomain = getHostname(parentWndLocation);
-
-        let typeMap = RegExpFilter.typeMap.DOCUMENT;
-        if (contentType == "ELEMHIDE")
-          typeMap = typeMap | RegExpFilter.typeMap.ELEMHIDE;
-        let whitelistMatch = defaultMatcher.matchesAny(testWndLocation, typeMap, parentDocDomain, false, testSitekey);
-        if (whitelistMatch instanceof WhitelistFilter)
-        {
-          let whitelistType = (whitelistMatch.contentType & RegExpFilter.typeMap.DOCUMENT) ? "DOCUMENT" : "ELEMHIDE";
-          addHit(i, whitelistType, parentDocDomain, false, testWndLocation,
-              whitelistMatch);
+        let [frameIndex, matchType, docDomain, thirdParty, location, filter] = whitelistHit;
+        addHit(frameIndex, matchType, docDomain, thirdParty, location, filter);
+        if (matchType == "DOCUMENT" || matchType == "ELEMHIDE")
           return response(true, false);
-        }
-
-        let genericType = (contentType == "ELEMHIDE" ? "GENERICHIDE" : "GENERICBLOCK");
-        let nogenericMatch = defaultMatcher.matchesAny(testWndLocation,
-            RegExpFilter.typeMap[genericType], parentDocDomain, false, testSitekey);
-        if (nogenericMatch instanceof WhitelistFilter)
-        {
+        else
           nogeneric = true;
-          addHit(i, genericType, parentDocDomain, false, testWndLocation,
-              nogenericMatch);
-        }
-
-        if (frame == testSitekeyFrame)
-          [testSitekey, testSitekeyFrame] = getSitekey(frames.slice(i + 1));
       }
     }
 
-    if (!match && contentType == "ELEMHIDE")
+    let match = null;
+    let wndLocation = frames[0].location;
+    let docDomain = getHostname(wndLocation);
+    let [sitekey, sitekeyFrame] = getSitekey(frames);
+    if (contentType == "ELEMHIDE")
     {
       match = ElemHide.getFilterByKey(location);
       location = match.text.replace(/^.*?#/, '#');
@@ -240,13 +217,13 @@ var Policy = exports.Policy =
   },
 
   /**
-   * Checks whether a page is whitelisted.
+   * Checks whether a top-level window is whitelisted.
    * @param {String} url
-   * @param {String} [parentUrl] location of the parent page
-   * @param {String} [sitekey] public key provided on the page
-   * @return {Filter} filter that matched the URL or null if not whitelisted
+   *    URL of the document loaded into the window
+   * @return {?WhitelistFilter}
+   *    exception rule that matched the URL if any
    */
-  isWhitelisted: function(url, parentUrl, sitekey)
+  isWhitelisted: function(url)
   {
     if (!url)
       return null;
@@ -255,19 +232,68 @@ var Policy = exports.Policy =
     if (!this.isBlockableScheme(url))
       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, RegExpFilter.typeMap.DOCUMENT, getHostname(parentUrl), false, sitekey);
+    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 = (whitelistMatch.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
diff --git a/lib/cssProperties.js b/lib/cssProperties.js
new file mode 100644
index 0000000..b0e878b
--- /dev/null
+++ b/lib/cssProperties.js
@@ -0,0 +1,47 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2016 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 is merely forwarding messages from the content script to
+ * message responder, these will hopefully be received directly soon.
+ */
+
+"use strict";
+
+let {port} = require("messaging");
+let {onMessage} = require("ext_background");
+
+port.on("cssPropertiesRequest", ({payload, frames}) =>
+{
+  let result = undefined;
+
+  // HACK: Message responder doesn't care about sender.page but it passes
+  // sender.frame to whitelisting.checkWhitelisted(). Instead of converting
+  // our frame list into the format used in Chrome we keep it as is, then our
+  // whitelisting.checkWhitelisted() implementation won't need to convert it
+  // back. We merely have to set frames.url, message responder needs it.
+  frames.url = new URL(frames[0].location);
+  let sender = {
+    page: null,
+    frame: frames
+  };
+
+  onMessage._dispatch(payload, sender, data => {
+    result = data;
+  });
+  return result;
+});
diff --git a/lib/main.js b/lib/main.js
index 742a9fb..dadca3a 100644
--- a/lib/main.js
+++ b/lib/main.js
@@ -32,6 +32,7 @@ require("sync");
 require("messageResponder");
 require("ui");
 require("objectTabs");
+require("cssProperties");
 
 function bootstrapChildProcesses()
 {
diff --git a/lib/whitelisting.js b/lib/whitelisting.js
new file mode 100644
index 0000000..518f31e
--- /dev/null
+++ b/lib/whitelisting.js
@@ -0,0 +1,46 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2016 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 is a dummy to provide a function needed by message
+ * responder.
+ */
+
+"use strict";
+
+let {Policy} = require("contentPolicy");
+let {RegExpFilter} = require("filterClasses");
+
+// NOTE: The function interface is supposed to be compatible with
+// checkWhitelisted in adblockpluschrome. That's why there is a typeMask
+// parameter here. However, this parameter is only used to decide whether
+// elemhide whitelisting should be considered, so only supported values for this
+// parameter are RegExpFilter.typeMap.DOCUMENT and
+// RegExpFilter.typeMap.DOCUMENT | RegExpFilter.typeMap.ELEMHIDE.
+exports.checkWhitelisted = function(page, frames, typeMask)
+{
+  let match =
+      Policy.isFrameWhitelisted(frames, typeMask & RegExpFilter.typeMap.ELEMHIDE);
+  if (match)
+  {
+    let [frameIndex, matchType, docDomain, thirdParty, location, filter] = match;
+    if (matchType == "DOCUMENT" || matchType == "ELEMHIDE")
+      return filter;
+  }
+
+  return null;
+};

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/adblock-plus.git



More information about the Pkg-mozext-commits mailing list