[Pkg-mozext-commits] [requestpolicy] 45/280: coding style (and indentation) changes

David Prévot taffit at moszumanska.debian.org
Sat May 2 20:29:58 UTC 2015


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

taffit pushed a commit to branch master
in repository requestpolicy.

commit 6a9d539ac9cf6c8893420efe8c346855e2c3b39c
Author: Martin Kimmerle <dev at 256k.de>
Date:   Fri Dec 5 03:48:07 2014 +0100

    coding style (and indentation) changes
    
    in overlay.js, menu.js and classicmenu.js
---
 src/content/ui/classicmenu.js |  178 ++--
 src/content/ui/menu.js        | 1986 ++++++++++++++++++------------------
 src/content/ui/overlay.js     | 2258 ++++++++++++++++++++---------------------
 3 files changed, 2210 insertions(+), 2212 deletions(-)

diff --git a/src/content/ui/classicmenu.js b/src/content/ui/classicmenu.js
index b5ec1b4..012a2c2 100644
--- a/src/content/ui/classicmenu.js
+++ b/src/content/ui/classicmenu.js
@@ -25,6 +25,8 @@
 
 
 requestpolicy.classicmenu = (function() {
+  let self = {};
+
 
   let mod = {};
   Cu.import("chrome://requestpolicy/content/lib/script-loader.jsm");
@@ -35,97 +37,95 @@ requestpolicy.classicmenu = (function() {
   let rpPrefBranch = mod.rpPrefBranch, StringUtils = mod.StringUtils;
 
 
-  let self = {
-    /**
-    * Reloads the current document if the user's preferences indicate it should
-    * be reloaded.
-    */
-    _conditionallyReloadDocument : function() {
-      if (rpPrefBranch.getBoolPref("autoReload")) {
-        content.document.location.reload(false);
-      }
-    },
-
-
-    addMenuSeparator : function(menu) {
-      var separator = document.createElement("menuseparator");
-      menu.insertBefore(separator, menu.firstChild);
-      return separator;
-    },
-
-    addMenuItem : function(menu, label, oncommand) {
-      var menuItem = document.createElement("menuitem");
-      menuItem.setAttribute("label", label);
-      oncommand = oncommand +
-          " requestpolicy.classicmenu._conditionallyReloadDocument();";
-      menuItem.setAttribute("oncommand", oncommand);
-      // menuItem.setAttribute("tooltiptext", node.getAttribute("tooltiptext"));
-      menu.insertBefore(menuItem, menu.firstChild);
-      return menuItem;
-    },
-
-
-    addMenuItemTemporarilyAllowOrigin : function(menu, originHost) {
-      var label = StringUtils.strbundle.formatStringFromName("allowOriginTemporarily",
-          [originHost], 1);
-      var command = "requestpolicy.overlay.temporarilyAllowOrigin('"
-          + requestpolicy.menu._sanitizeJsFunctionArg(originHost) + "');";
-      var item = self.addMenuItem(menu, label, command);
-      item.setAttribute("class", "requestpolicyTemporary");
-      return item;
-    },
-
-    addMenuItemAllowOrigin : function(menu, originHost) {
-      var label = StringUtils.strbundle.formatStringFromName("allowOrigin",
-          [originHost], 1);
-      var command = "requestpolicy.overlay.allowOrigin('"
-          + requestpolicy.menu._sanitizeJsFunctionArg(originHost) + "');";
-      return self.addMenuItem(menu, label, command);
-    },
-
-
-    addMenuItemTemporarilyAllowOriginToDest : function(menu, originHost,
-                                                       destHost) {
-      var label = StringUtils.strbundle.formatStringFromName(
-          "allowOriginToDestinationTemporarily", [originHost, destHost], 2);
-      var command = "requestpolicy.overlay.temporarilyAllowOriginToDestination('"
-          + requestpolicy.menu._sanitizeJsFunctionArg(originHost) + "', '"
-          + requestpolicy.menu._sanitizeJsFunctionArg(destHost) + "');";
-      var item = self.addMenuItem(menu, label, command);
-      item.setAttribute("class", "requestpolicyTemporary");
-      return item;
-    },
-
-    addMenuItemAllowOriginToDest : function(menu, originHost, destHost) {
-      var label = StringUtils.strbundle.formatStringFromName(
-          "allowOriginToDestination", [originHost, destHost], 2);
-      var command = "requestpolicy.overlay.allowOriginToDestination('"
-          + requestpolicy.menu._sanitizeJsFunctionArg(originHost) + "', '"
-          + requestpolicy.menu._sanitizeJsFunctionArg(destHost) + "');";
-      var item = self.addMenuItem(menu, label, command);
-      item.setAttribute("class", "requestpolicyAllowOriginToDest");
-      return item;
-    },
-
-
-    addMenuItemTemporarilyAllowDest : function(menu, destHost) {
-      var label = StringUtils.strbundle.formatStringFromName(
-          "allowDestinationTemporarily", [destHost], 1);
-      var command = "requestpolicy.overlay.temporarilyAllowDestination('"
-          + requestpolicy.menu._sanitizeJsFunctionArg(destHost) + "');";
-      var item = self.addMenuItem(menu, label, command);
-      item.setAttribute("class", "requestpolicyTemporary");
-      return item;
-    },
-
-    addMenuItemAllowDest : function(menu, destHost) {
-      var label = StringUtils.strbundle.formatStringFromName("allowDestination",
-          [destHost], 1);
-      var command = "requestpolicy.overlay.allowDestination('"
-          + requestpolicy.menu._sanitizeJsFunctionArg(destHost) + "');";
-      return self.addMenuItem(menu, label, command);
+  /**
+  * Reloads the current document if the user's preferences indicate it should
+  * be reloaded.
+  */
+  self._conditionallyReloadDocument = function() {
+    if (rpPrefBranch.getBoolPref("autoReload")) {
+      content.document.location.reload(false);
     }
   };
 
+
+  self.addMenuSeparator = function(menu) {
+    var separator = document.createElement("menuseparator");
+    menu.insertBefore(separator, menu.firstChild);
+    return separator;
+  };
+
+  self.addMenuItem = function(menu, label, oncommand) {
+    var menuItem = document.createElement("menuitem");
+    menuItem.setAttribute("label", label);
+    oncommand = oncommand +
+        " requestpolicy.classicmenu._conditionallyReloadDocument();";
+    menuItem.setAttribute("oncommand", oncommand);
+    // menuItem.setAttribute("tooltiptext", node.getAttribute("tooltiptext"));
+    menu.insertBefore(menuItem, menu.firstChild);
+    return menuItem;
+  };
+
+
+  self.addMenuItemTemporarilyAllowOrigin = function(menu, originHost) {
+    var label = StringUtils.strbundle.formatStringFromName("allowOriginTemporarily",
+        [originHost], 1);
+    var command = "requestpolicy.overlay.temporarilyAllowOrigin('"
+        + requestpolicy.menu._sanitizeJsFunctionArg(originHost) + "');";
+    var item = self.addMenuItem(menu, label, command);
+    item.setAttribute("class", "requestpolicyTemporary");
+    return item;
+  };
+
+  self.addMenuItemAllowOrigin = function(menu, originHost) {
+    var label = StringUtils.strbundle.formatStringFromName("allowOrigin",
+        [originHost], 1);
+    var command = "requestpolicy.overlay.allowOrigin('"
+        + requestpolicy.menu._sanitizeJsFunctionArg(originHost) + "');";
+    return self.addMenuItem(menu, label, command);
+  };
+
+
+  self.addMenuItemTemporarilyAllowOriginToDest = function(menu, originHost,
+                                                     destHost) {
+    var label = StringUtils.strbundle.formatStringFromName(
+        "allowOriginToDestinationTemporarily", [originHost, destHost], 2);
+    var command = "requestpolicy.overlay.temporarilyAllowOriginToDestination('"
+        + requestpolicy.menu._sanitizeJsFunctionArg(originHost) + "', '"
+        + requestpolicy.menu._sanitizeJsFunctionArg(destHost) + "');";
+    var item = self.addMenuItem(menu, label, command);
+    item.setAttribute("class", "requestpolicyTemporary");
+    return item;
+  };
+
+  self.addMenuItemAllowOriginToDest = function(menu, originHost, destHost) {
+    var label = StringUtils.strbundle.formatStringFromName(
+        "allowOriginToDestination", [originHost, destHost], 2);
+    var command = "requestpolicy.overlay.allowOriginToDestination('"
+        + requestpolicy.menu._sanitizeJsFunctionArg(originHost) + "', '"
+        + requestpolicy.menu._sanitizeJsFunctionArg(destHost) + "');";
+    var item = self.addMenuItem(menu, label, command);
+    item.setAttribute("class", "requestpolicyAllowOriginToDest");
+    return item;
+  };
+
+
+  self.addMenuItemTemporarilyAllowDest = function(menu, destHost) {
+    var label = StringUtils.strbundle.formatStringFromName(
+        "allowDestinationTemporarily", [destHost], 1);
+    var command = "requestpolicy.overlay.temporarilyAllowDestination('"
+        + requestpolicy.menu._sanitizeJsFunctionArg(destHost) + "');";
+    var item = self.addMenuItem(menu, label, command);
+    item.setAttribute("class", "requestpolicyTemporary");
+    return item;
+  };
+
+  self.addMenuItemAllowDest = function(menu, destHost) {
+    var label = StringUtils.strbundle.formatStringFromName("allowDestination",
+        [destHost], 1);
+    var command = "requestpolicy.overlay.allowDestination('"
+        + requestpolicy.menu._sanitizeJsFunctionArg(destHost) + "');";
+    return self.addMenuItem(menu, label, command);
+  };
+
   return self;
 }());
diff --git a/src/content/ui/menu.js b/src/content/ui/menu.js
index ab5baa6..8c1e846 100644
--- a/src/content/ui/menu.js
+++ b/src/content/ui/menu.js
@@ -62,8 +62,6 @@ requestpolicy.menu = (function() {
 
 
   let self = {
-    // public attributes and methods
-
     addedMenuItems : [],
     _menu : null,
 
@@ -81,1145 +79,1145 @@ requestpolicy.menu = (function() {
     _isCurrentlySelectedDestBlocked : null,
     _isCurrentlySelectedDestAllowed : null,
 
-    _ruleChangeQueues : {},
+    _ruleChangeQueues : {}
+  };
 
-    init: function() {
-      if (initialized === false) {
-        initialized = true;
+  self.init = function() {
+    if (initialized === false) {
+      initialized = true;
 
-        self._menu = document.getElementById("rp-popup");
+      self._menu = document.getElementById("rp-popup");
 
-        self._originItem = document.getElementById("rp-origin");
-        self._originDomainnameItem = document.getElementById('rp-origin-domainname');
-        self._originNumRequestsItem = document.getElementById('rp-origin-num-requests');
+      self._originItem = document.getElementById("rp-origin");
+      self._originDomainnameItem = document.getElementById('rp-origin-domainname');
+      self._originNumRequestsItem = document.getElementById('rp-origin-num-requests');
 
-        self._otherOriginsList = document.getElementById("rp-other-origins-list");
-        self._blockedDestinationsList = document
-              .getElementById("rp-blocked-destinations-list");
-        self._mixedDestinationsList = document
-              .getElementById("rp-mixed-destinations-list");
-        self._allowedDestinationsList = document
-              .getElementById("rp-allowed-destinations-list");
-        self._addRulesList = document.getElementById("rp-rules-add");
-        self._removeRulesList = document.getElementById("rp-rules-remove");
+      self._otherOriginsList = document.getElementById("rp-other-origins-list");
+      self._blockedDestinationsList = document
+            .getElementById("rp-blocked-destinations-list");
+      self._mixedDestinationsList = document
+            .getElementById("rp-mixed-destinations-list");
+      self._allowedDestinationsList = document
+            .getElementById("rp-allowed-destinations-list");
+      self._addRulesList = document.getElementById("rp-rules-add");
+      self._removeRulesList = document.getElementById("rp-rules-remove");
 
-        var conflictCount = rpService.getConflictingExtensions().length;
-        var hideConflictInfo = (conflictCount == 0);
-      }
-    },
+      var conflictCount = rpService.getConflictingExtensions().length;
+      var hideConflictInfo = (conflictCount == 0);
+    }
+  };
 
-    prepareMenu: function() {
-      try {
-        var disabled = Prefs.isBlockingDisabled();
-        document.getElementById('rp-link-enable-blocking').hidden = !disabled;
-        document.getElementById('rp-link-disable-blocking').hidden = disabled;
-
-        document.getElementById('rp-revoke-temporary-permissions').hidden =
-            !PolicyManager.temporaryRulesExist();
-
-        self._currentUri = requestpolicy.overlay.getTopLevelDocumentUri();
-
-        try {
-          self._currentBaseDomain = DomainUtil.getBaseDomain(self._currentUri);
-        } catch (e) {
-          Logger.info(Logger.TYPE_INTERNAL, "Unable to prepare menu because " +
-              "base domain can't be determined: " + self._currentUri);
-          self._populateMenuForUncontrollableOrigin();
-          return;
-        }
+  self.prepareMenu = function() {
+    try {
+      var disabled = Prefs.isBlockingDisabled();
+      document.getElementById('rp-link-enable-blocking').hidden = !disabled;
+      document.getElementById('rp-link-disable-blocking').hidden = disabled;
 
-        self._currentIdentifier = requestpolicy.overlay
-            .getTopLevelDocumentUriIdentifier();
+      document.getElementById('rp-revoke-temporary-permissions').hidden =
+          !PolicyManager.temporaryRulesExist();
 
-        //Logger.info(Logger.TYPE_POLICY,
-        //                              "self._currentUri: " + self._currentUri);
-        self._currentUriObj = DomainUtil.getUriObject(self._currentUri);
+      self._currentUri = requestpolicy.overlay.getTopLevelDocumentUri();
 
-        self._isChromeUri = self._currentUriObj.scheme == "chrome";
-        //self._currentUriIsHttps = self._currentUriObj.scheme == "https";
+      try {
+        self._currentBaseDomain = DomainUtil.getBaseDomain(self._currentUri);
+      } catch (e) {
+        Logger.info(Logger.TYPE_INTERNAL, "Unable to prepare menu because " +
+            "base domain can't be determined: " + self._currentUri);
+        self._populateMenuForUncontrollableOrigin();
+        return;
+      }
 
-        Logger.info(Logger.TYPE_INTERNAL,
-            "self._currentUri: " + self._currentUri);
+      self._currentIdentifier = requestpolicy.overlay
+          .getTopLevelDocumentUriIdentifier();
 
-        if (self._isChromeUri) {
-          self._populateMenuForUncontrollableOrigin();
-          return;
-        }
+      //Logger.info(Logger.TYPE_POLICY,
+      //                              "self._currentUri: " + self._currentUri);
+      self._currentUriObj = DomainUtil.getUriObject(self._currentUri);
 
-        // The fact that getAllRequestsInBrowser uses currentURI.spec directly
-        // from the browser is important because getTopLevelDocumentUri will
-        // not return the real URI if there is an applicable
-        // top-level document translation rule (these are used sometimes
-        // for extension compatibility). For example, this is essential to the
-        // menu showing relevant info when using the Update Scanner extension.
-        self._allRequestsOnDocument = RequestProcessor
-              .getAllRequestsInBrowser(gBrowser.selectedBrowser);
-        self._allRequestsOnDocument.print("_allRequestsOnDocument");
-
-        self._privateBrowsingEnabled = rpService.isPrivateBrowsingEnabled()
-            && !rpPrefBranch.getBoolPref("privateBrowsingPermanentWhitelisting");
-
-        self._setPrivateBrowsingStyles();
-
-    //      var hidePrefetchInfo = !Prefs.isPrefetchEnabled();
-    //      self._itemPrefetchWarning.hidden = hidePrefetchInfo;
-    //      self._itemPrefetchWarningSeparator.hidden = hidePrefetchInfo;
-    //
-    //      if (isChromeUri) {
-    //        self._itemUnrestrictedOrigin.setAttribute("label",
-    //            StringUtils.strbundle.formatStringFromName(
-    //                "unrestrictedOrigin", ["chrome://"]), 1);
-    //        self._itemUnrestrictedOrigin.hidden = false;
-    //        return;
-    //      }
-
-        self._populateOrigin();
-        self._populateOtherOrigins();
-        self._activateOriginItem(self._originItem);
+      self._isChromeUri = self._currentUriObj.scheme == "chrome";
+      //self._currentUriIsHttps = self._currentUriObj.scheme == "https";
 
-      } catch (e) {
-        Logger.severe(Logger.TYPE_ERROR,
-            "Fatal Error, " + e + ", stack was: " + e.stack);
-        Logger.severe(Logger.TYPE_ERROR, "Unable to prepare menu due to error.");
-        throw e;
+      Logger.info(Logger.TYPE_INTERNAL,
+          "self._currentUri: " + self._currentUri);
+
+      if (self._isChromeUri) {
+        self._populateMenuForUncontrollableOrigin();
+        return;
       }
-    },
-
-    _populateMenuForUncontrollableOrigin: function() {
-      self._originDomainnameItem.setAttribute('value',
-          StringUtils.strbundle.GetStringFromName('noOrigin'));
-      self._originNumRequestsItem.setAttribute('value', '');
-      self._originItem.removeAttribute("default-policy");
-      self._originItem.removeAttribute("requests-blocked");
-
-      self._removeChildren(self._otherOriginsList);
-      self._removeChildren(self._blockedDestinationsList);
-      self._removeChildren(self._mixedDestinationsList);
-      self._removeChildren(self._allowedDestinationsList);
-      self._removeChildren(self._removeRulesList);
-      self._removeChildren(self._addRulesList);
-      document.getElementById('rp-other-origins').hidden = true;
-      document.getElementById('rp-blocked-destinations').hidden = true;
-      document.getElementById('rp-mixed-destinations').hidden = true;
-      document.getElementById('rp-allowed-destinations').hidden = true;
-      // TODO: show some message about why the menu is empty.
-    },
-
-    _populateList: function(list, values) {
-      self._removeChildren(list);
-
-      // check whether there are objects of GUILocation or just strings
-      var guiLocations = values[0] && (values[0] instanceof GUILocation);
-
-      if (true === guiLocations) {
-        // get prefs
-        var sorting = rpPrefBranch.getCharPref('menu.sorting');
-        var showNumRequests = rpPrefBranch.getBoolPref('menu.info.showNumRequests');
-
-        if (sorting == "numRequests") {
-          values.sort(GUILocation.sortByNumRequestsCompareFunction);
-        } else if (sorting == "destName") {
-          values.sort(GUILocation.compareFunction);
-        }
 
-        for (var i in values) {
-          var guiLocation = values[i];
-          var props = guiLocation.properties;
+      // The fact that getAllRequestsInBrowser uses currentURI.spec directly
+      // from the browser is important because getTopLevelDocumentUri will
+      // not return the real URI if there is an applicable
+      // top-level document translation rule (these are used sometimes
+      // for extension compatibility). For example, this is essential to the
+      // menu showing relevant info when using the Update Scanner extension.
+      self._allRequestsOnDocument = RequestProcessor
+            .getAllRequestsInBrowser(gBrowser.selectedBrowser);
+      self._allRequestsOnDocument.print("_allRequestsOnDocument");
+
+      self._privateBrowsingEnabled = rpService.isPrivateBrowsingEnabled()
+          && !rpPrefBranch.getBoolPref("privateBrowsingPermanentWhitelisting");
+
+      self._setPrivateBrowsingStyles();
+
+  //      var hidePrefetchInfo = !Prefs.isPrefetchEnabled();
+  //      self._itemPrefetchWarning.hidden = hidePrefetchInfo;
+  //      self._itemPrefetchWarningSeparator.hidden = hidePrefetchInfo;
+  //
+  //      if (isChromeUri) {
+  //        self._itemUnrestrictedOrigin.setAttribute("label",
+  //            StringUtils.strbundle.formatStringFromName(
+  //                "unrestrictedOrigin", ["chrome://"]), 1);
+  //        self._itemUnrestrictedOrigin.hidden = false;
+  //        return;
+  //      }
+
+      self._populateOrigin();
+      self._populateOtherOrigins();
+      self._activateOriginItem(self._originItem);
+
+    } catch (e) {
+      Logger.severe(Logger.TYPE_ERROR,
+          "Fatal Error, " + e + ", stack was: " + e.stack);
+      Logger.severe(Logger.TYPE_ERROR, "Unable to prepare menu due to error.");
+      throw e;
+    }
+  };
+
+  self._populateMenuForUncontrollableOrigin = function() {
+    self._originDomainnameItem.setAttribute('value',
+        StringUtils.strbundle.GetStringFromName('noOrigin'));
+    self._originNumRequestsItem.setAttribute('value', '');
+    self._originItem.removeAttribute("default-policy");
+    self._originItem.removeAttribute("requests-blocked");
+
+    self._removeChildren(self._otherOriginsList);
+    self._removeChildren(self._blockedDestinationsList);
+    self._removeChildren(self._mixedDestinationsList);
+    self._removeChildren(self._allowedDestinationsList);
+    self._removeChildren(self._removeRulesList);
+    self._removeChildren(self._addRulesList);
+    document.getElementById('rp-other-origins').hidden = true;
+    document.getElementById('rp-blocked-destinations').hidden = true;
+    document.getElementById('rp-mixed-destinations').hidden = true;
+    document.getElementById('rp-allowed-destinations').hidden = true;
+    // TODO: show some message about why the menu is empty.
+  };
+
+  self._populateList = function(list, values) {
+    self._removeChildren(list);
+
+    // check whether there are objects of GUILocation or just strings
+    var guiLocations = values[0] && (values[0] instanceof GUILocation);
+
+    if (true === guiLocations) {
+      // get prefs
+      var sorting = rpPrefBranch.getCharPref('menu.sorting');
+      var showNumRequests = rpPrefBranch.getBoolPref('menu.info.showNumRequests');
+
+      if (sorting == "numRequests") {
+        values.sort(GUILocation.sortByNumRequestsCompareFunction);
+      } else if (sorting == "destName") {
+        values.sort(GUILocation.compareFunction);
+      }
 
-          var num = undefined;
-          if (true === showNumRequests) {
-            num = props.numRequests;
-            if (props.numAllowedRequests > 0 && props.numBlockedRequests > 0) {
-              num += " (" + props.numBlockedRequests +
-                  "+" + props.numAllowedRequests + ")";
-            }
-          }
-          var newitem = self._addListItem(list, 'rp-od-item', guiLocation, num);
+      for (var i in values) {
+        var guiLocation = values[i];
+        var props = guiLocation.properties;
 
-          newitem.setAttribute("default-policy",
-              (props.numDefaultPolicyRequests > 0 ? "true" : "false"));
-          newitem.setAttribute("requests-blocked",
-              (props.numBlockedRequests > 0 ? "true" : "false"));
-        }
-      } else {
-        values.sort();
-        for (var i in values) {
-          self._addListItem(list, 'rp-od-item', values[i]);
+        var num = undefined;
+        if (true === showNumRequests) {
+          num = props.numRequests;
+          if (props.numAllowedRequests > 0 && props.numBlockedRequests > 0) {
+            num += " (" + props.numBlockedRequests +
+                "+" + props.numAllowedRequests + ")";
+          }
         }
+        var newitem = self._addListItem(list, 'rp-od-item', guiLocation, num);
+
+        newitem.setAttribute("default-policy",
+            (props.numDefaultPolicyRequests > 0 ? "true" : "false"));
+        newitem.setAttribute("requests-blocked",
+            (props.numBlockedRequests > 0 ? "true" : "false"));
       }
-    },
+    } else {
+      values.sort();
+      for (var i in values) {
+        self._addListItem(list, 'rp-od-item', values[i]);
+      }
+    }
+  };
 
-    _populateOrigin: function() {
-      self._originDomainnameItem.setAttribute("value", self._currentBaseDomain);
+  self._populateOrigin = function() {
+    self._originDomainnameItem.setAttribute("value", self._currentBaseDomain);
 
-      var showNumRequests = rpPrefBranch
-          .getBoolPref('menu.info.showNumRequests');
+    var showNumRequests = rpPrefBranch
+        .getBoolPref('menu.info.showNumRequests');
 
-      var props = self._getOriginGUILocationProperties();
+    var props = self._getOriginGUILocationProperties();
 
-      var numRequests = '';
-      if (true === showNumRequests) {
-        if (props.numAllowedRequests > 0 && props.numBlockedRequests > 0) {
-          numRequests = props.numRequests + " (" +
-              props.numBlockedRequests + "+" + props.numAllowedRequests + ")";
-        } else {
-          numRequests = props.numRequests;
-        }
+    var numRequests = '';
+    if (true === showNumRequests) {
+      if (props.numAllowedRequests > 0 && props.numBlockedRequests > 0) {
+        numRequests = props.numRequests + " (" +
+            props.numBlockedRequests + "+" + props.numAllowedRequests + ")";
+      } else {
+        numRequests = props.numRequests;
       }
-      self._originNumRequestsItem.setAttribute("value", numRequests);
-
-      self._originItem.setAttribute("default-policy",
-          (props.numDefaultPolicyRequests > 0 ? "true" : "false"));
-      self._originItem.setAttribute("requests-blocked",
-          (props.numBlockedRequests > 0 ? "true" : "false"));
-    },
-
-    _populateOtherOrigins: function() {
-      var guiOrigins = self._getOtherOriginsAsGUILocations();
-      self._populateList(self._otherOriginsList, guiOrigins);
-      document.getElementById('rp-other-origins').hidden = guiOrigins.length == 0;
-    },
-
-    _populateDestinations: function(originIdentifier) {
-      var destsWithBlockedRequests = self._getBlockedDestinationsAsGUILocations();
-      var destsWithAllowedRequests = self._getAllowedDestinationsAsGUILocations();
-
-      var destsWithSolelyBlockedRequests = [];
-      var destsMixed = [];
-      var destsWithSolelyAllowedRequests = [];
-
-      // Set operations would be nice. These are small arrays, so keep it simple.
-      for (var i = 0; i < destsWithBlockedRequests.length; i++) {
-        let blockedGUIDest = destsWithBlockedRequests[i];
-
-        if (false === GUILocation.existsInArray(blockedGUIDest,
-            destsWithAllowedRequests)) {
-          destsWithSolelyBlockedRequests.push(blockedGUIDest);
-        } else {
-          destsMixed.push(blockedGUIDest);
-        }
+    }
+    self._originNumRequestsItem.setAttribute("value", numRequests);
+
+    self._originItem.setAttribute("default-policy",
+        (props.numDefaultPolicyRequests > 0 ? "true" : "false"));
+    self._originItem.setAttribute("requests-blocked",
+        (props.numBlockedRequests > 0 ? "true" : "false"));
+  };
+
+  self._populateOtherOrigins = function() {
+    var guiOrigins = self._getOtherOriginsAsGUILocations();
+    self._populateList(self._otherOriginsList, guiOrigins);
+    document.getElementById('rp-other-origins').hidden = guiOrigins.length == 0;
+  };
+
+  self._populateDestinations = function(originIdentifier) {
+    var destsWithBlockedRequests = self._getBlockedDestinationsAsGUILocations();
+    var destsWithAllowedRequests = self._getAllowedDestinationsAsGUILocations();
+
+    var destsWithSolelyBlockedRequests = [];
+    var destsMixed = [];
+    var destsWithSolelyAllowedRequests = [];
+
+    // Set operations would be nice. These are small arrays, so keep it simple.
+    for (var i = 0; i < destsWithBlockedRequests.length; i++) {
+      let blockedGUIDest = destsWithBlockedRequests[i];
+
+      if (false === GUILocation.existsInArray(blockedGUIDest,
+          destsWithAllowedRequests)) {
+        destsWithSolelyBlockedRequests.push(blockedGUIDest);
+      } else {
+        destsMixed.push(blockedGUIDest);
       }
-      for (var i = 0; i < destsWithAllowedRequests.length; i++) {
-        let allowedGUIDest = destsWithAllowedRequests[i];
+    }
+    for (var i = 0; i < destsWithAllowedRequests.length; i++) {
+      let allowedGUIDest = destsWithAllowedRequests[i];
 
-        var indexRawBlocked = GUIDestination.
-            indexOfDestInArray(allowedGUIDest, destsWithBlockedRequests);
-        var destsMixedIndex = GUIDestination.
-            indexOfDestInArray(allowedGUIDest, destsMixed);
+      var indexRawBlocked = GUIDestination.
+          indexOfDestInArray(allowedGUIDest, destsWithBlockedRequests);
+      var destsMixedIndex = GUIDestination.
+          indexOfDestInArray(allowedGUIDest, destsMixed);
 
-        if (indexRawBlocked == -1) {
-          destsWithSolelyAllowedRequests.push(allowedGUIDest);
+      if (indexRawBlocked == -1) {
+        destsWithSolelyAllowedRequests.push(allowedGUIDest);
+      } else {
+        if (destsMixedIndex != -1) {
+          Logger.info(Logger.TYPE_INTERNAL,
+              "Merging dest: <" + allowedGUIDest + ">");
+          destsMixed[destsMixedIndex] = GUIDestination.merge(
+              allowedGUIDest, destsMixed[destsMixedIndex]);
         } else {
-          if (destsMixedIndex != -1) {
-            Logger.info(Logger.TYPE_INTERNAL,
-                "Merging dest: <" + allowedGUIDest + ">");
-            destsMixed[destsMixedIndex] = GUIDestination.merge(
-                allowedGUIDest, destsMixed[destsMixedIndex]);
-          } else {
-            // If the allowedGUIDest is in destsWithBlockedRequests and
-            // destsWithAllowedRequests, but not in destsMixed.
-            // This should never happen, the destsMixed destination should have
-            // been added in the destsWithBlockedRequests-loop.
-            Logger.warning(Logger.TYPE_INTERNAL, "mixed dest was" +
-                " not added to `destsMixed` list: <" + dest.dest + ">");
-            destsMixed.push(allowedGUIDest);
-          }
+          // If the allowedGUIDest is in destsWithBlockedRequests and
+          // destsWithAllowedRequests, but not in destsMixed.
+          // This should never happen, the destsMixed destination should have
+          // been added in the destsWithBlockedRequests-loop.
+          Logger.warning(Logger.TYPE_INTERNAL, "mixed dest was" +
+              " not added to `destsMixed` list: <" + dest.dest + ">");
+          destsMixed.push(allowedGUIDest);
         }
       }
+    }
 
-      self._populateList(self._blockedDestinationsList,
-          destsWithSolelyBlockedRequests);
-      document.getElementById('rp-blocked-destinations').hidden =
-          destsWithSolelyBlockedRequests.length == 0;
-
-      self._populateList(self._mixedDestinationsList, destsMixed);
-      document.getElementById('rp-mixed-destinations').hidden =
-          destsMixed.length == 0;
-
-      self._populateList(self._allowedDestinationsList,
-          destsWithSolelyAllowedRequests);
-      document.getElementById('rp-allowed-destinations').hidden =
-          destsWithSolelyAllowedRequests.length == 0;
-    },
-
-    _populateDetails: function() {
-      var origin = self._currentlySelectedOrigin;
-      var dest = self._currentlySelectedDest;
-      self._removeChildren(self._removeRulesList);
-      self._removeChildren(self._addRulesList);
+    self._populateList(self._blockedDestinationsList,
+        destsWithSolelyBlockedRequests);
+    document.getElementById('rp-blocked-destinations').hidden =
+        destsWithSolelyBlockedRequests.length == 0;
+
+    self._populateList(self._mixedDestinationsList, destsMixed);
+    document.getElementById('rp-mixed-destinations').hidden =
+        destsMixed.length == 0;
+
+    self._populateList(self._allowedDestinationsList,
+        destsWithSolelyAllowedRequests);
+    document.getElementById('rp-allowed-destinations').hidden =
+        destsWithSolelyAllowedRequests.length == 0;
+  };
+
+  self._populateDetails = function() {
+    var origin = self._currentlySelectedOrigin;
+    var dest = self._currentlySelectedDest;
+    self._removeChildren(self._removeRulesList);
+    self._removeChildren(self._addRulesList);
+
+    var ruleData = {
+      'o' : {
+        'h' : self._addWildcard(origin)
+      }
+    };
+
+    // Note: in PBR we'll need to still use the old string for the temporary
+    // rule. We won't be able to use just "allow temporarily".
+
+    if (!self._currentlySelectedDest) {
+      if (Prefs.isDefaultAllow()) {
+        // It seems pretty rare that someone will want to add a rule to block all
+        // requests from a given origin.
+        //if (!self._privateBrowsingEnabled) {
+        //  var item = self._addMenuItemDenyOrigin(
+        //    self._addRulesList, ruleData);
+        //}
+        //var item = self._addMenuItemTempDenyOrigin(self._addRulesList, ruleData);
+      } else {
+        if (!self._privateBrowsingEnabled) {
+          var item = self._addMenuItemAllowOrigin(self._addRulesList, ruleData);
+        }
+        var item = self._addMenuItemTempAllowOrigin(self._addRulesList, ruleData);
+      }
+    }
 
-      var ruleData = {
-        'o' : {
-          'h' : self._addWildcard(origin)
+    if (dest) {
+      ruleData['d'] = {
+        'h' : self._addWildcard(dest)
+      };
+      var destOnlyRuleData = {
+        'd' : {
+          'h' : self._addWildcard(dest)
         }
       };
-
-      // Note: in PBR we'll need to still use the old string for the temporary
-      // rule. We won't be able to use just "allow temporarily".
-
-      if (!self._currentlySelectedDest) {
-        if (Prefs.isDefaultAllow()) {
-          // It seems pretty rare that someone will want to add a rule to block all
-          // requests from a given origin.
-          //if (!self._privateBrowsingEnabled) {
-          //  var item = self._addMenuItemDenyOrigin(
-          //    self._addRulesList, ruleData);
-          //}
-          //var item = self._addMenuItemTempDenyOrigin(self._addRulesList, ruleData);
-        } else {
+      //if (Prefs.isDefaultAllow()) {
+      if (self._isCurrentlySelectedDestAllowed ||
+           (!PolicyManager.ruleExists(mod.RULE_ACTION_DENY, ruleData) &&
+            !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, destOnlyRuleData))) {
+        // show "Block requests" if the destination was allowed
+        // OR if there's no blocking rule (i.e. the request was blocked "by default")
+        //  -- this enables support for blacklisting.
+        if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, ruleData) &&
+            !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, ruleData)) {
           if (!self._privateBrowsingEnabled) {
-            var item = self._addMenuItemAllowOrigin(self._addRulesList, ruleData);
+              var item = self._addMenuItemDenyOriginToDest(
+                  self._addRulesList, ruleData);
           }
-          var item = self._addMenuItemTempAllowOrigin(self._addRulesList, ruleData);
+          var item = self._addMenuItemTempDenyOriginToDest(
+            self._addRulesList, ruleData);
         }
-      }
 
-      if (dest) {
-        ruleData['d'] = {
-          'h' : self._addWildcard(dest)
-        };
-        var destOnlyRuleData = {
-          'd' : {
-            'h' : self._addWildcard(dest)
-          }
-        };
-        //if (Prefs.isDefaultAllow()) {
-        if (self._isCurrentlySelectedDestAllowed ||
-             (!PolicyManager.ruleExists(mod.RULE_ACTION_DENY, ruleData) &&
-              !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, destOnlyRuleData))) {
-          // show "Block requests" if the destination was allowed
-          // OR if there's no blocking rule (i.e. the request was blocked "by default")
-          //  -- this enables support for blacklisting.
-          if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, ruleData) &&
-              !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, ruleData)) {
-            if (!self._privateBrowsingEnabled) {
-                var item = self._addMenuItemDenyOriginToDest(
-                    self._addRulesList, ruleData);
-            }
-            var item = self._addMenuItemTempDenyOriginToDest(
-              self._addRulesList, ruleData);
-          }
-
-          if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, destOnlyRuleData) &&
-              !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, destOnlyRuleData)) {
-            if (!self._privateBrowsingEnabled) {
-              var item = self._addMenuItemDenyDest(
-                  self._addRulesList, destOnlyRuleData);
-            }
-            var item = self._addMenuItemTempDenyDest(
+        if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, destOnlyRuleData) &&
+            !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, destOnlyRuleData)) {
+          if (!self._privateBrowsingEnabled) {
+            var item = self._addMenuItemDenyDest(
                 self._addRulesList, destOnlyRuleData);
           }
+          var item = self._addMenuItemTempDenyDest(
+              self._addRulesList, destOnlyRuleData);
         }
-        if (self._isCurrentlySelectedDestBlocked ||
-             (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, ruleData) &&
-              !PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, destOnlyRuleData))) {
-          // show "Allow requests" if the destination was blocked
-          // OR if there's no allow-rule (i.e. the request was allowed "by default")
-          //  -- this enables support for whitelisting.
-          if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, ruleData) &&
-              !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, ruleData)) {
-            if (!self._privateBrowsingEnabled) {
-              var item = self._addMenuItemAllowOriginToDest(
-                  self._addRulesList, ruleData);
-            }
-            var item = self._addMenuItemTempAllowOriginToDest(
+      }
+      if (self._isCurrentlySelectedDestBlocked ||
+           (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, ruleData) &&
+            !PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, destOnlyRuleData))) {
+        // show "Allow requests" if the destination was blocked
+        // OR if there's no allow-rule (i.e. the request was allowed "by default")
+        //  -- this enables support for whitelisting.
+        if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, ruleData) &&
+            !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, ruleData)) {
+          if (!self._privateBrowsingEnabled) {
+            var item = self._addMenuItemAllowOriginToDest(
                 self._addRulesList, ruleData);
           }
+          var item = self._addMenuItemTempAllowOriginToDest(
+              self._addRulesList, ruleData);
+        }
 
-          if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, destOnlyRuleData) &&
-              !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, destOnlyRuleData)) {
-            if (!self._privateBrowsingEnabled) {
-              var item = self._addMenuItemAllowDest(
-                  self._addRulesList, destOnlyRuleData);
-            }
-            var item = self._addMenuItemTempAllowDest(
+        if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, destOnlyRuleData) &&
+            !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, destOnlyRuleData)) {
+          if (!self._privateBrowsingEnabled) {
+            var item = self._addMenuItemAllowDest(
                 self._addRulesList, destOnlyRuleData);
           }
+          var item = self._addMenuItemTempAllowDest(
+              self._addRulesList, destOnlyRuleData);
         }
       }
+    }
 
-      if (self._currentlySelectedDest) {
-        if (!Prefs.isDefaultAllow() &&
-            !Prefs.isDefaultAllowSameDomain()) {
-          self._populateDetailsAddSubdomainAllowRules(self._addRulesList);
-        }
+    if (self._currentlySelectedDest) {
+      if (!Prefs.isDefaultAllow() &&
+          !Prefs.isDefaultAllowSameDomain()) {
+        self._populateDetailsAddSubdomainAllowRules(self._addRulesList);
       }
+    }
 
-      self._populateDetailsRemoveAllowRules(self._removeRulesList);
-      self._populateDetailsRemoveDenyRules(self._removeRulesList);
-    },
-
-    _removeChildren: function(el) {
-      while (el.firstChild) {
-        el.removeChild(el.firstChild);
-      }
-    },
-
-    _addListItem: function(list, cssClass, value, numRequests) {
-      var hbox = document.createElement("hbox");
-      hbox.setAttribute("class", cssClass);
-      hbox.setAttribute("onclick", 'requestpolicy.menu.itemSelected(event);');
-      list.insertBefore(hbox, null);
-
-      var destLabel = document.createElement("label");
-      destLabel.setAttribute("value", value);
-      destLabel.setAttribute("class", "domainname");
-      destLabel.setAttribute("flex", "2");
-      hbox.insertBefore(destLabel, null);
-
-      if (numRequests) {
-        var numReqLabel = document.createElement("label");
-        numReqLabel.setAttribute("value", numRequests);
-        numReqLabel.setAttribute("class", "numRequests");
-        hbox.insertBefore(numReqLabel, null);
-      }
+    self._populateDetailsRemoveAllowRules(self._removeRulesList);
+    self._populateDetailsRemoveDenyRules(self._removeRulesList);
+  };
 
-      return hbox;
-    },
+  self._removeChildren = function(el) {
+    while (el.firstChild) {
+      el.removeChild(el.firstChild);
+    }
+  };
+
+  self._addListItem = function(list, cssClass, value, numRequests) {
+    var hbox = document.createElement("hbox");
+    hbox.setAttribute("class", cssClass);
+    hbox.setAttribute("onclick", 'requestpolicy.menu.itemSelected(event);');
+    list.insertBefore(hbox, null);
+
+    var destLabel = document.createElement("label");
+    destLabel.setAttribute("value", value);
+    destLabel.setAttribute("class", "domainname");
+    destLabel.setAttribute("flex", "2");
+    hbox.insertBefore(destLabel, null);
+
+    if (numRequests) {
+      var numReqLabel = document.createElement("label");
+      numReqLabel.setAttribute("value", numRequests);
+      numReqLabel.setAttribute("class", "numRequests");
+      hbox.insertBefore(numReqLabel, null);
+    }
 
-    _disableIfNoChildren: function(el) {
-      // TODO: this isn't working.
-      el.hidden = el.firstChild ? false : true;
-    },
+    return hbox;
+  };
 
-    _setPrivateBrowsingStyles: function() {
-      document.getElementById('rp-details').setAttribute(
-        'class', self._privateBrowsingEnabled ? 'privatebrowsing' : '');
-    },
+  self._disableIfNoChildren = function(el) {
+    // TODO: this isn't working.
+    el.hidden = el.firstChild ? false : true;
+  };
 
-    _resetSelectedOrigin: function() {
-      self._originItem.setAttribute('selected-origin', 'false');
-      for (var i = 0; i < self._otherOriginsList.childNodes.length; i++) {
-        var child = self._otherOriginsList.childNodes[i];
-        child.setAttribute('selected-origin', 'false');
-      }
-    },
-
-    _resetSelectedDest: function() {
-      for (var i = 0; i < self._blockedDestinationsList.childNodes.length; i++) {
-        var child = self._blockedDestinationsList.childNodes[i];
-        child.setAttribute('selected-dest', 'false');
-      }
-      for (var i = 0; i < self._mixedDestinationsList.childNodes.length; i++) {
-        var child = self._mixedDestinationsList.childNodes[i];
-        child.setAttribute('selected-dest', 'false');
-      }
-      for (var i = 0; i < self._allowedDestinationsList.childNodes.length; i++) {
-        var child = self._allowedDestinationsList.childNodes[i];
-        child.setAttribute('selected-dest', 'false');
-      }
-    },
-
-    _activateOriginItem: function(item) {
-      if (item.id == 'rp-origin') {
-        // it's _the_ origin
-        self._currentlySelectedOrigin = self._originDomainnameItem.value;
-      } else if (item.parentNode.id == 'rp-other-origins-list') {
-        // it's an otherOrigin
-        self._currentlySelectedOrigin = item.getElementsByClassName("domainname")[0].value;
-      }
-      self._currentlySelectedDest = null;
-      // TODO: if the document's origin (rather than an other origin) is being
-      // activated, then regenerate the other origins list, as well.
-      self._resetSelectedOrigin();
-      item.setAttribute('selected-origin', 'true');
-      self._populateDestinations();
-      self._resetSelectedDest();
-      self._populateDetails();
-    },
-
-    _activateDestinationItem: function(item) {
-      self._currentlySelectedDest = item.getElementsByClassName("domainname")[0].value;
-
-      if (item.parentNode.id == 'rp-blocked-destinations-list') {
-        self._isCurrentlySelectedDestBlocked = true;
-        self._isCurrentlySelectedDestAllowed = false;
-      } else if (item.parentNode.id == 'rp-allowed-destinations-list') {
-        self._isCurrentlySelectedDestBlocked = false;
-        self._isCurrentlySelectedDestAllowed = true;
-      } else {
-        self._isCurrentlySelectedDestBlocked = true;
-        self._isCurrentlySelectedDestAllowed = true;
-      }
-
-      self._resetSelectedDest();
-      item.setAttribute('selected-dest', 'true');
-      self._populateDetails();
-    },
+  self._setPrivateBrowsingStyles = function() {
+    document.getElementById('rp-details').setAttribute(
+      'class', self._privateBrowsingEnabled ? 'privatebrowsing' : '');
+  };
 
+  self._resetSelectedOrigin = function() {
+    self._originItem.setAttribute('selected-origin', 'false');
+    for (var i = 0; i < self._otherOriginsList.childNodes.length; i++) {
+      var child = self._otherOriginsList.childNodes[i];
+      child.setAttribute('selected-origin', 'false');
+    }
+  };
 
-    itemSelected: function(event) {
-      var item = event.target;
-      // TODO: rather than compare IDs, this should probably compare against
-      // the elements we already have stored in variables. That is, assuming
-      // equality comparisons work that way here.
-      if (item.nodeName == "label" && item.parentNode.nodeName == "hbox") {
-        // item should be the <hbox>
-        item = item.parentNode;
-      }
-      if (item.id == 'rp-origin' ||
-          item.parentNode.id == 'rp-other-origins-list') {
-        self._activateOriginItem(item);
-      } else if (item.parentNode.id == 'rp-blocked-destinations-list' ||
-                 item.parentNode.id == 'rp-mixed-destinations-list' ||
-                 item.parentNode.id == 'rp-allowed-destinations-list') {
-        self._activateDestinationItem(item);
-      } else if (item.parentNode.id == 'rp-rule-options' ||
-                 item.parentNode.id == 'rp-rules-remove' ||
-                 item.parentNode.id == 'rp-rules-add') {
-        self._processRuleSelection(item);
-      } else {
-        Logger.severe(Logger.TYPE_ERROR,
-            'Unable to figure out which item type was selected.');
-      }
-    },
+  self._resetSelectedDest = function() {
+    for (var i = 0; i < self._blockedDestinationsList.childNodes.length; i++) {
+      var child = self._blockedDestinationsList.childNodes[i];
+      child.setAttribute('selected-dest', 'false');
+    }
+    for (var i = 0; i < self._mixedDestinationsList.childNodes.length; i++) {
+      var child = self._mixedDestinationsList.childNodes[i];
+      child.setAttribute('selected-dest', 'false');
+    }
+    for (var i = 0; i < self._allowedDestinationsList.childNodes.length; i++) {
+      var child = self._allowedDestinationsList.childNodes[i];
+      child.setAttribute('selected-dest', 'false');
+    }
+  };
+
+  self._activateOriginItem = function(item) {
+    if (item.id == 'rp-origin') {
+      // it's _the_ origin
+      self._currentlySelectedOrigin = self._originDomainnameItem.value;
+    } else if (item.parentNode.id == 'rp-other-origins-list') {
+      // it's an otherOrigin
+      self._currentlySelectedOrigin = item.getElementsByClassName("domainname")[0].value;
+    }
+    self._currentlySelectedDest = null;
+    // TODO: if the document's origin (rather than an other origin) is being
+    // activated, then regenerate the other origins list, as well.
+    self._resetSelectedOrigin();
+    item.setAttribute('selected-origin', 'true');
+    self._populateDestinations();
+    self._resetSelectedDest();
+    self._populateDetails();
+  };
+
+  self._activateDestinationItem = function(item) {
+    self._currentlySelectedDest = item.getElementsByClassName("domainname")[0].value;
+
+    if (item.parentNode.id == 'rp-blocked-destinations-list') {
+      self._isCurrentlySelectedDestBlocked = true;
+      self._isCurrentlySelectedDestAllowed = false;
+    } else if (item.parentNode.id == 'rp-allowed-destinations-list') {
+      self._isCurrentlySelectedDestBlocked = false;
+      self._isCurrentlySelectedDestAllowed = true;
+    } else {
+      self._isCurrentlySelectedDestBlocked = true;
+      self._isCurrentlySelectedDestAllowed = true;
+    }
 
-    _processRuleSelection: function(item) {
-      var ruleData = item.requestpolicyRuleData;
-      var ruleAction = item.requestpolicyRuleAction;
+    self._resetSelectedDest();
+    item.setAttribute('selected-dest', 'true');
+    self._populateDetails();
+  };
 
-      if (item.getAttribute('selected-rule') == 'true') {
-        item.setAttribute('selected-rule', 'false');
-        var undo = true;
-      } else {
-        item.setAttribute('selected-rule', 'true');
-        var undo = false;
-      }
 
-      if (!ruleData) {
-        Logger.severe(Logger.TYPE_ERROR,
-            'ruleData is empty in menu._processRuleSelection()');
-        return;
-      }
-      if (!ruleAction) {
-        Logger.severe(Logger.TYPE_ERROR,
-            'ruleAction is empty in menu._processRuleSelection()');
-        return;
-      }
+  self.itemSelected = function(event) {
+    var item = event.target;
+    // TODO: rather than compare IDs, this should probably compare against
+    // the elements we already have stored in variables. That is, assuming
+    // equality comparisons work that way here.
+    if (item.nodeName == "label" && item.parentNode.nodeName == "hbox") {
+      // item should be the <hbox>
+      item = item.parentNode;
+    }
+    if (item.id == 'rp-origin' ||
+        item.parentNode.id == 'rp-other-origins-list') {
+      self._activateOriginItem(item);
+    } else if (item.parentNode.id == 'rp-blocked-destinations-list' ||
+               item.parentNode.id == 'rp-mixed-destinations-list' ||
+               item.parentNode.id == 'rp-allowed-destinations-list') {
+      self._activateDestinationItem(item);
+    } else if (item.parentNode.id == 'rp-rule-options' ||
+               item.parentNode.id == 'rp-rules-remove' ||
+               item.parentNode.id == 'rp-rules-add') {
+      self._processRuleSelection(item);
+    } else {
+      Logger.severe(Logger.TYPE_ERROR,
+          'Unable to figure out which item type was selected.');
+    }
+  };
+
+  self._processRuleSelection = function(item) {
+    var ruleData = item.requestpolicyRuleData;
+    var ruleAction = item.requestpolicyRuleAction;
+
+    if (item.getAttribute('selected-rule') == 'true') {
+      item.setAttribute('selected-rule', 'false');
+      var undo = true;
+    } else {
+      item.setAttribute('selected-rule', 'true');
+      var undo = false;
+    }
 
-      var canonicalRule = Ruleset.rawRuleToCanonicalString(ruleData);
-      Logger.dump("ruleData: " + canonicalRule);
-      Logger.dump("ruleAction: " + ruleAction);
-      Logger.dump("undo: " + undo);
-
-      // TODO: does all of this get replaced with a generic rule processor that
-      // only cares whether it's an allow/deny and temporary and drops the ruleData
-      // argument straight into the ruleset?
-      var origin, dest;
-      if (ruleData['o'] && ruleData['o']['h']) {
-        origin = ruleData['o']['h'];
-      }
-      if (ruleData['d'] && ruleData['d']['h']) {
-        dest = ruleData['d']['h'];
-      }
+    if (!ruleData) {
+      Logger.severe(Logger.TYPE_ERROR,
+          'ruleData is empty in menu._processRuleSelection()');
+      return;
+    }
+    if (!ruleAction) {
+      Logger.severe(Logger.TYPE_ERROR,
+          'ruleAction is empty in menu._processRuleSelection()');
+      return;
+    }
 
-      if (!self._ruleChangeQueues[ruleAction]) {
-        self._ruleChangeQueues[ruleAction] = {};
-      }
+    var canonicalRule = Ruleset.rawRuleToCanonicalString(ruleData);
+    Logger.dump("ruleData: " + canonicalRule);
+    Logger.dump("ruleAction: " + ruleAction);
+    Logger.dump("undo: " + undo);
+
+    // TODO: does all of this get replaced with a generic rule processor that
+    // only cares whether it's an allow/deny and temporary and drops the ruleData
+    // argument straight into the ruleset?
+    var origin, dest;
+    if (ruleData['o'] && ruleData['o']['h']) {
+      origin = ruleData['o']['h'];
+    }
+    if (ruleData['d'] && ruleData['d']['h']) {
+      dest = ruleData['d']['h'];
+    }
 
-      if (undo) {
-        delete self._ruleChangeQueues[ruleAction][canonicalRule];
-      } else {
-        self._ruleChangeQueues[ruleAction][canonicalRule] = ruleData;
-      }
-    },
-
-    processQueuedRuleChanges: function() {
-      var rulesChanged = false;
-      for (var ruleAction in self._ruleChangeQueues) {
-        for (var canonicalRule in self._ruleChangeQueues[ruleAction]) {
-          var ruleData = self._ruleChangeQueues[ruleAction][canonicalRule];
-          self._processRuleChange(ruleAction, ruleData);
-          var rulesChanged = true;
-        }
-      }
+    if (!self._ruleChangeQueues[ruleAction]) {
+      self._ruleChangeQueues[ruleAction] = {};
+    }
 
-      self._ruleChangeQueues = {};
-      return rulesChanged;
-    },
-
-    _processRuleChange: function(ruleAction, ruleData) {
-
-      switch (ruleAction) {
-        case 'allow':
-          PolicyManager.addAllowRule(ruleData);
-          break;
-        case 'allow-temp':
-          PolicyManager.addTemporaryAllowRule(ruleData);
-          break;
-        case 'stop-allow':
-          PolicyManager.removeAllowRule(ruleData);
-          break;
-        case 'deny':
-          PolicyManager.addDenyRule(ruleData);
-          break;
-        case 'deny-temp':
-          PolicyManager.addTemporaryDenyRule(ruleData);
-          break;
-        case 'stop-deny':
-          PolicyManager.removeDenyRule(ruleData);
-          break;
-        default:
-          throw 'action not implemented: ' + ruleAction;
-          break;
+    if (undo) {
+      delete self._ruleChangeQueues[ruleAction][canonicalRule];
+    } else {
+      self._ruleChangeQueues[ruleAction][canonicalRule] = ruleData;
+    }
+  };
+
+  self.processQueuedRuleChanges = function() {
+    var rulesChanged = false;
+    for (var ruleAction in self._ruleChangeQueues) {
+      for (var canonicalRule in self._ruleChangeQueues[ruleAction]) {
+        var ruleData = self._ruleChangeQueues[ruleAction][canonicalRule];
+        self._processRuleChange(ruleAction, ruleData);
+        var rulesChanged = true;
       }
-    },
-
-
-    // Note to self: It's been too long since I looked at some of the new code.
-    // I think I may have assumed that I'd get rid of the different strictness
-    // levels and just use what is currently called LEVEL_SOP. If using anything
-    // else there will be errors from within getDeniedRequests().
-
+    }
 
-    _getBlockedDestinationsAsGUILocations: function() {
-      var reqSet = RequestProcessor.getDeniedRequests(
-          self._currentlySelectedOrigin, self._allRequestsOnDocument);
-      var requests = reqSet.getAllMergedOrigins();
+    self._ruleChangeQueues = {};
+    return rulesChanged;
+  };
+
+  self._processRuleChange = function(ruleAction, ruleData) {
+
+    switch (ruleAction) {
+      case 'allow':
+        PolicyManager.addAllowRule(ruleData);
+        break;
+      case 'allow-temp':
+        PolicyManager.addTemporaryAllowRule(ruleData);
+        break;
+      case 'stop-allow':
+        PolicyManager.removeAllowRule(ruleData);
+        break;
+      case 'deny':
+        PolicyManager.addDenyRule(ruleData);
+        break;
+      case 'deny-temp':
+        PolicyManager.addTemporaryDenyRule(ruleData);
+        break;
+      case 'stop-deny':
+        PolicyManager.removeDenyRule(ruleData);
+        break;
+      default:
+        throw 'action not implemented: ' + ruleAction;
+        break;
+    }
+  };
 
-      var result = [];
-      for (var destBase in requests) {
-        var properties = new GUILocationProperties();
-        properties.accumulate(requests[destBase], mod.RULE_ACTION_DENY);
-        result.push(new GUIDestination(destBase, properties));
-      }
-      return result;
-    },
 
-    _getAllowedDestinationsAsGUILocations: function() {
-      var reqSet = RequestProcessor.getAllowedRequests(
-          self._currentlySelectedOrigin, self._allRequestsOnDocument);
-      var requests = reqSet.getAllMergedOrigins();
+  // Note to self: It's been too long since I looked at some of the new code.
+  // I think I may have assumed that I'd get rid of the different strictness
+  // levels and just use what is currently called LEVEL_SOP. If using anything
+  // else there will be errors from within getDeniedRequests().
 
-      var result = [];
-      for (var destBase in requests) {
-        // For everybody except users with default deny who are not allowing all
-        // requests to the same domain:
-        // Ignore the selected origin's domain when listing destinations.
-        if (Prefs.isDefaultAllow() || Prefs.isDefaultAllowSameDomain()) {
-          if (destBase == self._currentlySelectedOrigin) {
-            continue;
-          }
-        }
 
-        var properties = new GUILocationProperties();
-        properties.accumulate(requests[destBase], mod.RULE_ACTION_ALLOW);
-        result.push(new GUIDestination(destBase, properties));
-      }
-      return result;
-    },
-
-    /**
-     * TODO: optimize this for performance (_getOriginGUILocationProperties and
-     * _getOtherOriginsAsGUILocations could be merged.)
-     *
-     * @return {GUILocationProperties}
-     *         the properties of the "main" origin (the one in the location bar).
-     */
-    _getOriginGUILocationProperties: function() {
-      var allRequests = self._allRequestsOnDocument.getAll();
-
-      var allowSameDomain = Prefs.isDefaultAllow() ||
-          Prefs.isDefaultAllowSameDomain();
+  self._getBlockedDestinationsAsGUILocations = function() {
+    var reqSet = RequestProcessor.getDeniedRequests(
+        self._currentlySelectedOrigin, self._allRequestsOnDocument);
+    var requests = reqSet.getAllMergedOrigins();
 
+    var result = [];
+    for (var destBase in requests) {
       var properties = new GUILocationProperties();
-
-      for (var originUri in allRequests) {
-        var originBase = DomainUtil.getBaseDomain(originUri);
-        if (originBase != self._currentBaseDomain) {
+      properties.accumulate(requests[destBase], mod.RULE_ACTION_DENY);
+      result.push(new GUIDestination(destBase, properties));
+    }
+    return result;
+  };
+
+  self._getAllowedDestinationsAsGUILocations = function() {
+    var reqSet = RequestProcessor.getAllowedRequests(
+        self._currentlySelectedOrigin, self._allRequestsOnDocument);
+    var requests = reqSet.getAllMergedOrigins();
+
+    var result = [];
+    for (var destBase in requests) {
+      // For everybody except users with default deny who are not allowing all
+      // requests to the same domain:
+      // Ignore the selected origin's domain when listing destinations.
+      if (Prefs.isDefaultAllow() || Prefs.isDefaultAllowSameDomain()) {
+        if (destBase == self._currentlySelectedOrigin) {
           continue;
         }
-
-        for (var destBase in allRequests[originUri]) {
-          properties.accumulate(allRequests[originUri][destBase]);
-        }
       }
-      return properties;
-    },
 
-    _getOtherOriginsAsGUILocations: function() {
-      var allRequests = self._allRequestsOnDocument.getAll();
-
-      var allowSameDomain = Prefs.isDefaultAllow() ||
-          Prefs.isDefaultAllowSameDomain();
+      var properties = new GUILocationProperties();
+      properties.accumulate(requests[destBase], mod.RULE_ACTION_ALLOW);
+      result.push(new GUIDestination(destBase, properties));
+    }
+    return result;
+  };
+
+  /**
+   * TODO: optimize this for performance (_getOriginGUILocationProperties and
+   * _getOtherOriginsAsGUILocations could be merged.)
+   *
+   * @return {GUILocationProperties}
+   *         the properties of the "main" origin (the one in the location bar).
+   */
+  self._getOriginGUILocationProperties = function() {
+    var allRequests = self._allRequestsOnDocument.getAll();
+
+    var allowSameDomain = Prefs.isDefaultAllow() ||
+        Prefs.isDefaultAllowSameDomain();
+
+    var properties = new GUILocationProperties();
+
+    for (var originUri in allRequests) {
+      var originBase = DomainUtil.getBaseDomain(originUri);
+      if (originBase != self._currentBaseDomain) {
+        continue;
+      }
 
-      var guiOrigins = [];
-      for (var originUri in allRequests) {
-        var originBase = DomainUtil.getBaseDomain(originUri);
-        if (originBase == self._currentBaseDomain) {
-          continue;
-        }
+      for (var destBase in allRequests[originUri]) {
+        properties.accumulate(allRequests[originUri][destBase]);
+      }
+    }
+    return properties;
+  };
 
-        // TODO: we should prevent chrome://browser/ URLs from getting anywhere
-        // near here in the first place.
-        // Is this an issue anymore? This may have been slipping through due to
-        // a bug that has since been fixed. Disabling for now.
-        //if (originBase == 'browser') {
-        //  continue;
-        //}
+  self._getOtherOriginsAsGUILocations = function() {
+    var allRequests = self._allRequestsOnDocument.getAll();
 
-        var guiOriginsIndex = GUIOrigin.indexOfOriginInArray(originBase,
-            guiOrigins);
-        var properties;
-        if (guiOriginsIndex == -1) {
-          properties = new GUILocationProperties();
-        } else {
-          properties = guiOrigins[guiOriginsIndex].properties;
-        }
-        var addThisOriginBase = false;
-
-        for (var destBase in allRequests[originUri]) {
-          // Search for a destBase which wouldn't be allowed by the default policy.
-          // TODO: some users might want to know those "other origins" as well.
-          //       this should be made possible.
-
-          // For everybody except users with default deny who are not allowing all
-          // guiOrigins to the same domain:
-          // Only list other origins where there is a destination from that origin
-          // that is at a different domain, not just a different subdomain.
-          if (allowSameDomain && destBase == originBase) {
-            continue;
-          }
-          addThisOriginBase = true;
-          properties.accumulate(allRequests[originUri][destBase]);
-        }
+    var allowSameDomain = Prefs.isDefaultAllow() ||
+        Prefs.isDefaultAllowSameDomain();
 
-        if (addThisOriginBase && guiOriginsIndex == -1) {
-          guiOrigins.push(new GUIOrigin(originBase, properties));
-        }
+    var guiOrigins = [];
+    for (var originUri in allRequests) {
+      var originBase = DomainUtil.getBaseDomain(originUri);
+      if (originBase == self._currentBaseDomain) {
+        continue;
       }
-      return guiOrigins;
-    },
-
-    _sanitizeJsFunctionArg: function(str) {
-      // strip single quotes and backslashes
-      return str.replace(/['\\]/g, "");
-    },
-
-    _isIPAddressOrSingleName: function(hostname) {
-      return DomainUtil.isIPAddress(hostname) ||
-          hostname.indexOf(".") == -1;
-    },
-
-    _addWildcard: function(hostname) {
-      if (self._isIPAddressOrSingleName(hostname)) {
-        return hostname;
+
+      // TODO: we should prevent chrome://browser/ URLs from getting anywhere
+      // near here in the first place.
+      // Is this an issue anymore? This may have been slipping through due to
+      // a bug that has since been fixed. Disabling for now.
+      //if (originBase == 'browser') {
+      //  continue;
+      //}
+
+      var guiOriginsIndex = GUIOrigin.indexOfOriginInArray(originBase,
+          guiOrigins);
+      var properties;
+      if (guiOriginsIndex == -1) {
+        properties = new GUILocationProperties();
       } else {
-        return "*." + hostname;
+        properties = guiOrigins[guiOriginsIndex].properties;
       }
-    },
-
-    // TODO: the 12 _addMenuItem* functions below hopefully can be refactored.
-
-    // Stop allowing
-
-    _addMenuItemStopAllowingOrigin: function(list, ruleData, subscriptionOverride) {
-      var originHost = ruleData["o"]["h"];
-      var ruleAction = subscriptionOverride ? 'deny' : 'stop-allow';
-      return self._addMenuItemHelper(list, ruleData, 'stopAllowingOrigin', [originHost], ruleAction, 'rp-stop-rule rp-stop-allow');
-    },
-
-    _addMenuItemStopAllowingDest: function(list, ruleData, subscriptionOverride) {
-      var destHost = ruleData["d"]["h"];
-      var ruleAction = subscriptionOverride ? 'deny' : 'stop-allow';
-      return self._addMenuItemHelper(list, ruleData, 'stopAllowingDestination', [destHost], ruleAction, 'rp-stop-rule rp-stop-allow');
-    },
-
-    _addMenuItemStopAllowingOriginToDest: function(list, ruleData, subscriptionOverride) {
-      var originHost = ruleData["o"]["h"];
-      var destHost = ruleData["d"]["h"];
-      var ruleAction = subscriptionOverride ? 'deny' : 'stop-allow';
-      return self._addMenuItemHelper(list, ruleData, 'stopAllowingOriginToDestination', [originHost, destHost], ruleAction, 'rp-stop-rule rp-stop-allow');
-    },
-
-    // Allow
-
-    _addMenuItemAllowOrigin: function(list, ruleData) {
-      var originHost = ruleData["o"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'allowOrigin', [originHost], 'allow', 'rp-start-rule rp-allow');
-    },
-
-    _addMenuItemAllowDest: function(list, ruleData) {
-      var destHost = ruleData["d"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'allowDestination', [destHost], 'allow', 'rp-start-rule rp-allow');
-    },
-
-    _addMenuItemAllowOriginToDest: function(list, ruleData) {
-      var originHost = ruleData["o"]["h"];
-      var destHost = ruleData["d"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'allowOriginToDestination', [originHost, destHost], 'allow', 'rp-start-rule rp-allow');
-    },
-
-    // Allow temp
-
-    _addMenuItemTempAllowOrigin: function(list, ruleData) {
-      var originHost = ruleData["o"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'allowOriginTemporarily', [originHost], 'allow-temp', 'rp-start-rule rp-allow rp-temporary');
-    },
-
-    _addMenuItemTempAllowDest: function(list, ruleData) {
-      var destHost = ruleData["d"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'allowDestinationTemporarily', [destHost], 'allow-temp', 'rp-start-rule rp-allow rp-temporary');
-    },
-
-    _addMenuItemTempAllowOriginToDest: function(list, ruleData) {
-      var originHost = ruleData["o"]["h"];
-      var destHost = ruleData["d"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'allowOriginToDestinationTemporarily', [originHost, destHost], 'allow-temp', 'rp-start-rule rp-allow rp-temporary');
-    },
-
-    // Stop denying
-
-    _addMenuItemStopDenyingOrigin: function(list, ruleData, subscriptionOverride) {
-      var originHost = ruleData["o"]["h"];
-      var ruleAction = subscriptionOverride ? 'allow' : 'stop-deny';
-      return self._addMenuItemHelper(list, ruleData, 'stopDenyingOrigin', [originHost], ruleAction, 'rp-stop-rule rp-stop-deny');
-    },
-
-    _addMenuItemStopDenyingDest: function(list, ruleData, subscriptionOverride) {
-      var destHost = ruleData["d"]["h"];
-      var ruleAction = subscriptionOverride ? 'allow' : 'stop-deny';
-      return self._addMenuItemHelper(list, ruleData, 'stopDenyingDestination', [destHost], ruleAction, 'rp-stop-rule rp-stop-deny');
-    },
-
-    _addMenuItemStopDenyingOriginToDest: function(list, ruleData, subscriptionOverride) {
-      var originHost = ruleData["o"]["h"];
-      var destHost = ruleData["d"]["h"];
-      var ruleAction = subscriptionOverride ? 'allow' : 'stop-deny';
-      return self._addMenuItemHelper(list, ruleData, 'stopDenyingOriginToDestination', [originHost, destHost], ruleAction, 'rp-stop-rule rp-stop-deny');
-    },
-
-    // Deny
-
-    _addMenuItemDenyOrigin: function(list, ruleData) {
-      var originHost = ruleData["o"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'denyOrigin', [originHost], 'deny', 'rp-start-rule rp-deny');
-    },
-
-    _addMenuItemDenyDest: function(list, ruleData) {
-      var destHost = ruleData["d"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'denyDestination', [destHost], 'deny', 'rp-start-rule rp-deny');
-    },
-
-    _addMenuItemDenyOriginToDest: function(list, ruleData) {
-      var originHost = ruleData["o"]["h"];
-      var destHost = ruleData["d"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'denyOriginToDestination', [originHost, destHost], 'deny', 'rp-start-rule rp-deny');
-    },
-
-    // Deny temp
-
-    _addMenuItemTempDenyOrigin: function(list, ruleData) {
-      var originHost = ruleData["o"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'denyOriginTemporarily', [originHost], 'deny-temp', 'rp-start-rule rp-deny rp-temporary');
-    },
-
-    _addMenuItemTempDenyDest: function(list, ruleData) {
-      var destHost = ruleData["d"]["h"];
-      return self._addMenuItemHelper(list, ruleData, 'denyDestinationTemporarily', [destHost], 'deny-temp', 'rp-start-rule rp-deny rp-temporary');
-    },
-
-    _addMenuItemTempDenyOriginToDest: function(list, ruleData) {
-      var originHost = ruleData["o"]["h"];
-      var destHost = ruleData["d"]["h"];
-      return self._addMenuItemHelper(list, ruleData,
-          'denyOriginToDestinationTemporarily', [originHost, destHost],
-          'deny-temp', 'rp-start-rule rp-deny rp-temporary');
-    },
-
-    _addMenuItemHelper: function(list, ruleData, fmtStrName, fmtStrArgs,
-        ruleAction, cssClass) {
-      var label = StringUtils.strbundle.formatStringFromName(fmtStrName, fmtStrArgs,
-          fmtStrArgs.length);
-      var item = self._addListItem(list, 'rp-od-item', label);
-      item.requestpolicyRuleData = ruleData;
-      item.requestpolicyRuleAction = ruleAction;
-      //var statustext = ''; // TODO
-      item.setAttribute('class', 'rp-od-item ' + cssClass);
-      var canonicalRule = Ruleset.rawRuleToCanonicalString(ruleData);
-      if (self._ruleChangeQueues[ruleAction]) {
-        if (self._ruleChangeQueues[ruleAction][canonicalRule]) {
-          item.setAttribute('selected-rule', 'true');
+      var addThisOriginBase = false;
+
+      for (var destBase in allRequests[originUri]) {
+        // Search for a destBase which wouldn't be allowed by the default policy.
+        // TODO: some users might want to know those "other origins" as well.
+        //       this should be made possible.
+
+        // For everybody except users with default deny who are not allowing all
+        // guiOrigins to the same domain:
+        // Only list other origins where there is a destination from that origin
+        // that is at a different domain, not just a different subdomain.
+        if (allowSameDomain && destBase == originBase) {
+          continue;
         }
+        addThisOriginBase = true;
+        properties.accumulate(allRequests[originUri][destBase]);
       }
-      return item;
-    },
 
-    _ruleDataPartToDisplayString: function(ruleDataPart) {
-      var str = "";
-      if (ruleDataPart["s"]) {
-        str += ruleDataPart["s"] + "://";
-      }
-      str += ruleDataPart["h"] || "*";
-      if (ruleDataPart["port"]) {
-        str += ":" + ruleDataPart["port"];
-      }
-      // TODO: path
-      return str;
-    },
-
-    _ruleDataToFormatVariables: function(rawRule) {
-      var fmtVars = [];
-      if (rawRule["o"]) {
-        fmtVars.push(self._ruleDataPartToDisplayString(rawRule["o"]));
+      if (addThisOriginBase && guiOriginsIndex == -1) {
+        guiOrigins.push(new GUIOrigin(originBase, properties));
       }
-      if (rawRule["d"]) {
-        fmtVars.push(self._ruleDataPartToDisplayString(rawRule["d"]));
-      }
-      return fmtVars;
-    },
-
-    _addMenuItemRemoveAllowRule: function(list, rawRule, subscriptionOverride) {
-      var fmtVars = self._ruleDataToFormatVariables(rawRule);
-
-      if (rawRule["o"] && rawRule["d"]) {
-        return self._addMenuItemStopAllowingOriginToDest(list, rawRule, subscriptionOverride);
-      } else if (rawRule["o"]) {
-        return self._addMenuItemStopAllowingOrigin(list, rawRule, subscriptionOverride);
-      } else if (rawRule["d"]) {
-        return self._addMenuItemStopAllowingDest(list, rawRule, subscriptionOverride);
-      } else {
-        throw "Invalid rule data: no origin or destination parts.";
+    }
+    return guiOrigins;
+  };
+
+  self._sanitizeJsFunctionArg = function(str) {
+    // strip single quotes and backslashes
+    return str.replace(/['\\]/g, "");
+  };
+
+  self._isIPAddressOrSingleName = function(hostname) {
+    return DomainUtil.isIPAddress(hostname) ||
+        hostname.indexOf(".") == -1;
+  };
+
+  self._addWildcard = function(hostname) {
+    if (self._isIPAddressOrSingleName(hostname)) {
+      return hostname;
+    } else {
+      return "*." + hostname;
+    }
+  };
+
+  // TODO: the 12 _addMenuItem* functions below hopefully can be refactored.
+
+  // Stop allowing
+
+  self._addMenuItemStopAllowingOrigin = function(list, ruleData, subscriptionOverride) {
+    var originHost = ruleData["o"]["h"];
+    var ruleAction = subscriptionOverride ? 'deny' : 'stop-allow';
+    return self._addMenuItemHelper(list, ruleData, 'stopAllowingOrigin', [originHost], ruleAction, 'rp-stop-rule rp-stop-allow');
+  };
+
+  self._addMenuItemStopAllowingDest = function(list, ruleData, subscriptionOverride) {
+    var destHost = ruleData["d"]["h"];
+    var ruleAction = subscriptionOverride ? 'deny' : 'stop-allow';
+    return self._addMenuItemHelper(list, ruleData, 'stopAllowingDestination', [destHost], ruleAction, 'rp-stop-rule rp-stop-allow');
+  };
+
+  self._addMenuItemStopAllowingOriginToDest = function(list, ruleData, subscriptionOverride) {
+    var originHost = ruleData["o"]["h"];
+    var destHost = ruleData["d"]["h"];
+    var ruleAction = subscriptionOverride ? 'deny' : 'stop-allow';
+    return self._addMenuItemHelper(list, ruleData, 'stopAllowingOriginToDestination', [originHost, destHost], ruleAction, 'rp-stop-rule rp-stop-allow');
+  };
+
+  // Allow
+
+  self._addMenuItemAllowOrigin = function(list, ruleData) {
+    var originHost = ruleData["o"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'allowOrigin', [originHost], 'allow', 'rp-start-rule rp-allow');
+  };
+
+  self._addMenuItemAllowDest = function(list, ruleData) {
+    var destHost = ruleData["d"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'allowDestination', [destHost], 'allow', 'rp-start-rule rp-allow');
+  };
+
+  self._addMenuItemAllowOriginToDest = function(list, ruleData) {
+    var originHost = ruleData["o"]["h"];
+    var destHost = ruleData["d"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'allowOriginToDestination', [originHost, destHost], 'allow', 'rp-start-rule rp-allow');
+  };
+
+  // Allow temp
+
+  self._addMenuItemTempAllowOrigin = function(list, ruleData) {
+    var originHost = ruleData["o"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'allowOriginTemporarily', [originHost], 'allow-temp', 'rp-start-rule rp-allow rp-temporary');
+  };
+
+  self._addMenuItemTempAllowDest = function(list, ruleData) {
+    var destHost = ruleData["d"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'allowDestinationTemporarily', [destHost], 'allow-temp', 'rp-start-rule rp-allow rp-temporary');
+  };
+
+  self._addMenuItemTempAllowOriginToDest = function(list, ruleData) {
+    var originHost = ruleData["o"]["h"];
+    var destHost = ruleData["d"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'allowOriginToDestinationTemporarily', [originHost, destHost], 'allow-temp', 'rp-start-rule rp-allow rp-temporary');
+  };
+
+  // Stop denying
+
+  self._addMenuItemStopDenyingOrigin = function(list, ruleData, subscriptionOverride) {
+    var originHost = ruleData["o"]["h"];
+    var ruleAction = subscriptionOverride ? 'allow' : 'stop-deny';
+    return self._addMenuItemHelper(list, ruleData, 'stopDenyingOrigin', [originHost], ruleAction, 'rp-stop-rule rp-stop-deny');
+  };
+
+  self._addMenuItemStopDenyingDest = function(list, ruleData, subscriptionOverride) {
+    var destHost = ruleData["d"]["h"];
+    var ruleAction = subscriptionOverride ? 'allow' : 'stop-deny';
+    return self._addMenuItemHelper(list, ruleData, 'stopDenyingDestination', [destHost], ruleAction, 'rp-stop-rule rp-stop-deny');
+  };
+
+  self._addMenuItemStopDenyingOriginToDest = function(list, ruleData, subscriptionOverride) {
+    var originHost = ruleData["o"]["h"];
+    var destHost = ruleData["d"]["h"];
+    var ruleAction = subscriptionOverride ? 'allow' : 'stop-deny';
+    return self._addMenuItemHelper(list, ruleData, 'stopDenyingOriginToDestination', [originHost, destHost], ruleAction, 'rp-stop-rule rp-stop-deny');
+  };
+
+  // Deny
+
+  self._addMenuItemDenyOrigin = function(list, ruleData) {
+    var originHost = ruleData["o"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'denyOrigin', [originHost], 'deny', 'rp-start-rule rp-deny');
+  };
+
+  self._addMenuItemDenyDest = function(list, ruleData) {
+    var destHost = ruleData["d"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'denyDestination', [destHost], 'deny', 'rp-start-rule rp-deny');
+  };
+
+  self._addMenuItemDenyOriginToDest = function(list, ruleData) {
+    var originHost = ruleData["o"]["h"];
+    var destHost = ruleData["d"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'denyOriginToDestination', [originHost, destHost], 'deny', 'rp-start-rule rp-deny');
+  };
+
+  // Deny temp
+
+  self._addMenuItemTempDenyOrigin = function(list, ruleData) {
+    var originHost = ruleData["o"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'denyOriginTemporarily', [originHost], 'deny-temp', 'rp-start-rule rp-deny rp-temporary');
+  };
+
+  self._addMenuItemTempDenyDest = function(list, ruleData) {
+    var destHost = ruleData["d"]["h"];
+    return self._addMenuItemHelper(list, ruleData, 'denyDestinationTemporarily', [destHost], 'deny-temp', 'rp-start-rule rp-deny rp-temporary');
+  };
+
+  self._addMenuItemTempDenyOriginToDest = function(list, ruleData) {
+    var originHost = ruleData["o"]["h"];
+    var destHost = ruleData["d"]["h"];
+    return self._addMenuItemHelper(list, ruleData,
+        'denyOriginToDestinationTemporarily', [originHost, destHost],
+        'deny-temp', 'rp-start-rule rp-deny rp-temporary');
+  };
+
+  self._addMenuItemHelper = function(list, ruleData, fmtStrName, fmtStrArgs,
+      ruleAction, cssClass) {
+    var label = StringUtils.strbundle.formatStringFromName(fmtStrName, fmtStrArgs,
+        fmtStrArgs.length);
+    var item = self._addListItem(list, 'rp-od-item', label);
+    item.requestpolicyRuleData = ruleData;
+    item.requestpolicyRuleAction = ruleAction;
+    //var statustext = ''; // TODO
+    item.setAttribute('class', 'rp-od-item ' + cssClass);
+    var canonicalRule = Ruleset.rawRuleToCanonicalString(ruleData);
+    if (self._ruleChangeQueues[ruleAction]) {
+      if (self._ruleChangeQueues[ruleAction][canonicalRule]) {
+        item.setAttribute('selected-rule', 'true');
       }
-    },
-
-    _addMenuItemRemoveDenyRule: function(list, rawRule, subscriptionOverride) {
-      var fmtVars = self._ruleDataToFormatVariables(rawRule);
+    }
+    return item;
+  };
 
-      if (rawRule["o"] && rawRule["d"]) {
-        return self._addMenuItemStopDenyingOriginToDest(list, rawRule, subscriptionOverride);
-      } else if (rawRule["o"]) {
-        return self._addMenuItemStopDenyingOrigin(list, rawRule, subscriptionOverride);
-      } else if (rawRule["d"]) {
-        return self._addMenuItemStopDenyingDest(list, rawRule, subscriptionOverride);
-      } else {
-        throw "Invalid rule data: no origin or destination parts.";
-      }
-    },
+  self._ruleDataPartToDisplayString = function(ruleDataPart) {
+    var str = "";
+    if (ruleDataPart["s"]) {
+      str += ruleDataPart["s"] + "://";
+    }
+    str += ruleDataPart["h"] || "*";
+    if (ruleDataPart["port"]) {
+      str += ":" + ruleDataPart["port"];
+    }
+    // TODO: path
+    return str;
+  };
+
+  self._ruleDataToFormatVariables = function(rawRule) {
+    var fmtVars = [];
+    if (rawRule["o"]) {
+      fmtVars.push(self._ruleDataPartToDisplayString(rawRule["o"]));
+    }
+    if (rawRule["d"]) {
+      fmtVars.push(self._ruleDataPartToDisplayString(rawRule["d"]));
+    }
+    return fmtVars;
+  };
+
+  self._addMenuItemRemoveAllowRule = function(list, rawRule, subscriptionOverride) {
+    var fmtVars = self._ruleDataToFormatVariables(rawRule);
+
+    if (rawRule["o"] && rawRule["d"]) {
+      return self._addMenuItemStopAllowingOriginToDest(list, rawRule, subscriptionOverride);
+    } else if (rawRule["o"]) {
+      return self._addMenuItemStopAllowingOrigin(list, rawRule, subscriptionOverride);
+    } else if (rawRule["d"]) {
+      return self._addMenuItemStopAllowingDest(list, rawRule, subscriptionOverride);
+    } else {
+      throw "Invalid rule data: no origin or destination parts.";
+    }
+  };
+
+  self._addMenuItemRemoveDenyRule = function(list, rawRule, subscriptionOverride) {
+    var fmtVars = self._ruleDataToFormatVariables(rawRule);
+
+    if (rawRule["o"] && rawRule["d"]) {
+      return self._addMenuItemStopDenyingOriginToDest(list, rawRule, subscriptionOverride);
+    } else if (rawRule["o"]) {
+      return self._addMenuItemStopDenyingOrigin(list, rawRule, subscriptionOverride);
+    } else if (rawRule["d"]) {
+      return self._addMenuItemStopDenyingDest(list, rawRule, subscriptionOverride);
+    } else {
+      throw "Invalid rule data: no origin or destination parts.";
+    }
+  };
 
-    _populateDetailsRemoveAllowRules: function(list) {
-      // TODO: can we avoid calling getAllowedRequests here and reuse a result
-      // from calling it earlier?
+  self._populateDetailsRemoveAllowRules = function(list) {
+    // TODO: can we avoid calling getAllowedRequests here and reuse a result
+    // from calling it earlier?
 
-      var reqSet = RequestProcessor.getAllowedRequests(
-          self._currentlySelectedOrigin, self._allRequestsOnDocument);
-      var requests = reqSet.getAllMergedOrigins();
+    var reqSet = RequestProcessor.getAllowedRequests(
+        self._currentlySelectedOrigin, self._allRequestsOnDocument);
+    var requests = reqSet.getAllMergedOrigins();
 
-      //var rules = {};
+    //var rules = {};
 
-      var userRules = {};
-      var subscriptionRules = {};
+    var userRules = {};
+    var subscriptionRules = {};
 
-      //reqSet.print('allowedRequests');
+    //reqSet.print('allowedRequests');
 
-      // TODO: there is no dest if no dest is selected (origin only).
-      //var destBase = DomainUtil.getBaseDomain(
-      //      self._currentlySelectedDest);
+    // TODO: there is no dest if no dest is selected (origin only).
+    //var destBase = DomainUtil.getBaseDomain(
+    //      self._currentlySelectedDest);
 
-      for (var destBase in requests) {
+    for (var destBase in requests) {
 
-        if (self._currentlySelectedDest &&
-            self._currentlySelectedDest != destBase) {
-          continue;
-        }
+      if (self._currentlySelectedDest &&
+          self._currentlySelectedDest != destBase) {
+        continue;
+      }
 
-        for (var destIdent in requests[destBase]) {
+      for (var destIdent in requests[destBase]) {
 
-          var destinations = requests[destBase][destIdent];
-          for (var destUri in destinations) {
+        var destinations = requests[destBase][destIdent];
+        for (var destUri in destinations) {
 
-            // This will be null when the request was denied because of a default
-            // allow rule. However about any other time?
-            // TODO: we at least in default allow mode, we need to give an option
-            // to add a deny rule for these requests.
-            if (!destinations[destUri]) {
-              Logger.dump("destinations[destUri] is null or undefined for " +
-                  "destUri: " + destUri);
-              continue;
-            }
+          // This will be null when the request was denied because of a default
+          // allow rule. However about any other time?
+          // TODO: we at least in default allow mode, we need to give an option
+          // to add a deny rule for these requests.
+          if (!destinations[destUri]) {
+            Logger.dump("destinations[destUri] is null or undefined for " +
+                "destUri: " + destUri);
+            continue;
+          }
 
 
-            var results = destinations[destUri][0]; // TODO: Do not look only
-            // at the first RequestResult object, but at all. (there might be
-            // several requests with identical origin and destination URI.)
+          var results = destinations[destUri][0]; // TODO: Do not look only
+          // at the first RequestResult object, but at all. (there might be
+          // several requests with identical origin and destination URI.)
 
-            for (var i in results.matchedAllowRules) {
+          for (var i in results.matchedAllowRules) {
 
-              var ruleset, match;
-              [ruleset, match] = results.matchedAllowRules[i];
-              var rawRule = Ruleset.matchToRawRule(match);
+            var ruleset, match;
+            [ruleset, match] = results.matchedAllowRules[i];
+            var rawRule = Ruleset.matchToRawRule(match);
 
-              if (!self._currentlySelectedDest) {
-                if (rawRule['d'] && rawRule['d']['h']) {
-                  continue;
-                }
+            if (!self._currentlySelectedDest) {
+              if (rawRule['d'] && rawRule['d']['h']) {
+                continue;
               }
+            }
 
-              var rawRuleStr = Ruleset.rawRuleToCanonicalString(rawRule);
-              //Logger.info(Logger.TYPE_POLICY,
-              //       "matched allow rule: " + rawRuleStr);
-              // This is how we remove duplicates: if two rules have the same
-              // canonical string, they'll have in the same key.
-              if (ruleset.userRuleset) {
-                userRules[rawRuleStr] = rawRule;
-              } else {
-                subscriptionRules[rawRuleStr] = rawRule;
-              }
+            var rawRuleStr = Ruleset.rawRuleToCanonicalString(rawRule);
+            //Logger.info(Logger.TYPE_POLICY,
+            //       "matched allow rule: " + rawRuleStr);
+            // This is how we remove duplicates: if two rules have the same
+            // canonical string, they'll have in the same key.
+            if (ruleset.userRuleset) {
+              userRules[rawRuleStr] = rawRule;
+            } else {
+              subscriptionRules[rawRuleStr] = rawRule;
             }
           }
         }
       }
+    }
 
-      for (var i in userRules) {
-        self._addMenuItemRemoveAllowRule(list, userRules[i], false);
-      }
-      // TODO: for subscription rules, we need the effect of the menu item to be
-      // adding a deny rule instead of removing an allow rule. However, the text
-      // used for the item needs to be the same as removing an allow rule.
-      for (var i in subscriptionRules) {
-        self._addMenuItemRemoveAllowRule(list, subscriptionRules[i], true);
-      }
-    },
+    for (var i in userRules) {
+      self._addMenuItemRemoveAllowRule(list, userRules[i], false);
+    }
+    // TODO: for subscription rules, we need the effect of the menu item to be
+    // adding a deny rule instead of removing an allow rule. However, the text
+    // used for the item needs to be the same as removing an allow rule.
+    for (var i in subscriptionRules) {
+      self._addMenuItemRemoveAllowRule(list, subscriptionRules[i], true);
+    }
+  };
 
-    _populateDetailsRemoveDenyRules: function(list) {
-      // TODO: can we avoid calling getDeniedRequests here and reuse a result
-      // from calling it earlier?
+  self._populateDetailsRemoveDenyRules = function(list) {
+    // TODO: can we avoid calling getDeniedRequests here and reuse a result
+    // from calling it earlier?
 
-      var reqSet = RequestProcessor.getDeniedRequests(
-          self._currentlySelectedOrigin, self._allRequestsOnDocument);
-      var requests = reqSet.getAllMergedOrigins();
+    var reqSet = RequestProcessor.getDeniedRequests(
+        self._currentlySelectedOrigin, self._allRequestsOnDocument);
+    var requests = reqSet.getAllMergedOrigins();
 
-      //var rules = {};
+    //var rules = {};
 
-      var userRules = {};
-      var subscriptionRules = {};
+    var userRules = {};
+    var subscriptionRules = {};
 
-      reqSet.print('deniedRequests');
+    reqSet.print('deniedRequests');
 
-      // TODO: there is no dest if no dest is selected (origin only).
-      //var destBase = DomainUtil.getBaseDomain(
-      //      self._currentlySelectedDest);
+    // TODO: there is no dest if no dest is selected (origin only).
+    //var destBase = DomainUtil.getBaseDomain(
+    //      self._currentlySelectedDest);
 
-      for (var destBase in requests) {
+    for (var destBase in requests) {
 
-        if (self._currentlySelectedDest &&
-          self._currentlySelectedDest != destBase) {
-          continue;
-        }
+      if (self._currentlySelectedDest &&
+        self._currentlySelectedDest != destBase) {
+        continue;
+      }
 
-        for (var destIdent in requests[destBase]) {
+      for (var destIdent in requests[destBase]) {
 
-          var destinations = requests[destBase][destIdent];
-          for (var destUri in destinations) {
+        var destinations = requests[destBase][destIdent];
+        for (var destUri in destinations) {
 
-            // This will be null when the request was denied because of a default
-            // deny rule. However about any other time?
-            // TODO: we at least in default deny mode, we need to give an option
-            // to add a allow rule for these requests.
-            if (!destinations[destUri]) {
-              Logger.dump("destinations[destUri] is null or undefined for destUri: " + destUri);
-              continue;
-            }
+          // This will be null when the request was denied because of a default
+          // deny rule. However about any other time?
+          // TODO: we at least in default deny mode, we need to give an option
+          // to add a allow rule for these requests.
+          if (!destinations[destUri]) {
+            Logger.dump("destinations[destUri] is null or undefined for destUri: " + destUri);
+            continue;
+          }
 
-            var results = destinations[destUri][0]; // TODO: Do not look only
-            // at the first RequestResult object, but at all. (there may be
-            // several requests with identical origin and destination URI.)
+          var results = destinations[destUri][0]; // TODO: Do not look only
+          // at the first RequestResult object, but at all. (there may be
+          // several requests with identical origin and destination URI.)
 
-            for (var i in results.matchedDenyRules) {
+          for (var i in results.matchedDenyRules) {
 
-              var ruleset, match;
-              [ruleset, match] = results.matchedDenyRules[i];
-              var rawRule = Ruleset.matchToRawRule(match);
+            var ruleset, match;
+            [ruleset, match] = results.matchedDenyRules[i];
+            var rawRule = Ruleset.matchToRawRule(match);
 
-              if (!self._currentlySelectedDest) {
-                if (rawRule['d'] && rawRule['d']['h']) {
-                  continue;
-                }
+            if (!self._currentlySelectedDest) {
+              if (rawRule['d'] && rawRule['d']['h']) {
+                continue;
               }
+            }
 
-              var rawRuleStr = Ruleset.rawRuleToCanonicalString(rawRule);
-              //Logger.info(Logger.TYPE_POLICY,
-              //       "matched allow rule: " + rawRuleStr);
-              // This is how we remove duplicates: if two rules have the same
-              // canonical string, they'll have in the same key.
-              if (ruleset.userRuleset) {
-                userRules[rawRuleStr] = rawRule;
-              } else {
-                subscriptionRules[rawRuleStr] = rawRule;
-              }
+            var rawRuleStr = Ruleset.rawRuleToCanonicalString(rawRule);
+            //Logger.info(Logger.TYPE_POLICY,
+            //       "matched allow rule: " + rawRuleStr);
+            // This is how we remove duplicates: if two rules have the same
+            // canonical string, they'll have in the same key.
+            if (ruleset.userRuleset) {
+              userRules[rawRuleStr] = rawRule;
+            } else {
+              subscriptionRules[rawRuleStr] = rawRule;
             }
           }
         }
       }
+    }
 
-      for (var i in userRules) {
-        self._addMenuItemRemoveDenyRule(list, userRules[i], false);
-      }
-      // TODO: for subscription rules, we need the effect of the menu item to be
-      // adding an allow rule instead of removing a deny rule. However, the text
-      // used for the item needs to be the same as removing a deny rule.
-      for (var i in subscriptionRules) {
-        self._addMenuItemRemoveDenyRule(list, subscriptionRules[i], true);
-      }
-    },
+    for (var i in userRules) {
+      self._addMenuItemRemoveDenyRule(list, userRules[i], false);
+    }
+    // TODO: for subscription rules, we need the effect of the menu item to be
+    // adding an allow rule instead of removing a deny rule. However, the text
+    // used for the item needs to be the same as removing a deny rule.
+    for (var i in subscriptionRules) {
+      self._addMenuItemRemoveDenyRule(list, subscriptionRules[i], true);
+    }
+  };
 
-    _populateDetailsAddSubdomainAllowRules: function(list) {
-      var origin = self._currentlySelectedOrigin;
+  self._populateDetailsAddSubdomainAllowRules = function(list) {
+    var origin = self._currentlySelectedOrigin;
 
-      // TODO: can we avoid calling getDeniedRequests here and reuse a result
-      // from calling it earlier?
+    // TODO: can we avoid calling getDeniedRequests here and reuse a result
+    // from calling it earlier?
 
-      var reqSet = RequestProcessor.getDeniedRequests(
-          self._currentlySelectedOrigin, self._allRequestsOnDocument);
-      var requests = reqSet.getAllMergedOrigins();
+    var reqSet = RequestProcessor.getDeniedRequests(
+        self._currentlySelectedOrigin, self._allRequestsOnDocument);
+    var requests = reqSet.getAllMergedOrigins();
 
-      var destHosts = {};
+    var destHosts = {};
 
-      for (var destBase in requests) {
-        if (self._currentlySelectedDest &&
-            self._currentlySelectedDest != destBase) {
-          continue;
-        }
-        for (var destIdent in requests[destBase]) {
-          var destinations = requests[destBase][destIdent];
-          for (var destUri in destinations) {
-            destHosts[DomainUtil.getHost(destUri)] = null;
-          }
+    for (var destBase in requests) {
+      if (self._currentlySelectedDest &&
+          self._currentlySelectedDest != destBase) {
+        continue;
+      }
+      for (var destIdent in requests[destBase]) {
+        var destinations = requests[destBase][destIdent];
+        for (var destUri in destinations) {
+          destHosts[DomainUtil.getHost(destUri)] = null;
         }
       }
+    }
 
-      for (var destHost in destHosts) {
-        var ruleData = {
-          'o' : {
-            'h' : self._addWildcard(origin)
-          },
-          'd' : {
-            'h': destHost
-          }
-        };
-        if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, ruleData) &&
-            !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, ruleData)) {
-          if (!self._privateBrowsingEnabled) {
-            var item = self._addMenuItemAllowOriginToDest(list, ruleData);
-          }
-          var item = self._addMenuItemTempAllowOriginToDest(list, ruleData);
+    for (var destHost in destHosts) {
+      var ruleData = {
+        'o' : {
+          'h' : self._addWildcard(origin)
+        },
+        'd' : {
+          'h': destHost
         }
+      };
+      if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, ruleData) &&
+          !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, ruleData)) {
+        if (!self._privateBrowsingEnabled) {
+          var item = self._addMenuItemAllowOriginToDest(list, ruleData);
+        }
+        var item = self._addMenuItemTempAllowOriginToDest(list, ruleData);
+      }
 
-        var destOnlyRuleData = {
-          'd' : {
-            'h': destHost
-          }
-        };
-        if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, destOnlyRuleData) &&
-            !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, destOnlyRuleData)) {
-          if (!self._privateBrowsingEnabled) {
-            var item = self._addMenuItemAllowDest(list, destOnlyRuleData);
-          }
-          var item = self._addMenuItemTempAllowDest(list, destOnlyRuleData);
+      var destOnlyRuleData = {
+        'd' : {
+          'h': destHost
+        }
+      };
+      if (!PolicyManager.ruleExists(mod.RULE_ACTION_ALLOW, destOnlyRuleData) &&
+          !PolicyManager.ruleExists(mod.RULE_ACTION_DENY, destOnlyRuleData)) {
+        if (!self._privateBrowsingEnabled) {
+          var item = self._addMenuItemAllowDest(list, destOnlyRuleData);
         }
+        var item = self._addMenuItemTempAllowDest(list, destOnlyRuleData);
       }
     }
-  }
+  };
 
   return self;
 }());
diff --git a/src/content/ui/overlay.js b/src/content/ui/overlay.js
index 529448d..97b59f1 100644
--- a/src/content/ui/overlay.js
+++ b/src/content/ui/overlay.js
@@ -83,1212 +83,1212 @@ requestpolicy.overlay = (function() {
 
 
   let self = {
-
     // This is set by request-log.js when it is initialized. We don't need to worry
     // about setting it here.
-    requestLogTreeView : null,
-
-    toString : function() {
-      return "[requestpolicy.overlay " + overlayId + "]";
-    },
+    requestLogTreeView : null
+  };
 
-    /**
-     * Initialize the object. This must be done after the DOM is loaded.
-     */
-    init: function() {
-      try {
-        if (initialized == false) {
-          initialized = true;
-          overlayId = (new Date()).getTime();
 
-          requestpolicy.menu.init();
+  self.toString = function() {
+    return "[requestpolicy.overlay " + overlayId + "]";
+  };
 
-          menu = document.getElementById("rp-popup");
+  /**
+   * Initialize the object. This must be done after the DOM is loaded.
+   */
+  self.init = function() {
+    try {
+      if (initialized == false) {
+        initialized = true;
+        overlayId = (new Date()).getTime();
+
+        requestpolicy.menu.init();
+
+        menu = document.getElementById("rp-popup");
+
+        //statusbar = document.getElementById("status-bar");
+        //rpContextMenu = document
+        //    .getElementById("requestpolicyContextMenu");
+        toolbox = document.getElementById("navigator-toolbox");
+
+        var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
+            .getService(Components.interfaces.nsIXULAppInfo);
+        isFennec = (appInfo.ID == "{a23983c0-fd0e-11dc-95ff-0800200c9a66}");
+
+        if (isFennec) {
+          Logger.dump("Detected Fennec.");
+          // Set an attribute for CSS usage.
+          menu.setAttribute("fennec", "true");
+          menu.setAttribute("position", "after_end");
+        }
 
-          //statusbar = document.getElementById("status-bar");
-          //rpContextMenu = document
-          //    .getElementById("requestpolicyContextMenu");
-          toolbox = document.getElementById("navigator-toolbox");
+        // Register this window with the requestpolicy service so that we can be
+        // notified of blocked requests. When blocked requests happen, this
+        // object's observerBlockedRequests() method will be called.
+        RequestProcessor.addRequestObserver(self);
 
-          var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
-              .getService(Components.interfaces.nsIXULAppInfo);
-          isFennec = (appInfo.ID == "{a23983c0-fd0e-11dc-95ff-0800200c9a66}");
+        //self.setContextMenuEnabled(rpPrefBranch.getBoolPref("contextMenu"));
+        self._setPermissiveNotification(Prefs.isBlockingDisabled());
+      }
+    } catch (e) {
+      Logger.severe(Logger.TYPE_ERROR,
+          "Fatal Error, " + e + ", stack was: " + e.stack);
+      Logger.severe(Logger.TYPE_ERROR,
+          "Unable to initialize requestpolicy.overlay.");
+      throw e;
+    }
+  };
 
-          if (isFennec) {
-            Logger.dump("Detected Fennec.");
-            // Set an attribute for CSS usage.
-            menu.setAttribute("fennec", "true");
-            menu.setAttribute("position", "after_end");
-          }
+  //setContextMenuEnabled : function(isEnabled) {
+  //  rpContextMenu.setAttribute("hidden", !isEnabled);
+  //},
 
-          // Register this window with the requestpolicy service so that we can be
-          // notified of blocked requests. When blocked requests happen, this
-          // object's observerBlockedRequests() method will be called.
-          RequestProcessor.addRequestObserver(self);
+  self.onWindowUnload = function() {
+    RequestProcessor.removeRequestObserver(self);
+    self._removeHistoryObserver();
+    self._removeLocationObserver();
+  };
 
-          //self.setContextMenuEnabled(rpPrefBranch.getBoolPref("contextMenu"));
-          self._setPermissiveNotification(Prefs.isBlockingDisabled());
+  /**
+   * Perform the actions required once the window has loaded. This just sets a
+   * listener for when the content of the window has changed (a page is loaded).
+   *
+   * @param {Event}
+   *          event
+   */
+  self.onWindowLoad = function() {
+    //try {
+      // Info on detecting page load at:
+      // http://developer.mozilla.org/En/Code_snippets/On_page_load
+      var appcontent = document.getElementById("appcontent"); // browser
+      const requestpolicyOverlay = this;
+      if (appcontent) {
+        if (isFennec) {
+          appcontent.addEventListener("TabSelect", function(event) {
+            requestpolicyOverlay.tabChanged();
+          }, false);
         }
-      } catch (e) {
-        Logger.severe(Logger.TYPE_ERROR,
-            "Fatal Error, " + e + ", stack was: " + e.stack);
-        Logger.severe(Logger.TYPE_ERROR,
-            "Unable to initialize requestpolicy.overlay.");
-        throw e;
       }
-    },
-
-    //setContextMenuEnabled : function(isEnabled) {
-    //  rpContextMenu.setAttribute("hidden", !isEnabled);
-    //},
-
-    onWindowUnload: function() {
-      RequestProcessor.removeRequestObserver(self);
-      self._removeHistoryObserver();
-      self._removeLocationObserver();
-    },
-
-    /**
-     * Perform the actions required once the window has loaded. This just sets a
-     * listener for when the content of the window has changed (a page is loaded).
-     *
-     * @param {Event}
-     *          event
-     */
-    onWindowLoad: function() {
-      //try {
-        // Info on detecting page load at:
-        // http://developer.mozilla.org/En/Code_snippets/On_page_load
-        var appcontent = document.getElementById("appcontent"); // browser
-        const requestpolicyOverlay = this;
-        if (appcontent) {
-          if (isFennec) {
-            appcontent.addEventListener("TabSelect", function(event) {
-              requestpolicyOverlay.tabChanged();
-            }, false);
-          }
-        }
 
 
 
-        messageManager.addMessageListener(
-            MMID + ":notifyDocumentLoaded",
-            function(message) {
-              dump("notifyDocumentLoaded\n\n");
-              let {docID, documentURI} = message.data;
-
-              // the <browser> element of the corresponding tab.
-              let browser = message.target;
-
-              if (rpPrefBranch.getBoolPref("indicateBlockedObjects")) {
-                var indicateBlacklisted = rpPrefBranch
-                    .getBoolPref("indicateBlacklistedObjects");
-
-                var rejectedRequests = RequestProcessor._rejectedRequests
-                    .getOriginUri(documentURI);
-                let blockedURIs = {};
-                for (var destBase in rejectedRequests) {
-                  for (var destIdent in rejectedRequests[destBase]) {
-                    for (var destUri in rejectedRequests[destBase][destIdent]) {
-                      // case 1: indicateBlacklisted == true
-                      //         ==> indicate the object has been blocked
-                      //
-                      // case 2: indicateBlacklisted == false
-                      // case 2a: all requests have been blocked because of a blacklist
-                      //          ==> do *not* indicate
-                      //
-                      // case 2b: at least one of the blocked (identical) requests has been
-                      //          blocked by a rule *other than* the blacklist
-                      //          ==> *do* indicate
-                      let requests = rejectedRequests[destBase][destIdent][destUri];
-                      if (indicateBlacklisted ||
-                          requestpolicyOverlay._containsNonBlacklistedRequests(
-                              requests)) {
-                        blockedURIs[destUri] = blockedURIs[destUri] ||
-                            {identifier: DomainUtil.getIdentifier(destUri)};
-                      }
+      messageManager.addMessageListener(
+          MMID + ":notifyDocumentLoaded",
+          function(message) {
+            dump("notifyDocumentLoaded\n\n");
+            let {docID, documentURI} = message.data;
+
+            // the <browser> element of the corresponding tab.
+            let browser = message.target;
+
+            if (rpPrefBranch.getBoolPref("indicateBlockedObjects")) {
+              var indicateBlacklisted = rpPrefBranch
+                  .getBoolPref("indicateBlacklistedObjects");
+
+              var rejectedRequests = RequestProcessor._rejectedRequests
+                  .getOriginUri(documentURI);
+              let blockedURIs = {};
+              for (var destBase in rejectedRequests) {
+                for (var destIdent in rejectedRequests[destBase]) {
+                  for (var destUri in rejectedRequests[destBase][destIdent]) {
+                    // case 1: indicateBlacklisted == true
+                    //         ==> indicate the object has been blocked
+                    //
+                    // case 2: indicateBlacklisted == false
+                    // case 2a: all requests have been blocked because of a blacklist
+                    //          ==> do *not* indicate
+                    //
+                    // case 2b: at least one of the blocked (identical) requests has been
+                    //          blocked by a rule *other than* the blacklist
+                    //          ==> *do* indicate
+                    let requests = rejectedRequests[destBase][destIdent][destUri];
+                    if (indicateBlacklisted ||
+                        requestpolicyOverlay._containsNonBlacklistedRequests(
+                            requests)) {
+                      blockedURIs[destUri] = blockedURIs[destUri] ||
+                          {identifier: DomainUtil.getIdentifier(destUri)};
                     }
                   }
                 }
-                message.target.messageManager.sendAsyncMessage(
-                    MMID + ":indicateBlockedVisibleObjects",
-                    {blockedURIs: blockedURIs, docID: docID});
               }
+              message.target.messageManager.sendAsyncMessage(
+                  MMID + ":indicateBlockedVisibleObjects",
+                  {blockedURIs: blockedURIs, docID: docID});
+            }
 
-              if ("requestpolicy" in browser &&
-                  documentURI in browser.requestpolicy.blockedRedirects) {
-                var dest = browser.requestpolicy.blockedRedirects[documentURI];
-                Logger.warning(Logger.TYPE_HEADER_REDIRECT,
-                    "Showing notification for blocked redirect. To <" + dest +
-                    "> " + "from <" + documentURI + ">");
-                self._showRedirectNotification(browser, dest);
+            if ("requestpolicy" in browser &&
+                documentURI in browser.requestpolicy.blockedRedirects) {
+              var dest = browser.requestpolicy.blockedRedirects[documentURI];
+              Logger.warning(Logger.TYPE_HEADER_REDIRECT,
+                  "Showing notification for blocked redirect. To <" + dest +
+                  "> " + "from <" + documentURI + ">");
+              self._showRedirectNotification(browser, dest);
 
-                delete browser.requestpolicy.blockedRedirects[documentURI];
-              }
-            });
-
-        messageManager.addMessageListener(
-            MMID + ":notifyTopLevelDocumentLoaded",
-            function (message) {
-              // Clear any notifications that may have been present.
-              self._setContentBlockedState(false);
-              // We don't do this immediately anymore because slow systems might have
-              // this slow down the loading of the page, which is noticable
-              // especially with CSS loading delays (it's not unlikely that slow
-              // webservers have a hand in this, too).
-              // Note that the change to _updateBlockedContentStateAfterTimeout seems to have
-              // added a bug where opening a blank tab and then quickly switching back
-              // to the original tab can cause the original tab's blocked content
-              // notification to be cleared. A simple compensation was to decrease
-              // the timeout from 1000ms to 250ms, making it much less likely the tab
-              // switch can be done in time for a blank opened tab. This isn't a real
-              // solution, though.
-              self._updateBlockedContentStateAfterTimeout();
-            });
-
-        messageManager.addMessageListener(
-            MMID + ":notifyDOMFrameContentLoaded",
-            function (message) {
-              // This has an advantage over just relying on the
-              // observeBlockedRequest() call in that this will clear a blocked
-              // content notification if there no longer blocked content. Another way
-              // to solve this would be to observe allowed requests as well as blocked
-              // requests.
-              blockedContentCheckLastTime = (new Date()).getTime();
-              self._stopBlockedContentCheckTimeout();
-              self._updateBlockedContentState(message.target);
-            });
-
-        messageManager.addMessageListener(MMID + ":handleMetaRefreshes",
-                                          self.handleMetaRefreshes);
-
-        messageManager.addMessageListener(
-            MMID + ":notifyLinkClicked", function (message) {
-                RequestProcessor.registerLinkClicked(message.data.origin,
+              delete browser.requestpolicy.blockedRedirects[documentURI];
+            }
+          });
+
+      messageManager.addMessageListener(
+          MMID + ":notifyTopLevelDocumentLoaded",
+          function (message) {
+            // Clear any notifications that may have been present.
+            self._setContentBlockedState(false);
+            // We don't do this immediately anymore because slow systems might have
+            // this slow down the loading of the page, which is noticable
+            // especially with CSS loading delays (it's not unlikely that slow
+            // webservers have a hand in this, too).
+            // Note that the change to _updateBlockedContentStateAfterTimeout seems to have
+            // added a bug where opening a blank tab and then quickly switching back
+            // to the original tab can cause the original tab's blocked content
+            // notification to be cleared. A simple compensation was to decrease
+            // the timeout from 1000ms to 250ms, making it much less likely the tab
+            // switch can be done in time for a blank opened tab. This isn't a real
+            // solution, though.
+            self._updateBlockedContentStateAfterTimeout();
+          });
+
+      messageManager.addMessageListener(
+          MMID + ":notifyDOMFrameContentLoaded",
+          function (message) {
+            // This has an advantage over just relying on the
+            // observeBlockedRequest() call in that this will clear a blocked
+            // content notification if there no longer blocked content. Another way
+            // to solve this would be to observe allowed requests as well as blocked
+            // requests.
+            blockedContentCheckLastTime = (new Date()).getTime();
+            self._stopBlockedContentCheckTimeout();
+            self._updateBlockedContentState(message.target);
+          });
+
+      messageManager.addMessageListener(MMID + ":handleMetaRefreshes",
+                                        self.handleMetaRefreshes);
+
+      messageManager.addMessageListener(
+          MMID + ":notifyLinkClicked", function (message) {
+              RequestProcessor.registerLinkClicked(message.data.origin,
+                                                   message.data.dest);
+          });
+
+      messageManager.addMessageListener(
+          MMID + ":notifyFormSubmitted", function (message) {
+              RequestProcessor.registerFormSubmitted(message.data.origin,
                                                      message.data.dest);
-            });
+          });
 
-        messageManager.addMessageListener(
-            MMID + ":notifyFormSubmitted", function (message) {
-                RequestProcessor.registerFormSubmitted(message.data.origin,
-                                                       message.data.dest);
-            });
 
 
 
+      // Add an event listener for when the contentAreaContextMenu (generally
+      // the right-click menu within the document) is shown.
+      var contextMenu = document.getElementById("contentAreaContextMenu");
+      if (contextMenu) {
+        contextMenu.addEventListener("popupshowing",
+            self._contextMenuOnPopupShowing, false);
+      }
 
-        // Add an event listener for when the contentAreaContextMenu (generally
-        // the right-click menu within the document) is shown.
-        var contextMenu = document.getElementById("contentAreaContextMenu");
-        if (contextMenu) {
-          contextMenu.addEventListener("popupshowing",
-              self._contextMenuOnPopupShowing, false);
-        }
+      // We consider the default place for the popup to be attached to the
+      // context menu, so attach it there.
+      //self._attachPopupToContextMenu();
 
-        // We consider the default place for the popup to be attached to the
-        // context menu, so attach it there.
-        //self._attachPopupToContextMenu();
+      // Listen for the user changing tab so we can update any notification or
+      // indication of blocked requests.
+      if (!isFennec) {
+        var container = gBrowser.tabContainer;
+        container.addEventListener("TabSelect", function(event) {
+          requestpolicyOverlay.tabChanged();
+        }, false);
+        self._wrapAddTab();
+        self._addLocationObserver();
+        self._addHistoryObserver();
+      }
 
-        // Listen for the user changing tab so we can update any notification or
-        // indication of blocked requests.
-        if (!isFennec) {
-          var container = gBrowser.tabContainer;
-          container.addEventListener("TabSelect", function(event) {
-            requestpolicyOverlay.tabChanged();
-          }, false);
-          self._wrapAddTab();
-          self._addLocationObserver();
-          self._addHistoryObserver();
-        }
+    //} catch (e) {
+    //  Logger.severeError("Fatal Error, " + e, e);
+    //  Logger.severeError(
+    //      "Unable to complete requestpolicy.overlay.onWindowLoad actions.");
+    //}
+  };
+
+  self.handleMetaRefreshes = function(message) {
+    let {documentURI, metaRefreshes} = message.data;
+    let browser = message.target;
 
-      //} catch (e) {
-      //  Logger.severeError("Fatal Error, " + e, e);
-      //  Logger.severeError(
-      //      "Unable to complete requestpolicy.overlay.onWindowLoad actions.");
-      //}
-    },
-
-    handleMetaRefreshes: function(message) {
-      let {documentURI, metaRefreshes} = message.data;
-      let browser = message.target;
-
-      for (let i = 0, len = metaRefreshes.length; i < len; ++i) {
-        let {delay, destURI, originalDestURI} = metaRefreshes[i];
-
-        Logger.info(Logger.TYPE_META_REFRESH, "meta refresh to <" +
-            destURI + "> (" + delay + " second delay) found in document at <" +
-            documentURI + ">");
-
-        if (originalDestURI) {
-          Logger.info(Logger.TYPE_META_REFRESH,
-              "meta refresh destination <" + originalDestURI + "> " +
-              "appeared to be relative to <" + documentURI + ">, so " +
-              "it has been resolved to <" + destURI + ">");
+    for (let i = 0, len = metaRefreshes.length; i < len; ++i) {
+      let {delay, destURI, originalDestURI} = metaRefreshes[i];
+
+      Logger.info(Logger.TYPE_META_REFRESH, "meta refresh to <" +
+          destURI + "> (" + delay + " second delay) found in document at <" +
+          documentURI + ">");
+
+      if (originalDestURI) {
+        Logger.info(Logger.TYPE_META_REFRESH,
+            "meta refresh destination <" + originalDestURI + "> " +
+            "appeared to be relative to <" + documentURI + ">, so " +
+            "it has been resolved to <" + destURI + ">");
+      }
+
+      // We don't automatically perform any allowed redirects. Instead, we
+      // just detect when they will be blocked and show a notification. If
+      // the docShell has allowMetaRedirects disabled, it will be respected.
+      if (!Prefs.isBlockingDisabled()
+          && !RequestProcessor.isAllowedRedirect(documentURI, destURI)) {
+        // Ignore redirects to javascript. The browser will ignore them, as well.
+        if (DomainUtil.getUriObject(destURI).schemeIs("javascript")) {
+          Logger.warning(Logger.TYPE_META_REFRESH,
+              "Ignoring redirect to javascript URI <" + destURI + ">");
+          continue;
         }
+        // The request will be blocked by shouldLoad.
+        self._showRedirectNotification(browser, destURI, delay);
+      }
+    }
+  };
 
-        // We don't automatically perform any allowed redirects. Instead, we
-        // just detect when they will be blocked and show a notification. If
-        // the docShell has allowMetaRedirects disabled, it will be respected.
-        if (!Prefs.isBlockingDisabled()
-            && !RequestProcessor.isAllowedRedirect(documentURI, destURI)) {
-          // Ignore redirects to javascript. The browser will ignore them, as well.
-          if (DomainUtil.getUriObject(destURI).schemeIs("javascript")) {
-            Logger.warning(Logger.TYPE_META_REFRESH,
-                "Ignoring redirect to javascript URI <" + destURI + ">");
-            continue;
+  /**
+   * Shows a notification that an unknown scheme has been detected.
+   * This notification in only necessary for 1.0 beta versions until custom
+   * URI schemes are supported in RequestPolicy.
+   *
+   * issue: https://github.com/RequestPolicyContinued/requestpolicy/issues/447
+   *
+   * @param {nsIDOMWindow} contentWindow
+   * @param {String} scheme
+   */
+  self.showSchemeNotification = function(contentWindow, scheme) {
+    let browser = gBrowser.getBrowserForContentWindow(contentWindow);
+    let notificationBox = gBrowser.getNotificationBox(browser)
+    let notificationValue = "requestpolicy-scheme-notification";
+
+    let notification = notificationBox
+        .getNotificationWithValue(notificationValue);
+
+    var notificationLabel = "This page contains a request with a '" + scheme +
+        "' scheme which is unknown to RequestPolicy. Please report it.";
+
+    if (notification) {
+      notification.label = notificationLabel;
+    } else {
+      var buttons = [
+        {
+          label : "report this / more info",
+          accessKey : "r",
+          popup : null,
+          callback : function() {
+            let url = "https://github.com/RequestPolicyContinued/requestpolicy/issues/447";
+            window.openUILinkIn(url, "tab", {relatedToCurrent: true});
+          }
+        },
+        {
+          label : "hide",
+          accessKey : "h",
+          popup : null,
+          callback : function() {
+            // Do nothing. The notification closes when this is called.
           }
-          // The request will be blocked by shouldLoad.
-          self._showRedirectNotification(browser, destURI, delay);
         }
-      }
-    },
-
-    /**
-     * Shows a notification that an unknown scheme has been detected.
-     * This notification in only necessary for 1.0 beta versions until custom
-     * URI schemes are supported in RequestPolicy.
-     *
-     * issue: https://github.com/RequestPolicyContinued/requestpolicy/issues/447
-     *
-     * @param {nsIDOMWindow} contentWindow
-     * @param {String} scheme
-     */
-    showSchemeNotification : function(contentWindow, scheme) {
-      let browser = gBrowser.getBrowserForContentWindow(contentWindow);
-      let notificationBox = gBrowser.getNotificationBox(browser)
-      let notificationValue = "requestpolicy-scheme-notification";
-
-      let notification = notificationBox
-          .getNotificationWithValue(notificationValue);
-
-      var notificationLabel = "This page contains a request with a '" + scheme +
-          "' scheme which is unknown to RequestPolicy. Please report it.";
-
-      if (notification) {
-        notification.label = notificationLabel;
-      } else {
-        var buttons = [
-          {
-            label : "report this / more info",
-            accessKey : "r",
-            popup : null,
-            callback : function() {
-              let url = "https://github.com/RequestPolicyContinued/requestpolicy/issues/447";
-              window.openUILinkIn(url, "tab", {relatedToCurrent: true});
-            }
-          },
-          {
-            label : "hide",
-            accessKey : "h",
-            popup : null,
-            callback : function() {
-              // Do nothing. The notification closes when this is called.
-            }
+      ];
+      const priority = notificationBox.PRIORITY_WARNING_LOW;
+      let iconURI = "chrome://requestpolicy/skin/requestpolicy-icon-blocked.png";
+      notificationBox.appendNotification(notificationLabel, notificationValue,
+                                         iconURI, priority, buttons);
+    }
+  };
+
+  /**
+   * Shows a notification that a redirect was requested by a page (meta refresh
+   * or with headers).
+   *
+   * @param {<browser> element} browser
+   * @param {String}
+   *          redirectTargetUri
+   * @param {int}
+   *          delay
+   */
+  self._showRedirectNotification = function(browser, redirectTargetUri, delay) {
+    // TODO: Do something with the delay. Not sure what the best thing to do is
+    // without complicating the UI.
+
+    // TODO: The following error seems to be resulting when the notification
+    // goes away with a redirect, either after clicking "allow" or if the
+    // redirect is allowed and happens automatically.
+    //
+    // Source file: chrome://browser/content/browser.js
+    // Line: 3704
+    // ----------
+    // Error: self._closedNotification.parentNode is null
+    // Source file: chrome://global/content/bindings/notification.xml
+    // Line: 260
+
+    if (isFennec) {
+      Logger.warning(Logger.TYPE_INTERNAL,
+          "Should have shown redirect notification to <" + redirectTargetUri +
+          ">, but it's not implemented yet on Fennec.");
+      return;
+    }
+
+    var notificationBox = gBrowser.getNotificationBox(browser)
+    var notificationValue = "request-policy-meta-redirect";
+
+    // There doesn't seem to be a way to use the xul crop attribute with the
+    // notification, so do our own cropping, showing at a minimum the entire
+    // prePath.
+    const maxLength = 50;
+    if (redirectTargetUri.length < maxLength) {
+      var shortUri = redirectTargetUri;
+    } else {
+      var prePathLength = DomainUtil.getPrePath(redirectTargetUri).length + 1;
+      shortUri = redirectTargetUri
+          .substring(0, Math.max(prePathLength, maxLength)) + "...";
+    }
+    var notificationLabel = StringUtils.strbundle.formatStringFromName(
+        "redirectNotification", [shortUri], 1);
+
+    var notificationButtonOptions = StringUtils.strbundle.GetStringFromName("more");
+    var notificationButtonOptionsKey = StringUtils.strbundle
+        .GetStringFromName("more.accesskey");
+    var notificationButtonAllow = StringUtils.strbundle.GetStringFromName("allow");
+    var notificationButtonAllowKey = StringUtils.strbundle
+        .GetStringFromName("allow.accesskey");
+    var notificationButtonDeny = StringUtils.strbundle.GetStringFromName("deny");
+    var notificationButtonDenyKey = StringUtils.strbundle
+        .GetStringFromName("deny.accesskey");
+
+    var optionsPopupName = "requestpolicyRedirectNotificationOptions";
+    var optionsPopup = document.getElementById(optionsPopupName);
+    while (optionsPopup.firstChild) {
+      optionsPopup.removeChild(optionsPopup.firstChild);
+    }
+
+    var origin = requestpolicy.menu._addWildcard(
+        DomainUtil.getBaseDomain(self.getTopLevelDocumentUri()));
+    var dest = requestpolicy.menu._addWildcard(
+        DomainUtil.getBaseDomain(redirectTargetUri));
+
+    requestpolicy.classicmenu.
+        addMenuItemTemporarilyAllowDest(optionsPopup, dest);
+    requestpolicy.classicmenu.addMenuItemAllowDest(optionsPopup, dest);
+    requestpolicy.classicmenu.addMenuSeparator(optionsPopup);
+
+    requestpolicy.classicmenu.
+        addMenuItemTemporarilyAllowOrigin(optionsPopup, origin);
+    requestpolicy.classicmenu.addMenuItemAllowOrigin(optionsPopup, origin);
+    requestpolicy.classicmenu.addMenuSeparator(optionsPopup);
+
+    requestpolicy.classicmenu.
+        addMenuItemTemporarilyAllowOriginToDest(optionsPopup, origin, dest);
+    requestpolicy.classicmenu.
+        addMenuItemAllowOriginToDest(optionsPopup, origin, dest);
+
+
+
+
+    var notification = notificationBox
+        .getNotificationWithValue(notificationValue);
+    if (notification) {
+      notification.label = notificationLabel;
+    } else {
+      var buttons = [
+        {
+          label : notificationButtonAllow,
+          accessKey : notificationButtonAllowKey,
+          popup : null,
+          callback : function() {
+            // Fx 3.7a5+ calls shouldLoad for location.href changes.
+            RequestProcessor.registerAllowedRedirect(
+                browser.documentURI.specIgnoringRef, redirectTargetUri);
+
+            browser.messageManager.sendAsyncMessage(MMID + ":setLocation",
+                {uri: redirectTargetUri});
           }
-        ];
-        const priority = notificationBox.PRIORITY_WARNING_LOW;
-        let iconURI = "chrome://requestpolicy/skin/requestpolicy-icon-blocked.png";
-        notificationBox.appendNotification(notificationLabel, notificationValue,
-                                           iconURI, priority, buttons);
-      }
-    },
-
-    /**
-     * Shows a notification that a redirect was requested by a page (meta refresh
-     * or with headers).
-     *
-     * @param {<browser> element} browser
-     * @param {String}
-     *          redirectTargetUri
-     * @param {int}
-     *          delay
-     */
-    _showRedirectNotification: function(browser, redirectTargetUri, delay) {
-      // TODO: Do something with the delay. Not sure what the best thing to do is
-      // without complicating the UI.
-
-      // TODO: The following error seems to be resulting when the notification
-      // goes away with a redirect, either after clicking "allow" or if the
-      // redirect is allowed and happens automatically.
-      //
-      // Source file: chrome://browser/content/browser.js
-      // Line: 3704
-      // ----------
-      // Error: self._closedNotification.parentNode is null
-      // Source file: chrome://global/content/bindings/notification.xml
-      // Line: 260
-
-      if (isFennec) {
-        Logger.warning(Logger.TYPE_INTERNAL,
-            "Should have shown redirect notification to <" + redirectTargetUri +
-            ">, but it's not implemented yet on Fennec.");
-        return;
+        },
+        {
+          label : notificationButtonDeny,
+          accessKey : notificationButtonDenyKey,
+          popup : null,
+          callback : function() {
+            // Do nothing. The notification closes when this is called.
+          }
+        },
+        {
+          label : notificationButtonOptions,
+          accessKey : notificationButtonOptionsKey,
+          popup : optionsPopupName,
+          callback : null
+        }
+      ];
+      const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
+      notificationBox.appendNotification(notificationLabel, notificationValue,
+          "chrome://browser/skin/Info.png", priority, buttons);
+    }
+  };
+
+
+  /**
+   * Performs actions required to be performed after a tab change.
+   */
+  self.tabChanged = function() {
+    // TODO: verify the Fennec and all supported browser versions update the
+    // status bar properly with only the ProgressListener. Once verified,
+    // remove calls to tabChanged();
+    // self._updateBlockedContentState(content.document);
+  };
+
+  self._containsNonBlacklistedRequests = function(requests) {
+    for (let i = 0, len = requests.length; i < len; i++) {
+      if (!requests[i].isOnBlacklist()) {
+        // This request has not been blocked by the blacklist
+        return true;
       }
+    }
+    return false;
+  };
 
-      var notificationBox = gBrowser.getNotificationBox(browser)
-      var notificationValue = "request-policy-meta-redirect";
+  /**
+   * Checks if the document has blocked content and shows appropriate
+   * notifications.
+   */
+  self._updateBlockedContentState = function() {
+    try {
+      let browser = gBrowser.selectedBrowser;
+      let uri = DomainUtil.stripFragment(browser.currentURI.spec);
+      Logger.debug(Logger.TYPE_INTERNAL,
+          "Checking for blocked requests from page <" + uri + ">");
+
+      // TODO: this needs to be rewritten. checking if there is blocked
+      // content could be done much more efficiently.
+      let documentContainsBlockedContent = RequestProcessor
+          .getAllRequestsInBrowser(browser).containsBlockedRequests();
+      self._setContentBlockedState(documentContainsBlockedContent);
+
+      let logText = documentContainsBlockedContent ?
+                    "Requests have been blocked." :
+                    "No requests have been blocked.";
+      Logger.debug(Logger.TYPE_INTERNAL, logText);
+    } catch (e) {
+      Logger.severeError(
+          "Unable to complete _updateBlockedContentState actions: " + e, e);
+    }
+  };
 
-      // There doesn't seem to be a way to use the xul crop attribute with the
-      // notification, so do our own cropping, showing at a minimum the entire
-      // prePath.
-      const maxLength = 50;
-      if (redirectTargetUri.length < maxLength) {
-        var shortUri = redirectTargetUri;
-      } else {
-        var prePathLength = DomainUtil.getPrePath(redirectTargetUri).length + 1;
-        shortUri = redirectTargetUri
-            .substring(0, Math.max(prePathLength, maxLength)) + "...";
+  /**
+   * Sets the blocked content notifications visible to the user.
+   */
+  self._setContentBlockedState = function(isContentBlocked) {
+    var button = document.getElementById(toolbarButtonId);
+    if (button) {
+      button.setAttribute("requestpolicyBlocked", isContentBlocked);
+    }
+  };
+
+  /**
+   * Sets the permissive status visible to the user for all windows.
+   */
+  self._setPermissiveNotificationForAllWindows = function(isPermissive) {
+    // We do it for all windows, not just the current one.
+    var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+        .getService(Components.interfaces.nsIWindowMediator);
+    var enumerator = wm.getEnumerator(null);
+    while (enumerator.hasMoreElements()) {
+      var window = enumerator.getNext();
+      if ("requestpolicy" in window && "overlay" in window.requestpolicy) {
+        window.requestpolicy.overlay._setPermissiveNotification(isPermissive);
       }
-      var notificationLabel = StringUtils.strbundle.formatStringFromName(
-          "redirectNotification", [shortUri], 1);
-
-      var notificationButtonOptions = StringUtils.strbundle.GetStringFromName("more");
-      var notificationButtonOptionsKey = StringUtils.strbundle
-          .GetStringFromName("more.accesskey");
-      var notificationButtonAllow = StringUtils.strbundle.GetStringFromName("allow");
-      var notificationButtonAllowKey = StringUtils.strbundle
-          .GetStringFromName("allow.accesskey");
-      var notificationButtonDeny = StringUtils.strbundle.GetStringFromName("deny");
-      var notificationButtonDenyKey = StringUtils.strbundle
-          .GetStringFromName("deny.accesskey");
-
-      var optionsPopupName = "requestpolicyRedirectNotificationOptions";
-      var optionsPopup = document.getElementById(optionsPopupName);
-      while (optionsPopup.firstChild) {
-        optionsPopup.removeChild(optionsPopup.firstChild);
+    }
+  };
+
+  /**
+   * Sets the permissive status visible to the user for just this window.
+   */
+  self._setPermissiveNotification = function(isPermissive) {
+    var button = document.getElementById(toolbarButtonId);
+    if (button) {
+      button.setAttribute("requestpolicyPermissive", isPermissive);
+    }
+  };
+
+  /**
+   * This function is called when any allowed requests happen. This must be as
+   * fast as possible because request processing blocks until this function
+   * returns.
+   *
+   * @param {}
+   *          originUri
+   * @param {}
+   *          destUri
+   */
+  self.observeAllowedRequest = function(originUri, destUri) {
+    if (self.requestLogTreeView) {
+      self.requestLogTreeView.addAllowedRequest(originUri, destUri);
+    }
+  };
+
+  /**
+   * This function is called when any blocked requests happen. This must be as
+   * fast as possible because request processing blocks until this function
+   * returns.
+   *
+   * @param {}
+   *          originUri
+   * @param {}
+   *          destUri
+   */
+  self.observeBlockedRequest = function(originUri, destUri) {
+    self._updateNotificationDueToBlockedContent();
+    if (self.requestLogTreeView) {
+      self.requestLogTreeView.addBlockedRequest(originUri, destUri);
+    }
+  };
+
+  self.observeBlockedLinkClickRedirect = function(sourcePageUri, linkDestUri,
+      blockedRedirectUri) {
+    // TODO: Figure out a good way to notify the user. For now, it should at
+    // least be showing up in the menu the first time it happens. After that,
+    // some caching issues seem to get in the way and the blocked request
+    // isn't tried again, so there's no awareness of it.
+    Logger.warning(Logger.TYPE_HEADER_REDIRECT,
+        "Observed blocked link click redirect from page <" + sourcePageUri
+            + "> with redirect origin <" + linkDestUri
+            + "> and redirect dest <" + blockedRedirectUri
+            + ">. --- WARNING: other than the menu "
+            + "showing this blocked request, there is no other indication.");
+  };
+
+  /**
+   * If the RP service noticed a blocked top-level document request, look for
+   * a tab where the current location is the same as the origin of the blocked
+   * request. If we find one, show a redirect notification. Note that if there
+   * is more than one tab in this window open to the same origin, then we only
+   * show the notification in the first one we find. However, if there are
+   * multiple windows open and two different windows have a tab open to this
+   * same origin, then the first tab at that location in each window will show
+   * the redirect notification. This is because the RP service informs each
+   * window separately to look for a document to show a notification in.
+   */
+  self.observeBlockedTopLevelDocRequest = function (originUri, destUri) {
+    const browser = self._getBrowserAtUri(originUri);
+    if (!browser) {
+      return;
+    }
+    // We're called indirectly from shouldLoad so we can't block.
+    window.setTimeout(function() {
+      requestpolicy.overlay._showRedirectNotification(browser, destUri, 0);
+    }, 0);
+  };
+
+  self._getBrowserAtUri = function(uri) {
+    for (let i = 0, len = gBrowser.browsers.length; i < len; i++) {
+      if (gBrowser.getBrowserAtIndex(i).currentURI.spec == uri) {
+        return gBrowser.getBrowserAtIndex(i);
       }
+    }
+    return null;
+  };
 
-      var origin = requestpolicy.menu._addWildcard(
-          DomainUtil.getBaseDomain(self.getTopLevelDocumentUri()));
-      var dest = requestpolicy.menu._addWildcard(
-          DomainUtil.getBaseDomain(redirectTargetUri));
+  // TODO: observeBlockedFormSubmissionRedirect
 
-      requestpolicy.classicmenu.
-          addMenuItemTemporarilyAllowDest(optionsPopup, dest);
-      requestpolicy.classicmenu.addMenuItemAllowDest(optionsPopup, dest);
-      requestpolicy.classicmenu.addMenuSeparator(optionsPopup);
+  self._updateNotificationDueToBlockedContent = function() {
+    if (!blockedContentCheckTimeoutId) {
+      self._updateBlockedContentStateAfterTimeout();
+    }
+  };
 
-      requestpolicy.classicmenu.
-          addMenuItemTemporarilyAllowOrigin(optionsPopup, origin);
-      requestpolicy.classicmenu.addMenuItemAllowOrigin(optionsPopup, origin);
-      requestpolicy.classicmenu.addMenuSeparator(optionsPopup);
+  self._updateBlockedContentStateAfterTimeout = function() {
+    const browser = gBrowser.selectedBrowser;
+    blockedContentCheckTimeoutId = window.setTimeout(function() {
+      requestpolicy.overlay._updateBlockedContentState(browser);
+    }, blockedContentStateUpdateDelay);
+  };
 
-      requestpolicy.classicmenu.
-          addMenuItemTemporarilyAllowOriginToDest(optionsPopup, origin, dest);
-      requestpolicy.classicmenu.
-          addMenuItemAllowOriginToDest(optionsPopup, origin, dest);
+  self._stopBlockedContentCheckTimeout = function() {
+    if (blockedContentCheckTimeoutId) {
+      window.clearTimeout(blockedContentCheckTimeoutId);
+      blockedContentCheckTimeoutId = null;
+    }
+  };
 
+  /**
+   * Called as an event listener when popupshowing fires on the
+   * contentAreaContextMenu.
+   */
+  self._contextMenuOnPopupShowing = function() {
+    requestpolicy.overlay._wrapOpenLink();
+    /*requestpolicy.overlay._attachPopupToContextMenu();*/
+  };
 
+  /**
+   * Called as an event listener when popuphidden fires on the
+   * contentAreaContextMenu.
+   */
+  //_contextMenuOnPopupHidden : function(event) {
+  //  if (event.currentTarget != event.originalTarget) {
+  //    return;
+  //  }
+  //  /*requestpolicy.overlay._attachPopupToStatusbar();*/
+  //},
+
+  /**
+   * Wraps (overrides) the following methods of gContextMenu
+   * - openLink()
+   * - openLinkInPrivateWindow()
+   * - openLinkInCurrent()
+   * so that RequestPolicy can register a link-click.
+   *
+   * The original methods are defined in Firefox' nsContextMenu.js:
+   * http://mxr.mozilla.org/mozilla-central/source/browser/base/content/nsContextMenu.js
+   *
+   * The openLinkInTab() method doesn't need to be wrapped because new tabs are already
+   * recognized by tabAdded(), which is wrapped elsewhere. The tabAdded() function ends up
+   * being called when openLinkInTab() is called.
+   *
+   * TODO: There are even more similar methods in gContextMenu (frame-specific),
+   *       and perhaps the number will increase in future. Frame-specific contextMenu-
+   *       entries are working, but are registered e.g. as "new window opened" by
+   *       the subsequent shouldLoad() call.
+   */
+  self._wrapOpenLink = function() {
+    if (!gContextMenu.requestpolicyMethodsOverridden) {
+      gContextMenu.requestpolicyMethodsOverridden = true;
+
+      gContextMenu.openLink = function() {
+        RequestProcessor.registerLinkClicked(this.target.ownerDocument.URL, this.linkURL);
+        return this.__proto__.openLink.call(this); // call the overridden method
+      };
 
+      // Below, we check whether the functions exist before overriding it, because
+      // those functions have been introduced in later versions of Firefox than openLink().
 
-      var notification = notificationBox
-          .getNotificationWithValue(notificationValue);
-      if (notification) {
-        notification.label = notificationLabel;
-      } else {
-        var buttons = [
-          {
-            label : notificationButtonAllow,
-            accessKey : notificationButtonAllowKey,
-            popup : null,
-            callback : function() {
-              // Fx 3.7a5+ calls shouldLoad for location.href changes.
-              RequestProcessor.registerAllowedRedirect(
-                  browser.documentURI.specIgnoringRef, redirectTargetUri);
-
-              browser.messageManager.sendAsyncMessage(MMID + ":setLocation",
-                  {uri: redirectTargetUri});
-            }
-          },
-          {
-            label : notificationButtonDeny,
-            accessKey : notificationButtonDenyKey,
-            popup : null,
-            callback : function() {
-              // Do nothing. The notification closes when this is called.
-            }
-          },
-          {
-            label : notificationButtonOptions,
-            accessKey : notificationButtonOptionsKey,
-            popup : optionsPopupName,
-            callback : null
-          }
-        ];
-        const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
-        notificationBox.appendNotification(notificationLabel, notificationValue,
-            "chrome://browser/skin/Info.png", priority, buttons);
+      if (gContextMenu.openLinkInPrivateWindow) {
+        gContextMenu.openLinkInPrivateWindow = function() {
+          RequestProcessor.registerLinkClicked(this.target.ownerDocument.URL, this.linkURL);
+          return this.__proto__.openLinkInPrivateWindow.call(this);
+        };
       }
-    },
-
-
-    /**
-     * Performs actions required to be performed after a tab change.
-     */
-    tabChanged: function() {
-      // TODO: verify the Fennec and all supported browser versions update the
-      // status bar properly with only the ProgressListener. Once verified,
-      // remove calls to tabChanged();
-      // self._updateBlockedContentState(content.document);
-    },
-
-    _containsNonBlacklistedRequests: function(requests) {
-      for (let i = 0, len = requests.length; i < len; i++) {
-        if (!requests[i].isOnBlacklist()) {
-          // This request has not been blocked by the blacklist
-          return true;
-        }
+
+      if (gContextMenu.openLinkInCurrent) {
+        gContextMenu.openLinkInCurrent = function() {
+          RequestProcessor.registerLinkClicked(this.target.ownerDocument.URL, this.linkURL);
+          return this.__proto__.openLinkInCurrent.call(this);
+        };
       }
-      return false;
-    },
-
-    /**
-     * Checks if the document has blocked content and shows appropriate
-     * notifications.
-     */
-    _updateBlockedContentState: function() {
-      try {
-        let browser = gBrowser.selectedBrowser;
-        let uri = DomainUtil.stripFragment(browser.currentURI.spec);
-        Logger.debug(Logger.TYPE_INTERNAL,
-            "Checking for blocked requests from page <" + uri + ">");
-
-        // TODO: this needs to be rewritten. checking if there is blocked
-        // content could be done much more efficiently.
-        let documentContainsBlockedContent = RequestProcessor
-            .getAllRequestsInBrowser(browser).containsBlockedRequests();
-        self._setContentBlockedState(documentContainsBlockedContent);
-
-        let logText = documentContainsBlockedContent ?
-                      "Requests have been blocked." :
-                      "No requests have been blocked.";
-        Logger.debug(Logger.TYPE_INTERNAL, logText);
-      } catch (e) {
-        Logger.severeError(
-            "Unable to complete _updateBlockedContentState actions: " + e, e);
+    }
+  };
+
+  /**
+   * Modifies 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.
+   */
+  self._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://github.com/RequestPolicyContinued/requestpolicy/issues/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]);
+    }
+  };
+
+  /**
+   * This is called by the modified addTab().
+   *
+   * @param {String}
+   *          url
+   * @param {nsIURI/hash}
+   *          referrerURI
+   */
+  self.tabAdded = function(url, referrerURI) {
+    // The second argument to addTab was changed to a hash.
+    // See https://github.com/RequestPolicyContinued/requestpolicy/issues/38
+    if (referrerURI && !(referrerURI instanceof Components.interfaces.nsIURI)) {
+      if ("referrerURI" in referrerURI) {
+        referrerURI = referrerURI.referrerURI;
+      } else {
+        referrerURI = null;
       }
-    },
-
-    /**
-     * Sets the blocked content notifications visible to the user.
-     */
-    _setContentBlockedState: function(isContentBlocked) {
-      var button = document.getElementById(toolbarButtonId);
-      if (button) {
-        button.setAttribute("requestpolicyBlocked", isContentBlocked);
+    }
+    if (referrerURI) {
+      RequestProcessor.registerLinkClicked(referrerURI.spec, url);
+    }
+  };
+
+  self._addLocationObserver = function() {
+    self.locationListener = {
+      onLocationChange : function(aProgress, aRequest, aURI) {
+        // This gets called both for tab changes and for history navigation.
+        // The timer is running on the main window, not the document's window,
+        // so we want to stop the timer when the tab is changed.
+        requestpolicy.overlay._stopBlockedContentCheckTimeout();
+        requestpolicy.overlay
+            ._updateBlockedContentState(gBrowser.selectedBrowser);
+      },
+      // Though unnecessary for Gecko 2.0, I'm leaving in onSecurityChange for
+      // SeaMonkey because of https://bugzilla.mozilla.org/show_bug.cgi?id=685466
+      onSecurityChange : function() {
+      },
+
+      QueryInterface : function(aIID) {
+        if (aIID.equals(Components.interfaces.nsIWebProgressListener)
+            || aIID.equals(Components.interfaces.nsISupportsWeakReference)
+            || aIID.equals(Components.interfaces.nsISupports))
+          return this;
+        throw Components.results.NS_NOINTERFACE;
       }
-    },
-
-    /**
-     * Sets the permissive status visible to the user for all windows.
-     */
-    _setPermissiveNotificationForAllWindows: function(isPermissive) {
-      // We do it for all windows, not just the current one.
-      var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
-          .getService(Components.interfaces.nsIWindowMediator);
-      var enumerator = wm.getEnumerator(null);
-      while (enumerator.hasMoreElements()) {
-        var window = enumerator.getNext();
-        if ("requestpolicy" in window && "overlay" in window.requestpolicy) {
-          window.requestpolicy.overlay._setPermissiveNotification(isPermissive);
+    };
+
+    // https://developer.mozilla.org/en/Code_snippets/Progress_Listeners
+    // "Starting in Gecko 2.0, all events are optional. The tabbrowser only
+    // notifies you of the events for which you provide a callback."
+    gBrowser.addProgressListener(self.locationListener);
+  };
+
+  self._removeLocationObserver = function() {
+    gBrowser.removeProgressListener(self.locationListener);
+  };
+
+  self._addHistoryObserver = function() {
+    // Implements nsISHistoryListener (and nsISupportsWeakReference)
+    self.historyListener = {
+      OnHistoryGoBack : function(backURI) {
+        RequestProcessor.registerHistoryRequest(backURI.asciiSpec);
+        return true;
+      },
+
+      OnHistoryGoForward : function(forwardURI) {
+        RequestProcessor.registerHistoryRequest(forwardURI.asciiSpec);
+        return true;
+      },
+
+      OnHistoryGotoIndex : function(index, gotoURI) {
+        RequestProcessor.registerHistoryRequest(gotoURI.asciiSpec);
+        return true;
+      },
+
+      OnHistoryNewEntry : function(newURI) {
+      },
+
+      OnHistoryPurge : function(numEntries) {
+        return true;
+      },
+
+      OnHistoryReload : function(reloadURI, reloadFlags) {
+        return true;
+      },
+
+      QueryInterface : function(aIID, aResult) {
+        if (aIID.equals(Components.interfaces.nsISHistoryListener)
+            || aIID.equals(Components.interfaces.nsISupportsWeakReference)
+            || aIID.equals(Components.interfaces.nsISupports)) {
+          return this;
         }
+        throw Components.results.NS_NOINTERFACE;
+      },
+
+      GetWeakReference : function() {
+        return Components.classes["@mozilla.org/appshell/appShellService;1"]
+            .createInstance(Components.interfaces.nsIWeakReference);
       }
-    },
-
-    /**
-     * Sets the permissive status visible to the user for just this window.
-     */
-    _setPermissiveNotification: function(isPermissive) {
-      var button = document.getElementById(toolbarButtonId);
-      if (button) {
-        button.setAttribute("requestpolicyPermissive", isPermissive);
-      }
-    },
-
-    /**
-     * This function is called when any allowed requests happen. This must be as
-     * fast as possible because request processing blocks until this function
-     * returns.
-     *
-     * @param {}
-     *          originUri
-     * @param {}
-     *          destUri
-     */
-    observeAllowedRequest: function(originUri, destUri) {
-      if (self.requestLogTreeView) {
-        self.requestLogTreeView.addAllowedRequest(originUri, destUri);
-      }
-    },
-
-    /**
-     * This function is called when any blocked requests happen. This must be as
-     * fast as possible because request processing blocks until this function
-     * returns.
-     *
-     * @param {}
-     *          originUri
-     * @param {}
-     *          destUri
-     */
-    observeBlockedRequest: function(originUri, destUri) {
-      self._updateNotificationDueToBlockedContent();
-      if (self.requestLogTreeView) {
-        self.requestLogTreeView.addBlockedRequest(originUri, destUri);
-      }
-    },
-
-    observeBlockedLinkClickRedirect: function(sourcePageUri, linkDestUri,
-        blockedRedirectUri) {
-      // TODO: Figure out a good way to notify the user. For now, it should at
-      // least be showing up in the menu the first time it happens. After that,
-      // some caching issues seem to get in the way and the blocked request
-      // isn't tried again, so there's no awareness of it.
-      Logger.warning(Logger.TYPE_HEADER_REDIRECT,
-          "Observed blocked link click redirect from page <" + sourcePageUri
-              + "> with redirect origin <" + linkDestUri
-              + "> and redirect dest <" + blockedRedirectUri
-              + ">. --- WARNING: other than the menu "
-              + "showing this blocked request, there is no other indication.");
-    },
-
-    /**
-     * If the RP service noticed a blocked top-level document request, look for
-     * a tab where the current location is the same as the origin of the blocked
-     * request. If we find one, show a redirect notification. Note that if there
-     * is more than one tab in this window open to the same origin, then we only
-     * show the notification in the first one we find. However, if there are
-     * multiple windows open and two different windows have a tab open to this
-     * same origin, then the first tab at that location in each window will show
-     * the redirect notification. This is because the RP service informs each
-     * window separately to look for a document to show a notification in.
-     */
-    observeBlockedTopLevelDocRequest: function (originUri, destUri) {
-      const browser = self._getBrowserAtUri(originUri);
-      if (!browser) {
+    };
+
+    // there seems to be a bug in Firefox ESR 24 – the session history is
+    // null. After waiting a few miliseconds it's available. To be sure this
+    let tries = 0, waitTime = 20, maxTries = 10;
+    let tryAddingSHistoryListener = function() {
+      ++tries;
+      try {
+        let sHistory = gBrowser.webNavigation.sessionHistory;
+        sHistory.addSHistoryListener(self.historyListener);
         return;
-      }
-      // We're called indirectly from shouldLoad so we can't block.
-      window.setTimeout(function() {
-        requestpolicy.overlay._showRedirectNotification(browser, destUri, 0);
-      }, 0);
-    },
-
-    _getBrowserAtUri: function(uri) {
-      for (let i = 0, len = gBrowser.browsers.length; i < len; i++) {
-        if (gBrowser.getBrowserAtIndex(i).currentURI.spec == uri) {
-          return gBrowser.getBrowserAtIndex(i);
+      } catch (e) {
+        if (tries >= maxTries) {
+          Logger.severeError("Can't add session history listener, even " +
+              "after " + tries + " tries. "+e, e);
+          return;
         }
+        // call this function again in a few miliseconds.
+        setTimeout(tryAddingSHistoryListener, waitTime);
       }
-      return null;
-    },
+    };
+    tryAddingSHistoryListener();
+  };
 
-    // TODO: observeBlockedFormSubmissionRedirect
+  self._removeHistoryObserver = function() {
+    var sHistory = gBrowser.webNavigation.sessionHistory;
+    try {
+      sHistory.removeSHistoryListener(self.historyListener);
+    } catch (e) {
+      // When closing the last window in a session where additional windows
+      // have been opened and closed, this will sometimes fail (bug #175).
+    }
+  };
 
-    _updateNotificationDueToBlockedContent: function() {
-      if (!blockedContentCheckTimeoutId) {
-        self._updateBlockedContentStateAfterTimeout();
-      }
-    },
-
-    _updateBlockedContentStateAfterTimeout: function() {
-      const browser = gBrowser.selectedBrowser;
-      blockedContentCheckTimeoutId = window.setTimeout(function() {
-        requestpolicy.overlay._updateBlockedContentState(browser);
-      }, blockedContentStateUpdateDelay);
-    },
-
-    _stopBlockedContentCheckTimeout: function() {
-      if (blockedContentCheckTimeoutId) {
-        window.clearTimeout(blockedContentCheckTimeoutId);
-        blockedContentCheckTimeoutId = null;
+  /**
+   * Called before the popup menu is shown.
+   *
+   * @param {Event}
+   *          event
+   */
+  self.onPopupShowing = function(event) {
+  //    if (event.currentTarget != event.originalTarget) {
+  //      return;
+  //    }
+    requestpolicy.menu.prepareMenu();
+  };
+
+  /**
+   * Called after the popup menu has been hidden.
+   *
+   * @param {Event}
+   *          event
+   */
+  self.onPopupHidden = function(event) {
+    var rulesChanged = requestpolicy.menu.processQueuedRuleChanges();
+    if (rulesChanged || self._needsReloadOnMenuClose) {
+      if (rpPrefBranch.getBoolPref("autoReload")) {
+        let mm = gBrowser.selectedBrowser.messageManager;
+        mm.sendAsyncMessage(MMID + ":reload");
       }
-    },
-
-    /**
-     * Called as an event listener when popupshowing fires on the
-     * contentAreaContextMenu.
-     */
-    _contextMenuOnPopupShowing: function() {
-      requestpolicy.overlay._wrapOpenLink();
-      /*requestpolicy.overlay._attachPopupToContextMenu();*/
-    },
-
-    /**
-     * Called as an event listener when popuphidden fires on the
-     * contentAreaContextMenu.
-     */
-    //_contextMenuOnPopupHidden : function(event) {
-    //  if (event.currentTarget != event.originalTarget) {
-    //    return;
-    //  }
-    //  /*requestpolicy.overlay._attachPopupToStatusbar();*/
-    //},
-
-    /**
-     * Wraps (overrides) the following methods of gContextMenu
-     * - openLink()
-     * - openLinkInPrivateWindow()
-     * - openLinkInCurrent()
-     * so that RequestPolicy can register a link-click.
-     *
-     * The original methods are defined in Firefox' nsContextMenu.js:
-     * http://mxr.mozilla.org/mozilla-central/source/browser/base/content/nsContextMenu.js
-     *
-     * The openLinkInTab() method doesn't need to be wrapped because new tabs are already
-     * recognized by tabAdded(), which is wrapped elsewhere. The tabAdded() function ends up
-     * being called when openLinkInTab() is called.
-     *
-     * TODO: There are even more similar methods in gContextMenu (frame-specific),
-     *       and perhaps the number will increase in future. Frame-specific contextMenu-
-     *       entries are working, but are registered e.g. as "new window opened" by
-     *       the subsequent shouldLoad() call.
-     */
-    _wrapOpenLink: function() {
-      if (!gContextMenu.requestpolicyMethodsOverridden) {
-        gContextMenu.requestpolicyMethodsOverridden = true;
-
-        gContextMenu.openLink = function() {
-          RequestProcessor.registerLinkClicked(this.target.ownerDocument.URL, this.linkURL);
-          return this.__proto__.openLink.call(this); // call the overridden method
-        };
+    }
+    self._needsReloadOnMenuClose = false;
+  //    if (event.currentTarget != event.originalTarget) {
+  //      return;
+  //    }
+    // Leave the popup attached to the context menu, as we consider that the
+    // default location for it.
+    //self._attachPopupToContextMenu();
+  };
 
-        // Below, we check whether the functions exist before overriding it, because
-        // those functions have been introduced in later versions of Firefox than openLink().
+  /**
+   * Determines the top-level document's uri identifier based on the current
+   * identifier level setting.
+   *
+   * @return {String} The current document's identifier.
+   */
+  self.getTopLevelDocumentUriIdentifier = function() {
+    return DomainUtil.getIdentifier(self.getTopLevelDocumentUri());
+  };
 
-        if (gContextMenu.openLinkInPrivateWindow) {
-          gContextMenu.openLinkInPrivateWindow = function() {
-            RequestProcessor.registerLinkClicked(this.target.ownerDocument.URL, this.linkURL);
-            return this.__proto__.openLinkInPrivateWindow.call(this);
-          };
-        }
+  /**
+   * Get the top-level document's uri.
+   */
+  self.getTopLevelDocumentUri = function() {
+    let uri = gBrowser.selectedBrowser.currentURI.spec;
+    return rpService.getTopLevelDocTranslation(uri) ||
+        DomainUtil.stripFragment(uri);
+  };
 
-        if (gContextMenu.openLinkInCurrent) {
-          gContextMenu.openLinkInCurrent = function() {
-            RequestProcessor.registerLinkClicked(this.target.ownerDocument.URL, this.linkURL);
-            return this.__proto__.openLinkInCurrent.call(this);
-          };
-        }
-      }
-    },
-
-    /**
-     * Modifies 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.
-     */
-    _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://github.com/RequestPolicyContinued/requestpolicy/issues/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]);
-      }
-    },
-
-    /**
-     * This is called by the modified addTab().
-     *
-     * @param {String}
-     *          url
-     * @param {nsIURI/hash}
-     *          referrerURI
-     */
-    tabAdded: function(url, referrerURI) {
-      // The second argument to addTab was changed to a hash.
-      // See https://github.com/RequestPolicyContinued/requestpolicy/issues/38
-      if (referrerURI && !(referrerURI instanceof Components.interfaces.nsIURI)) {
-        if ("referrerURI" in referrerURI) {
-          referrerURI = referrerURI.referrerURI;
-        } else {
-          referrerURI = null;
-        }
-      }
-      if (referrerURI) {
-        RequestProcessor.registerLinkClicked(referrerURI.spec, url);
-      }
-    },
-
-    _addLocationObserver: function() {
-      self.locationListener = {
-        onLocationChange : function(aProgress, aRequest, aURI) {
-          // This gets called both for tab changes and for history navigation.
-          // The timer is running on the main window, not the document's window,
-          // so we want to stop the timer when the tab is changed.
-          requestpolicy.overlay._stopBlockedContentCheckTimeout();
-          requestpolicy.overlay
-              ._updateBlockedContentState(gBrowser.selectedBrowser);
-        },
-        // Though unnecessary for Gecko 2.0, I'm leaving in onSecurityChange for
-        // SeaMonkey because of https://bugzilla.mozilla.org/show_bug.cgi?id=685466
-        onSecurityChange : function() {
-        },
+  /**
+   * Toggles disabling of all blocking for the current session.
+   *
+   * @param {Event}
+   *          event
+   */
+  self.toggleTemporarilyAllowAll = function(event) {
+    var disabled = !Prefs.isBlockingDisabled();
+    Prefs.setBlockingDisabled(disabled);
+
+    // Change the link displayed in the menu.
+    document.getElementById('rp-link-enable-blocking').hidden = !disabled;
+    document.getElementById('rp-link-disable-blocking').hidden = disabled;
+
+    self._setPermissiveNotificationForAllWindows(disabled);
+  };
 
-        QueryInterface : function(aIID) {
-          if (aIID.equals(Components.interfaces.nsIWebProgressListener)
-              || aIID.equals(Components.interfaces.nsISupportsWeakReference)
-              || aIID.equals(Components.interfaces.nsISupports))
-            return this;
-          throw Components.results.NS_NOINTERFACE;
-        }
-      };
+  /**
+   * Allows requests from the specified origin to any destination for the
+   * duration of the browser session.
+   */
+  self.temporarilyAllowOrigin = function(originHost) {
+    PolicyManager.temporarilyAllowOrigin(originHost);
+  };
 
-      // https://developer.mozilla.org/en/Code_snippets/Progress_Listeners
-      // "Starting in Gecko 2.0, all events are optional. The tabbrowser only
-      // notifies you of the events for which you provide a callback."
-      gBrowser.addProgressListener(self.locationListener);
-    },
-
-    _removeLocationObserver: function() {
-      gBrowser.removeProgressListener(self.locationListener);
-    },
-
-    _addHistoryObserver: function() {
-      // Implements nsISHistoryListener (and nsISupportsWeakReference)
-      self.historyListener = {
-        OnHistoryGoBack : function(backURI) {
-          RequestProcessor.registerHistoryRequest(backURI.asciiSpec);
-          return true;
-        },
+  /**
+   * Allows the current document's origin to request from any destination for
+   * the duration of the browser session.
+   *
+   * @param {Event}
+   *          event
+   */
+  self.temporarilyAllowCurrentOrigin = function(event) {
+    // Note: the available variable "content" is different than the avaialable
+    // "window.target".
+    var host = self.getTopLevelDocumentUriIdentifier();
+    PolicyManager.temporarilyAllowOrigin(host);
+  };
 
-        OnHistoryGoForward : function(forwardURI) {
-          RequestProcessor.registerHistoryRequest(forwardURI.asciiSpec);
-          return true;
-        },
+  /**
+   * Allows a destination to be requested from any origin for the duration of
+   * the browser session.
+   *
+   * @param {String}
+   *          destHost
+   */
+  self.temporarilyAllowDestination = function(destHost) {
+    PolicyManager.temporarilyAllowDestination(destHost);
+  };
 
-        OnHistoryGotoIndex : function(index, gotoURI) {
-          RequestProcessor.registerHistoryRequest(gotoURI.asciiSpec);
-          return true;
-        },
+  /**
+   * Allows a destination to be requested from a single origin for the duration
+   * of the browser session.
+   *
+   * @param {String}
+   *          originHost
+   * @param {String}
+   *          destHost
+   */
+  self.temporarilyAllowOriginToDestination = function(originHost, destHost) {
+    PolicyManager.temporarilyAllowOriginToDestination(originHost, destHost);
+  };
 
-        OnHistoryNewEntry : function(newURI) {
-        },
+  /**
+   * Allows requests from an origin, including in future browser sessions.
+   */
+  self.allowOrigin = function(originHost) {
+    PolicyManager.allowOrigin(originHost);
+  };
 
-        OnHistoryPurge : function(numEntries) {
-          return true;
-        },
+  /**
+   * Allows the current document's origin to request from any destination,
+   * including in future browser sessions.
+   *
+   * @param {Event}
+   *          event
+   */
+  self.allowCurrentOrigin = function(event) {
+    var host = self.getTopLevelDocumentUriIdentifier();
+    PolicyManager.allowOrigin(host);
+  };
 
-        OnHistoryReload : function(reloadURI, reloadFlags) {
-          return true;
-        },
+  /**
+   * Allows requests to a destination, including in future browser sessions.
+   *
+   * @param {String}
+   *          destHost
+   */
+  self.allowDestination = function(destHost) {
+    PolicyManager.allowDestination(destHost);
+  };
 
-        QueryInterface : function(aIID, aResult) {
-          if (aIID.equals(Components.interfaces.nsISHistoryListener)
-              || aIID.equals(Components.interfaces.nsISupportsWeakReference)
-              || aIID.equals(Components.interfaces.nsISupports)) {
-            return this;
-          }
-          throw Components.results.NS_NOINTERFACE;
-        },
+  /**
+   * Allows requests to a destination from a single origin, including in future
+   * browser sessions.
+   *
+   * @param {String}
+   *          originHost
+   * @param {String}
+   *          destHost
+   */
+  self.allowOriginToDestination = function(originHost, destHost) {
+    PolicyManager.allowOriginToDestination(originHost, destHost);
+  };
 
-        GetWeakReference : function() {
-          return Components.classes["@mozilla.org/appshell/appShellService;1"]
-              .createInstance(Components.interfaces.nsIWeakReference);
-        }
-      };
+  /**
+   * Forbids an origin from requesting from any destination. This revoke's
+   * temporary or permanent request permissions the origin had been given.
+   */
+  self.forbidOrigin = function(originHost) {
+    rpService.forbidOrigin(originHost);
+  };
 
-      // there seems to be a bug in Firefox ESR 24 – the session history is
-      // null. After waiting a few miliseconds it's available. To be sure this
-      let tries = 0, waitTime = 20, maxTries = 10;
-      let tryAddingSHistoryListener = function() {
-        ++tries;
-        try {
-          let sHistory = gBrowser.webNavigation.sessionHistory;
-          sHistory.addSHistoryListener(self.historyListener);
-          return;
-        } catch (e) {
-          if (tries >= maxTries) {
-            Logger.severeError("Can't add session history listener, even " +
-                "after " + tries + " tries. "+e, e);
-            return;
-          }
-          // call this function again in a few miliseconds.
-          setTimeout(tryAddingSHistoryListener, waitTime);
-        }
-      };
-      tryAddingSHistoryListener();
-    },
+  /**
+   * Forbids the current document's origin from requesting from any destination.
+   * This revoke's temporary or permanent request permissions the origin had
+   * been given.
+   *
+   * @param {Event}
+   *          event
+   */
+  self.forbidCurrentOrigin = function(event) {
+    var host = self.getTopLevelDocumentUriIdentifier();
+    rpService.forbidOrigin(host);
+  };
 
-    _removeHistoryObserver: function() {
-      var sHistory = gBrowser.webNavigation.sessionHistory;
-      try {
-        sHistory.removeSHistoryListener(self.historyListener);
-      } catch (e) {
-        // When closing the last window in a session where additional windows
-        // have been opened and closed, this will sometimes fail (bug #175).
-      }
-    },
-
-    /**
-     * Called before the popup menu is shown.
-     *
-     * @param {Event}
-     *          event
-     */
-    onPopupShowing: function(event) {
-    //    if (event.currentTarget != event.originalTarget) {
-    //      return;
-    //    }
-      requestpolicy.menu.prepareMenu();
-    },
-
-    /**
-     * Called after the popup menu has been hidden.
-     *
-     * @param {Event}
-     *          event
-     */
-    onPopupHidden: function(event) {
-      var rulesChanged = requestpolicy.menu.processQueuedRuleChanges();
-      if (rulesChanged || self._needsReloadOnMenuClose) {
-        if (rpPrefBranch.getBoolPref("autoReload")) {
-          let mm = gBrowser.selectedBrowser.messageManager;
-          mm.sendAsyncMessage(MMID + ":reload");
-        }
-      }
-      self._needsReloadOnMenuClose = false;
-    //    if (event.currentTarget != event.originalTarget) {
-    //      return;
-    //    }
-      // Leave the popup attached to the context menu, as we consider that the
-      // default location for it.
-      //self._attachPopupToContextMenu();
-    },
-
-    /**
-     * Determines the top-level document's uri identifier based on the current
-     * identifier level setting.
-     *
-     * @return {String} The current document's identifier.
-     */
-    getTopLevelDocumentUriIdentifier: function() {
-      return DomainUtil.getIdentifier(self.getTopLevelDocumentUri());
-    },
-
-    /**
-     * Get the top-level document's uri.
-     */
-    getTopLevelDocumentUri: function() {
-      let uri = gBrowser.selectedBrowser.currentURI.spec;
-      return rpService.getTopLevelDocTranslation(uri) ||
-          DomainUtil.stripFragment(uri);
-    },
-
-    /**
-     * Toggles disabling of all blocking for the current session.
-     *
-     * @param {Event}
-     *          event
-     */
-    toggleTemporarilyAllowAll: function(event) {
-      var disabled = !Prefs.isBlockingDisabled();
-      Prefs.setBlockingDisabled(disabled);
-
-      // Change the link displayed in the menu.
-      document.getElementById('rp-link-enable-blocking').hidden = !disabled;
-      document.getElementById('rp-link-disable-blocking').hidden = disabled;
-
-      self._setPermissiveNotificationForAllWindows(disabled);
-    },
-
-    /**
-     * Allows requests from the specified origin to any destination for the
-     * duration of the browser session.
-     */
-    temporarilyAllowOrigin: function(originHost) {
-      PolicyManager.temporarilyAllowOrigin(originHost);
-    },
-
-    /**
-     * Allows the current document's origin to request from any destination for
-     * the duration of the browser session.
-     *
-     * @param {Event}
-     *          event
-     */
-    temporarilyAllowCurrentOrigin: function(event) {
-      // Note: the available variable "content" is different than the avaialable
-      // "window.target".
-      var host = self.getTopLevelDocumentUriIdentifier();
-      PolicyManager.temporarilyAllowOrigin(host);
-    },
-
-    /**
-     * Allows a destination to be requested from any origin for the duration of
-     * the browser session.
-     *
-     * @param {String}
-     *          destHost
-     */
-    temporarilyAllowDestination: function(destHost) {
-      PolicyManager.temporarilyAllowDestination(destHost);
-    },
-
-    /**
-     * Allows a destination to be requested from a single origin for the duration
-     * of the browser session.
-     *
-     * @param {String}
-     *          originHost
-     * @param {String}
-     *          destHost
-     */
-    temporarilyAllowOriginToDestination: function(originHost, destHost) {
-      PolicyManager.temporarilyAllowOriginToDestination(originHost, destHost);
-    },
-
-    /**
-     * Allows requests from an origin, including in future browser sessions.
-     */
-    allowOrigin: function(originHost) {
-      PolicyManager.allowOrigin(originHost);
-    },
-
-    /**
-     * Allows the current document's origin to request from any destination,
-     * including in future browser sessions.
-     *
-     * @param {Event}
-     *          event
-     */
-    allowCurrentOrigin: function(event) {
-      var host = self.getTopLevelDocumentUriIdentifier();
-      PolicyManager.allowOrigin(host);
-    },
-
-    /**
-     * Allows requests to a destination, including in future browser sessions.
-     *
-     * @param {String}
-     *          destHost
-     */
-    allowDestination: function(destHost) {
-      PolicyManager.allowDestination(destHost);
-    },
-
-    /**
-     * Allows requests to a destination from a single origin, including in future
-     * browser sessions.
-     *
-     * @param {String}
-     *          originHost
-     * @param {String}
-     *          destHost
-     */
-    allowOriginToDestination: function(originHost, destHost) {
-      PolicyManager.allowOriginToDestination(originHost, destHost);
-    },
-
-    /**
-     * Forbids an origin from requesting from any destination. This revoke's
-     * temporary or permanent request permissions the origin had been given.
-     */
-    forbidOrigin: function(originHost) {
-      rpService.forbidOrigin(originHost);
-    },
-
-    /**
-     * Forbids the current document's origin from requesting from any destination.
-     * This revoke's temporary or permanent request permissions the origin had
-     * been given.
-     *
-     * @param {Event}
-     *          event
-     */
-    forbidCurrentOrigin: function(event) {
-      var host = self.getTopLevelDocumentUriIdentifier();
-      rpService.forbidOrigin(host);
-    },
-
-    /**
-     * Forbids a destination from being requested by any origin. This revoke's
-     * temporary or permanent request permissions the destination had been given.
-     *
-     * @param {String}
-     *          destHost
-     */
-    forbidDestination: function(destHost) {
-      rpService.forbidDestination(destHost);
-    },
-
-    /**
-     * Forbids a destination from being requested by a single origin. This
-     * revoke's temporary or permanent request permissions the destination had
-     * been given.
-     *
-     * @param {String}
-     *          originHost
-     * @param {String}
-     *          destHost
-     */
-    forbidOriginToDestination: function(originHost, destHost) {
-      rpService.forbidOriginToDestination(originHost, destHost);
-    },
-
-    /**
-     * Revokes all temporary permissions granted during the current session.
-     *
-     * @param {Event}
-     *          event
-     */
-    revokeTemporaryPermissions: function(event) {
-      PolicyManager.revokeTemporaryRules();
-      self._needsReloadOnMenuClose = true;
-      var popup = document.getElementById('rp-popup');
-      popup.hidePopup();
-    },
-
-    _openInNewTab: function(uri) {
-      gBrowser.selectedTab = gBrowser.addTab(uri);
-    },
-
-    openMenuByHotkey: function() {
-      var popup = document.getElementById('rp-popup');
-      // Ideally we'd put the popup in its normal place based on the rp toolbar
-      // button but let's not count on that being visible. So, we'll be safe and
-      // anchor it within the content element. However, there's no good way to
-      // right-align a popup. So, we can either let it be left aligned or we can
-      // figure out where we think the top-left corner should be. And that's what
-      // we do.
-      // The first time the width will be 0. The default value is determined by
-      // logging it or you can probably figure it out from the CSS which doesn't
-      // directly specify the width of the entire popup.
-      //Logger.dump('popup width: ' + popup.clientWidth);
-      var popupWidth = popup.clientWidth ? 730 : popup.clientWidth;
-      var anchor = document.getElementById('content');
-      var contentWidth = anchor.clientWidth;
-      // Take a few pixels off so it doesn't cover the browser chrome's border.
-      var xOffset = contentWidth - popupWidth - 2;
-      popup.openPopup(anchor, 'overlap', xOffset);
-    },
-
-    //  showExtensionConflictInfo : function() {
-    //    var ext = rpService.getConflictingExtensions();
-    //    var extJson = JSON.stringify(ext);
-    //    self._openInNewTab(self._extensionConflictInfoUri
-    //        + encodeURIComponent(extJson));
-    //  },
-
-    //  showPrefetchInfo : function() {
-    //    self._openInNewTab(self._prefetchInfoUri);
-    //  },
-    //
-    //  showPrefetchDisablingInstructions : function() {
-    //    self._openInNewTab(self._prefetchDisablingInstructionsUri);
-    //  },
-
-    openToolbarPopup: function(anchor) {
-    //    requestpolicy.overlay._toolbox.insertBefore(requestpolicy.overlay._menu,
-    //        null);
-      menu.openPopup(anchor, 'after_start', 0, 0, true, true);
-    },
-
-    openPrefs: function() {
-      self.openSettingsTab('about:requestpolicy');
-    },
-
-    openPolicyManager: function() {
-      self.openSettingsTab('about:requestpolicy?yourpolicy');
-    },
-
-    openHelp: function() {
-      var tab = gBrowser.addTab('https://github.com/RequestPolicyContinued/requestpolicy/wiki/Help-and-Support');
-      gBrowser.selectedTab = tab;
-      var popup = document.getElementById('rp-popup');
-      popup.hidePopup();
-    },
-
-    //  openAbout : function() {
-    //    var tab = gBrowser.addTab('https://www.requestpolicy.com/about.html');
-    //    gBrowser.selectedTab = tab;
-    //  },
-
-    openSettingsTab: function (url) {
-      // Modified from the example at
-      // https://developer.mozilla.org/en-US/docs/Code_snippets/Tabbed_browser
-      var attrName = 'RequestPolicySettingsTab';
-      var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
-          .getService(Components.interfaces.nsIWindowMediator);
-      for (var found = false, index = 0, tabbrowser = wm.getEnumerator('navigator:browser').getNext().gBrowser;
-           index < tabbrowser.tabContainer.childNodes.length && !found;
-           index++) {
-        var currentTab = tabbrowser.tabContainer.childNodes[index];
-        if (currentTab.hasAttribute(attrName)) {
-          gBrowser.getBrowserForTab(currentTab).loadURI(url);
-          tabbrowser.selectedTab = currentTab;
-          // Focus *this* browser window in case another one is currently focused
-          tabbrowser.ownerDocument.defaultView.focus();
-          found = true;
-        }
-      }
-      if (!found) {
-        // Our tab isn't open. Open it now.
-        var browserEnumerator = wm.getEnumerator("navigator:browser");
-        var tabbrowser = browserEnumerator.getNext().gBrowser;
-        var newTab = tabbrowser.addTab(url);
-        newTab.setAttribute(attrName, "xyz");
-        tabbrowser.selectedTab = newTab;
+  /**
+   * Forbids a destination from being requested by any origin. This revoke's
+   * temporary or permanent request permissions the destination had been given.
+   *
+   * @param {String}
+   *          destHost
+   */
+  self.forbidDestination = function(destHost) {
+    rpService.forbidDestination(destHost);
+  };
+
+  /**
+   * Forbids a destination from being requested by a single origin. This
+   * revoke's temporary or permanent request permissions the destination had
+   * been given.
+   *
+   * @param {String}
+   *          originHost
+   * @param {String}
+   *          destHost
+   */
+  self.forbidOriginToDestination = function(originHost, destHost) {
+    rpService.forbidOriginToDestination(originHost, destHost);
+  };
+
+  /**
+   * Revokes all temporary permissions granted during the current session.
+   *
+   * @param {Event}
+   *          event
+   */
+  self.revokeTemporaryPermissions = function(event) {
+    PolicyManager.revokeTemporaryRules();
+    self._needsReloadOnMenuClose = true;
+    var popup = document.getElementById('rp-popup');
+    popup.hidePopup();
+  };
+
+  self._openInNewTab = function(uri) {
+    gBrowser.selectedTab = gBrowser.addTab(uri);
+  };
+
+  self.openMenuByHotkey = function() {
+    var popup = document.getElementById('rp-popup');
+    // Ideally we'd put the popup in its normal place based on the rp toolbar
+    // button but let's not count on that being visible. So, we'll be safe and
+    // anchor it within the content element. However, there's no good way to
+    // right-align a popup. So, we can either let it be left aligned or we can
+    // figure out where we think the top-left corner should be. And that's what
+    // we do.
+    // The first time the width will be 0. The default value is determined by
+    // logging it or you can probably figure it out from the CSS which doesn't
+    // directly specify the width of the entire popup.
+    //Logger.dump('popup width: ' + popup.clientWidth);
+    var popupWidth = popup.clientWidth ? 730 : popup.clientWidth;
+    var anchor = document.getElementById('content');
+    var contentWidth = anchor.clientWidth;
+    // Take a few pixels off so it doesn't cover the browser chrome's border.
+    var xOffset = contentWidth - popupWidth - 2;
+    popup.openPopup(anchor, 'overlap', xOffset);
+  };
+
+  //  showExtensionConflictInfo : function() {
+  //    var ext = rpService.getConflictingExtensions();
+  //    var extJson = JSON.stringify(ext);
+  //    self._openInNewTab(self._extensionConflictInfoUri
+  //        + encodeURIComponent(extJson));
+  //  },
+
+  //  showPrefetchInfo : function() {
+  //    self._openInNewTab(self._prefetchInfoUri);
+  //  },
+  //
+  //  showPrefetchDisablingInstructions : function() {
+  //    self._openInNewTab(self._prefetchDisablingInstructionsUri);
+  //  },
+
+  self.openToolbarPopup = function(anchor) {
+  //    requestpolicy.overlay._toolbox.insertBefore(requestpolicy.overlay._menu,
+  //        null);
+    menu.openPopup(anchor, 'after_start', 0, 0, true, true);
+  };
+
+  self.openPrefs = function() {
+    self.openSettingsTab('about:requestpolicy');
+  };
+
+  self.openPolicyManager = function() {
+    self.openSettingsTab('about:requestpolicy?yourpolicy');
+  };
+
+  self.openHelp = function() {
+    var tab = gBrowser.addTab('https://github.com/RequestPolicyContinued/requestpolicy/wiki/Help-and-Support');
+    gBrowser.selectedTab = tab;
+    var popup = document.getElementById('rp-popup');
+    popup.hidePopup();
+  };
+
+  //  openAbout : function() {
+  //    var tab = gBrowser.addTab('https://www.requestpolicy.com/about.html');
+  //    gBrowser.selectedTab = tab;
+  //  },
+
+  self.openSettingsTab = function (url) {
+    // Modified from the example at
+    // https://developer.mozilla.org/en-US/docs/Code_snippets/Tabbed_browser
+    var attrName = 'RequestPolicySettingsTab';
+    var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+        .getService(Components.interfaces.nsIWindowMediator);
+    for (var found = false, index = 0, tabbrowser = wm.getEnumerator('navigator:browser').getNext().gBrowser;
+         index < tabbrowser.tabContainer.childNodes.length && !found;
+         index++) {
+      var currentTab = tabbrowser.tabContainer.childNodes[index];
+      if (currentTab.hasAttribute(attrName)) {
+        gBrowser.getBrowserForTab(currentTab).loadURI(url);
+        tabbrowser.selectedTab = currentTab;
         // Focus *this* browser window in case another one is currently focused
         tabbrowser.ownerDocument.defaultView.focus();
+        found = true;
       }
-      var popup = document.getElementById('rp-popup');
-      popup.hidePopup();
-    },
-
-    clearRequestLog: function() {
-      self.requestLogTreeView.clear();
-    },
-
-    toggleRequestLog: function() {
-      var requestLog = document.getElementById("requestpolicy-requestLog");
-      var requestLogSplitter = document.getElementById("requestpolicy-requestLog-splitter");
-      var requestLogFrame = document.getElementById("requestpolicy-requestLog-frame");
-      //var openRequestLog = document.getElementById("requestpolicyOpenRequestLog");
-
-      // TODO: figure out how this should interact with the new menu.
-      //var closeRequestLog = document
-      //    .getElementById("requestpolicyCloseRequestLog");
-      var closeRequestLog = {};
-
-      if (requestLog.hidden) {
-        requestLogFrame.setAttribute("src",
-            "chrome://requestpolicy/content/ui/request-log.xul");
-        requestLog.hidden = requestLogSplitter.hidden = closeRequestLog.hidden = false;
-        //openRequestLog.hidden = true;
-      } else {
-        requestLogFrame.setAttribute("src", "about:blank");
-        requestLog.hidden = requestLogSplitter.hidden = closeRequestLog.hidden = true;
-        //openRequestLog.hidden = false;
-        self.requestLogTreeView = null;
-      }
+    }
+    if (!found) {
+      // Our tab isn't open. Open it now.
+      var browserEnumerator = wm.getEnumerator("navigator:browser");
+      var tabbrowser = browserEnumerator.getNext().gBrowser;
+      var newTab = tabbrowser.addTab(url);
+      newTab.setAttribute(attrName, "xyz");
+      tabbrowser.selectedTab = newTab;
+      // Focus *this* browser window in case another one is currently focused
+      tabbrowser.ownerDocument.defaultView.focus();
+    }
+    var popup = document.getElementById('rp-popup');
+    popup.hidePopup();
+  };
+
+  self.clearRequestLog = function() {
+    self.requestLogTreeView.clear();
+  };
+
+  self.toggleRequestLog = function() {
+    var requestLog = document.getElementById("requestpolicy-requestLog");
+    var requestLogSplitter = document.getElementById("requestpolicy-requestLog-splitter");
+    var requestLogFrame = document.getElementById("requestpolicy-requestLog-frame");
+    //var openRequestLog = document.getElementById("requestpolicyOpenRequestLog");
+
+    // TODO: figure out how this should interact with the new menu.
+    //var closeRequestLog = document
+    //    .getElementById("requestpolicyCloseRequestLog");
+    var closeRequestLog = {};
+
+    if (requestLog.hidden) {
+      requestLogFrame.setAttribute("src",
+          "chrome://requestpolicy/content/ui/request-log.xul");
+      requestLog.hidden = requestLogSplitter.hidden = closeRequestLog.hidden = false;
+      //openRequestLog.hidden = true;
+    } else {
+      requestLogFrame.setAttribute("src", "about:blank");
+      requestLog.hidden = requestLogSplitter.hidden = closeRequestLog.hidden = true;
+      //openRequestLog.hidden = false;
+      self.requestLogTreeView = null;
     }
   };
 

-- 
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