Bug 1008901 - Fire 'onlogin' when the account is verified. r=jedp
authorSam Penrose <spenrose@mozilla.com>
Fri, 06 Jun 2014 10:42:22 -0700
changeset 206768 5c5e7c0f31c5718ddfc35bfc95ee71f54649522b
parent 206767 96e6a5f9fa3f2affa3cf6b3e412ec2d8d140a8ef
child 206769 344e71c36f9f7dab0053bc40a9bcf3056e83b004
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjedp
bugs1008901
milestone32.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 1008901 - Fire 'onlogin' when the account is verified. r=jedp
services/fxaccounts/FxAccounts.jsm
services/fxaccounts/FxAccountsCommon.js
services/fxaccounts/FxAccountsManager.jsm
toolkit/identity/FirefoxAccounts.jsm
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -753,19 +753,19 @@ FxAccountsInternal.prototype = {
       log.debug("whenVerified promise starts polling for verified email");
       this.pollEmailStatus(currentState, data.sessionToken, "start");
     }
     return currentState.whenVerifiedDeferred.promise.then(
       result => currentState.resolve(result)
     );
   },
 
-  notifyObservers: function(topic) {
+  notifyObservers: function(topic, data) {
     log.debug("Notifying observers of " + topic);
-    Services.obs.notifyObservers(null, topic, null);
+    Services.obs.notifyObservers(null, topic, data);
   },
 
   // XXX - pollEmailStatus should maybe be on the AccountState object?
   pollEmailStatus: function pollEmailStatus(currentState, sessionToken, why) {
     log.debug("entering pollEmailStatus: " + why);
     if (why == "start") {
       // If we were already polling, stop and start again.  This could happen
       // if the user requested the verification email to be resent while we
@@ -795,16 +795,18 @@ FxAccountsInternal.prototype = {
               return currentState.setUserAccountData(data);
             })
             .then((data) => {
               // Now that the user is verified, we can proceed to fetch keys
               if (currentState.whenVerifiedDeferred) {
                 currentState.whenVerifiedDeferred.resolve(data);
                 delete currentState.whenVerifiedDeferred;
               }
+              // Tell FxAccountsManager to clear its cache
+              this.notifyObservers(ON_FXA_UPDATE_NOTIFICATION, ONVERIFIED_NOTIFICATION);
             });
         } else {
           log.debug("polling with step = " + this.POLL_STEP);
           this.pollTimeRemaining -= this.POLL_STEP;
           log.debug("time remaining: " + this.pollTimeRemaining);
           if (this.pollTimeRemaining > 0) {
             this.currentTimer = setTimeout(() => {
               this.pollEmailStatus(currentState, sessionToken, "timer")}, this.POLL_STEP);
--- a/services/fxaccounts/FxAccountsCommon.js
+++ b/services/fxaccounts/FxAccountsCommon.js
@@ -78,16 +78,18 @@ this.KEY_LIFETIME       = 1000 * 3600 * 
 // Polling timings.
 this.POLL_SESSION       = 1000 * 60 * 5;    // 5 minutes
 this.POLL_STEP          = 1000 * 3;         // 3 seconds
 
 // Observer notifications.
 this.ONLOGIN_NOTIFICATION = "fxaccounts:onlogin";
 this.ONVERIFIED_NOTIFICATION = "fxaccounts:onverified";
 this.ONLOGOUT_NOTIFICATION = "fxaccounts:onlogout";
+// Internal to services/fxaccounts only
+this.ON_FXA_UPDATE_NOTIFICATION = "fxaccounts:update";
 
 // UI Requests.
 this.UI_REQUEST_SIGN_IN_FLOW = "signInFlow";
 this.UI_REQUEST_REFRESH_AUTH = "refreshAuthentication";
 
 // Server errno.
 // From https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#response-format
 this.ERRNO_ACCOUNT_ALREADY_EXISTS         = 101;
--- a/services/fxaccounts/FxAccountsManager.jsm
+++ b/services/fxaccounts/FxAccountsManager.jsm
@@ -20,25 +20,27 @@ Cu.import("resource://gre/modules/Servic
 Cu.import("resource://gre/modules/FxAccounts.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/FxAccountsCommon.js");
 
 this.FxAccountsManager = {
 
   init: function() {
     Services.obs.addObserver(this, ONLOGOUT_NOTIFICATION, false);
+    Services.obs.addObserver(this, ON_FXA_UPDATE_NOTIFICATION, false);
   },
 
   observe: function(aSubject, aTopic, aData) {
-    if (aTopic !== ONLOGOUT_NOTIFICATION) {
-      return;
+    // Both topics indicate our cache is invalid
+    this._activeSession = null;
+
+    if (aData == ONVERIFIED_NOTIFICATION) {
+      log.debug("FxAccountsManager: cache cleared, broadcasting: " + aData);
+      Services.obs.notifyObservers(null, aData, null);
     }
-
-    // Remove the cached session if we get a logout notification.
-    this._activeSession = null;
   },
 
   // We don't really need to save fxAccounts instance but this way we allow
   // to mock FxAccounts from tests.
   _fxAccounts: fxAccounts,
 
   // We keep the session details here so consumers don't need to deal with
   // session tokens and are only required to handle the email.
--- a/toolkit/identity/FirefoxAccounts.jsm
+++ b/toolkit/identity/FirefoxAccounts.jsm
@@ -34,40 +34,57 @@ try {
 let log = Log.repository.getLogger("Identity.FxAccounts");
 log.level = LOG_LEVEL;
 log.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
 
 #ifdef MOZ_B2G
 XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsManager",
                                   "resource://gre/modules/FxAccountsManager.jsm",
                                   "FxAccountsManager");
+Cu.import("resource://gre/modules/FxAccountsCommon.js");
 #else
 log.warn("The FxAccountsManager is only functional in B2G at this time.");
 var FxAccountsManager = null;
+var ONVERIFIED_NOTIFICATION = null;
 #endif
 
 function FxAccountsService() {
   Services.obs.addObserver(this, "quit-application-granted", false);
+  if (ONVERIFIED_NOTIFICATION) {
+    Services.obs.addObserver(this, ONVERIFIED_NOTIFICATION, false);
+  }
 
   // Maintain interface parity with Identity.jsm and MinimalIdentity.jsm
   this.RP = this;
 
   this._rpFlows = new Map();
 
   // Enable us to mock FxAccountsManager service in testing
   this.fxAccountsManager = FxAccountsManager;
 }
 
 FxAccountsService.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
 
   observe: function observe(aSubject, aTopic, aData) {
     switch (aTopic) {
+      case null:
+        // Paranoia against matching null ONVERIFIED_NOTIFICATION
+        break;
+      case ONVERIFIED_NOTIFICATION:
+        log.debug("Received " + ONVERIFIED_NOTIFICATION + "; firing request()s");
+        for (let [rpId,] of this._rpFlows) {
+          this.request(rpId);
+        }
+        break;
       case "quit-application-granted":
         Services.obs.removeObserver(this, "quit-application-granted");
+        if (ONVERIFIED_NOTIFICATION) {
+          Services.obs.removeObserver(this, ONVERIFIED_NOTIFICATION);
+        }
         break;
     }
   },
 
   /**
    * Register a listener for a given windowID as a result of a call to
    * navigator.id.watch().
    *