Bug 781946 - Clean up notifications usage; r=rnewman
authorGregory Szorc <gps@mozilla.com>
Mon, 13 Aug 2012 16:51:58 -0700
changeset 111033 7a7aff2f35d33cdb857902753bdee8c45b5c1c67
parent 104149 75cdb3f932c629a06f811404fb1ff1322610a6be
child 111034 0dfcb4b9a89b6e7ae60744a70d62fb0ebe91bbf5
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersrnewman
bugs781946
milestone17.0a1
Bug 781946 - Clean up notifications usage; r=rnewman
browser/base/content/sync/setup.js
services/sync/modules/service.js
--- a/browser/base/content/sync/setup.js
+++ b/browser/base/content/sync/setup.js
@@ -55,20 +55,20 @@ var gSyncSetup = {
   get _usingMainServers() {
     if (this._settingUpNew)
       return document.getElementById("server").selectedIndex == 0;
     return document.getElementById("existingServer").selectedIndex == 0;
   },
 
   init: function () {
     let obs = [
-      ["weave:service:changepph:finish", "onResetPassphrase"],
-      ["weave:service:login:start",  "onLoginStart"],
-      ["weave:service:login:error",  "onLoginEnd"],
-      ["weave:service:login:finish", "onLoginEnd"]];
+      ["weave:service:change-passphrase", "onResetPassphrase"],
+      ["weave:service:login:start",       "onLoginStart"],
+      ["weave:service:login:error",       "onLoginEnd"],
+      ["weave:service:login:finish",      "onLoginEnd"]];
 
     // Add the observers now and remove them on unload
     let self = this;
     let addRem = function(add) {
       obs.forEach(function([topic, func]) {
         //XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
         //        of `this`. Fix in a followup. (bug 583347)
         if (add)
--- a/services/sync/modules/service.js
+++ b/services/sync/modules/service.js
@@ -17,16 +17,17 @@ const CLUSTER_BACKOFF = 5 * 60 * 1000; /
 const PBKDF2_KEY_BYTES = 16;
 
 const CRYPTO_COLLECTION = "crypto";
 const KEYS_WBO = "keys";
 
 const LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/record.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/engines/clients.js");
 Cu.import("resource://services-common/preferences.js");
 Cu.import("resource://services-sync/identity.js");
 Cu.import("resource://services-common/log4moz.js");
 Cu.import("resource://services-sync/resource.js");
@@ -625,104 +626,103 @@ WeaveSvc.prototype = {
       // This means no keys are present, or there's a network error.
       this._log.debug("Failed to fetch and verify keys: "
                       + Utils.exceptionStr(ex));
       ErrorHandler.checkServerError(ex);
       return false;
     }
   },
 
-  verifyLogin: function verifyLogin()
-    this._notify("verify-login", "", function onNotify() {
-      if (!this._identity.username) {
-        this._log.warn("No username in verifyLogin.");
-        Status.login = LOGIN_FAILED_NO_USERNAME;
-        return false;
-      }
+  verifyLogin: function verifyLogin() {
+    if (!this._identity.username) {
+      this._log.warn("No username in verifyLogin.");
+      Status.login = LOGIN_FAILED_NO_USERNAME;
+      return false;
+    }
 
-      // Unlock master password, or return.
-      // Attaching auth credentials to a request requires access to
-      // passwords, which means that Resource.get can throw MP-related
-      // exceptions!
-      // Try to fetch the passphrase first, while we still have control.
-      try {
-        this._identity.syncKey;
-      } catch (ex) {
-        this._log.debug("Fetching passphrase threw " + ex +
-                        "; assuming master password locked.");
-        Status.login = MASTER_PASSWORD_LOCKED;
-        return false;
+    // Unlock master password, or return.
+    // Attaching auth credentials to a request requires access to
+    // passwords, which means that Resource.get can throw MP-related
+    // exceptions!
+    // Try to fetch the passphrase first, while we still have control.
+    try {
+      this._identity.syncKey;
+    } catch (ex) {
+      this._log.debug("Fetching passphrase threw " + ex +
+                      "; assuming master password locked.");
+      Status.login = MASTER_PASSWORD_LOCKED;
+      return false;
+    }
+
+    try {
+      // Make sure we have a cluster to verify against.
+      // This is a little weird, if we don't get a node we pretend
+      // to succeed, since that probably means we just don't have storage.
+      if (this.clusterURL == "" && !this._setCluster()) {
+        Status.sync = NO_SYNC_NODE_FOUND;
+        Svc.Obs.notify("weave:service:sync:delayed");
+        return true;
       }
 
-      try {
-        // Make sure we have a cluster to verify against.
-        // This is a little weird, if we don't get a node we pretend
-        // to succeed, since that probably means we just don't have storage.
-        if (this.clusterURL == "" && !this._setCluster()) {
-          Status.sync = NO_SYNC_NODE_FOUND;
-          Svc.Obs.notify("weave:service:sync:delayed");
-          return true;
-        }
+      // Fetch collection info on every startup.
+      let test = new Resource(this.infoURL).get();
 
-        // Fetch collection info on every startup.
-        let test = new Resource(this.infoURL).get();
+      switch (test.status) {
+        case 200:
+          // The user is authenticated.
 
-        switch (test.status) {
-          case 200:
-            // The user is authenticated.
+          // We have no way of verifying the passphrase right now,
+          // so wait until remoteSetup to do so.
+          // Just make the most trivial checks.
+          if (!this._identity.syncKey) {
+            this._log.warn("No passphrase in verifyLogin.");
+            Status.login = LOGIN_FAILED_NO_PASSPHRASE;
+            return false;
+          }
 
-            // We have no way of verifying the passphrase right now,
-            // so wait until remoteSetup to do so.
-            // Just make the most trivial checks.
-            if (!this._identity.syncKey) {
-              this._log.warn("No passphrase in verifyLogin.");
-              Status.login = LOGIN_FAILED_NO_PASSPHRASE;
-              return false;
-            }
+          // Go ahead and do remote setup, so that we can determine
+          // conclusively that our passphrase is correct.
+          if (this._remoteSetup()) {
+            // Username/password verified.
+            Status.login = LOGIN_SUCCEEDED;
+            return true;
+          }
+
+          this._log.warn("Remote setup failed.");
+          // Remote setup must have failed.
+          return false;
 
-            // Go ahead and do remote setup, so that we can determine
-            // conclusively that our passphrase is correct.
-            if (this._remoteSetup()) {
-              // Username/password verified.
-              Status.login = LOGIN_SUCCEEDED;
-              return true;
-            }
+        case 401:
+          this._log.warn("401: login failed.");
+          // Fall through to the 404 case.
 
-            this._log.warn("Remote setup failed.");
-            // Remote setup must have failed.
-            return false;
+        case 404:
+          // Check that we're verifying with the correct cluster
+          if (this._setCluster()) {
+            return this.verifyLogin();
+          }
 
-          case 401:
-            this._log.warn("401: login failed.");
-            // Fall through to the 404 case.
+          // We must have the right cluster, but the server doesn't expect us
+          Status.login = LOGIN_FAILED_LOGIN_REJECTED;
+          return false;
 
-          case 404:
-            // Check that we're verifying with the correct cluster
-            if (this._setCluster())
-              return this.verifyLogin();
-
-            // We must have the right cluster, but the server doesn't expect us
-            Status.login = LOGIN_FAILED_LOGIN_REJECTED;
-            return false;
-
-          default:
-            // Server didn't respond with something that we expected
-            Status.login = LOGIN_FAILED_SERVER_ERROR;
-            ErrorHandler.checkServerError(test);
-            return false;
-        }
+        default:
+          // Server didn't respond with something that we expected
+          Status.login = LOGIN_FAILED_SERVER_ERROR;
+          ErrorHandler.checkServerError(test);
+          return false;
       }
-      catch (ex) {
-        // Must have failed on some network issue
-        this._log.debug("verifyLogin failed: " + Utils.exceptionStr(ex));
-        Status.login = LOGIN_FAILED_NETWORK_ERROR;
-        ErrorHandler.checkServerError(ex);
-        return false;
-      }
-    })(),
+    } catch (ex) {
+      // Must have failed on some network issue
+      this._log.debug("verifyLogin failed: " + Utils.exceptionStr(ex));
+      Status.login = LOGIN_FAILED_NETWORK_ERROR;
+      ErrorHandler.checkServerError(ex);
+      return false;
+    }
+  },
 
   generateNewSymmetricKeys: function generateNewSymmetricKeys() {
     this._log.info("Generating new keys WBO...");
     let wbo = CollectionKeys.generateNewKeysWBO();
     this._log.info("Encrypting new key bundle.");
     wbo.encrypt(this._identity.syncKeyBundle);
 
     this._log.info("Uploading...");
@@ -772,57 +772,58 @@ WeaveSvc.prototype = {
     let keysChanged = this.handleFetchedKeys(this._identity.syncKeyBundle,
                                              cryptoKeys, true);
     if (keysChanged) {
       this._log.info("Downloaded keys differed, as expected.");
     }
   },
 
   changePassword: function changePassword(newpass) {
-    return this._notify("changepwd", "", function onNotify() {
-      let url = this.userAPI + this._identity.username + "/password";
-      try {
-        let resp = new Resource(url).post(Utils.encodeUTF8(newpass));
-        if (resp.status != 200) {
-          this._log.debug("Password change failed: " + resp);
-          return false;
-        }
-      }
-      catch(ex) {
-        // Must have failed on some network issue
-        this._log.debug("changePassword failed: " + Utils.exceptionStr(ex));
+    let url = this.userAPI + this._identity.username + "/password";
+    try {
+      let resp = new Resource(url).post(Utils.encodeUTF8(newpass));
+      if (resp.status != 200) {
+        this._log.debug("Password change failed: " + resp);
         return false;
       }
+    }
+    catch(ex) {
+      // Must have failed on some network issue
+      this._log.debug("changePassword failed: " + Utils.exceptionStr(ex));
+      return false;
+    }
 
-      // Save the new password for requests and login manager.
-      this._identity.basicPassword = newpass;
-      this.persistLogin();
-      return true;
-    })();
+    // Save the new password for requests and login manager.
+    this._identity.basicPassword = newpass;
+    this.persistLogin();
+    return true;
   },
 
   changePassphrase: function changePassphrase(newphrase) {
-    return this._catch(this._notify("changepph", "", function onNotify() {
+    return this._catch(function doChangePasphrase() {
       /* Wipe. */
       this.wipeServer();
 
       this.logout();
 
       /* Set this so UI is updated on next run. */
       this._identity.syncKey = newphrase;
       this.persistLogin();
 
       /* We need to re-encrypt everything, so reset. */
       this.resetClient();
       CollectionKeys.clear();
 
       /* Login and sync. This also generates new keys. */
       this.sync();
+
+      Svc.Obs.notify("weave:service:change-passphrase", true);
+
       return true;
-    }))();
+    })();
   },
 
   startOver: function startOver() {
     this._log.trace("Invoking Service.startOver.");
     Svc.Obs.notify("weave:engine:stop-tracking");
     Status.resetSync();
 
     // We want let UI consumers of the following notification know as soon as
@@ -1497,85 +1498,90 @@ WeaveSvc.prototype = {
    * Wipe user data from the server.
    *
    * @param collections [optional]
    *        Array of collections to wipe. If not given, all collections are
    *        wiped by issuing a DELETE request for `storageURL`.
    *
    * @return the server's timestamp of the (last) DELETE.
    */
-  wipeServer: function wipeServer(collections)
-    this._notify("wipe-server", "", function onNotify() {
-      let response;
-      if (!collections) {
-        // Strip the trailing slash.
-        let res = new Resource(this.storageURL.slice(0, -1));
-        res.setHeader("X-Confirm-Delete", "1");
-        try {
-          response = res.delete();
-        } catch (ex) {
-          this._log.debug("Failed to wipe server: " + Utils.exceptionStr(ex));
-          throw ex;
-        }
-        if (response.status != 200 && response.status != 404) {
-          this._log.debug("Aborting wipeServer. Server responded with " +
-                          response.status + " response for " + this.storageURL);
-          throw response;
-        }
-        return response.headers["x-weave-timestamp"];
+  wipeServer: function wipeServer(collections) {
+    let response;
+    if (!collections) {
+      // Strip the trailing slash.
+      let res = new Resource(this.storageURL.slice(0, -1));
+      res.setHeader("X-Confirm-Delete", "1");
+      try {
+        response = res.delete();
+      } catch (ex) {
+        this._log.debug("Failed to wipe server: " + CommonUtils.exceptionStr(ex));
+        throw ex;
+      }
+      if (response.status != 200 && response.status != 404) {
+        this._log.debug("Aborting wipeServer. Server responded with " +
+                        response.status + " response for " + this.storageURL);
+        throw response;
       }
-      let timestamp;
-      for each (let name in collections) {
-        let url = this.storageURL + name;
-        try {
-          response = new Resource(url).delete();
-        } catch (ex) {
-          this._log.debug("Failed to wipe '" + name + "' collection: " +
-                          Utils.exceptionStr(ex));
-          throw ex;
-        }
-        if (response.status != 200 && response.status != 404) {
-          this._log.debug("Aborting wipeServer. Server responded with " +
-                          response.status + " response for " + url);
-          throw response;
-        }
-        if ("x-weave-timestamp" in response.headers) {
-          timestamp = response.headers["x-weave-timestamp"];
-        }
+      return response.headers["x-weave-timestamp"];
+    }
+
+    let timestamp;
+    for (let name of collections) {
+      let url = this.storageURL + name;
+      try {
+        response = new Resource(url).delete();
+      } catch (ex) {
+        this._log.debug("Failed to wipe '" + name + "' collection: " +
+                        Utils.exceptionStr(ex));
+        throw ex;
       }
-      return timestamp;
-    })(),
+
+      if (response.status != 200 && response.status != 404) {
+        this._log.debug("Aborting wipeServer. Server responded with " +
+                        response.status + " response for " + url);
+        throw response;
+      }
+
+      if ("x-weave-timestamp" in response.headers) {
+        timestamp = response.headers["x-weave-timestamp"];
+      }
+    }
+
+    return timestamp;
+  },
 
   /**
    * Wipe all local user data.
    *
    * @param engines [optional]
    *        Array of engine names to wipe. If not given, all engines are used.
    */
-  wipeClient: function wipeClient(engines)
-    this._notify("wipe-client", "", function onNotify() {
-      // If we don't have any engines, reset the service and wipe all engines
-      if (!engines) {
-        // Clear out any service data
-        this.resetService();
+  wipeClient: function wipeClient(engines) {
+    // If we don't have any engines, reset the service and wipe all engines
+    if (!engines) {
+      // Clear out any service data
+      this.resetService();
 
-        engines = [Clients].concat(Engines.getAll());
+      engines = [Clients].concat(Engines.getAll());
+    }
+    // Convert the array of names into engines
+    else {
+      engines = Engines.get(engines);
+    }
+
+    // Fully wipe each engine if it's able to decrypt data
+    for each (let engine in engines) {
+      if (engine.canDecrypt()) {
+        engine.wipeClient();
       }
-      // Convert the array of names into engines
-      else
-        engines = Engines.get(engines);
+    }
 
-      // Fully wipe each engine if it's able to decrypt data
-      for each (let engine in engines)
-        if (engine.canDecrypt())
-          engine.wipeClient();
-
-      // Save the password/passphrase just in-case they aren't restored by sync
-      this.persistLogin();
-    })(),
+    // Save the password/passphrase just in-case they aren't restored by sync
+    this.persistLogin();
+  },
 
   /**
    * Wipe all remote user data by wiping the server then telling each remote
    * client to wipe itself.
    *
    * @param engines [optional]
    *        Array of engine names to wipe. If not given, all engines are used.
    */
@@ -1602,48 +1608,52 @@ WeaveSvc.prototype = {
       ErrorHandler.checkServerError(ex);
       throw ex;
     }
   },
 
   /**
    * Reset local service information like logs, sync times, caches.
    */
-  resetService: function resetService()
-    this._catch(this._notify("reset-service", "", function onNotify() {
+  resetService: function resetService() {
+    this._catch(function reset() {
       this._log.info("Service reset.");
 
       // Pretend we've never synced to the server and drop cached data
       this.syncID = "";
       Records.clearCache();
-    }))(),
+    })();
+  },
 
   /**
    * Reset the client by getting rid of any local server data and client data.
    *
    * @param engines [optional]
    *        Array of engine names to reset. If not given, all engines are used.
    */
-  resetClient: function resetClient(engines)
-    this._catch(this._notify("reset-client", "", function onNotify() {
+  resetClient: function resetClient(engines) {
+    this._catch(function doResetClient() {
       // If we don't have any engines, reset everything including the service
       if (!engines) {
         // Clear out any service data
         this.resetService();
 
         engines = [Clients].concat(Engines.getAll());
       }
       // Convert the array of names into engines
-      else
+      else {
         engines = Engines.get(engines);
+      }
 
       // Have each engine drop any temporary meta data
-      for each (let engine in engines)
+      for each (let engine in engines) {
         engine.resetClient();
-    }))(),
+      }
+    })();
+  },
 
   /**
    * Fetch storage info from the server.
    *
    * @param type
    *        String specifying what info to fetch from the server. Must be one
    *        of the INFO_* values. See Sync Storage Server API spec for details.
    * @param callback