Bug 1365375 - Disconnect Sync on account destroyed. r=markh
☠☠ backed out by 30ef16860449 ☠ ☠
authorEdouard Oger <eoger@fastmail.com>
Wed, 17 May 2017 16:25:00 -0400
changeset 360108 d11aec13b38e0837c07d0906c1ab506e162b2a2f
parent 360107 600b709c2634cfd9d57f0eefd56af8d1200791c9
child 360109 aec720895e5e79d126283c118cb4d26744c3750a
push id43239
push usereoger@mozilla.com
push dateTue, 23 May 2017 17:21:28 +0000
treeherderautoland@d11aec13b38e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmarkh
bugs1365375
milestone55.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 1365375 - Disconnect Sync on account destroyed. r=markh This connects to the fxa-auth-server PR: https://github.com/mozilla/fxa-auth-server/pull/1900 MozReview-Commit-ID: IIYnytYGIpw
services/fxaccounts/FxAccounts.jsm
services/fxaccounts/FxAccountsCommon.js
services/fxaccounts/FxAccountsPush.js
services/fxaccounts/tests/xpcshell/test_push_service.js
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -47,16 +47,17 @@ var publicProperties = [
   "getDeviceId",
   "getDeviceList",
   "getKeys",
   "getOAuthToken",
   "getProfileCache",
   "getSignedInUser",
   "getSignedInUserProfile",
   "handleDeviceDisconnection",
+  "handleAccountDestroyed",
   "invalidateCertificate",
   "loadAndPoll",
   "localtimeOffsetMsec",
   "notifyDevices",
   "now",
   "promiseAccountsChangeProfileURI",
   "promiseAccountsForceSigninURI",
   "promiseAccountsManageURI",
@@ -1563,26 +1564,45 @@ FxAccountsInternal.prototype = {
       .then(localDeviceId => {
         if (!localDeviceId) {
           // We've already been logged out (and that logout is probably what
           // caused us to get here via push!), so don't make noise here.
           log.info(`Push request to disconnect, but we've already disconnected`);
           return null;
         }
         if (deviceId == localDeviceId) {
-          this.notifyObservers(ON_DEVICE_DISCONNECTED_NOTIFICATION, deviceId);
+          this.notifyObservers(ON_DEVICE_DISCONNECTED_NOTIFICATION);
           return this.signOut(true);
         }
         log.error(
           `The device ID to disconnect doesn't match with the local device ID. ` +
           `Local: ${localDeviceId}, ID to disconnect: ${deviceId}`);
         return null;
     });
   },
 
+  handleAccountDestroyed(uid) {
+    return this.currentAccountState.getUserAccountData()
+      .then(data => data ? data.uid : null)
+      .then(localUid => {
+        if (!localUid) {
+          log.info(`Account destroyed push notification received, but we're already logged-out`);
+          return null;
+        }
+        if (uid == localUid) {
+          this.notifyObservers(ON_DEVICE_DISCONNECTED_NOTIFICATION);
+          return this.signOut(true);
+        }
+        log.info(
+          `The destroyed account uid doesn't match with the local uid. ` +
+          `Local: ${localUid}, account uid destroyed: ${uid}`);
+        return null;
+    });
+  },
+
   /**
    * Delete all the cached persisted credentials we store for FxA.
    *
    * @return Promise resolves when the user data has been persisted
   */
   resetCredentials() {
     // Delete all fields except those required for the user to
     // reauthenticate.
--- a/services/fxaccounts/FxAccountsCommon.js
+++ b/services/fxaccounts/FxAccountsCommon.js
@@ -89,16 +89,17 @@ exports.ONVERIFIED_NOTIFICATION = "fxacc
 exports.ONLOGOUT_NOTIFICATION = "fxaccounts:onlogout";
 // Internal to services/fxaccounts only
 exports.ON_FXA_UPDATE_NOTIFICATION = "fxaccounts:update";
 exports.ON_DEVICE_CONNECTED_NOTIFICATION = "fxaccounts:device_connected";
 exports.ON_DEVICE_DISCONNECTED_NOTIFICATION = "fxaccounts:device_disconnected";
 exports.ON_PROFILE_UPDATED_NOTIFICATION = "fxaccounts:profile_updated"; // Push
 exports.ON_PASSWORD_CHANGED_NOTIFICATION = "fxaccounts:password_changed";
 exports.ON_PASSWORD_RESET_NOTIFICATION = "fxaccounts:password_reset";
+exports.ON_ACCOUNT_DESTROYED_NOTIFICATION = "fxaccounts:account_destroyed";
 exports.ON_COLLECTION_CHANGED_NOTIFICATION = "sync:collection_changed";
 
 exports.FXA_PUSH_SCOPE_ACCOUNT_UPDATE = "chrome://fxa-device-update";
 
 exports.ON_PROFILE_CHANGE_NOTIFICATION = "fxaccounts:profilechange"; // WebChannel
 exports.ON_ACCOUNT_STATE_CHANGE_NOTIFICATION = "fxaccounts:statechange";
 
 // UI Requests.
--- a/services/fxaccounts/FxAccountsPush.js
+++ b/services/fxaccounts/FxAccountsPush.js
@@ -174,16 +174,19 @@ FxAccountsPushService.prototype = {
         // We already have a "profile updated" notification sent via WebChannel,
         // let's just re-use that.
         Services.obs.notifyObservers(null, ON_PROFILE_CHANGE_NOTIFICATION);
         return;
       case ON_PASSWORD_CHANGED_NOTIFICATION:
       case ON_PASSWORD_RESET_NOTIFICATION:
         this._onPasswordChanged();
         return;
+      case ON_ACCOUNT_DESTROYED_NOTIFICATION:
+        this.fxAccounts.handleAccountDestroyed(payload.data.uid);
+        return;
       case ON_COLLECTION_CHANGED_NOTIFICATION:
         Services.obs.notifyObservers(null, ON_COLLECTION_CHANGED_NOTIFICATION, payload.data.collections);
       default:
         this.log.warn("FxA Push command unrecognized: " + payload.command);
     }
   },
   /**
    * Check the FxA session status after a password change/reset event.
--- a/services/fxaccounts/tests/xpcshell/test_push_service.js
+++ b/services/fxaccounts/tests/xpcshell/test_push_service.js
@@ -196,16 +196,46 @@ add_test(function observePushTopicDevice
   let pushService = new FxAccountsPushService({
     pushService: mockPushService,
     fxAccounts: customAccounts,
   });
 
   pushService.observe(msg, mockPushService.pushTopic, FXA_PUSH_SCOPE_ACCOUNT_UPDATE);
 });
 
+add_test(function observePushTopicAccountDestroyed() {
+  const uid = "bogusuid";
+  let msg = {
+    data: {
+      json: () => ({
+        command: ON_ACCOUNT_DESTROYED_NOTIFICATION,
+        data: {
+          uid: uid
+        }
+      })
+    },
+    QueryInterface() {
+      return this;
+    }
+  };
+  let customAccounts = Object.assign(mockFxAccounts, {
+    handleAccountDestroyed() {
+      // checking verification status on push messages without data
+      run_next_test();
+    }
+  });
+
+  let pushService = new FxAccountsPushService({
+    pushService: mockPushService,
+    fxAccounts: customAccounts,
+  });
+
+  pushService.observe(msg, mockPushService.pushTopic, FXA_PUSH_SCOPE_ACCOUNT_UPDATE);
+});
+
 add_test(function observePushTopicProfileUpdated() {
   let msg = {
     data: {
       json: () => ({
         command: ON_PROFILE_UPDATED_NOTIFICATION
       })
     },
     QueryInterface() {