Bug 1357517 - Remove or delay Preferences.jsm usage from some browser/components/* files. r=Gijs
authorMarco Castelluccio <mcastelluccio@mozilla.com>
Mon, 31 Jul 2017 13:25:41 +0200
changeset 423182 0f64ae9515a8efd0e234d7801cdc6b4f1c31a679
parent 423181 10de190a839b48b4271d5bcc6272bd68c74c9d81
child 423183 9079c02563e7fdf6a4558e917189b323000096b7
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1357517
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1357517 - Remove or delay Preferences.jsm usage from some browser/components/* files. r=Gijs
browser/components/distribution.js
browser/components/extensions/test/browser/head.js
browser/components/newtab/NewTabPrefsProvider.jsm
browser/components/newtab/NewTabWebChannel.jsm
browser/components/newtab/aboutNewTabService.js
browser/components/newtab/tests/browser/browser_newtab_overrides.js
browser/components/nsBrowserGlue.js
browser/components/originattributes/test/browser/browser_imageCacheIsolation.js
browser/components/selfsupport/SelfSupportService.js
browser/components/selfsupport/test/browser_selfsupportAPI.js
browser/components/sessionstore/SessionFile.jsm
browser/components/sessionstore/content/content-sessionStore.js
browser/components/uitour/UITour.jsm
browser/experiments/Experiments.jsm
browser/experiments/ExperimentsService.js
--- a/browser/components/distribution.js
+++ b/browser/components/distribution.js
@@ -9,17 +9,18 @@ var Cc = Components.classes;
 var Cr = Components.results;
 var Cu = Components.utils;
 
 const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC =
   "distribution-customization-complete";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Preferences.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
+                                  "resource://gre/modules/Preferences.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 
 this.DistributionCustomizer = function DistributionCustomizer() {
   // For parallel xpcshell testing purposes allow loading the distribution.ini
   // file from the profile folder through an hidden pref.
   let loadFromProfile = Services.prefs.getBoolPref("distribution.testing.loadFromProfile", false);
   let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -29,16 +29,17 @@
 //       should use "expectUncaughtRejection" to flag individual failures.
 const {PromiseTestUtils} = Cu.import("resource://testing-common/PromiseTestUtils.jsm", {});
 PromiseTestUtils.whitelistRejectionsGlobally(/Message manager disconnected/);
 PromiseTestUtils.whitelistRejectionsGlobally(/No matching message handler/);
 PromiseTestUtils.whitelistRejectionsGlobally(/Receiving end does not exist/);
 
 const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm", {});
 const {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm", {});
+const {Preferences} = Cu.import("resource://gre/modules/Preferences.jsm", {});
 
 // We run tests under two different configurations, from browser.ini and
 // browser-remote.ini. When running from browser-remote.ini, the tests are
 // copied to the sub-directory "test-oop-extensions", which we detect here, and
 // use to select our configuration.
 let remote = gTestPath.includes("test-oop-extensions");
 SpecialPowers.pushPrefEnv({set: [
   ["extensions.webextensions.remote", remote],
--- a/browser/components/newtab/NewTabPrefsProvider.jsm
+++ b/browser/components/newtab/NewTabPrefsProvider.jsm
@@ -1,15 +1,14 @@
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["NewTabPrefsProvider"];
 
 const {interfaces: Ci, utils: Cu} = Components;
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "EventEmitter", function() {
   const {EventEmitter} = Cu.import("resource://gre/modules/EventEmitter.jsm", {});
   return EventEmitter;
 });
 
 // Supported prefs and data type
@@ -41,26 +40,30 @@ let PrefsProvider = function PrefsProvid
 
 PrefsProvider.prototype = {
 
   observe(subject, topic, data) { // jshint ignore:line
     if (topic === "nsPref:changed") {
       if (gPrefsMap.has(data)) {
         switch (gPrefsMap.get(data)) {
           case "bool":
-            this.emit(data, Preferences.get(data, false));
+            this.emit(data, Services.prefs.getBoolPref(data, false));
             break;
           case "str":
-            this.emit(data, Preferences.get(data, ""));
+            this.emit(data, Services.prefs.getStringPref(data, ""));
             break;
           case "localized":
-            try {
-              this.emit(data, Preferences.get(data, "", Ci.nsIPrefLocalizedString));
-            } catch (e) {
-              this.emit(data, Preferences.get(data, ""));
+            if (Services.prefs.getPrefType(data) == Ci.nsIPrefBranch.PREF_INVALID) {
+              this.emit(data, "");
+            } else {
+              try {
+                this.emit(data, Services.prefs.getComplexValue(data, Ci.nsIPrefLocalizedString));
+              } catch (e) {
+                this.emit(data, Services.prefs.getStringPref(data));
+              }
             }
             break;
           default:
             this.emit(data);
             break;
         }
       }
     } else {
@@ -69,17 +72,35 @@ PrefsProvider.prototype = {
   },
 
   /*
    * Return the preferences that are important to the newtab page
    */
   get newtabPagePrefs() {
     let results = {};
     for (let pref of gNewtabPagePrefs) {
-      results[pref] = Preferences.get(pref, null);
+      results[pref] = null;
+
+      if (Services.prefs.getPrefType(pref) != Ci.nsIPrefBranch.PREF_INVALID) {
+        switch (gPrefsMap.get(pref)) {
+          case "bool":
+            results[pref] = Services.prefs.getBoolPref(pref);
+            break;
+          case "str":
+            results[pref] = Services.prefs.getStringPref(pref);
+            break;
+          case "localized":
+            try {
+              results[pref] = Services.prefs.getComplexValue(pref, Ci.nsIPrefLocalizedString);
+            } catch (e) {
+              results[pref] = Services.prefs.getStringPref(pref);
+            }
+            break;
+        }
+      }
     }
     return results;
   },
 
   get prefsMap() {
     return gPrefsMap;
   },
 
--- a/browser/components/newtab/NewTabWebChannel.jsm
+++ b/browser/components/newtab/NewTabWebChannel.jsm
@@ -1,16 +1,15 @@
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["NewTabWebChannel"];
 
 const {utils: Cu} = Components;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Preferences.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
                                   "resource:///modules/NewTabPrefsProvider.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabRemoteResources",
                                   "resource:///modules/NewTabRemoteResources.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "WebChannel",
                                   "resource://gre/modules/WebChannel.jsm");
 XPCOMUtils.defineLazyGetter(this, "EventEmitter", function() {
@@ -240,19 +239,19 @@ NewTabWebChannelImpl.prototype = {
         break;
     }
   },
 
   /*
    * Sets up the internal state
    */
   setupState() {
-    this._prefs.enabled = Preferences.get(PREF_ENABLED, false);
+    this._prefs.enabled = Services.prefs.getBoolPref(PREF_ENABLED, false);
 
-    let mode = Preferences.get(PREF_MODE, "production");
+    let mode = Services.prefs.getStringPref(PREF_MODE, "production");
     if (!(mode in NewTabRemoteResources.MODE_CHANNEL_MAP)) {
       mode = "production";
     }
     this._prefs.mode = mode;
     this._principals = new WeakMap();
     this._browsers = new Set();
 
     if (this._prefs.enabled) {
--- a/browser/components/newtab/aboutNewTabService.js
+++ b/browser/components/newtab/aboutNewTabService.js
@@ -5,17 +5,18 @@
 */
 
 "use strict";
 
 const {utils: Cu, interfaces: Ci} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Preferences.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
+                                  "resource://gre/modules/Preferences.jsm");
 
 const LOCAL_NEWTAB_URL = "chrome://browser/content/newtab/newTab.xhtml";
 
 const ACTIVITY_STREAM_URL = "resource://activity-stream/data/content/activity-stream.html";
 
 const ABOUT_URL = "about:newtab";
 
 // Pref that tells if activity stream is enabled
--- a/browser/components/newtab/tests/browser/browser_newtab_overrides.js
+++ b/browser/components/newtab/tests/browser/browser_newtab_overrides.js
@@ -1,14 +1,13 @@
 "use strict";
 
 let Cu = Components.utils;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Preferences.jsm");
 const PREF_NEWTAB_ACTIVITY_STREAM = "browser.newtabpage.activity-stream.enabled";
 
 Services.prefs.setBoolPref(PREF_NEWTAB_ACTIVITY_STREAM, false);
 
 XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
                                    "@mozilla.org/browser/aboutnewtab-service;1",
                                    "nsIAboutNewTabService");
 
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -471,23 +471,20 @@ BrowserGlue.prototype = {
         let win = RecentWindow.getMostRecentBrowserWindow();
         win.BrowserSearch.recordSearchInTelemetry(engine, "urlbar");
         break;
       case "browser-search-engine-modified":
         // Ensure we cleanup the hiddenOneOffs pref when removing
         // an engine, and that newly added engines are visible.
         if (data == "engine-added" || data == "engine-removed") {
           let engineName = subject.QueryInterface(Ci.nsISearchEngine).name;
-          let Preferences =
-            Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
-          let pref = Preferences.get("browser.search.hiddenOneOffs");
+          let pref = Services.prefs.getStringPref("browser.search.hiddenOneOffs");
           let hiddenList = pref ? pref.split(",") : [];
           hiddenList = hiddenList.filter(x => x !== engineName);
-          Preferences.set("browser.search.hiddenOneOffs",
-                          hiddenList.join(","));
+          Services.prefs.setStringPref("browser.search.hiddenOneOffs", hiddenList.join(","));
         }
         break;
       case "flash-plugin-hang":
         this._handleFlashHang();
         break;
       case "xpi-signature-changed":
         let disabledAddons = JSON.parse(data).disabled;
         AddonManager.getAddonsByIDs(disabledAddons, (addons) => {
--- a/browser/components/originattributes/test/browser/browser_imageCacheIsolation.js
+++ b/browser/components/originattributes/test/browser/browser_imageCacheIsolation.js
@@ -13,21 +13,21 @@ const NUM_CACHED_LOADS = 1;
 let gHits = 0;
 
 let server = new HttpServer();
 server.registerPathHandler("/image.png", imageHandler);
 server.registerPathHandler("/file.html", fileHandler);
 server.start(-1);
 
 // Disable rcwn to make cache behavior deterministic.
-let rcwnEnabled = Preferences.get("network.http.rcwn.enabled");
-Preferences.set("network.http.rcwn.enabled", false);
+let rcwnEnabled = Services.prefs.getBoolPref("network.http.rcwn.enabled");
+Services.prefs.setBoolPref("network.http.rcwn.enabled", false);
 
 registerCleanupFunction(() => {
-  Preferences.set("network.http.rcwn.enabled", rcwnEnabled);
+  Services.prefs.setBoolPref("network.http.rcwn.enabled", rcwnEnabled);
 
   server.stop(() => {
     server = null;
   });
 });
 
 let BASE_URI = "http://localhost:" + server.identity.primaryPort;
 let IMAGE_URI = BASE_URI + "/image.png";
--- a/browser/components/selfsupport/SelfSupportService.js
+++ b/browser/components/selfsupport/SelfSupportService.js
@@ -3,17 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Preferences.jsm");
 
 const PREF_FHR_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled";
 
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryArchive",
                                   "resource://gre/modules/TelemetryArchive.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryEnvironment",
                                   "resource://gre/modules/TelemetryEnvironment.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryController",
@@ -30,21 +29,21 @@ MozSelfSupportInterface.prototype = {
 
   _window: null,
 
   init(window) {
     this._window = window;
   },
 
   get healthReportDataSubmissionEnabled() {
-    return Preferences.get(PREF_FHR_UPLOAD_ENABLED, false);
+    return Services.prefs.getBoolPref(PREF_FHR_UPLOAD_ENABLED, false);
   },
 
   set healthReportDataSubmissionEnabled(enabled) {
-    Preferences.set(PREF_FHR_UPLOAD_ENABLED, enabled);
+    Services.prefs.setBoolPref(PREF_FHR_UPLOAD_ENABLED, enabled);
   },
 
   resetPref(name) {
     Services.prefs.clearUserPref(name);
   },
 
   resetSearchEngines() {
     Services.search.restoreDefaultEngines();
--- a/browser/components/selfsupport/test/browser_selfsupportAPI.js
+++ b/browser/components/selfsupport/test/browser_selfsupportAPI.js
@@ -1,49 +1,55 @@
-Cu.import("resource://gre/modules/Preferences.jsm");
+function prefHas(pref) {
+  return Services.prefs.getPrefType(pref) != Ci.nsIPrefBranch.PREF_INVALID;
+}
+
+function prefIsSet(pref) {
+  return Services.prefs.prefHasUserValue(pref);
+}
 
 function test_resetPref() {
   const prefNewName = "browser.newpref.fake";
-  Assert.ok(!Preferences.has(prefNewName), "pref should not exist");
+  Assert.ok(!prefHas(prefNewName), "pref should not exist");
 
   const prefExistingName = "extensions.hotfix.id";
-  Assert.ok(Preferences.has(prefExistingName), "pref should exist");
-  Assert.ok(!Preferences.isSet(prefExistingName), "pref should not be user-set");
-  let prefExistingOriginalValue = Preferences.get(prefExistingName);
+  Assert.ok(prefHas(prefExistingName), "pref should exist");
+  Assert.ok(!prefIsSet(prefExistingName), "pref should not be user-set");
+  let prefExistingOriginalValue = Services.prefs.getStringPref(prefExistingName);
 
   registerCleanupFunction(function() {
-    Preferences.set(prefExistingName, prefExistingOriginalValue);
+    Services.prefs.setStringPref(prefExistingName, prefExistingOriginalValue);
     Services.prefs.deleteBranch(prefNewName);
   });
 
   // 1. do nothing on an inexistent pref
   MozSelfSupport.resetPref(prefNewName);
-  Assert.ok(!Preferences.has(prefNewName), "pref should still not exist");
+  Assert.ok(!prefHas(prefNewName), "pref should still not exist");
 
   // 2. creation of a new pref
-  Preferences.set(prefNewName, 10);
-  Assert.ok(Preferences.has(prefNewName), "pref should exist");
-  Assert.equal(Preferences.get(prefNewName), 10, "pref value should be 10");
+  Services.prefs.setIntPref(prefNewName, 10);
+  Assert.ok(prefHas(prefNewName), "pref should exist");
+  Assert.equal(Services.prefs.getIntPref(prefNewName), 10, "pref value should be 10");
 
   MozSelfSupport.resetPref(prefNewName);
-  Assert.ok(!Preferences.has(prefNewName), "pref should not exist any more");
+  Assert.ok(!prefHas(prefNewName), "pref should not exist any more");
 
   // 3. do nothing on an unchanged existing pref
   MozSelfSupport.resetPref(prefExistingName);
-  Assert.ok(Preferences.has(prefExistingName), "pref should still exist");
-  Assert.equal(Preferences.get(prefExistingName), prefExistingOriginalValue, "pref value should be the same as original");
+  Assert.ok(prefHas(prefExistingName), "pref should still exist");
+  Assert.equal(Services.prefs.getStringPref(prefExistingName), prefExistingOriginalValue, "pref value should be the same as original");
 
   // 4. change the value of an existing pref
-  Preferences.set(prefExistingName, "anyone@mozilla.org");
-  Assert.ok(Preferences.has(prefExistingName), "pref should exist");
-  Assert.equal(Preferences.get(prefExistingName), "anyone@mozilla.org", "pref value should have changed");
+  Services.prefs.setStringPref(prefExistingName, "anyone@mozilla.org");
+  Assert.ok(prefHas(prefExistingName), "pref should exist");
+  Assert.equal(Services.prefs.getStringPref(prefExistingName), "anyone@mozilla.org", "pref value should have changed");
 
   MozSelfSupport.resetPref(prefExistingName);
-  Assert.ok(Preferences.has(prefExistingName), "pref should still exist");
-  Assert.equal(Preferences.get(prefExistingName), prefExistingOriginalValue, "pref value should be the same as original");
+  Assert.ok(prefHas(prefExistingName), "pref should still exist");
+  Assert.equal(Services.prefs.getStringPref(prefExistingName), prefExistingOriginalValue, "pref value should be the same as original");
 
   // 5. delete an existing pref
   // deleteBranch is implemented in such a way that
   // clearUserPref can't undo its action
   // see discussion in bug 1075160
 }
 
 function test_resetSearchEngines() {
--- a/browser/components/sessionstore/SessionFile.jsm
+++ b/browser/components/sessionstore/SessionFile.jsm
@@ -29,17 +29,16 @@ const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://gre/modules/AsyncShutdown.jsm");
-Cu.import("resource://gre/modules/Preferences.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "console",
   "resource://gre/modules/Console.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
   "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "RunState",
   "resource:///modules/sessionstore/RunState.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
@@ -298,19 +297,19 @@ var SessionFileInternal = {
       };
     }
 
     result.noFilesFound = noFilesFound;
 
     // Initialize the worker (in the background) to let it handle backups and also
     // as a workaround for bug 964531.
     let promiseInitialized = SessionWorker.post("init", [result.origin, result.useOldExtension, this.Paths, {
-      maxUpgradeBackups: Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3),
-      maxSerializeBack: Preferences.get(PREF_MAX_SERIALIZE_BACK, 10),
-      maxSerializeForward: Preferences.get(PREF_MAX_SERIALIZE_FWD, -1)
+      maxUpgradeBackups: Services.prefs.getIntPref(PREF_MAX_UPGRADE_BACKUPS, 3),
+      maxSerializeBack: Services.prefs.getIntPref(PREF_MAX_SERIALIZE_BACK, 10),
+      maxSerializeForward: Services.prefs.getIntPref(PREF_MAX_SERIALIZE_FWD, -1)
     }]);
 
     promiseInitialized.catch(err => {
       // Ensure that we report errors but that they do not stop us.
       Promise.reject(err);
     }).then(() => this._deferredInitialized.resolve());
 
     return result;
--- a/browser/components/sessionstore/content/content-sessionStore.js
+++ b/browser/components/sessionstore/content/content-sessionStore.js
@@ -19,18 +19,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   "resource://gre/modules/TelemetryStopwatch.jsm");
 
 function debug(msg) {
   Services.console.logStringMessage("SessionStoreContent: " + msg);
 }
 
 XPCOMUtils.defineLazyModuleGetter(this, "FormData",
   "resource://gre/modules/FormData.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
-  "resource://gre/modules/Preferences.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "DocShellCapabilities",
   "resource:///modules/sessionstore/DocShellCapabilities.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ScrollPosition",
   "resource://gre/modules/ScrollPosition.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionHistory",
   "resource://gre/modules/sessionstore/SessionHistory.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionStorage",
@@ -560,17 +558,17 @@ var SessionStorageListener = {
     // How much data does DOMSessionStorage contain?
     let usage = content.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIDOMWindowUtils)
                        .getStorageUsage(event.storageArea);
     Services.telemetry.getHistogramById("FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS").add(usage);
 
     // Don't store any data if we exceed the limit. Wipe any data we previously
     // collected so that we don't confuse websites with partial state.
-    if (usage > Preferences.get(DOM_STORAGE_LIMIT_PREF)) {
+    if (usage > Services.prefs.getIntPref(DOM_STORAGE_LIMIT_PREF)) {
       MessageQueue.push("storage", () => null);
       return;
     }
 
     let {url, key, newValue} = event;
     let uri = Services.io.newURI(url);
     let domain = uri.prePath;
     if (!this._changes) {
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -6,17 +6,16 @@
 
 this.EXPORTED_SYMBOLS = ["UITour"];
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/AppConstants.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/TelemetryController.jsm");
 Cu.import("resource://gre/modules/Timer.jsm");
 
 Cu.importGlobalProperties(["URL"]);
 
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
   "resource://gre/modules/LightweightThemeManager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ResetProfile",
@@ -1536,19 +1535,19 @@ this.UITour = {
             data = {engines: [], searchEngineIdentifier: ""};
           }
           this.sendPageCallback(aMessageManager, aCallbackID, data);
         });
         break;
       case "sync":
         this.sendPageCallback(aMessageManager, aCallbackID, {
           setup: Services.prefs.prefHasUserValue("services.sync.username"),
-          desktopDevices: Preferences.get("services.sync.clients.devices.desktop", 0),
-          mobileDevices: Preferences.get("services.sync.clients.devices.mobile", 0),
-          totalDevices: Preferences.get("services.sync.numClients", 0),
+          desktopDevices: Services.prefs.getIntPref("services.sync.clients.devices.desktop", 0),
+          mobileDevices: Services.prefs.getIntPref("services.sync.clients.devices.mobile", 0),
+          totalDevices: Services.prefs.getIntPref("services.sync.numClients", 0),
         });
         break;
       case "canReset":
         this.sendPageCallback(aMessageManager, aCallbackID, ResetProfile.resetSupported());
         break;
       default:
         log.error("getConfiguration: Unknown configuration requested: " + aConfiguration);
         break;
--- a/browser/experiments/Experiments.jsm
+++ b/browser/experiments/Experiments.jsm
@@ -9,17 +9,16 @@ this.EXPORTED_SYMBOLS = [
 ];
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://gre/modules/Log.jsm");
-Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/AsyncShutdown.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
                                   "resource://gre/modules/UpdateUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                   "resource://gre/modules/AddonManager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManagerPrivate",
                                   "resource://gre/modules/AddonManager.jsm");
@@ -33,32 +32,32 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://services-common/utils.js");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
                                    "@mozilla.org/xre/app-info;1",
                                    "nsICrashReporter");
 
 const FILE_CACHE                = "experiments.json";
 const EXPERIMENTS_CHANGED_TOPIC = "experiments-changed";
+const PREF_CHANGED_TOPIC        = "nsPref:changed";
 const MANIFEST_VERSION          = 1;
 const CACHE_VERSION             = 1;
 
 const KEEP_HISTORY_N_DAYS       = 180;
 
 const PREF_BRANCH               = "experiments.";
 const PREF_ENABLED              = "enabled"; // experiments.enabled
 const PREF_ACTIVE_EXPERIMENT    = "activeExperiment"; // whether we have an active experiment
 const PREF_LOGGING              = "logging";
 const PREF_LOGGING_LEVEL        = PREF_LOGGING + ".level"; // experiments.logging.level
 const PREF_LOGGING_DUMP         = PREF_LOGGING + ".dump"; // experiments.logging.dump
 const PREF_MANIFEST_URI         = "manifest.uri"; // experiments.logging.manifest.uri
 const PREF_FORCE_SAMPLE         = "force-sample-value"; // experiments.force-sample-value
 
-const PREF_BRANCH_TELEMETRY     = "toolkit.telemetry.";
-const PREF_TELEMETRY_ENABLED    = "enabled";
+const PREF_TELEMETRY_ENABLED      = "toolkit.telemetry.enabled";
 
 const URI_EXTENSION_STRINGS     = "chrome://mozapps/locale/extensions/extensions.properties";
 const STRING_TYPE_NAME          = "type.%ID%.name";
 
 const CACHE_WRITE_RETRY_DELAY_SEC = 60 * 3;
 const MANIFEST_FETCH_TIMEOUT_MSEC = 60 * 3 * 1000; // 3 minutes
 
 const TELEMETRY_LOG = {
@@ -87,18 +86,17 @@ const TELEMETRY_LOG = {
     EXPIRED: "EXPIRED",
     // Disabled after re-evaluating conditions. If this is specified,
     // details will be provided.
     RECHECK: "RECHECK",
   },
 };
 XPCOMUtils.defineConstant(this, "TELEMETRY_LOG", TELEMETRY_LOG);
 
-const gPrefs = new Preferences(PREF_BRANCH);
-const gPrefsTelemetry = new Preferences(PREF_BRANCH_TELEMETRY);
+const gPrefs = Services.prefs.getBranch(PREF_BRANCH);
 var gExperimentsEnabled = false;
 var gAddonProvider = null;
 var gExperiments = null;
 var gLogAppenderDump = null;
 var gPolicyCounter = 0;
 var gExperimentsCounter = 0;
 var gExperimentEntryCounter = 0;
 var gPreviousProviderCounter = 0;
@@ -114,19 +112,19 @@ var gActiveUninstallAddonIDs = new Set()
 var gLogger;
 var gLogDumping = false;
 
 function configureLogging() {
   if (!gLogger) {
     gLogger = Log.repository.getLogger("Browser.Experiments");
     gLogger.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
   }
-  gLogger.level = gPrefs.get(PREF_LOGGING_LEVEL, Log.Level.Warn);
+  gLogger.level = gPrefs.getIntPref(PREF_LOGGING_LEVEL, Log.Level.Warn);
 
-  let logDumping = gPrefs.get(PREF_LOGGING_DUMP, false);
+  let logDumping = gPrefs.getBoolPref(PREF_LOGGING_DUMP, false);
   if (logDumping != gLogDumping) {
     if (logDumping) {
       gLogAppenderDump = new Log.DumpAppender(new Log.BasicFormatter());
       gLogger.addAppender(gLogAppenderDump);
     } else {
       gLogger.removeAppender(gLogAppenderDump);
       gLogAppenderDump = null;
     }
@@ -246,17 +244,17 @@ Experiments.Policy = function() {
 };
 
 Experiments.Policy.prototype = {
   now() {
     return new Date();
   },
 
   random() {
-    let pref = gPrefs.get(PREF_FORCE_SAMPLE);
+    let pref = gPrefs.getStringPref(PREF_FORCE_SAMPLE, undefined);
     if (pref !== undefined) {
       let val = Number.parseFloat(pref);
       this._log.debug("random sample forced: " + val);
       if (isNaN(val) || val < 0) {
         return 0;
       }
       if (val > 1) {
         return 1;
@@ -367,38 +365,52 @@ Experiments.Experiments = function(polic
   // We need to tell when we first evaluated the experiments to fire an
   // experiments-changed notification when we only loaded completed experiments.
   this._firstEvaluate = true;
 
   this.init();
 };
 
 Experiments.Experiments.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback, Ci.nsIObserver]),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback, Ci.nsIObserver, Ci.nsISupportsWeakReference]),
 
   /**
    * `true` if the experiments manager is currently setup (has been fully initialized
    * and not uninitialized yet).
    */
   get isReady() {
     return !this._shutdown;
   },
 
+  observe(subject, topic, data) {
+    switch (topic) {
+      case PREF_CHANGED_TOPIC:
+        if (data == PREF_BRANCH + PREF_MANIFEST_URI) {
+          this.updateManifest();
+        } else if (data == PREF_BRANCH + PREF_ENABLED) {
+          this._toggleExperimentsEnabled(gPrefs.getBoolPref(PREF_ENABLED, false));
+        } else if (data == PREF_TELEMETRY_ENABLED) {
+          this._telemetryStatusChanged();
+        }
+        break;
+    }
+  },
+
   init() {
     this._shutdown = false;
     configureLogging();
 
-    gExperimentsEnabled = gPrefs.get(PREF_ENABLED, false) && TelemetryUtils.isTelemetryEnabled;
+    gExperimentsEnabled = gPrefs.getBoolPref(PREF_ENABLED, false) && TelemetryUtils.isTelemetryEnabled;
     this._log.trace("enabled=" + gExperimentsEnabled + ", " + this.enabled);
 
-    gPrefs.observe(PREF_LOGGING, configureLogging);
-    gPrefs.observe(PREF_MANIFEST_URI, this.updateManifest, this);
-    gPrefs.observe(PREF_ENABLED, this._toggleExperimentsEnabled, this);
+    Services.prefs.addObserver(PREF_BRANCH + PREF_LOGGING, configureLogging);
+    Services.prefs.addObserver(PREF_BRANCH + PREF_MANIFEST_URI, this, true);
+    Services.prefs.addObserver(PREF_BRANCH + PREF_ENABLED, this, true);
 
-    gPrefsTelemetry.observe(PREF_TELEMETRY_ENABLED, this._telemetryStatusChanged, this);
+    Services.prefs.addObserver(PREF_TELEMETRY_ENABLED, this, true);
 
     AddonManager.shutdown.addBlocker("Experiments.jsm shutdown",
       this.uninit.bind(this),
       this._getState.bind(this)
     );
 
     this._registerWithAddonManager();
 
@@ -433,21 +445,21 @@ Experiments.Experiments.prototype = {
     this._log.trace("uninit: started");
     await this._loadTask;
     this._log.trace("uninit: finished with _loadTask");
 
     if (!this._shutdown) {
       this._log.trace("uninit: no previous shutdown");
       this._unregisterWithAddonManager();
 
-      gPrefs.ignore(PREF_LOGGING, configureLogging);
-      gPrefs.ignore(PREF_MANIFEST_URI, this.updateManifest, this);
-      gPrefs.ignore(PREF_ENABLED, this._toggleExperimentsEnabled, this);
+      Services.prefs.removeObserver(PREF_BRANCH + PREF_LOGGING, configureLogging);
+      Services.prefs.removeObserver(PREF_BRANCH + PREF_MANIFEST_URI, this);
+      Services.prefs.removeObserver(PREF_BRANCH + PREF_ENABLED, this);
 
-      gPrefsTelemetry.ignore(PREF_TELEMETRY_ENABLED, this._telemetryStatusChanged, this);
+      Services.prefs.removeObserver(PREF_TELEMETRY_ENABLED, this);
 
       if (this._timer) {
         this._timer.clear();
       }
     }
 
     this._shutdown = true;
     if (this._mainTask) {
@@ -576,17 +588,17 @@ Experiments.Experiments.prototype = {
     return gExperimentsEnabled;
   },
 
   /**
    * Toggle whether the experiments feature is enabled or not.
    */
   set enabled(enabled) {
     this._log.trace("set enabled(" + enabled + ")");
-    gPrefs.set(PREF_ENABLED, enabled);
+    gPrefs.setBoolPref(PREF_ENABLED, enabled);
   },
 
   async _toggleExperimentsEnabled(enabled) {
     this._log.trace("_toggleExperimentsEnabled(" + enabled + ")");
     let wasEnabled = gExperimentsEnabled;
     gExperimentsEnabled = enabled && TelemetryUtils.isTelemetryEnabled;
 
     if (wasEnabled == gExperimentsEnabled) {
@@ -599,17 +611,17 @@ Experiments.Experiments.prototype = {
       await this.disableExperiment(TELEMETRY_LOG.TERMINATION.SERVICE_DISABLED);
       if (this._timer) {
         this._timer.clear();
       }
     }
   },
 
   _telemetryStatusChanged() {
-    this._toggleExperimentsEnabled(gPrefs.get(PREF_ENABLED, false));
+    this._toggleExperimentsEnabled(gPrefs.getBoolPref(PREF_ENABLED, false));
   },
 
   /**
    * Returns a promise that is resolved with an array of `ExperimentInfo` objects,
    * which provide info on the currently and recently active experiments.
    * The array is in chronological order.
    *
    * The experiment info is of the form:
@@ -1218,17 +1230,17 @@ Experiments.Experiments.prototype = {
       await uninstallAddons(unknownAddons);
     }
 
     let activeExperiment = this._getActiveExperiment();
     let activeChanged = false;
 
     if (!activeExperiment) {
       // Avoid this pref staying out of sync if there were e.g. crashes.
-      gPrefs.set(PREF_ACTIVE_EXPERIMENT, false);
+      gPrefs.setBoolPref(PREF_ACTIVE_EXPERIMENT, false);
     }
 
     // Ensure the active experiment is in the proper state. This may install,
     // uninstall, upgrade, or enable the experiment add-on. What exactly is
     // abstracted away from us by design.
     if (activeExperiment) {
       let changes;
       let shouldStopResult = await activeExperiment.shouldStop();
@@ -1298,17 +1310,17 @@ Experiments.Experiments.prototype = {
           // On failure, clean up the best we can and try the next experiment.
           this._log.error("evaluateExperiments() - Unable to start experiment: " + e.message);
           experiment._enabled = false;
           await experiment.reconcileAddonState();
         }
       }
     }
 
-    gPrefs.set(PREF_ACTIVE_EXPERIMENT, activeExperiment != null);
+    gPrefs.setBoolPref(PREF_ACTIVE_EXPERIMENT, activeExperiment != null);
 
     if (activeChanged || this._firstEvaluate) {
       Services.obs.notifyObservers(null, EXPERIMENTS_CHANGED_TOPIC);
       this._firstEvaluate = false;
     }
 
     if ("@mozilla.org/toolkit/crash-reporter;1" in Cc && activeExperiment) {
       try {
--- a/browser/experiments/ExperimentsService.js
+++ b/browser/experiments/ExperimentsService.js
@@ -3,55 +3,44 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Preferences.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Experiments",
                                   "resource:///modules/experiments/Experiments.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
                                   "resource://services-common/utils.js");
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryUtils",
                                   "resource://gre/modules/TelemetryUtils.jsm");
 
 
 const PREF_EXPERIMENTS_ENABLED  = "experiments.enabled";
 const PREF_ACTIVE_EXPERIMENT    = "experiments.activeExperiment"; // whether we have an active experiment
 const DELAY_INIT_MS             = 30 * 1000;
 
-XPCOMUtils.defineLazyGetter(
-  this, "gPrefs", () => {
-    return new Preferences();
-  });
-
-XPCOMUtils.defineLazyGetter(
-  this, "gActiveExperiment", () => {
-    return gPrefs.get(PREF_ACTIVE_EXPERIMENT);
-  });
-
 function ExperimentsService() {
   this._initialized = false;
   this._delayedInitTimer = null;
 }
 
 ExperimentsService.prototype = {
   classID: Components.ID("{f7800463-3b97-47f9-9341-b7617e6d8d49}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback, Ci.nsIObserver]),
 
   get _experimentsEnabled() {
     // We can enable experiments if either unified Telemetry or FHR is on, and the user
     // has opted into Telemetry.
-    return gPrefs.get(PREF_EXPERIMENTS_ENABLED, false) &&
+    return Services.prefs.getBoolPref(PREF_EXPERIMENTS_ENABLED, false) &&
            TelemetryUtils.isTelemetryEnabled;
   },
 
   notify(timer) {
     if (!this._experimentsEnabled) {
       return;
     }
     if (OS.Constants.Path.profileDir === undefined) {
@@ -77,17 +66,17 @@ ExperimentsService.prototype = {
   observe(subject, topic, data) {
     switch (topic) {
       case "profile-after-change":
         if (this._experimentsEnabled) {
           Services.obs.addObserver(this, "quit-application");
           Services.obs.addObserver(this, "sessionstore-state-finalized");
           Services.obs.addObserver(this, "EM-loaded");
 
-          if (gActiveExperiment) {
+          if (Services.prefs.getBoolPref(PREF_ACTIVE_EXPERIMENT, false)) {
             this._initialized = true;
             Experiments.instance(); // for side effects
           }
         }
         break;
       case "sessionstore-state-finalized":
         if (!this._initialized) {
           CommonUtils.namedTimer(this._delayedInit, DELAY_INIT_MS, this, "_delayedInitTimer");