Bug 1210896, Part 2 - Use JS errors to reject internal Push promises. r=mt
authorKit Cambridge <kcambridge@mozilla.com>
Mon, 09 Nov 2015 13:58:50 -0800
changeset 305986 963ad639d9fa794770ef299a9b69f3b390185b6f
parent 305985 03fac612bbc89f691398b28b0a138eff3bbd6efd
child 305987 273714c71f4122fa4e6e45124a5fc5b2f8e537c0
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmt
bugs1210896
milestone45.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 1210896, Part 2 - Use JS errors to reject internal Push promises. r=mt
dom/push/PushClient.js
dom/push/PushDB.jsm
dom/push/PushNotificationService.js
dom/push/PushService.jsm
dom/push/PushServiceHttp2.jsm
dom/push/PushServiceWebSocket.jsm
dom/push/test/xpcshell/test_reconnect_retry.js
dom/push/test/xpcshell/test_register_5xxCode_http2.js
dom/push/test/xpcshell/test_register_case.js
dom/push/test/xpcshell/test_register_error_http2.js
dom/push/test/xpcshell/test_register_flush.js
dom/push/test/xpcshell/test_register_invalid_channel.js
dom/push/test/xpcshell/test_register_invalid_endpoint.js
dom/push/test/xpcshell/test_register_invalid_json.js
dom/push/test/xpcshell/test_register_no_id.js
dom/push/test/xpcshell/test_register_request_queue.js
dom/push/test/xpcshell/test_register_rollback.js
dom/push/test/xpcshell/test_register_success.js
dom/push/test/xpcshell/test_register_success_http2.js
dom/push/test/xpcshell/test_register_timeout.js
dom/push/test/xpcshell/test_register_wrong_id.js
dom/push/test/xpcshell/test_register_wrong_type.js
dom/push/test/xpcshell/test_registration_missing_scope.js
dom/push/test/xpcshell/test_unregister_empty_scope.js
dom/push/test/xpcshell/test_updateRecordNoEncryptionKeys_ws.js
--- a/dom/push/PushClient.js
+++ b/dom/push/PushClient.js
@@ -95,16 +95,20 @@ PushClient.prototype = {
       requestId);
     this._cpmm.sendAsyncMessage("Push:Registration", {
                                 scope: scope,
                                 requestID: requestId,
                               }, null, principal);
   },
 
   _deliverPushEndpoint: function(request, registration) {
+    if (!registration) {
+      request.onPushEndpoint(Cr.NS_OK, "", 0, null);
+      return;
+    }
     if (registration.p256dhKey) {
       let key = new Uint8Array(registration.p256dhKey);
       request.onPushEndpoint(Cr.NS_OK,
                              registration.pushEndpoint,
                              key.length,
                              key);
       return;
     }
@@ -120,34 +124,25 @@ PushClient.prototype = {
 
     if (!request) {
       console.error("receiveMessage: Unknown request ID", json.requestID);
       return;
     }
 
     switch (aMessage.name) {
       case "PushService:Register:OK":
-        this._deliverPushEndpoint(request, json);
-        break;
-      case "PushService:Register:KO":
-        request.onPushEndpoint(Cr.NS_ERROR_FAILURE, "", 0, null);
+      case "PushService:Registration:OK":
+        this._deliverPushEndpoint(request, json.result);
         break;
-      case "PushService:Registration:OK":
-      {
-        let endpoint = "";
-        if (!json.registration) {
-          request.onPushEndpoint(Cr.NS_OK, "", 0, null);
-        } else {
-          this._deliverPushEndpoint(request, json.registration);
-        }
-        break;
-      }
+
+      case "PushService:Register:KO":
       case "PushService:Registration:KO":
         request.onPushEndpoint(Cr.NS_ERROR_FAILURE, "", 0, null);
         break;
+
       case "PushService:Unregister:OK":
         if (typeof json.result !== "boolean") {
           console.error("receiveMessage: Expected boolean for unregister response",
             json.result);
           request.onUnsubscribe(Cr.NS_ERROR_FAILURE, false);
           return;
         }
 
--- a/dom/push/PushDB.jsm
+++ b/dom/push/PushDB.jsm
@@ -3,16 +3,17 @@
  * 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 Cu = Components.utils;
 Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
 Cu.import("resource://gre/modules/Preferences.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.importGlobalProperties(["indexedDB"]);
 
 this.EXPORTED_SYMBOLS = ["PushDB"];
 
 XPCOMUtils.defineLazyGetter(this, "console", () => {
   let {ConsoleAPI} = Cu.import("resource://gre/modules/Console.jsm", {});
   return new ConsoleAPI({
     maxLogLevelPref: "dom.push.loglevel",
--- a/dom/push/PushNotificationService.js
+++ b/dom/push/PushNotificationService.js
@@ -34,29 +34,29 @@ PushNotificationService.prototype = {
   contractID: "@mozilla.org/push/NotificationService;1",
 
   _xpcom_factory: XPCOMUtils.generateSingletonFactory(PushNotificationService),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference,
                                          Ci.nsIPushNotificationService]),
 
   register: function register(scope, originAttributes) {
-    return PushService._register({
+    return PushService.register({
       scope: scope,
       originAttributes: originAttributes,
       maxQuota: Infinity,
     });
   },
 
   unregister: function unregister(scope, originAttributes) {
-    return PushService._unregister({scope, originAttributes});
+    return PushService.unregister({scope, originAttributes});
   },
 
   registration: function registration(scope, originAttributes) {
-    return PushService._registration({scope, originAttributes});
+    return PushService.registration({scope, originAttributes});
   },
 
   clearAll: function clearAll() {
     return PushService._clearAll();
   },
 
   clearForDomain: function(domain) {
     return PushService._clearForDomain(domain);
--- a/dom/push/PushService.jsm
+++ b/dom/push/PushService.jsm
@@ -112,17 +112,17 @@ this.PushService = {
   // Pending request. If a worker try to register for the same scope again, do
   // not send a new registration request. Therefore we need queue of pending
   // register requests. This is the list of scopes which pending registration.
   _pendingRegisterRequest: {},
   _notifyActivated: null,
   _activated: null,
   _checkActivated: function() {
     if (this._state < PUSH_SERVICE_ACTIVATING) {
-      return Promise.reject({state: 0, error: "Service not active"});
+      return Promise.reject(new Error("Push service not active"));
     } else if (this._state > PUSH_SERVICE_ACTIVATING) {
       return Promise.resolve();
     } else {
       return (this._activated) ? this._activated :
                                  this._activated = new Promise((res, rej) =>
                                    this._notifyActivated = {resolve: res,
                                                             reject: rej});
     }
@@ -156,17 +156,17 @@ this.PushService = {
     }
 
     if (this._state == PUSH_SERVICE_ACTIVATING) {
       // It is not important what is the new state as soon as we leave
       // PUSH_SERVICE_ACTIVATING
       this._state = aNewState;
       if (this._notifyActivated) {
         if (aNewState < PUSH_SERVICE_ACTIVATING) {
-          this._notifyActivated.reject({state: 0, error: "Service not active"});
+          this._notifyActivated.reject(new Error("Push service not active"));
         } else {
           this._notifyActivated.resolve();
         }
       }
       this._notifyActivated = null;
       this._activated = null;
     }
     this._state = aNewState;
@@ -907,22 +907,22 @@ this.PushService = {
   },
 
   getAllUnexpired: function() {
     return this._db.getAllUnexpired();
   },
 
   _sendRequest: function(action, aRecord) {
     if (this._state == PUSH_SERVICE_CONNECTION_DISABLE) {
-      return Promise.reject({state: 0, error: "Service not active"});
+      return Promise.reject(new Error("Push service disabled"));
     } else if (this._state == PUSH_SERVICE_ACTIVE_OFFLINE) {
       if (this._service.serviceType() == "WebSocket" && action == "unregister") {
         return Promise.resolve();
       }
-      return Promise.reject({state: 0, error: "NetworkError"});
+      return Promise.reject(new Error("Push service offline"));
     }
     return this._service.request(action, aRecord);
   },
 
   /**
    * Called on message from the child process. aPageRecord is an object sent by
    * navigator.push, identifying the sending page and other fields.
    */
@@ -930,52 +930,23 @@ this.PushService = {
     console.debug("registerWithServer()", aPageRecord);
 
     Services.telemetry.getHistogramById("PUSH_API_SUBSCRIBE_ATTEMPT").add();
     return this._sendRequest("register", aPageRecord)
       .then(record => this._onRegisterSuccess(record),
             err => this._onRegisterError(err))
       .then(record => {
         this._deletePendingRequest(aPageRecord);
-        return record;
+        return record.toRegister();
       }, err => {
         this._deletePendingRequest(aPageRecord);
         throw err;
      });
   },
 
-  _register: function(aPageRecord) {
-    console.debug("_register()");
-    if (!aPageRecord.scope || aPageRecord.originAttributes === undefined) {
-      return Promise.reject({state: 0, error: "NotFoundError"});
-    }
-
-    return this._checkActivated()
-      .then(_ => this._db.getByIdentifiers(aPageRecord))
-      .then(record => {
-        if (!record) {
-          return this._lookupOrPutPendingRequest(aPageRecord);
-        }
-        if (record.isExpired()) {
-          return record.quotaChanged().then(isChanged => {
-            if (isChanged) {
-              // If the user revisited the site, drop the expired push
-              // registration and re-register.
-              return this._db.delete(record.keyID);
-            }
-            throw {state: 0, error: "NotFoundError"};
-          }).then(_ => this._lookupOrPutPendingRequest(aPageRecord));
-        }
-        return record;
-      }, error => {
-        console.error("register: getByIdentifiers failed", error);
-        throw error;
-      });
-  },
-
   _sendUnregister: function(aRecord) {
     Services.telemetry.getHistogramById("PUSH_API_UNSUBSCRIBE_ATTEMPT").add();
     return this._sendRequest("unregister", aRecord).then(function(v) {
       Services.telemetry.getHistogramById("PUSH_API_UNSUBSCRIBE_SUCCEEDED").add();
       return v;
     }).catch(function(e) {
       Services.telemetry.getHistogramById("PUSH_API_UNSUBSCRIBE_FAILED").add();
       return Promise.reject(e);
@@ -1045,61 +1016,77 @@ this.PushService = {
 
     if (!aMessage.target.assertPermission("push")) {
       console.debug("receiveMessage: Got message from a child process that",
         "does not have 'push' permission");
       return null;
     }
 
     let mm = aMessage.target.QueryInterface(Ci.nsIMessageSender);
-    let pageRecord = aMessage.data;
 
+    let name = aMessage.name.slice("Push:".length);
+    Promise.resolve().then(_ => {
+      let pageRecord = this._validatePageRecord(aMessage);
+      return this[name.toLowerCase()](pageRecord);
+    }).then(result => {
+      mm.sendAsyncMessage("PushService:" + name + ":OK", {
+        requestID: aMessage.data.requestID,
+        result: result,
+      });
+    }, error => {
+      console.error("receiveMessage: Error handling message", aMessage, error);
+      mm.sendAsyncMessage("PushService:" + name + ":KO", {
+        requestID: aMessage.data.requestID,
+      });
+    }).catch(error => {
+      console.error("receiveMessage: Error sending reply", error);
+    });
+  },
+
+  _validatePageRecord: function(aMessage) {
     let principal = aMessage.principal;
     if (!principal) {
-      console.debug("receiveMessage: No principal passed",
-        pageRecord.requestID);
-      let message = {
-        requestID: pageRecord.requestID,
-        error: "SecurityError"
-      };
-      mm.sendAsyncMessage("PushService:Register:KO", message);
-      return;
+      throw new Error("Missing message principal");
+    }
+
+    let pageRecord = aMessage.data;
+    if (!pageRecord.scope) {
+      throw new Error("Missing page record scope");
     }
 
     pageRecord.originAttributes =
       ChromeUtils.originAttributesToSuffix(principal.originAttributes);
 
-    if (!pageRecord.scope || pageRecord.originAttributes === undefined) {
-      console.debug("receiveMessage: Incorrect identifier values set",
-        pageRecord);
-      let message = {
-        requestID: pageRecord.requestID,
-        error: "SecurityError"
-      };
-      mm.sendAsyncMessage("PushService:Register:KO", message);
-      return;
-    }
-
-    this[aMessage.name.slice("Push:".length).toLowerCase()](pageRecord, mm);
+    return pageRecord;
   },
 
-  register: function(aPageRecord, aMessageManager) {
+  register: function(aPageRecord) {
     console.debug("register()", aPageRecord);
 
-    this._register(aPageRecord)
+    if (!aPageRecord.scope || aPageRecord.originAttributes === undefined) {
+      return Promise.reject(new Error("Invalid page record"));
+    }
+
+    return this._checkActivated()
+      .then(_ => this._db.getByIdentifiers(aPageRecord))
       .then(record => {
-        let message = record.toRegister();
-        message.requestID = aPageRecord.requestID;
-        aMessageManager.sendAsyncMessage("PushService:Register:OK", message);
-      }, error => {
-        let message = {
-          requestID: aPageRecord.requestID,
-          error
-        };
-        aMessageManager.sendAsyncMessage("PushService:Register:KO", message);
+        if (!record) {
+          return this._lookupOrPutPendingRequest(aPageRecord);
+        }
+        if (record.isExpired()) {
+          return record.quotaChanged().then(isChanged => {
+            if (isChanged) {
+              // If the user revisited the site, drop the expired push
+              // registration and re-register.
+              return this._db.delete(record.keyID);
+            }
+            throw new Error("Push subscription expired");
+          }).then(_ => this._lookupOrPutPendingRequest(aPageRecord));
+        }
+        return record.toRegister();
       });
   },
 
   /**
    * Called on message from the child process.
    *
    * Why is the record being deleted from the local database before the server
    * is told?
@@ -1118,54 +1105,37 @@ this.PushService = {
    * failure, the application is never informed. In addition the application may
    * retry the unregister when it fails due to timeout (websocket) or any other
    * reason at which point the server will say it does not know of this
    * unregistration.  We'll have to make the registration/unregistration phases
    * have retries and attempts to resend messages from the server, and have the
    * client acknowledge. On a server, data is cheap, reliable notification is
    * not.
    */
-  _unregister: function(aPageRecord) {
-    console.debug("_unregister()");
+  unregister: function(aPageRecord) {
+    console.debug("unregister()", aPageRecord);
+
     if (!aPageRecord.scope || aPageRecord.originAttributes === undefined) {
-      return Promise.reject({state: 0, error: "NotFoundError"});
+      return Promise.reject(new Error("Invalid page record"));
     }
 
     return this._checkActivated()
       .then(_ => this._db.getByIdentifiers(aPageRecord))
       .then(record => {
         if (record === undefined) {
           return false;
         }
 
         return Promise.all([
           this._sendUnregister(record),
           this._db.delete(record.keyID),
         ]).then(() => true);
       });
   },
 
-  unregister: function(aPageRecord, aMessageManager) {
-    console.debug("unregister()", aPageRecord);
-
-    this._unregister(aPageRecord)
-      .then(result => {
-          aMessageManager.sendAsyncMessage("PushService:Unregister:OK", {
-            requestID: aPageRecord.requestID,
-            result: result,
-          })
-        }, error => {
-          console.debug("unregister: Error removing registration", error);
-          aMessageManager.sendAsyncMessage("PushService:Unregister:KO", {
-            requestID: aPageRecord.requestID,
-          })
-        }
-      );
-  },
-
   _clearAll: function _clearAll() {
     return this._checkActivated()
       .then(_ => this._db.drop())
       .catch(_ => Promise.resolve());
   },
 
   _clearForDomain: function(domain) {
     /**
@@ -1204,23 +1174,20 @@ this.PushService = {
     return this._checkActivated()
       .then(_ => clear(this._db, domain))
       .catch(e => {
         console.warn("clearForDomain: Error forgetting about domain", e);
         return Promise.resolve();
       });
   },
 
-  /**
-   * Called on message from the child process
-   */
-  _registration: function(aPageRecord) {
-    console.debug("_registration()");
+  registration: function(aPageRecord) {
+    console.debug("registration()");
     if (!aPageRecord.scope || aPageRecord.originAttributes === undefined) {
-      return Promise.reject({state: 0, error: "NotFoundError"});
+      return Promise.reject(new Error("Invalid page record"));
     }
 
     return this._checkActivated()
       .then(_ => this._db.getByIdentifiers(aPageRecord))
       .then(record => {
         if (!record) {
           return null;
         }
@@ -1231,32 +1198,16 @@ this.PushService = {
             }
             return null;
           });
         }
         return record.toRegistration();
       });
   },
 
-  registration: function(aPageRecord, aMessageManager) {
-    console.debug("registration()");
-
-    return this._registration(aPageRecord)
-      .then(registration =>
-        aMessageManager.sendAsyncMessage("PushService:Registration:OK", {
-          requestID: aPageRecord.requestID,
-          registration
-        }), error =>
-        aMessageManager.sendAsyncMessage("PushService:Registration:KO", {
-          requestID: aPageRecord.requestID,
-          error
-        })
-      );
-  },
-
   _dropExpiredRegistrations: function() {
     console.debug("dropExpiredRegistrations()");
 
     return this._db.getAllExpired().then(records => {
       return Promise.all(records.map(record =>
         record.quotaChanged().then(isChanged => {
           if (isChanged) {
             // If the user revisited the site, drop the expired push
--- a/dom/push/PushServiceHttp2.jsm
+++ b/dom/push/PushServiceHttp2.jsm
@@ -222,17 +222,17 @@ PushServiceDelete.prototype = {
     var data = inputStream.read(aCount);
   },
 
   onStopRequest: function(aRequest, aContext, aStatusCode) {
 
     if (Components.isSuccessCode(aStatusCode)) {
        this._resolve();
     } else {
-       this._reject({status: 0, error: "NetworkError"});
+       this._reject(new Error("Error removing subscription: " + aStatusCode));
     }
   }
 };
 
 var SubscriptionListener = function(aSubInfo, aResolve, aReject,
                                     aServerURI, aPushServiceHttp2) {
   console.debug("SubscriptionListener()");
   this._subInfo = aSubInfo;
@@ -264,82 +264,83 @@ SubscriptionListener.prototype = {
     this._data.concat(inputStream.read(aCount));
   },
 
   onStopRequest: function(aRequest, aContext, aStatus) {
     console.debug("SubscriptionListener: onStopRequest()");
 
     // Check if pushService is still active.
     if (!this._service.hasmainPushService()) {
-      this._reject({error: "Service deactivated"});
+      this._reject(new Error("Push service unavailable"));
       return;
     }
 
     if (!Components.isSuccessCode(aStatus)) {
-      this._reject({error: "Error status" + aStatus});
+      this._reject(new Error("Error listening for messages: " + aStatus));
       return;
     }
 
     var statusCode = aRequest.QueryInterface(Ci.nsIHttpChannel).responseStatus;
 
     if (Math.floor(statusCode / 100) == 5) {
       if (this._subInfo.retries < prefs.get("http2.maxRetries")) {
         this._subInfo.retries++;
         var retryAfter = retryAfterParser(aRequest);
         setTimeout(_ => this._reject(
           {
             retry: true,
             subInfo: this._subInfo
           }),
           retryAfter);
       } else {
-        this._reject({error: "Error response code: " + statusCode });
+        this._reject(new Error("Unexpected server response: " + statusCode));
       }
       return;
     } else if (statusCode != 201) {
-      this._reject({error: "Error response code: " + statusCode });
+      this._reject(new Error("Unexpected server response: " + statusCode));
       return;
     }
 
     var subscriptionUri;
     try {
       subscriptionUri = aRequest.getResponseHeader("location");
     } catch (err) {
-      this._reject({error: "Return code 201, but the answer is bogus"});
+      this._reject(new Error("Missing Location header"));
       return;
     }
 
     console.debug("onStopRequest: subscriptionUri", subscriptionUri);
 
     var linkList;
     try {
       linkList = aRequest.getResponseHeader("link");
     } catch (err) {
-      this._reject({error: "Return code 201, but the answer is bogus"});
+      this._reject(new Error("Missing Link header"));
       return;
     }
 
-    var linkParserResult = linkParser(linkList, this._serverURI);
-    if (linkParserResult.error) {
-      this._reject(linkParserResult);
+    var linkParserResult;
+    try {
+      linkParserResult = linkParser(linkList, this._serverURI);
+    } catch (e) {
+      this._reject(e);
       return;
     }
 
     if (!subscriptionUri) {
-      this._reject({error: "Return code 201, but the answer is bogus," +
-                           " missing subscriptionUri"});
+      this._reject(new Error("Invalid Location header"));
       return;
     }
     try {
       let uriTry = Services.io.newURI(subscriptionUri, null, null);
     } catch (e) {
       console.error("onStopRequest: Invalid subscription URI",
         subscriptionUri);
-      this._reject({error: "Return code 201, but URI is bogus. " +
-                    subscriptionUri});
+      this._reject(new Error("Invalid subscription endpoint: " +
+        subscriptionUri));
       return;
     }
 
     let reply = new PushRecordHttp2({
       subscriptionUri: subscriptionUri,
       pushEndpoint: linkParserResult.pushEndpoint,
       pushReceiptEndpoint: linkParserResult.pushReceiptEndpoint,
       scope: this._subInfo.record.scope,
@@ -367,17 +368,17 @@ function retryAfterParser(aRequest) {
 
   return retryAfter;
 }
 
 function linkParser(linkHeader, serverURI) {
 
   var linkList = linkHeader.split(',');
   if ((linkList.length < 1)) {
-    return {error: "Return code 201, but the answer is bogus"};
+    throw new Error("Invalid Link header");
   }
 
   var pushEndpoint;
   var pushReceiptEndpoint;
 
   linkList.forEach(link => {
     var linkElems = link.split(';');
 
@@ -392,38 +393,29 @@ function linkParser(linkHeader, serverUR
       }
     }
   });
 
   console.debug("linkParser: pushEndpoint", pushEndpoint);
   console.debug("linkParser: pushReceiptEndpoint", pushReceiptEndpoint);
   // Missing pushReceiptEndpoint is allowed.
   if (!pushEndpoint) {
-    return {error: "Return code 201, but the answer is bogus, missing" +
-                   " pushEndpoint"};
+    throw new Error("Missing push endpoint");
   }
 
-  var uri;
-  var resUri = [];
-  try {
-    [pushEndpoint, pushReceiptEndpoint].forEach(u => {
-      if (u) {
-        uri = u;
-        resUri[u] = Services.io.newURI(uri, null, serverURI);
-      }
-    });
-  } catch (e) {
-    console.debug("linkParser: Invalid URI", uri);
-    return {error: "Return code 201, but URI is bogus. " + uri};
+  var pushURI = Services.io.newURI(pushEndpoint, null, serverURI);
+  var pushReceiptURI;
+  if (pushReceiptEndpoint) {
+    pushReceiptURI = Services.io.newURI(pushReceiptEndpoint, null,
+                                        serverURI);
   }
 
   return {
-    pushEndpoint: resUri[pushEndpoint].spec,
-    pushReceiptEndpoint: (pushReceiptEndpoint) ? resUri[pushReceiptEndpoint].spec
-                                               : ""
+    pushEndpoint: pushURI.spec,
+    pushReceiptEndpoint: (pushReceiptURI) ? pushReceiptURI.spec : "",
   };
 }
 
 /**
  * The implementation of the WebPush.
  */
 this.PushServiceHttp2 = {
   _mainPushService: null,
@@ -539,41 +531,33 @@ this.PushServiceHttp2 = {
       var listener = new SubscriptionListener(aSubInfo,
                                               resolve,
                                               reject,
                                               this._serverURI,
                                               this);
 
       var chan = this._makeChannel(this._serverURI.spec);
       chan.requestMethod = "POST";
-      try {
-        chan.asyncOpen(listener, null);
-      } catch(e) {
-        reject({status: 0, error: "NetworkError"});
-      }
+      chan.asyncOpen(listener, null);
     })
     .catch(err => {
       if ("retry" in err) {
         return this._subscribeResourceInternal(err.subInfo);
       } else {
         throw err;
       }
     })
   },
 
   _deleteResource: function(aUri) {
 
     return new Promise((resolve,reject) => {
       var chan = this._makeChannel(aUri);
       chan.requestMethod = "DELETE";
-      try {
-        chan.asyncOpen(new PushServiceDelete(resolve, reject), null);
-      } catch(err) {
-        reject({status: 0, error: "NetworkError"});
-      }
+      chan.asyncOpen(new PushServiceDelete(resolve, reject), null);
     });
   },
 
   /**
    * Unsubscribe the resource with a subscription uri aSubscriptionUri.
    * We can't do anything about it if it fails, so we don't listen for response.
    */
   _unsubscribeResource: function(aSubscriptionUri) {
--- a/dom/push/PushServiceWebSocket.jsm
+++ b/dom/push/PushServiceWebSocket.jsm
@@ -179,21 +179,20 @@ this.PushServiceWebSocket = {
         // Set to true if at least one request timed out.
         let requestTimedOut = false;
         for (let channelID in this._registerRequests) {
           let duration = Date.now() - this._registerRequests[channelID].ctime;
           // If any of the registration requests time out, all the ones after it
           // also made to fail, since we are going to be disconnecting the
           // socket.
           if (requestTimedOut || duration > this._requestTimeout) {
-            console.debug("observe: Register request timed out for channel",
-              channelID);
             requestTimedOut = true;
             this._registerRequests[channelID]
-              .reject({status: 0, error: "TimeoutError"});
+              .reject(new Error("Register request timed out for channel ID " +
+                  channelID));
 
             delete this._registerRequests[channelID];
           }
         }
 
         // The most likely reason for a registration request timing out is
         // that the socket has disconnected. Best to reconnect.
         if (requestTimedOut) {
@@ -868,36 +867,35 @@ this.PushServiceWebSocket = {
       this._requestTimeoutTimer.cancel();
     }
 
     if (reply.status == 200) {
       try {
         Services.io.newURI(reply.pushEndpoint, null, null);
       }
       catch (e) {
-        console.error("handleRegisterReply: Invalid pushEndpoint",
-          reply.pushEndpoint);
-        tmp.reject({state: 0, error: "Invalid pushEndpoint " +
-                                     reply.pushEndpoint});
+        tmp.reject(new Error("Invalid push endpoint: " + reply.pushEndpoint));
         return;
       }
 
       let record = new PushRecordWebSocket({
         channelID: reply.channelID,
         pushEndpoint: reply.pushEndpoint,
         scope: tmp.record.scope,
         originAttributes: tmp.record.originAttributes,
         version: null,
         quota: tmp.record.maxQuota,
         ctime: Date.now(),
       });
       Services.telemetry.getHistogramById("PUSH_API_SUBSCRIBE_WS_TIME").add(Date.now() - tmp.ctime);
       tmp.resolve(record);
     } else {
-      tmp.reject(reply);
+      console.error("handleRegisterReply: Unexpected server response", reply);
+      tmp.reject(new Error("Wrong status code for register reply: " +
+        reply.status));
     }
   },
 
   _handleDataUpdate: function(update) {
     let promise;
     if (typeof update.channelID != "string") {
       console.warn("handleDataUpdate: Discarding update without channel ID",
         update);
@@ -1269,17 +1267,17 @@ this.PushServiceWebSocket = {
 
   /**
    * Rejects all pending register requests with errors.
    */
   _cancelRegisterRequests: function() {
     for (let channelID in this._registerRequests) {
       let request = this._registerRequests[channelID];
       delete this._registerRequests[channelID];
-      request.reject({status: 0, error: "AbortError"});
+      request.reject(new Error("Register request aborted"));
     }
   },
 
   _makeUDPSocket: function() {
     return Cc["@mozilla.org/network/udp-socket;1"]
              .createInstance(Ci.nsIUDPSocket);
   },
 
--- a/dom/push/test/xpcshell/test_reconnect_retry.js
+++ b/dom/push/test/xpcshell/test_reconnect_retry.js
@@ -42,30 +42,31 @@ add_task(function* test_reconnect_retry(
           }
           if (registers == 2) {
             equal(request.channelID, channelID,
               'Should retry registers after reconnect');
           }
           this.serverSendMsg(JSON.stringify({
             messageType: 'register',
             channelID: request.channelID,
-            pushEndpoint: 'https://example.org/push/' + registers,
+            pushEndpoint: 'https://example.org/push/' + request.channelID,
             status: 200,
           }));
         }
       });
     }
   });
 
   let registration = yield PushNotificationService.register(
     'https://example.com/page/1',
     ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })
   );
-  equal(registration.channelID, channelID, 'Wrong channel ID for retried request');
+  let retryEndpoint = 'https://example.org/push/' + channelID;
+  equal(registration.pushEndpoint, retryEndpoint, 'Wrong endpoint for retried request');
 
   registration = yield PushNotificationService.register(
     'https://example.com/page/2',
     ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })
   );
-  notEqual(registration.channelID, channelID, 'Wrong channel ID for new request');
+  notEqual(registration.pushEndpoint, retryEndpoint, 'Wrong endpoint for new request')
 
   equal(registers, 3, 'Wrong registration count');
 });
--- a/dom/push/test/xpcshell/test_register_5xxCode_http2.js
+++ b/dom/push/test/xpcshell/test_register_5xxCode_http2.js
@@ -86,25 +86,21 @@ add_task(function* test1() {
   let newRecord = yield PushNotificationService.register(
     'https://example.com/retry5xxCode',
     ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })
   );
 
   var subscriptionUri = serverURL + '/subscription';
   var pushEndpoint = serverURL + '/pushEndpoint';
   var pushReceiptEndpoint = serverURL + '/receiptPushEndpoint';
-  equal(newRecord.subscriptionUri, subscriptionUri,
-    'Wrong subscription ID in registration record');
   equal(newRecord.pushEndpoint, pushEndpoint,
     'Wrong push endpoint in registration record');
 
   equal(newRecord.pushReceiptEndpoint, pushReceiptEndpoint,
     'Wrong push endpoint receipt in registration record');
-  equal(newRecord.scope, 'https://example.com/retry5xxCode',
-    'Wrong scope in registration record');
 
   let record = yield db.getByKeyID(subscriptionUri);
   equal(record.subscriptionUri, subscriptionUri,
     'Wrong subscription ID in database record');
   equal(record.pushEndpoint, pushEndpoint,
     'Wrong push endpoint in database record');
   equal(record.pushReceiptEndpoint, pushReceiptEndpoint,
     'Wrong push endpoint receipt in database record');
--- a/dom/push/test/xpcshell/test_register_case.js
+++ b/dom/push/test/xpcshell/test_register_case.js
@@ -49,17 +49,13 @@ add_task(function* test_register_case() 
   let newRecord = yield waitForPromise(
     PushNotificationService.register('https://example.net/case',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
     DEFAULT_TIMEOUT,
     'Mixed-case register response timed out'
   );
   equal(newRecord.pushEndpoint, 'https://example.com/update/case',
     'Wrong push endpoint in registration record');
-  equal(newRecord.scope, 'https://example.net/case',
-    'Wrong scope in registration record');
 
-  let record = yield db.getByKeyID(newRecord.channelID);
-  equal(record.pushEndpoint, 'https://example.com/update/case',
-    'Wrong push endpoint in database record');
+  let record = yield db.getByPushEndpoint('https://example.com/update/case');
   equal(record.scope, 'https://example.net/case',
     'Wrong scope in database record');
 });
--- a/dom/push/test/xpcshell/test_register_error_http2.js
+++ b/dom/push/test/xpcshell/test_register_error_http2.js
@@ -44,20 +44,17 @@ add_task(function* test_pushSubscription
     serverURI: serverURL + "/pushSubscriptionNoConnection/subscribe",
     db
   });
 
   yield rejects(
     PushNotificationService.register(
       'https://example.net/page/invalid-response',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error && error.includes("Error");
-    },
-    'Wrong error for not being able to establish connecion.'
+    'Expected error for not being able to establish connecion.'
   );
 
   let record = yield db.getAllKeyIDs();
   ok(record.length === 0, "Should not store records when connection couldn't be established.");
   PushService.uninit();
 });
 
 add_task(function* test_TLS() {
@@ -85,20 +82,17 @@ add_task(function* test_pushSubscription
     serverURI: serverURL + "/pushSubscriptionMissingLocation/subscribe",
     db
   });
 
   yield rejects(
     PushNotificationService.register(
       'https://example.net/page/invalid-response',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error && error.includes("Return code 201, but the answer is bogus");
-    },
-    'Wrong error for the missing location header.'
+    'Expected error for the missing location header.'
   );
 
   let record = yield db.getAllKeyIDs();
   ok(record.length === 0, 'Should not store records when the location header is missing.');
   PushService.uninit();
 });
 
 add_task(function* test_pushSubscriptionMissingLink() {
@@ -112,20 +106,17 @@ add_task(function* test_pushSubscription
     serverURI: serverURL + "/pushSubscriptionMissingLink/subscribe",
     db
   });
 
   yield rejects(
     PushNotificationService.register(
       'https://example.net/page/invalid-response',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error && error.includes("Return code 201, but the answer is bogus");
-    },
-    'Wrong error for the missing link header.'
+    'Expected error for the missing link header.'
   );
 
   let record = yield db.getAllKeyIDs();
   ok(record.length === 0, 'Should not store records when a link header is missing.');
   PushService.uninit();
 });
 
 add_task(function* test_pushSubscriptionMissingLink1() {
@@ -139,20 +130,17 @@ add_task(function* test_pushSubscription
     serverURI: serverURL + "/pushSubscriptionMissingLink1/subscribe",
     db
   });
 
   yield rejects(
     PushNotificationService.register(
       'https://example.net/page/invalid-response',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error && error.includes("Return code 201, but the answer is bogus");
-    },
-    'Wrong error for the missing push endpoint.'
+    'Expected error for the missing push endpoint.'
   );
 
   let record = yield db.getAllKeyIDs();
   ok(record.length === 0, 'Should not store records when the push endpoint is missing.');
   PushService.uninit();
 });
 
 add_task(function* test_pushSubscriptionLocationBogus() {
@@ -166,20 +154,17 @@ add_task(function* test_pushSubscription
     serverURI: serverURL + "/pushSubscriptionLocationBogus/subscribe",
     db
   });
 
   yield rejects(
     PushNotificationService.register(
       'https://example.net/page/invalid-response',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error && error.includes("Return code 201, but URI is bogus.");
-    },
-    'Wrong error for the bogus location'
+    'Expected error for the bogus location'
   );
 
   let record = yield db.getAllKeyIDs();
   ok(record.length === 0, 'Should not store records when location header is bogus.');
   PushService.uninit();
 });
 
 add_task(function* test_pushSubscriptionNot2xxCode() {
@@ -193,20 +178,17 @@ add_task(function* test_pushSubscription
     serverURI: serverURL + "/pushSubscriptionNot201Code/subscribe",
     db
   });
 
   yield rejects(
     PushNotificationService.register(
       'https://example.net/page/invalid-response',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error && error.includes("Error");
-    },
-    'Wrong error for not 201 responce code.'
+    'Expected error for not 201 responce code.'
   );
 
   let record = yield db.getAllKeyIDs();
   ok(record.length === 0, 'Should not store records when respons code is not 201.');
 });
 
 add_task(function* test_complete() {
   prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlsProfile);
--- a/dom/push/test/xpcshell/test_register_flush.js
+++ b/dom/push/test/xpcshell/test_register_flush.js
@@ -75,30 +75,26 @@ add_task(function* test_register_flush()
       });
     }
   });
 
   let newRecord = yield PushNotificationService.register(
     'https://example.com/page/2', '');
   equal(newRecord.pushEndpoint, 'https://example.org/update/2',
     'Wrong push endpoint in record');
-  equal(newRecord.scope, 'https://example.com/page/2',
-    'Wrong scope in record');
 
   let {data: scope} = yield waitForPromise(notifyPromise, DEFAULT_TIMEOUT,
     'Timed out waiting for notification');
   equal(scope, 'https://example.com/page/1', 'Wrong notification scope');
 
   yield waitForPromise(ackPromise, DEFAULT_TIMEOUT,
      'Timed out waiting for acknowledgements');
 
   let prevRecord = yield db.getByKeyID(
     '9bcc7efb-86c7-4457-93ea-e24e6eb59b74');
   equal(prevRecord.pushEndpoint, 'https://example.org/update/1',
     'Wrong existing push endpoint');
   strictEqual(prevRecord.version, 3,
     'Should record version updates sent before register responses');
 
-  let registeredRecord = yield db.getByKeyID(newRecord.channelID);
-  equal(registeredRecord.pushEndpoint, 'https://example.org/update/2',
-    'Wrong new push endpoint');
+  let registeredRecord = yield db.getByPushEndpoint('https://example.org/update/2');
   ok(!registeredRecord.version, 'Should not record premature updates');
 });
--- a/dom/push/test/xpcshell/test_register_invalid_channel.js
+++ b/dom/push/test/xpcshell/test_register_invalid_channel.js
@@ -45,17 +45,14 @@ add_task(function* test_register_invalid
         }
       });
     }
   });
 
   yield rejects(
     PushNotificationService.register('https://example.com/invalid-channel',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error == 'Invalid channel ID';
-    },
-    'Wrong error for invalid channel ID'
+    'Expected error for invalid channel ID'
   );
 
   let record = yield db.getByKeyID(channelID);
   ok(!record, 'Should not store records for error responses');
 });
--- a/dom/push/test/xpcshell/test_register_invalid_endpoint.js
+++ b/dom/push/test/xpcshell/test_register_invalid_endpoint.js
@@ -47,17 +47,14 @@ add_task(function* test_register_invalid
       });
     }
   });
 
   yield rejects(
     PushNotificationService.register(
       'https://example.net/page/invalid-endpoint',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error && error.includes('Invalid pushEndpoint');
-    },
-    'Wrong error for invalid endpoint'
+    'Expected error for invalid endpoint'
   );
 
   let record = yield db.getByKeyID(channelID);
   ok(!record, 'Should not store records with invalid endpoints');
 });
--- a/dom/push/test/xpcshell/test_register_invalid_json.js
+++ b/dom/push/test/xpcshell/test_register_invalid_json.js
@@ -46,18 +46,15 @@ add_task(function* test_register_invalid
         }
       });
     }
   });
 
   yield rejects(
     PushNotificationService.register('https://example.net/page/invalid-json',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error == 'TimeoutError';
-    },
-    'Wrong error for invalid JSON response'
+    'Expected error for invalid JSON response'
   );
 
   yield waitForPromise(helloPromise, DEFAULT_TIMEOUT,
     'Reconnect after invalid JSON response timed out');
   equal(registers, 1, 'Wrong register count');
 });
--- a/dom/push/test/xpcshell/test_register_no_id.js
+++ b/dom/push/test/xpcshell/test_register_no_id.js
@@ -50,18 +50,15 @@ add_task(function* test_register_no_id()
         }
       });
     }
   });
 
   yield rejects(
     PushNotificationService.register('https://example.com/incomplete',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error == 'TimeoutError';
-    },
-    'Wrong error for incomplete register response'
+    'Expected error for incomplete register response'
   );
 
   yield waitForPromise(helloPromise, DEFAULT_TIMEOUT,
     'Reconnect after incomplete register response timed out');
   equal(registers, 1, 'Wrong register count');
 });
--- a/dom/push/test/xpcshell/test_register_request_queue.js
+++ b/dom/push/test/xpcshell/test_register_request_queue.js
@@ -50,19 +50,15 @@ add_task(function* test_register_request
     ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })
   );
   let secondRegister = PushNotificationService.register(
     'https://example.com/page/1',
     ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })
   );
 
   yield waitForPromise(Promise.all([
-    rejects(firstRegister, function(error) {
-      return error == 'TimeoutError';
-    }, 'Should time out the first request'),
-    rejects(secondRegister, function(error) {
-      return error == 'TimeoutError';
-    }, 'Should time out the second request')
+    rejects(firstRegister, 'Should time out the first request'),
+    rejects(secondRegister, 'Should time out the second request')
   ]), DEFAULT_TIMEOUT, 'Queued requests did not time out');
 
   yield waitForPromise(helloPromise, DEFAULT_TIMEOUT,
     'Timed out waiting for reconnect');
 });
--- a/dom/push/test/xpcshell/test_register_rollback.js
+++ b/dom/push/test/xpcshell/test_register_rollback.js
@@ -72,20 +72,17 @@ add_task(function* test_register_rollbac
       });
     }
   });
 
   // Should return a rejected promise if storage fails.
   yield rejects(
     PushNotificationService.register('https://example.com/storage-error',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error == 'universe has imploded';
-    },
-    'Wrong error for unregister database failure'
+    'Expected error for unregister database failure'
   );
 
   // Should send an out-of-band unregister request.
   yield waitForPromise(unregisterPromise, DEFAULT_TIMEOUT,
     'Unregister request timed out');
   equal(handshakes, 1, 'Wrong handshake count');
   equal(registers, 1, 'Wrong register count');
 });
--- a/dom/push/test/xpcshell/test_register_success.js
+++ b/dom/push/test/xpcshell/test_register_success.js
@@ -55,27 +55,19 @@ add_task(function* test_register_success
       });
     }
   });
 
   let newRecord = yield PushNotificationService.register(
     'https://example.org/1',
     ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })
   );
-  equal(newRecord.channelID, channelID,
-    'Wrong channel ID in registration record');
   equal(newRecord.pushEndpoint, 'https://example.com/update/1',
     'Wrong push endpoint in registration record');
-  equal(newRecord.scope, 'https://example.org/1',
-    'Wrong scope in registration record');
-  equal(newRecord.quota, Infinity,
-    'Wrong quota in registration record');
 
   let record = yield db.getByKeyID(channelID);
   equal(record.channelID, channelID,
     'Wrong channel ID in database record');
   equal(record.pushEndpoint, 'https://example.com/update/1',
     'Wrong push endpoint in database record');
-  equal(record.scope, 'https://example.org/1',
-    'Wrong scope in database record');
   equal(record.quota, Infinity,
     'Wrong quota in database record');
 });
--- a/dom/push/test/xpcshell/test_register_success_http2.js
+++ b/dom/push/test/xpcshell/test_register_success_http2.js
@@ -59,25 +59,21 @@ add_task(function* test_pushSubscription
   let newRecord = yield PushNotificationService.register(
     'https://example.org/1',
     ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })
   );
 
   var subscriptionUri = serverURL + '/pushSubscriptionSuccesss';
   var pushEndpoint = serverURL + '/pushEndpointSuccess';
   var pushReceiptEndpoint = serverURL + '/receiptPushEndpointSuccess';
-  equal(newRecord.subscriptionUri, subscriptionUri,
-    'Wrong subscription ID in registration record');
   equal(newRecord.pushEndpoint, pushEndpoint,
     'Wrong push endpoint in registration record');
 
   equal(newRecord.pushReceiptEndpoint, pushReceiptEndpoint,
     'Wrong push endpoint receipt in registration record');
-  equal(newRecord.scope, 'https://example.org/1',
-    'Wrong scope in registration record');
 
   let record = yield db.getByKeyID(subscriptionUri);
   equal(record.subscriptionUri, subscriptionUri,
     'Wrong subscription ID in database record');
   equal(record.pushEndpoint, pushEndpoint,
     'Wrong push endpoint in database record');
   equal(record.pushReceiptEndpoint, pushReceiptEndpoint,
     'Wrong push endpoint receipt in database record');
@@ -102,25 +98,21 @@ add_task(function* test_pushSubscription
   let newRecord = yield PushNotificationService.register(
     'https://example.org/no_receiptEndpoint',
     ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })
   );
 
   var subscriptionUri = serverURL + '/subscriptionMissingLink2';
   var pushEndpoint = serverURL + '/pushEndpointMissingLink2';
   var pushReceiptEndpoint = '';
-  equal(newRecord.subscriptionUri, subscriptionUri,
-    'Wrong subscription ID in registration record');
   equal(newRecord.pushEndpoint, pushEndpoint,
     'Wrong push endpoint in registration record');
 
   equal(newRecord.pushReceiptEndpoint, pushReceiptEndpoint,
     'Wrong push endpoint receipt in registration record');
-  equal(newRecord.scope, 'https://example.org/no_receiptEndpoint',
-    'Wrong scope in registration record');
 
   let record = yield db.getByKeyID(subscriptionUri);
   equal(record.subscriptionUri, subscriptionUri,
     'Wrong subscription ID in database record');
   equal(record.pushEndpoint, pushEndpoint,
     'Wrong push endpoint in database record');
   equal(record.pushReceiptEndpoint, pushReceiptEndpoint,
     'Wrong push endpoint receipt in database record');
--- a/dom/push/test/xpcshell/test_register_timeout.js
+++ b/dom/push/test/xpcshell/test_register_timeout.js
@@ -72,20 +72,17 @@ add_task(function* test_register_timeout
         }
       });
     }
   });
 
   yield rejects(
     PushNotificationService.register('https://example.net/page/timeout',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error == 'TimeoutError';
-    },
-    'Wrong error for request timeout'
+    'Expected error for request timeout'
   );
 
   let record = yield db.getByKeyID(channelID);
   ok(!record, 'Should not store records for timed-out responses');
 
   yield waitForPromise(
     timeoutPromise,
     DEFAULT_TIMEOUT,
--- a/dom/push/test/xpcshell/test_register_wrong_id.js
+++ b/dom/push/test/xpcshell/test_register_wrong_id.js
@@ -56,18 +56,15 @@ add_task(function* test_register_wrong_i
         }
       });
     }
   });
 
   yield rejects(
     PushNotificationService.register('https://example.com/mismatched',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error == 'TimeoutError';
-    },
-    'Wrong error for mismatched register reply'
+    'Expected error for mismatched register reply'
   );
 
   yield waitForPromise(helloPromise, DEFAULT_TIMEOUT,
     'Reconnect after mismatched register reply timed out');
   equal(registers, 1, 'Wrong register count');
 });
--- a/dom/push/test/xpcshell/test_register_wrong_type.js
+++ b/dom/push/test/xpcshell/test_register_wrong_type.js
@@ -47,23 +47,18 @@ add_task(function* test_register_wrong_t
             uaid: userAgentID,
             pushEndpoint: 'https://example.org/update/wrong-type'
           }));
         }
       });
     }
   });
 
-  let promise =
-
   yield rejects(
     PushNotificationService.register('https://example.com/mistyped',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error == 'TimeoutError';
-    },
-    'Wrong error for non-string channel ID'
+    'Expected error for non-string channel ID'
   );
 
   yield waitForPromise(helloPromise, DEFAULT_TIMEOUT,
     'Reconnect after sending non-string channel ID timed out');
   equal(registers, 1, 'Wrong register count');
 });
--- a/dom/push/test/xpcshell/test_registration_missing_scope.js
+++ b/dom/push/test/xpcshell/test_registration_missing_scope.js
@@ -16,14 +16,11 @@ add_task(function* test_registration_mis
     serverURI: "wss://push.example.org/",
     networkInfo: new MockDesktopNetworkInfo(),
     makeWebSocket(uri) {
       return new MockWebSocket(uri);
     }
   });
   yield rejects(
     PushNotificationService.registration('', ''),
-    function(error) {
-      return error.error == 'NotFoundError';
-    },
     'Record missing page and manifest URLs'
   );
 });
--- a/dom/push/test/xpcshell/test_unregister_empty_scope.js
+++ b/dom/push/test/xpcshell/test_unregister_empty_scope.js
@@ -26,14 +26,11 @@ add_task(function* test_unregister_empty
         }
       });
     }
   });
 
   yield rejects(
     PushNotificationService.unregister('',
       ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })),
-    function(error) {
-      return error.error == 'NotFoundError';
-    },
-    'Wrong error for empty endpoint'
+    'Expected error for empty endpoint'
   );
 });
--- a/dom/push/test/xpcshell/test_updateRecordNoEncryptionKeys_ws.js
+++ b/dom/push/test/xpcshell/test_updateRecordNoEncryptionKeys_ws.js
@@ -72,18 +72,17 @@ add_task(function* test_with_data_enable
       });
     },
   });
 
   let newRecord = yield PushNotificationService.register(
     'https://example.com/page/3',
     ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false })
   );
-  ok(newRecord.p256dhPublicKey, 'Should generate public keys for new records');
-  ok(newRecord.p256dhPrivateKey, 'Should generate private keys for new records');
+  ok(newRecord.p256dhKey, 'Should generate public keys for new records');
 
   let record = yield db.getByKeyID('eb18f12a-cc42-4f14-accb-3bfc1227f1aa');
   ok(record.p256dhPublicKey, 'Should add public key to partial record');
   ok(record.p256dhPrivateKey, 'Should add private key to partial record');
 
   record = yield db.getByKeyID('0d8886b9-8da1-4778-8f5d-1cf93a877ed6');
   deepEqual(record.p256dhPublicKey, publicKey,
     'Should leave existing public key');