Backed out changeset a956d11fef6e (bug 1369436) for XPCshell failure on dom/push/test/xpcshell/test_notification_http2.js
authorDorel Luca <dluca@mozilla.com>
Fri, 13 Sep 2019 00:42:28 +0300
changeset 492912 e2f842a491c9dee26d4f47c57c9ac7e7c29428e3
parent 492911 63a10d0c96ce1e86e1f7bffffb9b3b20b003a090
child 492913 641f75b6c5d8d475ea7645aca80cb7237764cead
push id95233
push userdluca@mozilla.com
push dateThu, 12 Sep 2019 21:46:41 +0000
treeherderautoland@e2f842a491c9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1369436
milestone71.0a1
backs outa956d11fef6eae7ba0f9fe2f5219ed9df3c9a713
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
Backed out changeset a956d11fef6e (bug 1369436) for XPCshell failure on dom/push/test/xpcshell/test_notification_http2.js
browser/base/content/test/performance/browser_startup.js
browser/components/BrowserGlue.jsm
dom/push/PushComponents.jsm
dom/push/PushCrypto.jsm
dom/push/PushService.jsm
dom/push/PushServiceAndroidGCM.jsm
dom/push/PushServiceHttp2.jsm
dom/push/PushServiceWebSocket.jsm
--- a/browser/base/content/test/performance/browser_startup.js
+++ b/browser/base/content/test/performance/browser_startup.js
@@ -31,16 +31,18 @@ const startupPhases = {
         "resource:///modules/BrowserGlue.jsm",
         "resource://gre/modules/AppConstants.jsm",
         "resource://gre/modules/ActorManagerParent.jsm",
         "resource://gre/modules/CustomElementsListener.jsm",
         "resource://gre/modules/ExtensionUtils.jsm",
         "resource://gre/modules/MainProcessSingleton.jsm",
         "resource://gre/modules/XPCOMUtils.jsm",
         "resource://gre/modules/Services.jsm",
+        // Bugs to fix: The following components shouldn't be initialized that early.
+        "resource://gre/modules/PushComponents.jsm", // bug 1369436
       ]),
     },
   },
 
   // For the following phases of startup we have only a black list for now
 
   // We are at this phase after creating the first browser window (ie. after final-ui-startup).
   "before opening first browser window": {
@@ -75,17 +77,16 @@ const startupPhases = {
   // We are at this phase once we are ready to handle user events.
   // Anything loaded at this phase or before gets in the way of the user
   // interacting with the first browser window.
   "before handling user events": {
     blacklist: {
       components: new Set([
         "PageIconProtocolHandler.js",
         "PlacesCategoriesStarter.js",
-        "PushComponents.jsm",
         "nsPlacesExpiration.js",
       ]),
       modules: new Set([
         // Bug 1391495 - BrowserWindowTracker.jsm is intermittently used.
         // "resource:///modules/BrowserWindowTracker.jsm",
         "resource://gre/modules/BookmarkHTMLUtils.jsm",
         "resource://gre/modules/Bookmarks.jsm",
         "resource://gre/modules/ContextualIdentityService.jsm",
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -15,22 +15,16 @@ const { AppConstants } = ChromeUtils.imp
 );
 
 ChromeUtils.defineModuleGetter(
   this,
   "ActorManagerParent",
   "resource://gre/modules/ActorManagerParent.jsm"
 );
 
-ChromeUtils.defineModuleGetter(
-  this,
-  "PushService",
-  "resource://gre/modules/PushService.jsm"
-);
-
 const PREF_PDFJS_ENABLED_CACHE_STATE = "pdfjs.enabledCache.state";
 
 let ACTORS = {
   BrowserTab: {
     parent: {
       moduleURI: "resource:///actors/BrowserTabParent.jsm",
     },
     child: {
@@ -2002,21 +1996,16 @@ BrowserGlue.prototype = {
    * to the other ones scheduled together.
    */
   _scheduleStartupIdleTasks() {
     Services.tm.idleDispatchToMainThread(async () => {
       await ContextualIdentityService.load();
       Discovery.update();
     });
 
-    // Begin listening for incoming push messages.
-    Services.tm.idleDispatchToMainThread(() => {
-      PushService.ensureReady();
-    });
-
     Services.tm.idleDispatchToMainThread(() => {
       let enableCertErrorUITelemetry = Services.prefs.getBoolPref(
         "security.certerrors.recordEventTelemetry",
         false
       );
       Services.telemetry.setEventRecordingEnabled(
         "security.ui.certerror",
         enableCertErrorUITelemetry
--- a/dom/push/PushComponents.jsm
+++ b/dom/push/PushComponents.jsm
@@ -64,32 +64,41 @@ PushServiceBase.prototype = {
     Ci.nsIPushQuotaManager,
     Ci.nsIPushErrorReporter,
   ]),
 
   pushTopic: OBSERVER_TOPIC_PUSH,
   subscriptionChangeTopic: OBSERVER_TOPIC_SUBSCRIPTION_CHANGE,
   subscriptionModifiedTopic: OBSERVER_TOPIC_SUBSCRIPTION_MODIFIED,
 
-  ensureReady() {},
+  _handleReady() {},
 
   _addListeners() {
     for (let message of this._messages) {
       this._mm.addMessageListener(message, this);
     }
   },
 
   _isValidMessage(message) {
     return this._messages.includes(message.name);
   },
 
   observe(subject, topic, data) {
+    if (topic === "app-startup") {
+      Services.obs.addObserver(this, "sessionstore-windows-restored", true);
+      return;
+    }
+    if (topic === "sessionstore-windows-restored") {
+      Services.obs.removeObserver(this, "sessionstore-windows-restored");
+      this._handleReady();
+      return;
+    }
     if (topic === "android-push-service") {
       // Load PushService immediately.
-      this.ensureReady();
+      this._handleReady();
     }
   },
 
   _deliverSubscription(request, props) {
     if (!props) {
       request.onPushSubscription(Cr.NS_OK, null);
       return;
     }
@@ -251,17 +260,17 @@ Object.assign(PushServiceParent.prototyp
             requestID: data.requestID,
             result: error.result,
           });
         }
       )
       .catch(Cu.reportError);
   },
 
-  ensureReady() {
+  _handleReady() {
     this.service.init();
   },
 
   _toPageRecord(principal, data) {
     if (!data.scope) {
       throw new Error("Invalid page record: missing scope");
     }
     if (!principal) {
--- a/dom/push/PushCrypto.jsm
+++ b/dom/push/PushCrypto.jsm
@@ -10,17 +10,17 @@ const { XPCOMUtils } = ChromeUtils.impor
 );
 
 XPCOMUtils.defineLazyGetter(this, "gDOMBundle", () =>
   Services.strings.createBundle("chrome://global/locale/dom/dom.properties")
 );
 
 XPCOMUtils.defineLazyGlobalGetters(this, ["crypto"]);
 
-const EXPORTED_SYMBOLS = ["PushCrypto"];
+const EXPORTED_SYMBOLS = ["PushCrypto", "concatArray"];
 
 const UTF8 = new TextEncoder("utf-8");
 
 const ECDH_KEY = { name: "ECDH", namedCurve: "P-256" };
 const ECDSA_KEY = { name: "ECDSA", namedCurve: "P-256" };
 const HMAC_SHA256 = { name: "HMAC", hash: "SHA-256" };
 const NONCE_INFO = UTF8.encode("Content-Encoding: nonce");
 
@@ -598,18 +598,16 @@ class aesgcm128Decoder extends OldScheme
   }
 
   get padSize() {
     return 1;
   }
 }
 
 var PushCrypto = {
-  concatArray,
-
   generateAuthenticationSecret() {
     return crypto.getRandomValues(new Uint8Array(16));
   },
 
   validateAppServerKey(key) {
     return crypto.subtle
       .importKey("raw", key, ECDSA_KEY, true, ["verify"])
       .then(_ => key);
--- a/dom/push/PushService.jsm
+++ b/dom/push/PushService.jsm
@@ -15,16 +15,32 @@ const { clearTimeout, setTimeout } = Chr
   "resource://gre/modules/Timer.jsm"
 );
 const { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
 
 var PushServiceWebSocket, PushServiceHttp2;
 
+const CONNECTION_PROTOCOLS = (function() {
+  if ("android" != AppConstants.MOZ_WIDGET_TOOLKIT) {
+    ({ PushServiceWebSocket } = ChromeUtils.import(
+      "resource://gre/modules/PushServiceWebSocket.jsm"
+    ));
+    ({ PushServiceHttp2 } = ChromeUtils.import(
+      "resource://gre/modules/PushServiceHttp2.jsm"
+    ));
+    return [PushServiceWebSocket, PushServiceHttp2];
+  }
+  const { PushServiceAndroidGCM } = ChromeUtils.import(
+    "resource://gre/modules/PushServiceAndroidGCM.jsm"
+  );
+  return [PushServiceAndroidGCM];
+})();
+
 XPCOMUtils.defineLazyServiceGetter(
   this,
   "gPushNotifier",
   "@mozilla.org/push/Notifier;1",
   "nsIPushNotifier"
 );
 XPCOMUtils.defineLazyServiceGetter(
   this,
@@ -37,34 +53,16 @@ ChromeUtils.defineModuleGetter(
   "pushBroadcastService",
   "resource://gre/modules/PushBroadcastService.jsm"
 );
 ChromeUtils.defineModuleGetter(
   this,
   "PushCrypto",
   "resource://gre/modules/PushCrypto.jsm"
 );
-ChromeUtils.defineModuleGetter(
-  this,
-  "PushServiceAndroidGCM",
-  "resource://gre/modules/PushServiceAndroidGCM.jsm"
-);
-
-const CONNECTION_PROTOCOLS = (function() {
-  if ("android" != AppConstants.MOZ_WIDGET_TOOLKIT) {
-    ({ PushServiceWebSocket } = ChromeUtils.import(
-      "resource://gre/modules/PushServiceWebSocket.jsm"
-    ));
-    ({ PushServiceHttp2 } = ChromeUtils.import(
-      "resource://gre/modules/PushServiceHttp2.jsm"
-    ));
-    return [PushServiceWebSocket, PushServiceHttp2];
-  }
-  return [PushServiceAndroidGCM];
-})();
 
 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",
@@ -97,35 +95,16 @@ const PUSH_SERVICE_RUNNING = 5;
  **/
 
 // This is for starting and stopping service.
 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");
-  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;
-  }
-  if (uri.scheme == "https" || (allowInsecure && uri.scheme == "http")) {
-    return PushServiceHttp2;
-  }
-  return null;
-}
-
 /**
  * Annotates an error with an XPCOM result code. We use this helper
  * instead of `Components.Exception` because the latter can assert in
  * `nsXPCComponents_Exception::HasInstance` when inspected at shutdown.
  */
 function errorWithResult(message, result = Cr.NS_ERROR_FAILURE) {
   let error = new Error(message);
   error.result = result;
@@ -424,34 +403,41 @@ var PushService = {
       .catch(e => {
         console.error("backgroundUnregister: Error notifying server", e);
       });
   },
 
   _findService(serverURL) {
     console.debug("findService()");
 
+    let uri;
+    let service;
+
     if (!serverURL) {
       console.warn("findService: No dom.push.serverURL found");
       return [];
     }
 
-    let uri;
     try {
       uri = Services.io.newURI(serverURL);
     } catch (e) {
       console.warn(
         "findService: Error creating valid URI from",
         "dom.push.serverURL",
         serverURL
       );
       return [];
     }
 
-    let service = getServiceForServerURI(uri);
+    for (let connProtocol of CONNECTION_PROTOCOLS) {
+      if (connProtocol.validServerURI(uri)) {
+        service = connProtocol;
+        break;
+      }
+    }
     return [service, uri];
   },
 
   _changeServerURL(serverURI, event, options = {}) {
     console.debug("changeServerURL()");
 
     switch (event) {
       case UNINIT_EVENT:
--- a/dom/push/PushServiceAndroidGCM.jsm
+++ b/dom/push/PushServiceAndroidGCM.jsm
@@ -74,16 +74,35 @@ var PushServiceAndroidGCM = {
       kPUSHANDROIDGCMDB_DB_NAME,
       kPUSHANDROIDGCMDB_DB_VERSION,
       kPUSHANDROIDGCMDB_STORE_NAME,
       "channelID",
       PushRecordAndroidGCM
     );
   },
 
+  validServerURI(serverURI) {
+    if (!serverURI) {
+      return false;
+    }
+
+    if (serverURI.scheme == "https") {
+      return true;
+    }
+    if (serverURI.scheme == "http") {
+      // Allow insecure server URLs for development and testing.
+      return !!prefs.get("testing.allowInsecureServerURL");
+    }
+    console.info(
+      "Unsupported Android GCM dom.push.serverURL scheme",
+      serverURI.scheme
+    );
+    return false;
+  },
+
   observe(subject, topic, data) {
     switch (topic) {
       case "nsPref:changed":
         if (data == "dom.push.debug") {
           // Reconfigure.
           let debug = !!prefs.get("debug");
           console.info(
             "Debug parameter changed; updating configuration with new debug",
--- a/dom/push/PushServiceHttp2.jsm
+++ b/dom/push/PushServiceHttp2.jsm
@@ -420,16 +420,23 @@ var PushServiceHttp2 = {
       PushRecordHttp2
     );
   },
 
   hasmainPushService() {
     return this._mainPushService !== null;
   },
 
+  validServerURI(serverURI) {
+    if (serverURI.scheme == "http") {
+      return !!prefs.getBoolPref("testing.allowInsecureServerURL", false);
+    }
+    return serverURI.scheme == "https";
+  },
+
   async connect(broadcastListeners) {
     let subscriptions = await this._mainPushService.getAllUnexpired();
     this.startConnections(subscriptions);
   },
 
   async sendSubscribeBroadcast(serviceId, version) {
     // Not implemented yet
   },
--- a/dom/push/PushServiceWebSocket.jsm
+++ b/dom/push/PushServiceWebSocket.jsm
@@ -249,16 +249,23 @@ 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();
     }
   },
 
+  validServerURI(serverURI) {
+    if (serverURI.scheme == "ws") {
+      return !!prefs.get("testing.allowInsecureServerURL");
+    }
+    return serverURI.scheme == "wss";
+  },
+
   get _UAID() {
     return prefs.get("userAgentID");
   },
 
   set _UAID(newID) {
     if (typeof newID !== "string") {
       console.warn(
         "Got invalid, non-string UAID",