Bug 1385952, Remove usage of Preferences.jsm from PushService and PushServiceWebsocket in order to load preferences before becoming idle r=mconley
authorEmma Malysz <emalysz@mozilla.com>
Fri, 27 Sep 2019 20:43:48 +0000
changeset 495737 d7ab41d7d5f791fc97094b35588c8684936dd3df
parent 495736 4d973794f0e03354d5e695326d6e0aed6e2ea67c
child 495738 df8178d120eb6deb96f9f97eb77d6485149e94d1
push id114140
push userdvarga@mozilla.com
push dateWed, 02 Oct 2019 18:04:51 +0000
treeherdermozilla-inbound@32eb0ea893f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1385952
milestone71.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 1385952, Remove usage of Preferences.jsm from PushService and PushServiceWebsocket in order to load preferences before becoming idle r=mconley Differential Revision: https://phabricator.services.mozilla.com/D45608
dom/push/PushService.jsm
dom/push/PushServiceWebSocket.jsm
--- a/dom/push/PushService.jsm
+++ b/dom/push/PushService.jsm
@@ -2,19 +2,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { AppConstants } = ChromeUtils.import(
   "resource://gre/modules/AppConstants.jsm"
 );
-const { Preferences } = ChromeUtils.import(
-  "resource://gre/modules/Preferences.jsm"
-);
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const { clearTimeout, setTimeout } = ChromeUtils.import(
   "resource://gre/modules/Timer.jsm"
 );
 const { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
 
@@ -66,17 +63,17 @@ const EXPORTED_SYMBOLS = ["PushService"]
 XPCOMUtils.defineLazyGetter(this, "console", () => {
   let { ConsoleAPI } = ChromeUtils.import("resource://gre/modules/Console.jsm");
   return new ConsoleAPI({
     maxLogLevelPref: "dom.push.loglevel",
     prefix: "PushService",
   });
 });
 
-const prefs = new Preferences("dom.push.");
+const prefs = Services.prefs.getBranch("dom.push.");
 
 const PUSH_SERVICE_UNINIT = 0;
 const PUSH_SERVICE_INIT = 1; // No serverURI
 const PUSH_SERVICE_ACTIVATING = 2; // activating db
 const PUSH_SERVICE_CONNECTION_DISABLE = 3;
 const PUSH_SERVICE_ACTIVE_OFFLINE = 4;
 const PUSH_SERVICE_RUNNING = 5;
 
@@ -100,17 +97,20 @@ const PUSH_SERVICE_RUNNING = 5;
 const STARTING_SERVICE_EVENT = 0;
 const CHANGING_SERVICE_EVENT = 1;
 const STOPPING_SERVICE_EVENT = 2;
 const UNINIT_EVENT = 3;
 
 // Returns the backend for the given server URI.
 function getServiceForServerURI(uri) {
   // Insecure server URLs are allowed for development and testing.
-  let allowInsecure = prefs.get("testing.allowInsecureServerURL");
+  let allowInsecure = prefs.getBoolPref(
+    "testing.allowInsecureServerURL",
+    false
+  );
   if (AppConstants.MOZ_WIDGET_TOOLKIT == "android") {
     if (uri.scheme == "https" || (allowInsecure && uri.scheme == "http")) {
       return CONNECTION_PROTOCOLS;
     }
     return null;
   }
   if (uri.scheme == "wss" || (allowInsecure && uri.scheme == "ws")) {
     return PushServiceWebSocket;
@@ -337,31 +337,31 @@ var PushService = {
         break;
       case "network:offline-status-changed":
         this._stateChangeProcessEnqueue(_ =>
           this._changeStateOfflineEvent(aData === "offline", false)
         );
         break;
 
       case "nsPref:changed":
-        if (aData == "dom.push.serverURL") {
+        if (aData == "serverURL") {
           console.debug(
             "observe: dom.push.serverURL changed for websocket",
-            prefs.get("serverURL")
+            prefs.getStringPref("serverURL")
           );
           this._stateChangeProcessEnqueue(_ =>
             this._changeServerURL(
-              prefs.get("serverURL"),
+              prefs.getStringPref("serverURL"),
               CHANGING_SERVICE_EVENT
             )
           );
-        } else if (aData == "dom.push.connection.enabled") {
+        } else if (aData == "connection.enabled") {
           this._stateChangeProcessEnqueue(_ =>
             this._changeStateConnectionEnabledEvent(
-              prefs.get("connection.enabled")
+              prefs.getBoolPref("connection.enabled")
             )
           );
         }
         break;
 
       case "idle-daily":
         this._dropExpiredRegistrations().catch(error => {
           console.error("Failed to drop expired registrations on idle", error);
@@ -460,41 +460,41 @@ var PushService = {
       case STARTING_SERVICE_EVENT: {
         let [service, uri] = this._findService(serverURI);
         if (!service) {
           this._setState(PUSH_SERVICE_INIT);
           return Promise.resolve();
         }
         return this._startService(service, uri, options).then(_ =>
           this._changeStateConnectionEnabledEvent(
-            prefs.get("connection.enabled")
+            prefs.getBoolPref("connection.enabled")
           )
         );
       }
       case CHANGING_SERVICE_EVENT:
         let [service, uri] = this._findService(serverURI);
         if (service) {
           if (this._state == PUSH_SERVICE_INIT) {
             this._setState(PUSH_SERVICE_ACTIVATING);
             // The service has not been running - start it.
             return this._startService(service, uri, options).then(_ =>
               this._changeStateConnectionEnabledEvent(
-                prefs.get("connection.enabled")
+                prefs.getBoolPref("connection.enabled")
               )
             );
           }
           this._setState(PUSH_SERVICE_ACTIVATING);
           // If we already had running service - stop service, start the new
           // one and check connection.enabled and offline state(offline state
           // check is called in changeStateConnectionEnabledEvent function)
           return this._stopService(CHANGING_SERVICE_EVENT)
             .then(_ => this._startService(service, uri, options))
             .then(_ =>
               this._changeStateConnectionEnabledEvent(
-                prefs.get("connection.enabled")
+                prefs.getBoolPref("connection.enabled")
               )
             );
         }
         if (this._state == PUSH_SERVICE_INIT) {
           return Promise.resolve();
         }
         // The new serverUri is empty or misconfigured - stop service.
         this._setState(PUSH_SERVICE_INIT);
@@ -525,34 +525,37 @@ var PushService = {
     console.debug("init()");
 
     if (this._state > PUSH_SERVICE_UNINIT) {
       return;
     }
 
     this._setState(PUSH_SERVICE_ACTIVATING);
 
-    prefs.observe("serverURL", this);
+    prefs.addObserver("serverURL", this);
     Services.obs.addObserver(this, "quit-application");
 
     if (options.serverURI) {
       // this is use for xpcshell test.
 
       await this._stateChangeProcessEnqueue(_ =>
         this._changeServerURL(
           options.serverURI,
           STARTING_SERVICE_EVENT,
           options
         )
       );
     } else {
       // This is only used for testing. Different tests require connecting to
       // slightly different URLs.
       await this._stateChangeProcessEnqueue(_ =>
-        this._changeServerURL(prefs.get("serverURL"), STARTING_SERVICE_EVENT)
+        this._changeServerURL(
+          prefs.getStringPref("serverURL"),
+          STARTING_SERVICE_EVENT
+        )
       );
     }
   },
 
   _startObservers() {
     console.debug("startObservers()");
 
     if (this._state != PUSH_SERVICE_ACTIVATING) {
@@ -562,17 +565,17 @@ var PushService = {
     Services.obs.addObserver(this, "clear-origin-attributes-data");
 
     // The offline-status-changed event is used to know
     // when to (dis)connect. It may not fire if the underlying OS changes
     // networks; in such a case we rely on timeout.
     Services.obs.addObserver(this, "network:offline-status-changed");
 
     // Used to monitor if the user wishes to disable Push.
-    prefs.observe("connection.enabled", this);
+    prefs.addObserver("connection.enabled", this);
 
     // Prunes expired registrations and notifies dormant service workers.
     Services.obs.addObserver(this, "idle-daily");
 
     // Prunes registrations for sites for which the user revokes push
     // permissions.
     Services.obs.addObserver(this, "perm-changed");
   },
@@ -646,17 +649,17 @@ var PushService = {
 
   _stopObservers() {
     console.debug("stopObservers()");
 
     if (this._state < PUSH_SERVICE_ACTIVATING) {
       return;
     }
 
-    prefs.ignore("connection.enabled", this);
+    prefs.removeObserver("connection.enabled", this);
 
     Services.obs.removeObserver(this, "network:offline-status-changed");
     Services.obs.removeObserver(this, "clear-origin-attributes-data");
     Services.obs.removeObserver(this, "idle-daily");
     Services.obs.removeObserver(this, "perm-changed");
   },
 
   _shutdownService() {
@@ -668,17 +671,17 @@ var PushService = {
 
   async uninit() {
     console.debug("uninit()");
 
     if (this._state == PUSH_SERVICE_UNINIT) {
       return;
     }
 
-    prefs.ignore("serverURL", this);
+    prefs.removeObserver("serverURL", this);
     Services.obs.removeObserver(this, "quit-application");
 
     await this._stateChangeProcessEnqueue(_ => this._shutdownService());
   },
 
   /**
    * Drops all active registrations and notifies the associated service
    * workers. This function is called when the user switches Push servers,
@@ -812,17 +815,17 @@ var PushService = {
           // we check for visible notifications.
           let timeoutID = setTimeout(_ => {
             this._updateQuota(keyID);
             if (!this._updateQuotaTimeouts.delete(timeoutID)) {
               console.debug(
                 "receivedPushMessage: quota update timeout missing?"
               );
             }
-          }, prefs.get("quotaUpdateDelay"));
+          }, prefs.getIntPref("quotaUpdateDelay"));
           this._updateQuotaTimeouts.add(timeoutID);
         }
         return this._decryptAndNotifyApp(record, messageID, headers, data);
       })
       .catch(error => {
         console.error("receivedPushMessage: Error notifying app", error);
         return Ci.nsIPushErrorReporter.ACK_NOT_DELIVERED;
       });
--- a/dom/push/PushServiceWebSocket.jsm
+++ b/dom/push/PushServiceWebSocket.jsm
@@ -1,18 +1,15 @@
 /* jshint moz: true, esnext: true */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { Preferences } = ChromeUtils.import(
-  "resource://gre/modules/Preferences.jsm"
-);
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
 
 const { PushDB } = ChromeUtils.import("resource://gre/modules/PushDB.jsm");
 const { PushRecord } = ChromeUtils.import(
   "resource://gre/modules/PushRecord.jsm"
@@ -55,17 +52,17 @@ const kUNREGISTER_REASON_TO_CODE = {
 };
 
 const kDELIVERY_REASON_TO_CODE = {
   [Ci.nsIPushErrorReporter.DELIVERY_UNCAUGHT_EXCEPTION]: 301,
   [Ci.nsIPushErrorReporter.DELIVERY_UNHANDLED_REJECTION]: 302,
   [Ci.nsIPushErrorReporter.DELIVERY_INTERNAL_ERROR]: 303,
 };
 
-const prefs = new Preferences("dom.push.");
+const prefs = Services.prefs.getBranch("dom.push.");
 
 const EXPORTED_SYMBOLS = ["PushServiceWebSocket"];
 
 XPCOMUtils.defineLazyGetter(this, "console", () => {
   let { ConsoleAPI } = ChromeUtils.import("resource://gre/modules/Console.jsm");
   return new ConsoleAPI({
     maxLogLevelPref: "dom.push.loglevel",
     prefix: "PushServiceWebSocket",
@@ -250,30 +247,30 @@ var PushServiceWebSocket = {
     // The most likely reason for a pong or registration request timing out is
     // that the socket has disconnected. Best to reconnect.
     if (requestTimedOut) {
       this._reconnect();
     }
   },
 
   get _UAID() {
-    return prefs.get("userAgentID");
+    return prefs.getStringPref("userAgentID");
   },
 
   set _UAID(newID) {
     if (typeof newID !== "string") {
       console.warn(
         "Got invalid, non-string UAID",
         newID,
         "Not updating userAgentID"
       );
       return;
     }
     console.debug("New _UAID", newID);
-    prefs.set("userAgentID", newID);
+    prefs.setStringPref("userAgentID", newID);
   },
 
   _ws: null,
   _pendingRequests: new Map(),
   _currentState: STATE_SHUT_DOWN,
   _requestTimeout: 0,
   _requestTimeoutTimer: null,
   _retryFailCount: 0,
@@ -336,32 +333,32 @@ var PushServiceWebSocket = {
 
     // Override the default WebSocket factory function. The returned object
     // must be null or satisfy the nsIWebSocketChannel interface. Used by
     // the tests to provide a mock WebSocket implementation.
     if (options.makeWebSocket) {
       this._makeWebSocket = options.makeWebSocket;
     }
 
-    this._requestTimeout = prefs.get("requestTimeout");
+    this._requestTimeout = prefs.getIntPref("requestTimeout");
 
     return Promise.resolve();
   },
 
   _reconnect() {
     console.debug("reconnect()");
     this._shutdownWS(false);
     this._startBackoffTimer();
   },
 
   _shutdownWS(shouldCancelPending = true) {
     console.debug("shutdownWS()");
 
     if (this._currentState == STATE_READY) {
-      prefs.ignore("userAgentID", this);
+      prefs.removeObserver("userAgentID", this);
     }
 
     this._currentState = STATE_SHUT_DOWN;
     this._skipReconnect = false;
 
     if (this._wsListener) {
       this._wsListener._pushService = null;
     }
@@ -416,18 +413,18 @@ var PushServiceWebSocket = {
    * timer event comes in (because the timer fired the event before it was
    * cancelled), so the connection won't be reset.
    */
   _startBackoffTimer() {
     console.debug("startBackoffTimer()");
 
     // Calculate new timeout, but cap it to pingInterval.
     let retryTimeout =
-      prefs.get("retryBaseInterval") * Math.pow(2, this._retryFailCount);
-    retryTimeout = Math.min(retryTimeout, prefs.get("pingInterval"));
+      prefs.getIntPref("retryBaseInterval") * Math.pow(2, this._retryFailCount);
+    retryTimeout = Math.min(retryTimeout, prefs.getIntPref("pingInterval"));
 
     this._retryFailCount++;
 
     console.debug(
       "startBackoffTimer: Retry in",
       retryTimeout,
       "Try number",
       this._retryFailCount
@@ -468,23 +465,23 @@ var PushServiceWebSocket = {
 
   /** Starts or resets the ping timer. */
   _startPingTimer() {
     if (!this._pingTimer) {
       this._pingTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     }
     this._pingTimer.init(
       this,
-      prefs.get("pingInterval"),
+      prefs.getIntPref("pingInterval"),
       Ci.nsITimer.TYPE_ONE_SHOT
     );
   },
 
   _makeWebSocket(uri) {
-    if (!prefs.get("connection.enabled")) {
+    if (!prefs.getBoolPref("connection.enabled")) {
       console.warn(
         "makeWebSocket: connection.enabled is not set to true.",
         "Aborting."
       );
       return null;
     }
     if (Services.io.offline) {
       console.warn("makeWebSocket: Network is offline.");
@@ -604,17 +601,17 @@ var PushServiceWebSocket = {
         this._notifyRequestQueue = null;
       }
       this._sendPendingRequests();
     };
 
     function finishHandshake() {
       this._UAID = reply.uaid;
       this._currentState = STATE_READY;
-      prefs.observe("userAgentID", this);
+      prefs.addObserver("userAgentID", this);
 
       // Handle broadcasts received in response to the "hello" message.
       if (!ObjectUtils.isEmpty(reply.broadcasts)) {
         // The reply isn't technically a broadcast message, but it has
         // the shape of a broadcast message (it has a broadcasts field).
         const context = { phase: pushBroadcastService.PHASES.HELLO };
         this._mainPushService.receivedBroadcastMessage(reply, context);
       }