[Pkg-mozext-commits] [requestpolicy] 236/257: [ref] Prefs: make prefs more usable

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


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

taffit pushed a commit to branch master
in repository requestpolicy.

commit e0b5ee501fa12563b2d328abdeb8cc1833f2b8f1
Author: Martin Kimmerle <dev at 256k.de>
Date:   Tue Dec 22 17:31:21 2015 +0100

    [ref] Prefs: make prefs more usable
    
    Changes:
    * Create "models/prefs.jsm", it replaces "lib/prefs.js".
    Prefs getters and setters are now unified, that is, there
    is `Prefs.get()` and `Prefs.set()` which work for all three
    types (bool, int, char) as well as for both branches (RP,
    root). "PrefBranch" is an underlying class which assists the
    abstraction.
    * Create `Environment.prefObs`, which is a "PrefObserver". This
    replaces the "prefs" parts of `Environment.obsMan`
    (ObserverManager). So instead of `obsMan.observe*Pref()` we
    now use `prefObs.addListener()`. Just like the "Prefs" model
    described before, "PrefObserver" merges the two pref branches
    (RP, root) so there's only one `addListener()` function.
    
    Other changes:
    * The "PrefManager" now also uses the "Pref" model. There was
    no reason not to do so. It's just important that setting
    RequestPolicy's preferences on the "default pref branch" is
    done before "Prefs" is imported.
---
 src/content/lib/classes/map-of-sets.jsm        |  64 ++++++++
 src/content/lib/classes/pref-branch.jsm        |  78 +++++++++
 src/content/lib/classes/pref-observer.jsm      | 114 +++++++++++++
 src/content/lib/environment.jsm                |  16 +-
 src/content/lib/http-response.jsm              |   2 +-
 src/content/lib/logger.jsm                     |  24 ++-
 src/content/lib/observer-manager.jsm           |  53 +------
 src/content/lib/old-rules.jsm                  |   5 +-
 src/content/lib/prefs.jsm                      | 157 ------------------
 src/content/lib/request-processor.jsm          |   2 +-
 src/content/lib/request-processor.redirects.js |   2 +-
 src/content/lib/utils/info.jsm                 |  10 +-
 src/content/lib/utils/observers.jsm            |  23 +--
 src/content/lib/utils/windows.jsm              |   4 +-
 src/content/main/pref-manager.jsm              |  63 ++++----
 src/content/main/requestpolicy-service.jsm     |  14 +-
 src/content/models/prefs.jsm                   | 212 +++++++++++++++++++++++++
 src/content/settings/advancedprefs.js          |  36 ++---
 src/content/settings/basicprefs.js             |  28 ++--
 src/content/settings/common.js                 |   2 +-
 src/content/settings/defaultpolicy.js          |  15 +-
 src/content/settings/oldrules.js               |   9 +-
 src/content/settings/setup.js                  |  10 +-
 src/content/settings/subscriptions.js          |   2 +-
 src/content/settings/yourpolicy.js             |   2 +-
 src/content/ui/classicmenu.js                  |   4 +-
 src/content/ui/menu.js                         |  10 +-
 src/content/ui/overlay.js                      |  20 +--
 tests/xpcshell/test_map_of_sets.js             |  55 +++++++
 tests/xpcshell/test_oldrules.js                |   9 +-
 tests/xpcshell/xpcshell.ini                    |   1 +
 31 files changed, 668 insertions(+), 378 deletions(-)

diff --git a/src/content/lib/classes/map-of-sets.jsm b/src/content/lib/classes/map-of-sets.jsm
new file mode 100644
index 0000000..8a1fdd6
--- /dev/null
+++ b/src/content/lib/classes/map-of-sets.jsm
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ *
+ * RequestPolicy - A Firefox extension for control over cross-site requests.
+ * Copyright (c) 2015 Martin Kimmerle
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+/* exported MapOfSets */
+this.EXPORTED_SYMBOLS = ["MapOfSets"];
+
+//==============================================================================
+// MapOfSets
+//==============================================================================
+
+function MapOfSets() {
+  this._map = new Map();
+}
+
+MapOfSets.prototype.has = function(aMapKey) {
+  return this._map.has(aMapKey);
+};
+
+MapOfSets.prototype.get = function(aMapKey) {
+  return this._map.get(aMapKey);
+};
+
+MapOfSets.prototype.keys = function() {
+  return this._map.keys();
+};
+
+MapOfSets.prototype.addToSet = function(aMapKey, aValue) {
+  if (!this._map.has(aMapKey)) {
+    // automatically add a Set object to the Map
+    this._map.set(aMapKey, new Set());
+  }
+  this._map.get(aMapKey).add(aValue);
+};
+
+MapOfSets.prototype.deleteFromSet = function(aMapKey, aValue) {
+  if (!this._map.has(aMapKey)) {
+    return;
+  }
+  let set = this._map.get(aMapKey);
+  set.delete(aValue);
+  if (set.size === 0) {
+    // automatically remove the Set from the Map
+    this._map.delete(aMapKey);
+  }
+};
diff --git a/src/content/lib/classes/pref-branch.jsm b/src/content/lib/classes/pref-branch.jsm
new file mode 100644
index 0000000..f1824c0
--- /dev/null
+++ b/src/content/lib/classes/pref-branch.jsm
@@ -0,0 +1,78 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ *
+ * RequestPolicy - A Firefox extension for control over cross-site requests.
+ * Copyright (c) 2015 Martin Kimmerle
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+/* global Components */
+const {interfaces: Ci, utils: Cu} = Components;
+
+/* exported PrefBranch */
+this.EXPORTED_SYMBOLS = ["PrefBranch"];
+
+let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
+
+//==============================================================================
+// PrefBranch
+//==============================================================================
+
+/**
+ * @param {string} aBranchRoot
+ * @param {Object} aPrefNameToTypeMap A map from Pref Names to Pref Types.
+ *     Pref Types are "BoolPref", "CharPref", "IntPref", "ComplexValue".
+ */
+function PrefBranch(aBranchRoot, aPrefNameToTypeMap) {
+  this.branchRoot = aBranchRoot;
+  this.branch = Services.prefs.getBranch(aBranchRoot).
+      QueryInterface(Ci.nsIPrefBranch2);
+
+  // How should a pref name "foo.bar.baz" be translated to
+  // "getBoolPref" or "setIntPref"?
+  this._namesToTypesMap = aPrefNameToTypeMap;
+}
+
+PrefBranch.prototype._type = function(aPrefName) {
+  return this._namesToTypesMap[aPrefName];
+};
+
+PrefBranch.prototype.get = function(aPrefName) {
+  let getterFnName = "get" + this._type(aPrefName);
+  return this.branch[getterFnName](aPrefName);
+};
+
+PrefBranch.prototype.set = function(aPrefName, aValue) {
+  let setterFnName = "set" + this._type(aPrefName);
+  return this.branch[setterFnName](aPrefName, aValue);
+};
+
+PrefBranch.prototype.reset = function(aPrefName) {
+  this.branch.clearUserPref(aPrefName);
+};
+
+PrefBranch.prototype.isSet = function(aPrefName) {
+  return this.branch.prefHasUserValue(aPrefName);
+};
+
+PrefBranch.prototype.addObserver = function(aDomain, aObserver, aHoldWeak) {
+  return this.branch.addObserver(aDomain, aObserver, aHoldWeak);
+};
+
+PrefBranch.prototype.removeObserver = function(aDomain, aObserver) {
+  return this.branch.removeObserver(aDomain, aObserver);
+};
diff --git a/src/content/lib/classes/pref-observer.jsm b/src/content/lib/classes/pref-observer.jsm
new file mode 100644
index 0000000..d0d8080
--- /dev/null
+++ b/src/content/lib/classes/pref-observer.jsm
@@ -0,0 +1,114 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ *
+ * RequestPolicy - A Firefox extension for control over cross-site requests.
+ * Copyright (c) 2015 Martin Kimmerle
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+/* global Components */
+const {utils: Cu} = Components;
+
+/* exported PrefObserver */
+this.EXPORTED_SYMBOLS = ["PrefObserver"];
+
+let {ScriptLoader: {importModule}} = Cu.import(
+    "chrome://rpcontinued/content/lib/script-loader.jsm", {});
+let {MapOfSets} = importModule("lib/classes/map-of-sets");
+let {Prefs} = importModule("models/prefs");
+
+//==============================================================================
+// PrefObserver
+//==============================================================================
+
+function PrefObserver() {
+  this._maps = {
+    // Storage for listeners.
+    domainsToListeners: new MapOfSets(),
+
+    // Storage for observers.
+    domainsToObservers: new Map()
+  };
+}
+
+/**
+ * @param {string} aDomain The preference on which to listen for changes.
+ * @param {Function} aListener The callback.
+ */
+PrefObserver.prototype.addListener = function(aDomain, aListener) {
+  if (false === this._maps.domainsToObservers.has(aDomain)) {
+    // start to observe this Pref Domain
+    let observer = {
+      observe: this._onObserve.bind(this, aDomain)
+    };
+    Prefs._addObserver(aDomain, observer);
+    this._maps.domainsToObservers.set(aDomain, observer);
+  }
+
+  this._maps.domainsToListeners.addToSet(aDomain, aListener);
+};
+
+PrefObserver.prototype.addListeners = function(aDomains, aListener) {
+  for (let domain of aDomains) {
+    this.addListener(domain, aListener);
+  }
+};
+
+/**
+ * @param {string} aDomain The preference which is being observed for changes.
+ * @param {Function} aListener The callback.
+ */
+PrefObserver.prototype.removeListener = function(aDomain, aListener) {
+  this._maps.domainsToListeners.deleteFromSet(aDomain, aListener);
+
+  // no more listeners?
+  if (false === this._maps.domainsToListeners.has(aDomain)) {
+    // stop to observe this Pref Domain
+    let observer = this._maps.domainsToObservers.get(aDomain);
+    Prefs._removeObserver(aDomain, observer);
+    this._maps.domainsToObservers.delete(aDomain);
+  }
+};
+
+/**
+ * Remove all listeners in this Pref Observer.
+ */
+PrefObserver.prototype.removeAllListeners = function() {
+  for (let domain of this._maps.domainsToListeners.keys()) {
+    let listeners = this._maps.domainsToListeners.get(domain);
+    for (let listener of listeners.values()) {
+      this.removeListener(domain, listener);
+    }
+  }
+};
+
+/**
+ * Callback for nsIObserver.observe(). Call (notify) all listeners.
+ *
+ * @param {string} aDomain The Pref Domain of the corresponding observer.
+ * @param {nsIPrefBranch} aSubject The pref branch.
+ * @param {string} aTopic Always "nsPref:changed".
+ * @param {string} aData The name of the preference which has changed,
+ *     relative to the "root" of the aSubject branch.
+ */
+PrefObserver.prototype._onObserve = function(aDomain, aSubject, aTopic, aData) {
+  let prefName = aData;
+  let listeners = this._maps.domainsToListeners.get(aDomain);
+  for (let listener of listeners.values()) {
+    listener.call(null, prefName);
+  }
+};
diff --git a/src/content/lib/environment.jsm b/src/content/lib/environment.jsm
index 57b0487..c200bce 100644
--- a/src/content/lib/environment.jsm
+++ b/src/content/lib/environment.jsm
@@ -46,7 +46,9 @@ ScriptLoader.defineLazyModuleGetters({
   /* global ManagerForMessageListeners */
   "lib/manager-for-message-listeners": ["ManagerForMessageListeners"],
   /* global ObserverManager */
-  "lib/observer-manager": ["ObserverManager"]
+  "lib/observer-manager": ["ObserverManager"],
+  /* global PrefObserver */
+  "lib/classes/pref-observer": ["PrefObserver"]
 }, globalScope);
 
 //==============================================================================
@@ -218,6 +220,18 @@ var Environment = (function() {
     // #endif
   }
 
+  Object.defineProperty(Environment.prototype, "prefObs", {
+    get: function() {
+      if (!this._prefObserver) {
+        this._prefObserver = new PrefObserver();
+        this.addShutdownFunction(Environment.LEVELS.INTERFACE, () => {
+          this._prefObserver.removeAllListeners();
+        });
+      }
+      return this._prefObserver;
+    }
+  });
+
   Environment.LEVELS = LEVELS;
   Environment.ENV_STATES = ENV_STATES;
 
diff --git a/src/content/lib/http-response.jsm b/src/content/lib/http-response.jsm
index 38c5717..64ec5a0 100644
--- a/src/content/lib/http-response.jsm
+++ b/src/content/lib/http-response.jsm
@@ -34,7 +34,7 @@ let {ScriptLoader: {importModule}} = Cu.import(
 let {Logger} = importModule("lib/logger");
 let {DomainUtil} = importModule("lib/utils/domains");
 let {WindowUtils} = importModule("lib/utils/windows");
-let {Prefs} = importModule("lib/prefs");
+let {Prefs} = importModule("models/prefs");
 
 //==============================================================================
 // HttpResponse
diff --git a/src/content/lib/logger.jsm b/src/content/lib/logger.jsm
index 1b4f5b0..0aa00a0 100644
--- a/src/content/lib/logger.jsm
+++ b/src/content/lib/logger.jsm
@@ -34,7 +34,7 @@ let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
 let {ScriptLoader: {importModule}} = Cu.import(
     "chrome://rpcontinued/content/lib/script-loader.jsm", {});
 let {Environment, ProcessEnvironment} = importModule("lib/environment");
-let {rpPrefBranch} = importModule("lib/prefs");
+let {Prefs} = importModule("models/prefs");
 
 //==============================================================================
 // Logger
@@ -104,9 +104,9 @@ var Logger = (function() {
   let types = self.TYPE_ALL;
 
   function updateLoggingSettings() {
-    enabled = rpPrefBranch.getBoolPref("log");
-    level = rpPrefBranch.getIntPref("log.level");
-    types = rpPrefBranch.getIntPref("log.types");
+    enabled = Prefs.get("log");
+    level = Prefs.get("log.level");
+    types = Prefs.get("log.types");
   }
 
   /**
@@ -120,14 +120,8 @@ var Logger = (function() {
       return;
     }
 
-    // rpPrefBranch is available now.
-    ProcessEnvironment.obMan.observeRPPref(
-        ["log"],
-        function(subject, topic) {
-          if (topic === "nsPref:changed") {
-            updateLoggingSettings();
-          }
-        });
+    // RequestPolicy's pref branch is available now.
+    ProcessEnvironment.prefObs.addListener("log", updateLoggingSettings);
     updateLoggingSettings();
 
     // don't call init() anymore when doLog() is called
@@ -144,9 +138,9 @@ var Logger = (function() {
     // #ifdef UNIT_TESTING
     if (aType === self.TYPE_ERROR || aLevel === self.LEVEL_SEVERE) {
       // increment the error count
-      let errorCount = rpPrefBranch.getIntPref("unitTesting.errorCount");
-      rpPrefBranch.setIntPref("unitTesting.errorCount", ++errorCount);
-      Services.prefs.savePrefFile(null);
+      let errorCount = Prefs.get("unitTesting.errorCount");
+      Prefs.set("unitTesting.errorCount", ++errorCount);
+      Prefs.save();
 
       // log even if logging is disabled
       shouldLog = true;
diff --git a/src/content/lib/observer-manager.jsm b/src/content/lib/observer-manager.jsm
index 5d89d5b..048321c 100644
--- a/src/content/lib/observer-manager.jsm
+++ b/src/content/lib/observer-manager.jsm
@@ -27,22 +27,12 @@ const {utils: Cu} = Components;
 /* exported ObserverManager */
 this.EXPORTED_SYMBOLS = ["ObserverManager"];
 
-let globalScope = this;
-
 let {ScriptLoader} = Cu.import(
     "chrome://rpcontinued/content/lib/script-loader.jsm", {});
 let importModule = ScriptLoader.importModule;
-let {SingleTopicObserver, SinglePrefBranchObserver} = importModule(
-    "lib/utils/observers");
+let {SingleTopicObserver} = importModule("lib/utils/observers");
 let {Environment, ProcessEnvironment} = importModule("lib/environment");
 
-ScriptLoader.defineLazyModuleGetters({
-  "lib/prefs": [
-    "rpPrefBranch", /* global rpPrefBranch */
-    "rootPrefBranch" /* global rootPrefBranch */
-  ]
-}, globalScope);
-
 // Load the Logger at startup-time, not at load-time!
 // ( On load-time Logger might be null. )
 let Logger;
@@ -125,47 +115,6 @@ function ObserverManager(aEnv) {
       self.observeSingleTopic(topic, aCallback);
     });
   };
-
-  /**
-   * A shorthand for calling observe() with topic "rpcontinued-prefs-changed".
-   */
-  ObserverManager.prototype.observePrefChanges = function(aCallback) {
-    let self = this;
-    self.observeSingleTopic("rpcontinued-prefs-changed", aCallback);
-  };
-
-  //
-  // functions using nsIPrefBranch
-  //
-
-  /**
-   * Observe one single subdomain of a Pref Branch (using nsIPrefBranch).
-   * Details: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIPrefBranch#addObserver%28%29
-   *
-   * @param {nsIPrefBranch} aPrefBranch
-   * @param {String} aDomain
-   * @param {Function} aCallback
-   */
-  ObserverManager.prototype.observeSinglePrefBranch = function(aPrefBranch,
-                                                               aDomain,
-                                                               aCallback) {
-    let self = this;
-    let obs = new SinglePrefBranchObserver(aPrefBranch, aDomain, aCallback);
-    self.observers.push(obs);
-  };
-
-  ObserverManager.prototype.observeRPPref = function(aDomains, aCallback) {
-    let self = this;
-    aDomains.forEach(function(domain) {
-      self.observeSinglePrefBranch(rpPrefBranch, domain, aCallback);
-    });
-  };
-  ObserverManager.prototype.observeRootPref = function(aDomains, aCallback) {
-    let self = this;
-    aDomains.forEach(function(domain) {
-      self.observeSinglePrefBranch(rootPrefBranch, domain, aCallback);
-    });
-  };
 }
 
 /**
diff --git a/src/content/lib/old-rules.jsm b/src/content/lib/old-rules.jsm
index ec57fe5..a5d72b9 100644
--- a/src/content/lib/old-rules.jsm
+++ b/src/content/lib/old-rules.jsm
@@ -32,7 +32,7 @@ let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
 let {ScriptLoader: {importModule}} = Cu.import(
     "chrome://rpcontinued/content/lib/script-loader.jsm", {});
 let {DomainUtil} = importModule("lib/utils/domains");
-let {rpPrefBranch} = importModule("lib/prefs");
+let {Prefs} = importModule("models/prefs");
 
 //==============================================================================
 // OldRules
@@ -212,7 +212,8 @@ var OldRules = (function() {
    */
   OldRules._getPrefString = function(aPrefName) {
     try {
-      return rpPrefBranch.getComplexValue(aPrefName, Ci.nsISupportsString).data;
+      return Prefs.branches.rp.branch.
+          getComplexValue(aPrefName, Ci.nsISupportsString).data;
     } catch (e) {
       if (e.name !== "NS_ERROR_UNEXPECTED") {
         Cu.reportError(e);
diff --git a/src/content/lib/prefs.jsm b/src/content/lib/prefs.jsm
deleted file mode 100644
index cfb3bce..0000000
--- a/src/content/lib/prefs.jsm
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * ***** BEGIN LICENSE BLOCK *****
- *
- * RequestPolicy - A Firefox extension for control over cross-site requests.
- * Copyright (c) 2008-2012 Justin Samuel
- * Copyright (c) 2014-2015 Martin Kimmerle
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * ***** END LICENSE BLOCK *****
- */
-
-/* global Components */
-const {interfaces: Ci, utils: Cu} = Components;
-
-/* exported rpPrefBranch, rootPrefBranch, Prefs */
-this.EXPORTED_SYMBOLS = ["rpPrefBranch", "rootPrefBranch", "Prefs"];
-
-let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
-
-let {ScriptLoader: {importModule}} = Cu.import(
-    "chrome://rpcontinued/content/lib/script-loader.jsm", {});
-let {Environment, ProcessEnvironment} = importModule("lib/environment");
-let {Logger} = importModule("lib/logger");
-
-//==============================================================================
-// pref branches
-//==============================================================================
-
-var rpPrefBranch = Services.prefs.getBranch("extensions.requestpolicy.")
-    .QueryInterface(Ci.nsIPrefBranch2);
-var rootPrefBranch = Services.prefs.getBranch("")
-    .QueryInterface(Ci.nsIPrefBranch2);
-
-//==============================================================================
-// Prefs
-//==============================================================================
-
-var Prefs = (function() {
-  let self = {};
-
-  self.save = function() {
-    Services.prefs.savePrefFile(null);
-  };
-
-  function getRPBoolPref(aPrefName) {
-    return rpPrefBranch.getBoolPref(aPrefName);
-  }
-  function setRPBoolPref(aPrefName, aValue) {
-    rpPrefBranch.setBoolPref(aPrefName, aValue);
-  }
-  // not needed yet
-  //function getInvertedRPBoolPref(aPrefName) {
-  //  return !rpPrefBranch.getBoolPref(aPrefName);
-  //}
-  //function setInvertedRPBoolPref(aPrefName, aValue) {
-  //  rpPrefBranch.setBoolPref(aPrefName, !aValue);
-  //}
-
-  /**
-   * Define a list of pref aliases that will be available through
-   * `Prefs.getter_function_name()` and `Prefs.setter_function_name()`.
-   * Those functions will be added to `self` subsequently.
-   */
-  const RP_PREF_ALIASES = {
-    "bool": {
-      "defaultPolicy.allow": "DefaultAllow",
-      "defaultPolicy.allowSameDomain": "DefaultAllowSameDomain",
-
-      // As an example, this will become `isBlockingDisabled()` and
-      // `setBlockingDisabled()`:
-      "startWithAllowAllEnabled": "BlockingDisabled"
-    }
-  };
-
-  /**
-   * Dynamically create functions like `isDefaultAllow` or
-   * `setBlockingDisabled`.
-   */
-  {
-    for (let prefID in RP_PREF_ALIASES.bool) {
-      let prefName = RP_PREF_ALIASES.bool[prefID];
-
-      // define the pref's getter function to `self`
-      self["is" + prefName] = getRPBoolPref.bind(this, prefID);
-
-      // define the pref's getter function to `self`
-      self["set" + prefName] = setRPBoolPref.bind(this, prefID);
-    }
-  }
-
-  self.isPrefetchEnabled = function() {
-    return rootPrefBranch.getBoolPref("network.prefetch-next") ||
-        !rootPrefBranch.getBoolPref("network.dns.disablePrefetch");
-  };
-
-  function isPrefEmpty(pref) {
-    try {
-      let value = rpPrefBranch.getComplexValue(pref, Ci.nsISupportsString).data;
-      return value === "";
-    } catch (e) {
-      return true;
-    }
-  }
-
-  self.oldRulesExist = function() {
-    return !(isPrefEmpty("allowedOrigins") &&
-             isPrefEmpty("allowedDestinations") &&
-             isPrefEmpty("allowedOriginsToDestinations"));
-  };
-
-  self.clearPref = function(aPrefName) {
-    try {
-      if (rpPrefBranch.prefHasUserValue(aPrefName)) {
-        rpPrefBranch.clearUserPref(aPrefName);
-      }
-    } catch (e) {
-      Logger.dump("Clearing pref failed: " + e.toString());
-    }
-    Services.prefs.savePrefFile(null);
-  };
-
-  function observePref(subject, topic, data) {
-    if (topic === "nsPref:changed") {
-      // Send an observer notification that a pref that affects RP has been
-      // changed.
-      // TODO: also send the pref's name and its branch
-      Services.obs.notifyObservers(null, "rpcontinued-prefs-changed", null);
-    }
-  }
-
-  function registerPrefObserver() {
-    // observe everything on RP's pref branch
-    ProcessEnvironment.obMan.observeRPPref([""], observePref);
-
-    // observe what is needed else
-    ProcessEnvironment.obMan.observeRootPref([
-      "network.prefetch-next",
-      "network.dns.disablePrefetch"
-    ], observePref);
-  }
-  ProcessEnvironment.addStartupFunction(Environment.LEVELS.INTERFACE,
-                                        registerPrefObserver);
-
-  return self;
-}());
diff --git a/src/content/lib/request-processor.jsm b/src/content/lib/request-processor.jsm
index aa28992..e9d9ce7 100644
--- a/src/content/lib/request-processor.jsm
+++ b/src/content/lib/request-processor.jsm
@@ -36,7 +36,7 @@ let {ScriptLoader} = Cu.import(
 let importModule = ScriptLoader.importModule;
 
 let {Logger} = importModule("lib/logger");
-let {Prefs} = importModule("lib/prefs");
+let {Prefs} = importModule("models/prefs");
 let {PolicyManager} = importModule("lib/policy-manager");
 let {DomainUtil} = importModule("lib/utils/domains");
 let {RequestResult, REQUEST_REASON_USER_POLICY,
diff --git a/src/content/lib/request-processor.redirects.js b/src/content/lib/request-processor.redirects.js
index 973ec89..ea35178 100644
--- a/src/content/lib/request-processor.redirects.js
+++ b/src/content/lib/request-processor.redirects.js
@@ -29,7 +29,7 @@ const {interfaces: Ci, results: Cr, utils: Cu} = Components;
 let {ScriptLoader: {importModule}} = Cu.import(
     "chrome://rpcontinued/content/lib/script-loader.jsm", {});
 let {Logger} = importModule("lib/logger");
-let {Prefs} = importModule("lib/prefs");
+let {Prefs} = importModule("models/prefs");
 let {PolicyManager} = importModule("lib/policy-manager");
 let {DomainUtil} = importModule("lib/utils/domains");
 let {Utils} = importModule("lib/utils");
diff --git a/src/content/lib/utils/info.jsm b/src/content/lib/utils/info.jsm
index 11af9ad..fca19a2 100644
--- a/src/content/lib/utils/info.jsm
+++ b/src/content/lib/utils/info.jsm
@@ -32,7 +32,7 @@ let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
 
 let {ScriptLoader: {importModule}} = Cu.import(
     "chrome://rpcontinued/content/lib/script-loader.jsm", {});
-let {rpPrefBranch} = importModule("lib/prefs");
+let {Prefs} = importModule("models/prefs");
 let {C} = importModule("lib/utils/constants");
 let {ProcessEnvironment} = importModule("lib/environment");
 
@@ -54,12 +54,12 @@ var Info = (function() {
   // bad smell...
   // get/set last/current RP version
   if (ProcessEnvironment.isMainProcess) {
-    self.lastRPVersion = rpPrefBranch.getCharPref("lastVersion");
+    self.lastRPVersion = Prefs.get("lastVersion");
 
     self.curRPVersion = "0.0";
     // curRPVersion needs to be set asynchronously
     AddonManager.getAddonByID(C.EXTENSION_ID, function(addon) {
-      rpPrefBranch.setCharPref("lastVersion", addon.version);
+      Prefs.set("lastVersion", addon.version);
       self.curRPVersion = addon.version;
       if (self.lastRPVersion !== self.curRPVersion) {
         Services.prefs.savePrefFile(null);
@@ -78,11 +78,11 @@ var Info = (function() {
   // bad smell...
   // get/set last/current app (e.g. firefox) version
   if (ProcessEnvironment.isMainProcess) {
-    self.lastAppVersion = rpPrefBranch.getCharPref("lastAppVersion");
+    self.lastAppVersion = Prefs.get("lastAppVersion");
 
     let curAppVersion = Services.appinfo.version;
     self.curAppVersion = curAppVersion;
-    rpPrefBranch.setCharPref("lastAppVersion", curAppVersion);
+    Prefs.set("lastAppVersion", curAppVersion);
 
     if (self.lastAppVersion !== self.curAppVersion) {
       Services.prefs.savePrefFile(null);
diff --git a/src/content/lib/utils/observers.jsm b/src/content/lib/utils/observers.jsm
index c267341..4fb84d3 100644
--- a/src/content/lib/utils/observers.jsm
+++ b/src/content/lib/utils/observers.jsm
@@ -24,8 +24,8 @@
 /* global Components */
 const {utils: Cu} = Components;
 
-/* exported SingleTopicObserver, SinglePrefBranchObserver */
-this.EXPORTED_SYMBOLS = ["SingleTopicObserver", "SinglePrefBranchObserver"];
+/* exported SingleTopicObserver */
+this.EXPORTED_SYMBOLS = ["SingleTopicObserver"];
 
 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
 
@@ -80,22 +80,3 @@ SingleTopicObserver.prototype._register = function() {
 SingleTopicObserver.prototype._unregister = function() {
   Services.obs.removeObserver(this, this.topic);
 };
-
-//==============================================================================
-// SinglePrefBranchObserver
-//==============================================================================
-
-function SinglePrefBranchObserver(aBranch, aDomain, aCallback) {
-  this.branch = aBranch;
-  this.domain = aDomain;
-  Observer.call(this, aCallback);
-}
-SinglePrefBranchObserver.prototype = Object.create(Observer.prototype);
-SinglePrefBranchObserver.prototype.constructor = Observer;
-
-SinglePrefBranchObserver.prototype._register = function() {
-  this.branch.addObserver(this.domain, this, false);
-};
-SinglePrefBranchObserver.prototype._unregister = function() {
-  this.branch.removeObserver(this.domain, this);
-};
diff --git a/src/content/lib/utils/windows.jsm b/src/content/lib/utils/windows.jsm
index 367fa79..ebe64ea 100644
--- a/src/content/lib/utils/windows.jsm
+++ b/src/content/lib/utils/windows.jsm
@@ -29,7 +29,7 @@ this.EXPORTED_SYMBOLS = ["WindowUtils"];
 
 let {ScriptLoader: {importModule}} = Cu.import(
     "chrome://rpcontinued/content/lib/script-loader.jsm", {});
-let {rpPrefBranch} = importModule("lib/prefs");
+let {Prefs} = importModule("models/prefs");
 
 //==============================================================================
 // WindowUtils
@@ -124,7 +124,7 @@ var WindowUtils = (function() {
    */
   self.mayPermanentRulesBeAdded = function(aWindow) {
     return self.isWindowPrivate(aWindow) === false ||
-        rpPrefBranch.getBoolPref("privateBrowsingPermanentWhitelisting");
+        Prefs.get("privateBrowsingPermanentWhitelisting");
   };
 
   //
diff --git a/src/content/main/pref-manager.jsm b/src/content/main/pref-manager.jsm
index ddbf29a..22fd414 100644
--- a/src/content/main/pref-manager.jsm
+++ b/src/content/main/pref-manager.jsm
@@ -22,15 +22,12 @@
  */
 
 /* global Components */
-const {interfaces: Ci, utils: Cu} = Components;
+const {utils: Cu} = Components;
 
 /* exported PrefManager */
 this.EXPORTED_SYMBOLS = ["PrefManager"];
 
-let globalScope = this;
-
 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
-let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
 let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
 
 let {ScriptLoader: {importModule}} = Cu.import(
@@ -38,20 +35,8 @@ let {ScriptLoader: {importModule}} = Cu.import(
 let {C} = importModule("lib/utils/constants");
 let {Environment, ProcessEnvironment} = importModule("lib/environment");
 
-//==============================================================================
-// pref branches
-//==============================================================================
-
-/* global rpPrefBranch */
-XPCOMUtils.defineLazyGetter(globalScope, "rpPrefBranch", function() {
-  return Services.prefs.getBranch("extensions.requestpolicy.")
-      .QueryInterface(Ci.nsIPrefBranch2);
-});
-
-/* global rootPrefBranch */
-XPCOMUtils.defineLazyGetter(globalScope, "rootPrefBranch", function() {
-  return Services.prefs.getBranch("").QueryInterface(Ci.nsIPrefBranch2);
-});
+// Import when the default prefs have been set.
+let Prefs;
 
 //==============================================================================
 // PrefManager
@@ -62,19 +47,18 @@ var PrefManager = (function() {
 
   // TODO: move to bootstrap.js
   function handleUninstallOrDisable() {
-    var resetLinkPrefetch = rpPrefBranch.getBoolPref(
-        "prefetch.link.restoreDefaultOnUninstall");
-    var resetDNSPrefetch = rpPrefBranch.getBoolPref(
-        "prefetch.dns.restoreDefaultOnUninstall");
+    var resetLinkPrefetch = Prefs.get("prefetch.link." +
+                                      "restoreDefaultOnUninstall");
+    var resetDNSPrefetch = Prefs.get("prefetch.dns.restoreDefaultOnUninstall");
 
     if (resetLinkPrefetch) {
-      if (rootPrefBranch.prefHasUserValue("network.prefetch-next")) {
-        rootPrefBranch.clearUserPref("network.prefetch-next");
+      if (Prefs.isSet("root/ network.prefetch-next")) {
+        Prefs.reset("root/ network.prefetch-next");
       }
     }
     if (resetDNSPrefetch) {
-      if (rootPrefBranch.prefHasUserValue("network.dns.disablePrefetch")) {
-        rootPrefBranch.clearUserPref("network.dns.disablePrefetch");
+      if (Prefs.isSet("root/ network.dns.disablePrefetch")) {
+        Prefs.reset("root/ network.dns.disablePrefetch");
       }
     }
     Services.prefs.savePrefFile(null);
@@ -93,23 +77,30 @@ var PrefManager = (function() {
         {});
 
     // ================================
+    // Import `Prefs`
+    // --------------
+    /* jshint -W126 */ // JSHint issue #2775
+    ({Prefs} = importModule("models/prefs"));
+    /* jshint +W126 */
+
+    // ================================
     // Link/DNS prefetching
     // --------------------
     // Disable link prefetch.
-    if (rpPrefBranch.getBoolPref("prefetch.link.disableOnStartup")) {
-      if (rootPrefBranch.getBoolPref("network.prefetch-next")) {
-        rootPrefBranch.setBoolPref("network.prefetch-next", false);
+    if (Prefs.get("prefetch.link.disableOnStartup")) {
+      if (Prefs.get("root/ network.prefetch-next")) {
+        Prefs.set("root/ network.prefetch-next", false);
         console.info("Disabled link prefetch.");
       }
     }
     // Disable DNS prefetch.
-    if (rpPrefBranch.getBoolPref("prefetch.dns.disableOnStartup")) {
+    if (Prefs.get("prefetch.dns.disableOnStartup")) {
       // network.dns.disablePrefetch only exists starting in Firefox 3.1 (and it
       // doesn't have a default value, at least in 3.1b2, but if and when it
       // does have a default it will be false).
-      if (!rootPrefBranch.prefHasUserValue("network.dns.disablePrefetch") ||
-          !rootPrefBranch.getBoolPref("network.dns.disablePrefetch")) {
-        rootPrefBranch.setBoolPref("network.dns.disablePrefetch", true);
+      if (!Prefs.isSet("root/ network.dns.disablePrefetch") ||
+          !Prefs.get("root/ network.dns.disablePrefetch")) {
+        Prefs.set("root/ network.dns.disablePrefetch", true);
         console.info("Disabled DNS prefetch.");
       }
     }
@@ -122,9 +113,9 @@ var PrefManager = (function() {
       "temporarilyAllowedDestinations",
       "temporarilyAllowedOriginsToDestinations"
     ];
-    for (var i = 0; i < deletePrefs.length; i++) {
-      if (rpPrefBranch.prefHasUserValue(deletePrefs[i])) {
-        rpPrefBranch.clearUserPref(deletePrefs[i]);
+    for (let prefName of deletePrefs) {
+      if (Prefs.isSet(prefName)) {
+        Prefs.reset(prefName);
       }
     }
 
diff --git a/src/content/main/requestpolicy-service.jsm b/src/content/main/requestpolicy-service.jsm
index c03a1f4..00b37ac 100644
--- a/src/content/main/requestpolicy-service.jsm
+++ b/src/content/main/requestpolicy-service.jsm
@@ -33,7 +33,7 @@ let {AddonManager} = Cu.import("resource://gre/modules/AddonManager.jsm", {});
 let {ScriptLoader: {importModule}} = Cu.import(
     "chrome://rpcontinued/content/lib/script-loader.jsm", {});
 let {Logger} = importModule("lib/logger");
-let {Prefs, rpPrefBranch} = importModule("lib/prefs");
+let {Prefs} = importModule("models/prefs");
 let {PolicyManager} = importModule("lib/policy-manager");
 let {UserSubscriptions, SUBSCRIPTION_UPDATED_TOPIC, SUBSCRIPTION_ADDED_TOPIC,
      SUBSCRIPTION_REMOVED_TOPIC} = importModule("lib/subscription");
@@ -97,7 +97,7 @@ var rpService = (function() {
 
   // TODO: move to window manager
   function showWelcomeWindow() {
-    if (!rpPrefBranch.getBoolPref("welcomeWindowShown")) {
+    if (!Prefs.get("welcomeWindowShown")) {
       var url = "about:requestpolicy?setup";
 
       let win = WindowUtils.getMostRecentBrowserWindow();
@@ -110,10 +110,10 @@ var rpService = (function() {
       if (Info.isRPUpgrade) {
         // If the use has just upgraded from an 0.x version, set the
         // default-policy preferences based on the old preferences.
-        rpPrefBranch.setBoolPref("defaultPolicy.allow", false);
-        if (rpPrefBranch.prefHasUserValue("uriIdentificationLevel")) {
-          let identLevel = rpPrefBranch.getIntPref("uriIdentificationLevel");
-          rpPrefBranch.setBoolPref("defaultPolicy.allowSameDomain",
+        Prefs.set("defaultPolicy.allow", false);
+        if (Prefs.isSet("uriIdentificationLevel")) {
+          let identLevel = Prefs.get("uriIdentificationLevel");
+          Prefs.set("defaultPolicy.allowSameDomain",
               identLevel === 1);
         }
         Services.prefs.savePrefFile(null);
@@ -121,7 +121,7 @@ var rpService = (function() {
 
       tabbrowser.selectedTab = tabbrowser.addTab(url);
 
-      rpPrefBranch.setBoolPref("welcomeWindowShown", true);
+      Prefs.set("welcomeWindowShown", true);
       Services.prefs.savePrefFile(null);
     }
   }
diff --git a/src/content/models/prefs.jsm b/src/content/models/prefs.jsm
new file mode 100644
index 0000000..f1e1592
--- /dev/null
+++ b/src/content/models/prefs.jsm
@@ -0,0 +1,212 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ *
+ * RequestPolicy - A Firefox extension for control over cross-site requests.
+ * Copyright (c) 2008-2012 Justin Samuel
+ * Copyright (c) 2014-2015 Martin Kimmerle
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+/* global Components */
+const {interfaces: Ci, utils: Cu} = Components;
+
+/* exported Prefs */
+this.EXPORTED_SYMBOLS = ["Prefs"];
+
+let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
+
+let {ScriptLoader: {importModule}} = Cu.import(
+    "chrome://rpcontinued/content/lib/script-loader.jsm", {});
+let {PrefBranch} = importModule("lib/classes/pref-branch");
+
+//==============================================================================
+// Prefs
+//==============================================================================
+
+var Prefs = (function() {
+  let self = {};
+
+  self.save = function() {
+    Services.prefs.savePrefFile(null);
+  };
+
+  self.branches = {
+    rp: new PrefBranch("extensions.requestpolicy.", {
+      "autoReload": "BoolPref",
+      "contextMenu": "BoolPref",
+      "defaultPolicy.allow": "BoolPref",
+      "defaultPolicy.allowSameDomain": "BoolPref",
+      "indicateBlacklistedObjects": "BoolPref",
+      "indicateBlockedObjects": "BoolPref",
+      "lastAppVersion": "CharPref",
+      "lastVersion": "CharPref",
+      "log": "BoolPref",
+      "log.level": "IntPref",
+      "log.types": "IntPref",
+      "menu.info.showNumRequests": "BoolPref",
+      "menu.sorting": "CharPref",
+      "prefetch.dns.disableOnStartup": "BoolPref",
+      "prefetch.dns.restoreDefaultOnUninstall": "BoolPref",
+      "prefetch.link.disableOnStartup": "BoolPref",
+      "prefetch.link.restoreDefaultOnUninstall": "BoolPref",
+      "privateBrowsingPermanentWhitelisting": "BoolPref",
+      "startWithAllowAllEnabled": "BoolPref",
+      "welcomeWindowShown": "BoolPref",
+      // #ifdef UNIT_TESTING
+      "unitTesting.errorCount": "IntPref",
+      // #endif
+    }),
+
+    root: new PrefBranch("", {
+      "network.dns.disablePrefetch": "BoolPref",
+      "network.prefetch-next": "BoolPref",
+    })
+  };
+
+  /**
+   * Translate an alias into a real prefName, and also return the branch.
+   *
+   * Valid "fake pref names" are:
+   *   - "root/ network.prefetch-next" (root pref branch)
+   *   - "welcomeWindowShown" (RequestPolicy pref branch)
+   */
+  function getBranchAndRealName(aFakePrefName) {
+    if (aFakePrefName.startsWith("root/ ")) {
+      return {
+        branch: self.branches.root,
+        name: aFakePrefName.slice(6)
+      };
+    }
+    return {
+      branch: self.branches.rp,
+      name: aFakePrefName
+    };
+  }
+
+  self.get = function(aFakePrefName) {
+    let {branch, name} = getBranchAndRealName(aFakePrefName);
+    return branch.get(name);
+  };
+
+  self.set = function(aFakePrefName, aValue) {
+    let {branch, name} = getBranchAndRealName(aFakePrefName);
+    return branch.set(name, aValue);
+  };
+
+  self.reset = function(aFakePrefName) {
+    let {branch, name} = getBranchAndRealName(aFakePrefName);
+    return branch.reset(name);
+  };
+
+  self.isSet = function(aFakePrefName) {
+    let {branch, name} = getBranchAndRealName(aFakePrefName);
+    return branch.isSet(name);
+  };
+
+  //----------------------------------------------------------------------------
+  // Observer functions
+  //----------------------------------------------------------------------------
+
+  /**
+   * Notes about addObserver and removeObserver:
+   *
+   * The functions take fake domain names, but the actual observers
+   * will get the "real" pref names / domain names. If translation
+   * of names is needed, the two functions could be replaced by
+   * "addListener" and "removeListener" functions. In other words,
+   * the "domainsToObservers" object in "PrefObserver" could be moved
+   * here, and "PrefObserver" would only manage the listeners per
+   * environment.
+   *
+   * The addObserver and removeObserver functions are preixed with
+   * an underscore because they shouldn't be used directly, only
+   * by PrefObserver.
+   */
+
+  self._addObserver = function(aFakeDomain, aObserver, aHoldWeak) {
+    let {branch, name: domain} = getBranchAndRealName(aFakeDomain);
+    return branch.addObserver(domain, aObserver, aHoldWeak);
+  };
+
+  self._removeObserver = function(aFakeDomain, aObserver) {
+    let {branch, name: domain} = getBranchAndRealName(aFakeDomain);
+    return branch.removeObserver(domain, aObserver);
+  };
+
+  return self;
+}());
+
+//==============================================================================
+// Prefs - Aliases
+//==============================================================================
+
+(function(self) {
+  //----------------------------------------------------------------------------
+  // Dynamically created aliases
+  //----------------------------------------------------------------------------
+
+  /**
+   * Define a list of pref aliases that will be available through
+   * `Prefs.getter_function_name()` and `Prefs.setter_function_name()`.
+   * Those functions will be added to `self` subsequently.
+   */
+  const RP_PREF_ALIASES = {
+    "bool": [
+      ["defaultPolicy.allow", "DefaultAllow"],
+      ["defaultPolicy.allowSameDomain", "DefaultAllowSameDomain"],
+
+      // As an example, this will become `isBlockingDisabled()` and
+      // `setBlockingDisabled()`:
+      ["startWithAllowAllEnabled", "BlockingDisabled"]
+    ]
+  };
+
+  // Dynamically create functions like `isDefaultAllow` or
+  // `setBlockingDisabled`.
+  for (let [prefName, prefAlias] of RP_PREF_ALIASES.bool) {
+    // define the pref's getter function to `self`
+    self["is" + prefAlias] = self.get.bind(null, prefName);
+
+    // define the pref's getter function to `self`
+    self["set" + prefAlias] = self.set.bind(null, prefName);
+  }
+
+  //----------------------------------------------------------------------------
+  // Other aliases
+  //----------------------------------------------------------------------------
+
+  self.isPrefetchEnabled = function() {
+    return self.get("root/ network.prefetch-next") ||
+        !self.get("root/ network.dns.disablePrefetch");
+  };
+
+  function isOldRulePrefEmpty(pref) {
+    try {
+      let value = self.branches.rp.branch.
+          getComplexValue(pref, Ci.nsISupportsString).data;
+      return value === "";
+    } catch (e) {
+      return true;
+    }
+  }
+
+  self.oldRulesExist = function() {
+    return !(isOldRulePrefEmpty("allowedOrigins") &&
+             isOldRulePrefEmpty("allowedDestinations") &&
+             isOldRulePrefEmpty("allowedOriginsToDestinations"));
+  };
+}(Prefs));
diff --git a/src/content/settings/advancedprefs.js b/src/content/settings/advancedprefs.js
index 8aa598f..db49734 100644
--- a/src/content/settings/advancedprefs.js
+++ b/src/content/settings/advancedprefs.js
@@ -8,7 +8,7 @@
 
   var {ScriptLoader: {importModule}} = Cu.import(
       "chrome://rpcontinued/content/lib/script-loader.jsm", {});
-  var {rpPrefBranch, rootPrefBranch} = importModule("lib/prefs");
+  var {Prefs} = importModule("models/prefs");
 
   //============================================================================
 
@@ -39,27 +39,27 @@
   function updateDisplay() {
     // Link prefetch.
     $id("pref-linkPrefetch").checked =
-        rootPrefBranch.getBoolPref("network.prefetch-next");
+        Prefs.get("root/ network.prefetch-next");
 
     $id("pref-prefetch.link.disableOnStartup").checked =
-        rpPrefBranch.getBoolPref("prefetch.link.disableOnStartup");
+        Prefs.get("prefetch.link.disableOnStartup");
 
     $id("pref-prefetch.link.restoreDefaultOnUninstall").checked =
-        rpPrefBranch.getBoolPref("prefetch.link.restoreDefaultOnUninstall");
+        Prefs.get("prefetch.link.restoreDefaultOnUninstall");
 
     // DNS prefetch.
     $id("pref-dnsPrefetch").checked =
-        !rootPrefBranch.getBoolPref("network.dns.disablePrefetch");
+        !Prefs.get("root/ network.dns.disablePrefetch");
 
     $id("pref-prefetch.dns.disableOnStartup").checked =
-        rpPrefBranch.getBoolPref("prefetch.dns.disableOnStartup");
+        Prefs.get("prefetch.dns.disableOnStartup");
 
     $id("pref-prefetch.dns.restoreDefaultOnUninstall").checked =
-        rpPrefBranch.getBoolPref("prefetch.dns.restoreDefaultOnUninstall");
+        Prefs.get("prefetch.dns.restoreDefaultOnUninstall");
 
     // TODO: Create a class which acts as an API for preferences and which ensures
     // that the returned value is always a valid value for "string" preferences.
-    var sorting = rpPrefBranch.getCharPref("menu.sorting");
+    var sorting = Prefs.get("menu.sorting");
 
     if (sorting === $id("sortByNumRequests").value) {
       $id("sortByNumRequests").checked = true;
@@ -76,7 +76,7 @@
     }
 
     $id("menu.info.showNumRequests").checked =
-        rpPrefBranch.getBoolPref("menu.info.showNumRequests");
+        Prefs.get("menu.info.showNumRequests");
   }
 
   window.onload = function() {
@@ -84,14 +84,14 @@
 
     // Link prefetch.
     elManager.addListener($id("pref-linkPrefetch"), "change", function(event) {
-      rootPrefBranch.setBoolPref("network.prefetch-next", event.target.checked);
+      Prefs.set("root/ network.prefetch-next", event.target.checked);
       Services.prefs.savePrefFile(null);
     });
 
     elManager.addListener(
         $id("pref-prefetch.link.disableOnStartup"), "change",
         function(event) {
-          rpPrefBranch.setBoolPref("prefetch.link.disableOnStartup",
+          Prefs.set("prefetch.link.disableOnStartup",
                                    event.target.checked);
           Services.prefs.savePrefFile(null);
         });
@@ -99,14 +99,14 @@
     elManager.addListener(
         $id("pref-prefetch.link.restoreDefaultOnUninstall"), "change",
         function(event) {
-          rpPrefBranch.setBoolPref("prefetch.link.restoreDefaultOnUninstall",
+          Prefs.set("prefetch.link.restoreDefaultOnUninstall",
               event.target.checked);
           Services.prefs.savePrefFile(null);
         });
 
     // DNS prefetch.
     elManager.addListener($id("pref-dnsPrefetch"), "change", function(event) {
-      rootPrefBranch.setBoolPref("network.dns.disablePrefetch",
+      Prefs.set("root/ network.dns.disablePrefetch",
           !event.target.checked);
       Services.prefs.savePrefFile(null);
     });
@@ -114,7 +114,7 @@
     elManager.addListener(
         $id("pref-prefetch.dns.disableOnStartup"), "change",
         function(event) {
-          rpPrefBranch.setBoolPref("prefetch.dns.disableOnStartup",
+          Prefs.set("prefetch.dns.disableOnStartup",
               event.target.checked);
           Services.prefs.savePrefFile(null);
         });
@@ -122,13 +122,13 @@
     elManager.addListener(
         $id("pref-prefetch.dns.restoreDefaultOnUninstall"), "change",
         function(event) {
-          rpPrefBranch.setBoolPref("prefetch.dns.restoreDefaultOnUninstall",
+          Prefs.set("prefetch.dns.restoreDefaultOnUninstall",
               event.target.checked);
           Services.prefs.savePrefFile(null);
         });
 
     var sortingListener = function(event) {
-      rpPrefBranch.setCharPref("menu.sorting", event.target.value);
+      Prefs.set("menu.sorting", event.target.value);
       Services.prefs.savePrefFile(null);
     };
     elManager.addListener($id("sortByNumRequests"), "change", sortingListener);
@@ -138,13 +138,13 @@
     elManager.addListener(
         $id("menu.info.showNumRequests"), "change",
         function(event) {
-          rpPrefBranch.setBoolPref("menu.info.showNumRequests",
+          Prefs.set("menu.info.showNumRequests",
               event.target.checked);
           Services.prefs.savePrefFile(null);
         });
 
     // call updateDisplay() every time a preference gets changed
-    WinEnv.obMan.observePrefChanges(updateDisplay);
+    WinEnv.prefObs.addListener("", updateDisplay);
   };
 
 }());
diff --git a/src/content/settings/basicprefs.js b/src/content/settings/basicprefs.js
index 714f293..c2fd209 100644
--- a/src/content/settings/basicprefs.js
+++ b/src/content/settings/basicprefs.js
@@ -8,7 +8,7 @@
 
   var {ScriptLoader: {importModule}} = Cu.import(
       "chrome://rpcontinued/content/lib/script-loader.jsm", {});
-  var {rpPrefBranch} = importModule("lib/prefs");
+  var {Prefs} = importModule("models/prefs");
 
   //============================================================================
 
@@ -28,25 +28,25 @@
   });
 
   function updateDisplay() {
-    var indicate = rpPrefBranch.getBoolPref("indicateBlockedObjects");
+    var indicate = Prefs.get("indicateBlockedObjects");
     $id("pref-indicateBlockedObjects").checked = indicate;
     $id("indicateBlockedImages-details").hidden = !indicate;
 
     $id("pref-dontIndicateBlacklistedObjects").checked =
-        !rpPrefBranch.getBoolPref("indicateBlacklistedObjects");
+        !Prefs.get("indicateBlacklistedObjects");
 
     $id("pref-autoReload").checked =
-        rpPrefBranch.getBoolPref("autoReload");
+        Prefs.get("autoReload");
 
     $id("pref-privateBrowsingPermanentWhitelisting").checked =
-        rpPrefBranch.getBoolPref("privateBrowsingPermanentWhitelisting");
+        Prefs.get("privateBrowsingPermanentWhitelisting");
 
-    // if (rpPrefBranch.getBoolPref('defaultPolicy.allow')) {
-    //   var word = 'allow';
+    // if (Prefs.get("defaultPolicy.allow")) {
+    //   var word = "allow";
     // } else {
-    //   var word = 'block';
+    //   var word = "block";
     // }
-    // $id('defaultpolicyword').innerHTML = word;
+    // $id("defaultpolicyword").innerHTML = word;
   }
 
   window.onload = function() {
@@ -55,7 +55,7 @@
     elManager.addListener(
         $id("pref-indicateBlockedObjects"), "change",
         function(event) {
-          rpPrefBranch.setBoolPref("indicateBlockedObjects",
+          Prefs.set("indicateBlockedObjects",
               event.target.checked);
           Services.prefs.savePrefFile(null);
           updateDisplay();
@@ -64,14 +64,14 @@
     elManager.addListener(
         $id("pref-dontIndicateBlacklistedObjects"), "change",
         function(event) {
-          rpPrefBranch.setBoolPref("indicateBlacklistedObjects",
+          Prefs.set("indicateBlacklistedObjects",
                                    !event.target.checked);
           Services.prefs.savePrefFile(null);
           updateDisplay();
         });
 
     elManager.addListener($id("pref-autoReload"), "change", function(event) {
-      rpPrefBranch.setBoolPref("autoReload", event.target.checked);
+      Prefs.set("autoReload", event.target.checked);
       Services.prefs.savePrefFile(null);
       updateDisplay();
     });
@@ -79,14 +79,14 @@
     elManager.addListener(
         $id("pref-privateBrowsingPermanentWhitelisting"), "change",
         function(event) {
-          rpPrefBranch.setBoolPref("privateBrowsingPermanentWhitelisting",
+          Prefs.set("privateBrowsingPermanentWhitelisting",
                                    event.target.checked);
           Services.prefs.savePrefFile(null);
           updateDisplay();
         });
 
     // call updateDisplay() every time a preference gets changed
-    WinEnv.obMan.observePrefChanges(updateDisplay);
+    WinEnv.prefObs.addListener("", updateDisplay);
   };
 
 }());
diff --git a/src/content/settings/common.js b/src/content/settings/common.js
index 21662af..1900f17 100644
--- a/src/content/settings/common.js
+++ b/src/content/settings/common.js
@@ -10,7 +10,7 @@ var {common, WinEnv, elManager, $id, $str} = (function() {
   var {ScriptLoader: {importModule}} = Cu.import(
       "chrome://rpcontinued/content/lib/script-loader.jsm", {});
   var {StringUtils} = importModule("lib/utils/strings");
-  var {Prefs} = importModule("lib/prefs");
+  var {Prefs} = importModule("models/prefs");
   var {UserSubscriptions, SUBSCRIPTION_ADDED_TOPIC,
        SUBSCRIPTION_REMOVED_TOPIC} = importModule("lib/subscription");
   var {Environment, ProcessEnvironment} = importModule("lib/environment");
diff --git a/src/content/settings/defaultpolicy.js b/src/content/settings/defaultpolicy.js
index bbea0f4..aa61b5d 100644
--- a/src/content/settings/defaultpolicy.js
+++ b/src/content/settings/defaultpolicy.js
@@ -8,7 +8,7 @@
 
   var {ScriptLoader: {importModule}} = Cu.import(
       "chrome://rpcontinued/content/lib/script-loader.jsm", {});
-  var {rpPrefBranch} = importModule("lib/prefs");
+  var {Prefs} = importModule("models/prefs");
 
   //============================================================================
 
@@ -30,7 +30,7 @@
   });
 
   function updateDisplay() {
-    var defaultallow = rpPrefBranch.getBoolPref("defaultPolicy.allow");
+    var defaultallow = Prefs.get("defaultPolicy.allow");
     if (defaultallow) {
       $id("defaultallow").checked = true;
       $id("defaultdenysetting").hidden = true;
@@ -39,8 +39,7 @@
       $id("defaultdenysetting").hidden = false;
     }
 
-    var allowsamedomain = rpPrefBranch.getBoolPref(
-        "defaultPolicy.allowSameDomain");
+    var allowsamedomain = Prefs.get("defaultPolicy.allowSameDomain");
     $id("allowsamedomain").checked = allowsamedomain;
   }
 
@@ -55,7 +54,7 @@
         $id("defaultallow"), "change",
         function(event) {
           var allow = event.target.checked;
-          rpPrefBranch.setBoolPref("defaultPolicy.allow", allow);
+          Prefs.set("defaultPolicy.allow", allow);
           Services.prefs.savePrefFile(null);
           // Reload all subscriptions because it's likely that different
           // subscriptions will now be active.
@@ -68,7 +67,7 @@
         $id("defaultdeny"), "change",
         function(event) {
           var deny = event.target.checked;
-          rpPrefBranch.setBoolPref("defaultPolicy.allow", !deny);
+          Prefs.set("defaultPolicy.allow", !deny);
           Services.prefs.savePrefFile(null);
           // Reload all subscriptions because it's likely that different
           // subscriptions will now be active.
@@ -81,13 +80,13 @@
         $id("allowsamedomain"), "change",
         function(event) {
           var allowSameDomain = event.target.checked;
-          rpPrefBranch.setBoolPref("defaultPolicy.allowSameDomain",
+          Prefs.set("defaultPolicy.allowSameDomain",
               allowSameDomain);
           Services.prefs.savePrefFile(null);
         });
 
     // call updateDisplay() every time a preference gets changed
-    WinEnv.obMan.observePrefChanges(updateDisplay);
+    WinEnv.prefObs.addListener("", updateDisplay);
   };
 
 }());
diff --git a/src/content/settings/oldrules.js b/src/content/settings/oldrules.js
index c49f409..7340c96 100644
--- a/src/content/settings/oldrules.js
+++ b/src/content/settings/oldrules.js
@@ -6,7 +6,7 @@
 
   var {ScriptLoader: {importModule}} = Cu.import(
       "chrome://rpcontinued/content/lib/script-loader.jsm", {});
-  var {Prefs} = importModule("lib/prefs");
+  var {Prefs} = importModule("models/prefs");
   var {PolicyManager} = importModule("lib/policy-manager");
   var {OldRules} = importModule("lib/old-rules");
 
@@ -67,9 +67,10 @@
   }
 
   window.deleteOldRules = function() {
-    Prefs.clearPref("allowedOrigins");
-    Prefs.clearPref("allowedDestinations");
-    Prefs.clearPref("allowedOriginsToDestinations");
+    Prefs.reset("allowedOrigins");
+    Prefs.reset("allowedDestinations");
+    Prefs.reset("allowedOriginsToDestinations");
+    Prefs.save();
     $("#doimport").hide();
     $("#deletedone").show();
     $("#showReimportOptions").hide();
diff --git a/src/content/settings/setup.js b/src/content/settings/setup.js
index c23e783..b4894e7 100644
--- a/src/content/settings/setup.js
+++ b/src/content/settings/setup.js
@@ -9,7 +9,7 @@
   var {ScriptLoader: {importModule}} = Cu.import(
       "chrome://rpcontinued/content/lib/script-loader.jsm", {});
   var {Info} = importModule("lib/utils/info");
-  var {rpPrefBranch} = importModule("lib/prefs");
+  var {Prefs} = importModule("models/prefs");
   var {SUBSCRIPTION_ADDED_TOPIC, SUBSCRIPTION_REMOVED_TOPIC} =
       importModule("lib/subscription");
   var {rpService} = importModule("main/requestpolicy-service");
@@ -44,7 +44,7 @@
   }
 
   function handleDefaultPolicyChange() {
-    rpPrefBranch.setBoolPref("defaultPolicy.allow",
+    Prefs.set("defaultPolicy.allow",
         $id("defaultallow").checked);
     Services.prefs.savePrefFile(null);
     setAllowSameDomainBlockDisplay();
@@ -52,7 +52,7 @@
   }
 
   function handleAllowSameDomainChange() {
-    rpPrefBranch.setBoolPref("defaultPolicy.allowSameDomain",
+    Prefs.set("defaultPolicy.allowSameDomain",
         $id("allowsamedomain").checked);
     Services.prefs.savePrefFile(null);
   }
@@ -119,7 +119,7 @@
 
     // Populate the form values based on the user's current settings.
 
-    let defaultAllow = rpPrefBranch.getBoolPref("defaultPolicy.allow");
+    let defaultAllow = Prefs.get("defaultPolicy.allow");
     $id("defaultallow").checked = defaultAllow;
     $id("defaultdeny").checked = !defaultAllow;
     if (!defaultAllow) {
@@ -127,7 +127,7 @@
     }
 
     $id("allowsamedomain").checked =
-        rpPrefBranch.getBoolPref("defaultPolicy.allowSameDomain");
+        Prefs.get("defaultPolicy.allowSameDomain");
 
     // FIXME: Add a pref to disable subscriptions globally;  issue #713
     // Subscriptions are only simple here if we assume the user
diff --git a/src/content/settings/subscriptions.js b/src/content/settings/subscriptions.js
index 4213326..f93887a 100644
--- a/src/content/settings/subscriptions.js
+++ b/src/content/settings/subscriptions.js
@@ -8,7 +8,7 @@
 
   var {ScriptLoader: {importModule}} = Cu.import(
       "chrome://rpcontinued/content/lib/script-loader.jsm", {});
-  var {Prefs} = importModule("lib/prefs");
+  var {Prefs} = importModule("models/prefs");
   var {Logger} = importModule("lib/logger");
   var {SUBSCRIPTION_ADDED_TOPIC, SUBSCRIPTION_REMOVED_TOPIC} =
       importModule("lib/subscription");
diff --git a/src/content/settings/yourpolicy.js b/src/content/settings/yourpolicy.js
index 521d1f1..2ada85a 100644
--- a/src/content/settings/yourpolicy.js
+++ b/src/content/settings/yourpolicy.js
@@ -6,7 +6,7 @@
 
   var {ScriptLoader: {importModule}} = Cu.import(
       "chrome://rpcontinued/content/lib/script-loader.jsm", {});
-  var {Prefs} = importModule("lib/prefs");
+  var {Prefs} = importModule("models/prefs");
   var {PolicyManager} = importModule("lib/policy-manager");
 
   //============================================================================
diff --git a/src/content/ui/classicmenu.js b/src/content/ui/classicmenu.js
index 1790644..52b334e 100644
--- a/src/content/ui/classicmenu.js
+++ b/src/content/ui/classicmenu.js
@@ -32,7 +32,7 @@ window.rpcontinued.classicmenu = (function() {
   let {ScriptLoader: {importModule}} = Cu.import(
       "chrome://rpcontinued/content/lib/script-loader.jsm", {});
   let {Logger} = importModule("lib/logger");
-  let {rpPrefBranch} = importModule("lib/prefs");
+  let {Prefs} = importModule("models/prefs");
   let {StringUtils} = importModule("lib/utils/strings");
   let {DOMUtils} = importModule("lib/utils/dom");
 
@@ -45,7 +45,7 @@ window.rpcontinued.classicmenu = (function() {
   * be reloaded.
   */
   function conditionallyReloadDocument() {
-    if (rpPrefBranch.getBoolPref("autoReload")) {
+    if (Prefs.get("autoReload")) {
       window.content.document.location.reload(false);
     }
   }
diff --git a/src/content/ui/menu.js b/src/content/ui/menu.js
index fa9fa55..e45b5d5 100644
--- a/src/content/ui/menu.js
+++ b/src/content/ui/menu.js
@@ -32,7 +32,7 @@ window.rpcontinued.menu = (function() {
 
   let {Environment} = importModule("lib/environment");
   let {Logger} = importModule("lib/logger");
-  let {rpPrefBranch, Prefs} = importModule("lib/prefs");
+  let {Prefs} = importModule("models/prefs");
   let {RequestProcessor} = importModule("lib/request-processor");
   let {PolicyManager} = importModule("lib/policy-manager");
   let {DomainUtil} = importModule("lib/utils/domains");
@@ -236,9 +236,8 @@ window.rpcontinued.menu = (function() {
 
     if (true === guiLocations) {
       // get prefs
-      let sorting = rpPrefBranch.getCharPref("menu.sorting");
-      let showNumRequests = rpPrefBranch.getBoolPref(
-          "menu.info.showNumRequests");
+      let sorting = Prefs.get("menu.sorting");
+      let showNumRequests = Prefs.get("menu.info.showNumRequests");
 
       if (sorting === "numRequests") {
         values.sort(GUILocation.sortByNumRequestsCompareFunction);
@@ -276,8 +275,7 @@ window.rpcontinued.menu = (function() {
   self._populateOrigin = function() {
     self._originDomainnameItem.setAttribute("value", self._currentBaseDomain);
 
-    let showNumRequests = rpPrefBranch
-        .getBoolPref("menu.info.showNumRequests");
+    let showNumRequests = Prefs.get("menu.info.showNumRequests");
 
     let props = self._getOriginGUILocationProperties();
 
diff --git a/src/content/ui/overlay.js b/src/content/ui/overlay.js
index 9965159..52fc77c 100644
--- a/src/content/ui/overlay.js
+++ b/src/content/ui/overlay.js
@@ -40,7 +40,7 @@ window.rpcontinued.overlay = (function() {
   let {ManagerForMessageListeners} = importModule(
       "lib/manager-for-message-listeners");
   let {Logger} = importModule("lib/logger");
-  let {rpPrefBranch, Prefs} = importModule("lib/prefs");
+  let {Prefs} = importModule("models/prefs");
   let {RequestProcessor} = importModule("lib/request-processor");
   let {PolicyManager} = importModule("lib/policy-manager");
   let {DomainUtil} = importModule("lib/utils/domains");
@@ -125,7 +125,7 @@ window.rpcontinued.overlay = (function() {
         // object's observerBlockedRequests() method will be called.
         RequestProcessor.addRequestObserver(self);
 
-        setContextMenuEntryEnabled(rpPrefBranch.getBoolPref("contextMenu"));
+        setContextMenuEntryEnabled(Prefs.get("contextMenu"));
 
         OverlayEnvironment.shutdownOnUnload(window);
         OverlayEnvironment.startup();
@@ -232,9 +232,8 @@ window.rpcontinued.overlay = (function() {
 
     let blockedURIs = {};
 
-    if (rpPrefBranch.getBoolPref("indicateBlockedObjects")) {
-      var indicateBlacklisted = rpPrefBranch
-          .getBoolPref("indicateBlacklistedObjects");
+    if (Prefs.get("indicateBlockedObjects")) {
+      var indicateBlacklisted = Prefs.get("indicateBlacklistedObjects");
 
       var rejectedRequests = RequestProcessor._rejectedRequests
           .getOriginUri(documentURI);
@@ -628,13 +627,8 @@ window.rpcontinued.overlay = (function() {
    * register a pref observer
    */
   function updatePermissiveStatusOnPrefChanges() {
-    OverlayEnvironment.obMan.observeRPPref(
-        ["startWithAllowAllEnabled"],
-        function(subject, topic, data) {
-          if (topic === "nsPref:changed") {
-            updatePermissiveStatus();
-          }
-        });
+    OverlayEnvironment.prefObs.addListener("startWithAllowAllEnabled",
+                                           updatePermissiveStatus);
   }
   OverlayEnvironment.addStartupFunction(Environment.LEVELS.INTERFACE,
                                         updatePermissiveStatusOnPrefChanges);
@@ -926,7 +920,7 @@ window.rpcontinued.overlay = (function() {
   self.onPopupHidden = function(event) {
     var rulesChanged = rpcontinued.menu.processQueuedRuleChanges();
     if (rulesChanged || self._needsReloadOnMenuClose) {
-      if (rpPrefBranch.getBoolPref("autoReload")) {
+      if (Prefs.get("autoReload")) {
         let mm = gBrowser.selectedBrowser.messageManager;
         mm.sendAsyncMessage(C.MM_PREFIX + "reload");
       }
diff --git a/tests/xpcshell/test_map_of_sets.js b/tests/xpcshell/test_map_of_sets.js
new file mode 100644
index 0000000..4573851
--- /dev/null
+++ b/tests/xpcshell/test_map_of_sets.js
@@ -0,0 +1,55 @@
+/* exported run_test */
+
+Cu.import("chrome://rpcontinued/content/lib/classes/map-of-sets.jsm");
+
+
+function run_test() {
+  "use strict";
+
+  test_0();
+}
+
+
+function test_0() {
+  "use strict";
+
+  let map = new MapOfSets();
+  strictEqual(false, map.has("a"));
+
+  let first = {};
+  let second = {};
+
+  // Adding a first element to the "a" set.
+  map.addToSet("a", first);
+  strictEqual(true, map.has("a"));
+  strictEqual(1, map.get("a").size);
+
+  // Adding a second element to the same set.
+  map.addToSet("a", second);
+  strictEqual(true, map.has("a"));
+  strictEqual(2, map.get("a").size);
+
+  // Removing a nonexistant element.
+  map.deleteFromSet("a", {});
+  strictEqual(2, map.get("a").size);
+
+  // Removing a nonexistant element from nonexistant map "b".
+  map.deleteFromSet("b", {});
+  strictEqual(false, map.has("b"));
+
+  // Removing the first element again.
+  map.deleteFromSet("a", first);
+  strictEqual(true, map.has("a"));
+  strictEqual(1, map.get("a").size);
+
+  // Add "second" to "b"
+  map.addToSet("b", second);
+  strictEqual(true, map.has("b"));
+  strictEqual(1, map.get("b").size);
+
+  // Remove all remaining elements
+  map.deleteFromSet("a", second);
+  map.deleteFromSet("b", second);
+  strictEqual(false, map.has("a"));
+  strictEqual(false, map.has("b"));
+}
diff --git a/tests/xpcshell/test_oldrules.js b/tests/xpcshell/test_oldrules.js
index 05829f8..90e16b6 100644
--- a/tests/xpcshell/test_oldrules.js
+++ b/tests/xpcshell/test_oldrules.js
@@ -3,8 +3,8 @@
 
 /* global OldRules, OldRulesParseError */
 Cu.import("chrome://rpcontinued/content/lib/old-rules.jsm");
-/* global rpPrefBranch */
-Cu.import("chrome://rpcontinued/content/lib/prefs.jsm");
+/* global Prefs */
+Cu.import("chrome://rpcontinued/content/models/prefs.jsm");
 
 
 function run_test() {
@@ -202,7 +202,7 @@ function usingOldRulePrefs(aPrefs, aFunction) {
 
   // Clear the prefs.
   forEachPrefName(function (prefName) {
-    rpPrefBranch.clearUserPref(prefName);
+    Prefs.reset(prefName);
   });
 }
 
@@ -215,7 +215,8 @@ function setOldRulePref(aPrefName, aValue) {
   var str = Cc["@mozilla.org/supports-string;1"]
       .createInstance(Ci.nsISupportsString);
   str.data = aValue;
-  rpPrefBranch.setComplexValue(aPrefName, Ci.nsISupportsString, str);
+  Prefs.branches.rp.branch.
+      setComplexValue(aPrefName, Ci.nsISupportsString, str);
 }
 
 function testGetOldRulesAsNewRules(
diff --git a/tests/xpcshell/xpcshell.ini b/tests/xpcshell/xpcshell.ini
index f797b7a..d5bcf70 100644
--- a/tests/xpcshell/xpcshell.ini
+++ b/tests/xpcshell/xpcshell.ini
@@ -3,6 +3,7 @@ head = head_loadrp.js head_utils.js
 tail =
 
 [test_fileutil.js]
+[test_map_of_sets.js]
 [test_oldrules.js]
 ;[test_policymanager.js]
 [test_policystorage.js]

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