Bug 1433823 - Fix incorrect async handling during TPS login flow. r?markh draft
authorThom Chiovoloni <tchiovoloni@mozilla.com>
Tue, 30 Jan 2018 16:24:31 -0500
changeset 757571 434cf7b95b6b2443cdccbca1ba78414ae2d4d9fd
parent 757244 2c000486eac466da6623e4d7f7f1fd4e318f60e8
push id99781
push userbmo:tchiovoloni@mozilla.com
push dateTue, 20 Feb 2018 20:56:03 +0000
reviewersmarkh
bugs1433823
milestone60.0a1
Bug 1433823 - Fix incorrect async handling during TPS login flow. r?markh MozReview-Commit-ID: 4mcEcBvaKd
services/sync/tps/extensions/tps/resource/auth/fxaccounts.jsm
services/sync/tps/extensions/tps/resource/tps.jsm
--- a/services/sync/tps/extensions/tps/resource/auth/fxaccounts.jsm
+++ b/services/sync/tps/extensions/tps/resource/auth/fxaccounts.jsm
@@ -27,36 +27,44 @@ var Authentication = {
 
   /**
    * Check if an user has been logged in
    */
   async isLoggedIn() {
     return !!(await this.getSignedInUser());
   },
 
+  async isReady() {
+    let user = await this.getSignedInUser();
+    return user && user.verified;
+  },
+
   _getRestmailUsername(user) {
     const restmailSuffix = "@restmail.net";
     if (user.toLowerCase().endsWith(restmailSuffix)) {
       return user.slice(0, -restmailSuffix.length);
     }
     return null;
   },
 
   async shortWaitForVerification(ms) {
-    let userData = this.getSignedInUser();
+    let userData = await this.getSignedInUser();
+    let timeoutID;
+    let timeoutPromise = new Promise(resolve => {
+      timeoutID = setTimeout(() => {
+        Logger.logInfo(`Warning: no verification after ${ms}ms.`);
+        resolve();
+      }, ms);
+    });
     await Promise.race([
-      fxAccounts.whenVerified(userData),
-      new Promise(resolve => {
-        setTimeout(() => {
-          Logger.logInfo(`Warning: no verification after ${ms}ms.`);
-          resolve();
-        }, ms);
-      })
+      fxAccounts.whenVerified(userData)
+                .finally(() => clearTimeout(timeoutID)),
+      timeoutPromise,
     ]);
-    userData = this.getSignedInUser();
+    userData = await this.getSignedInUser();
     return userData && userData.verified;
   },
 
   async _openVerificationPage(uri) {
     let mainWindow = Services.wm.getMostRecentWindow("navigator:browser");
     let newtab = mainWindow.getBrowser().addTab(uri);
     let win = mainWindow.getBrowser().getBrowserForTab(newtab);
     await new Promise(resolve => {
@@ -74,19 +82,16 @@ var Authentication = {
       return false;
     }
     Logger.logInfo("Fetching mail (from restmail) for user " + username);
     let restmailURI = `https://www.restmail.net/mail/${encodeURIComponent(username)}`;
     let triedAlready = new Set();
     const tries = 10;
     const normalWait = 2000;
     for (let i = 0; i < tries; ++i) {
-      if (await this.shortWaitForVerification(normalWait)) {
-        return true;
-      }
       let resp = await fetch(restmailURI);
       let messages = await resp.json();
       // Sort so that the most recent emails are first.
       messages.sort((a, b) => new Date(b.receivedAt) - new Date(a.receivedAt));
       for (let m of messages) {
         // We look for a link that has a x-link that we haven't yet tried.
         if (!m.headers["x-link"] || triedAlready.has(m.headers["x-link"])) {
           continue;
@@ -101,16 +106,19 @@ var Authentication = {
         } catch (e) {
           Logger.logInfo("Warning: Failed to follow confirmation link: " + Log.exceptionStr(e));
         }
       }
       if (i === 0) {
         // first time through after failing we'll do this.
         await fxAccounts.resendVerificationEmail();
       }
+      if (await this.shortWaitForVerification(normalWait)) {
+        return true;
+      }
     }
     // One last try.
     return this.shortWaitForVerification(normalWait);
   },
 
   async deleteEmail(user) {
     let username = this._getRestmailUsername(user);
     if (!username) {
--- a/services/sync/tps/extensions/tps/resource/tps.jsm
+++ b/services/sync/tps/extensions/tps/resource/tps.jsm
@@ -1174,17 +1174,17 @@ var TPS = {
       await this.waitForEvent("weave:service:tracking-started");
     }
   },
 
   /**
    * Login on the server
    */
   async Login(force) {
-    if ((await Authentication.isLoggedIn()) && !force) {
+    if ((await Authentication.isReady()) && !force) {
       return;
     }
 
     // This might come during Authentication.signIn
     this._triggeredSync = true;
     Logger.logInfo("Setting client credentials and login.");
     await Authentication.signIn(this.config.fx_account);
     await this.waitForSetupComplete();
@@ -1212,18 +1212,20 @@ var TPS = {
     // will be overwritten by Sync itself (see bug 992198), so ensure that we
     // also handle it via the "weave:service:setup-complete" notification.
     if (wipeAction) {
       this._syncWipeAction = wipeAction;
       Weave.Svc.Prefs.set("firstSync", wipeAction);
     } else {
       Weave.Svc.Prefs.reset("firstSync");
     }
-
-    this.Login(false);
+    if (!await Weave.Service.login()) {
+      // We need to complete verification.
+      await this.Login(false);
+    }
     ++this._syncCount;
 
     this._triggeredSync = true;
     this.StartAsyncOperation();
     await Weave.Service.sync();
     Logger.logInfo("Sync is complete");
   },