[Pkg-mozext-commits] [requestpolicy] 03/09: [ref] overlay: wrap "addTab" without eval()

David Prévot taffit at moszumanska.debian.org
Thu Jan 28 03:20:29 UTC 2016


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

taffit pushed a commit to annotated tag v0.5.30
in repository requestpolicy.

commit 94834ad8e65051987ae898d69ea1660b546a0d46
Author: Martin Kimmerle <dev at 256k.de>
Date:   Wed Sep 2 19:33:20 2015 +0200

    [ref] overlay: wrap "addTab" without eval()
    
    The code is taken from commits 164d4e5 and 0a27f54 on the
    `dev-1.0` branch. The code uses default parameters for
    functions, which are supported since Gecko 15. The minVersion
    is set to the Gecko 16 version, which is the one used in the
    above commits.
---
 src/content/overlay.js | 43 +++++-----------------
 src/install.rdf        |  4 +--
 src/modules/Util.jsm   | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+), 37 deletions(-)

diff --git a/src/content/overlay.js b/src/content/overlay.js
index 6fb0c7c..1f13247 100644
--- a/src/content/overlay.js
+++ b/src/content/overlay.js
@@ -1076,45 +1076,18 @@ requestpolicy.overlay = {
   },
 
   /**
-   * Modifies the addTab() function so that RequestPolicy can be aware of the
+   * Wraps the addTab() function so that RequestPolicy can be aware of the
    * tab being opened. Assume that if the tab is being opened, it was an action
    * the user wanted (e.g. the equivalent of a link click). Using a TabOpen
-   * event handler, I was unable to determine the referrer, so that approach
-   * doesn't seem to be an option. This doesn't actually wrap addTab because the
-   * extension TabMixPlus modifies the function rather than wraps it, so
-   * wrapping it will break tabs if TabMixPlus is installed.
+   * event handler, I (Justin) was unable to determine the referrer,
+   * so that approach doesn't seem to be an option.
+   *
+   * Details on addTab():
+   * - https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/tabbrowser#m-addTab
+   * - See mozilla-central: "base/content/tabbrowser.xml"
    */
   _wrapAddTab : function() {
-    if (!gBrowser.requestpolicyAddTabModified) {
-      gBrowser.requestpolicyAddTabModified = true;
-
-      // For reference, the addTab() function signature looks like this:
-      // function addTab(aURI, aReferrerURI, aCharset, aPostData, aOwner,
-      // aAllowThirdPartyFixup) {";
-      // where it's possible that only two arguments are used and aReferrerURI
-      // is a hash of the other arguments as well as new ones.
-      // See https://www.requestpolicy.com/dev/ticket/38
-
-      // In order to keep our code from breaking if the signature of addTab
-      // changes (even just a change in variable names, for example), we'll
-      // simply insert our own line right after the first curly brace in the
-      // string representation of the addTab function.
-      var addTabString = gBrowser.addTab.toString();
-      var firstCurlyBrace = addTabString.indexOf("{");
-      var addTabParts = [];
-      // Includes the '{'
-      addTabParts[0] = addTabString.substring(0, firstCurlyBrace + 1);
-      // Starts after the '{'
-      addTabParts[1] = addTabString.substring(firstCurlyBrace + 1);
-
-      // We use 'arguments' so that we aren't dependent on the names of two
-      // parameters, as it seems not unlikely that these could change due to
-      // the second parameter's purpose having been changed.
-      var newFirstCodeLine = "\n    requestpolicy.overlay.tabAdded(arguments[0], arguments[1]);";
-      // Finally, add our line to the beginning of the addTab function.
-      eval("gBrowser.addTab = " + addTabParts[0] + newFirstCodeLine
-          + addTabParts[1]);
-    }
+    Util.wrapFunction(gBrowser, "addTab", this.tabAdded);
   },
 
   /**
diff --git a/src/install.rdf b/src/install.rdf
index 089c3e5..c59a5ea 100644
--- a/src/install.rdf
+++ b/src/install.rdf
@@ -44,7 +44,7 @@
     <em:targetApplication>
       <Description>
         <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-        <em:minVersion>4.0</em:minVersion>
+        <em:minVersion>16.0</em:minVersion>
         <em:maxVersion>40.0a2</em:maxVersion>
       </Description>
     </em:targetApplication>
@@ -53,7 +53,7 @@
     <em:targetApplication>
       <Description>
         <em:id>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</em:id>
-        <em:minVersion>2.1</em:minVersion>
+        <em:minVersion>2.13</em:minVersion>
         <em:maxVersion>2.33.*</em:maxVersion>
       </Description>
     </em:targetApplication>
diff --git a/src/modules/Util.jsm b/src/modules/Util.jsm
index dd9e47c..571859e 100644
--- a/src/modules/Util.jsm
+++ b/src/modules/Util.jsm
@@ -25,6 +25,8 @@ var EXPORTED_SYMBOLS = ["Util"];
 const CI = Components.interfaces;
 const CC = Components.classes;
 
+Components.utils.import("resource://requestpolicy/Logger.jsm");
+
 const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
 
 var Util = {
@@ -52,5 +54,100 @@ var Util = {
 
   isFirefox : function() {
     return this.appInfo.ID == FIREFOX_ID;
+  },
+
+  /**
+   * Wrap a function. Allow 'before' and 'after' functions.
+   * If the function was wrapped already earlier in time, the old
+   * wrapper function will be re-used.
+   *
+   * @param {Object} aOwnerObject The object which contains (a reference to)
+   *     the function which should be wrapped.
+   * @param {string} aFunctionName The function's name in the object.
+   * @param {Function=} aBeforeFunction The function to be called before the
+   *     original function.
+   * @param {Function=} aAfterFunction The function to be called after the
+   *     original function.
+   */
+  wrapFunction : function(aOwnerObject, aFunctionName, aBeforeFunction = null,
+                          aAfterFunction = null) {
+    initWrapperFunction(aOwnerObject, aFunctionName);
+
+    var fnMetadata = aOwnerObject.rpcontinuedWrappedFunctions[aFunctionName];
+    fnMetadata.before = aBeforeFunction;
+    fnMetadata.after = aAfterFunction;
+  },
+
+  /**
+   * Unwrap a function which has been wrapped before. The function won't
+   * be removed though, because another addon could have wrapped the same
+   * function as well. Instead, the 'before' and 'after' functions are
+   * set to `null`.
+   *
+   * @param {Object} aOwnerObject The object which contains (a reference to)
+   *     the function which should be wrapped.
+   * @param {string} aFunctionName The function's name in the object.
+   */
+  unwrapFunction : function(aOwnerObject, aFunctionName) {
+    this.wrapFunction(aOwnerObject, aFunctionName, null, null);
+  }
+}
+
+/**
+ * @param {Object} aOwnerObject The object which contains (a reference to)
+ *     the function which should be wrapped.
+ * @param {string} aFunctionName The function's name in the object.
+ */
+function initWrapperFunction(aOwnerObject, aFunctionName) {
+  // create metadata object
+  if (!aOwnerObject.hasOwnProperty("rpcontinuedWrappedFunctions")) {
+    aOwnerObject.rpcontinuedWrappedFunctions = {};
   }
+
+  var metadata = aOwnerObject.rpcontinuedWrappedFunctions;
+
+  if (metadata.hasOwnProperty(aFunctionName)) {
+    // the function is already wrapped by RequestPolicy
+    return;
+  }
+
+  // create metadata
+  metadata[aFunctionName] = {
+    main: aOwnerObject[aFunctionName], // the original function
+    before: null,
+    after: null
+  };
+
+  // actually wrap the object
+  aOwnerObject[aFunctionName] = function() {
+    var {main, before, after} = metadata[aFunctionName];
+
+    // Execute some action before the original function call.
+    try {
+      if (before) {
+        before.apply(aOwnerObject, arguments);
+      }
+    } catch (e) {
+      Logger.warning(Logger.TYPE_ERROR, "The 'before' function of the " +
+                     "`" + aFunctionName + "()` wrapper has thrown an " +
+                     "error.", e);
+    }
+
+    // Execute original function.
+    var rv = main.apply(aOwnerObject, arguments);
+
+    // Execute some action afterwards.
+    try {
+      if (after) {
+        after.apply(aOwnerObject, arguments);
+      }
+    } catch (e) {
+      Logger.warning(Logger.TYPE_ERROR, "The 'after' function of the " +
+                     "`" + aFunctionName + "()` wrapper has thrown an " +
+                     "error.", e);
+    }
+
+    // return the original result
+    return rv;
+  };
 }

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



More information about the Pkg-mozext-commits mailing list