Bug 1182071 - Allow System app to fetch Sync keys. r=spenrose
authorFernando Jimenez <ferjmoreno@gmail.com>
Tue, 21 Jul 2015 21:34:37 +0200
changeset 254001 fc38e238fcb060e5dc3c5c01b43196138b0c03e5
parent 253946 79be64bac133e5c4d91e2f907e3f486b5c84a927
child 254002 79d34da554972ca91a21b0f868ddb8a876ceb272
push id29087
push usercbook@mozilla.com
push dateWed, 22 Jul 2015 12:01:23 +0000
treeherdermozilla-central@e7434cafdf2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersspenrose
bugs1182071
milestone42.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 1182071 - Allow System app to fetch Sync keys. r=spenrose
b2g/components/FxAccountsMgmtService.jsm
services/fxaccounts/FxAccountsCommon.js
services/fxaccounts/FxAccountsManager.jsm
services/fxaccounts/tests/xpcshell/test_manager.js
--- a/b2g/components/FxAccountsMgmtService.jsm
+++ b/b2g/components/FxAccountsMgmtService.jsm
@@ -88,22 +88,29 @@ this.FxAccountsMgmtService = {
       return;
     }
     // Backwards compatibility: handle accountId coming from Gaia
     if (data.accountId && typeof(data.email === "undefined")) {
       data.email = data.accountId;
       delete data.accountId;
     }
 
+    // XXX dirty hack because Gaia is sending getAccounts.
+    if (data.method == "getAccounts") {
+      data.method = "getAccount";
+    }
+
     switch(data.method) {
-      case "getAccounts":
-        FxAccountsManager.getAccount().then(
-          account => {
-            // We only expose the email and verification status so far.
-            self._onFulfill(msg.id, account);
+      case "getAccount":
+      case "getKeys":
+        FxAccountsManager[data.method]().then(
+          result => {
+            // For the getAccounts case, we only expose the email and
+            // verification status so far.
+            self._onFulfill(msg.id, result);
           },
           reason => {
             self._onReject(msg.id, reason);
           }
         ).then(null, Components.utils.reportError);
         break;
       case "logout":
         FxAccountsManager.signOut().then(
--- a/services/fxaccounts/FxAccountsCommon.js
+++ b/services/fxaccounts/FxAccountsCommon.js
@@ -171,16 +171,17 @@ exports.ERROR_MISSING_BODY_PARAMETERS   
 exports.ERROR_MISSING_CONTENT_LENGTH         = "MISSING_CONTENT_LENGTH";
 exports.ERROR_NO_TOKEN_SESSION               = "NO_TOKEN_SESSION";
 exports.ERROR_NO_SILENT_REFRESH_AUTH         = "NO_SILENT_REFRESH_AUTH";
 exports.ERROR_NOT_VALID_JSON_BODY            = "NOT_VALID_JSON_BODY";
 exports.ERROR_OFFLINE                        = "OFFLINE";
 exports.ERROR_PERMISSION_DENIED              = "PERMISSION_DENIED";
 exports.ERROR_REQUEST_BODY_TOO_LARGE         = "REQUEST_BODY_TOO_LARGE";
 exports.ERROR_SERVER_ERROR                   = "SERVER_ERROR";
+exports.ERROR_SYNC_DISABLED                  = "SYNC_DISABLED";
 exports.ERROR_TOO_MANY_CLIENT_REQUESTS       = "TOO_MANY_CLIENT_REQUESTS";
 exports.ERROR_SERVICE_TEMP_UNAVAILABLE       = "SERVICE_TEMPORARY_UNAVAILABLE";
 exports.ERROR_UI_ERROR                       = "UI_ERROR";
 exports.ERROR_UI_REQUEST                     = "UI_REQUEST";
 exports.ERROR_PARSE                          = "PARSE_ERROR";
 exports.ERROR_NETWORK                        = "NETWORK_ERROR";
 exports.ERROR_UNKNOWN                        = "UNKNOWN_ERROR";
 exports.ERROR_UNVERIFIED_ACCOUNT             = "UNVERIFIED_ACCOUNT";
--- a/services/fxaccounts/FxAccountsManager.jsm
+++ b/services/fxaccounts/FxAccountsManager.jsm
@@ -122,17 +122,25 @@ this.FxAccountsManager = {
     let client = this._getFxAccountsClient();
     return this._fxAccounts.getSignedInUser().then(
       user => {
         if ((!this._refreshing) && user) {
           return this._error(ERROR_ALREADY_SIGNED_IN_USER, {
             user: this._user
           });
         }
-        return client[aMethod](aEmail, aPassword);
+        let syncEnabled = false;
+        try {
+          syncEnabled = Services.prefs.getBoolPref("services.sync.enabled");
+        } catch(e) {
+          dump(e + "\n");
+        }
+        // XXX Refetch FxA credentials if services.sync.enabled preference
+        //     changes. Bug 1183103
+        return client[aMethod](aEmail, aPassword, syncEnabled);
       }
     ).then(
       user => {
         let error = this._getError(user);
         if (!user || !user.uid || !user.sessionToken || error) {
           return this._error(error ? error : ERROR_INTERNAL_INVALID_USER, {
             user: user
           });
@@ -572,13 +580,42 @@ this.FxAccountsManager = {
         }
         log.debug("No signed in user");
         if (aOptions && aOptions.silent) {
           return Promise.resolve(null);
         }
         return this._uiRequest(UI_REQUEST_SIGN_IN_FLOW, aAudience, principal);
       }
     );
+  },
+
+  getKeys: function() {
+    let syncEnabled = false;
+    try {
+      syncEnabled = Services.prefs.getBoolPref("services.sync.enabled");
+    } catch(e) {
+      dump("Sync is disabled, so you won't get the keys. " + e + "\n");
+    }
+
+    if (!syncEnabled) {
+      return Promise.reject(ERROR_SYNC_DISABLED);
+    }
+
+    return this.getAccount().then(
+      user => {
+        if (!user) {
+          log.debug("No signed in user");
+          return Promise.resolve(null);
+        }
+
+        if (!user.verified) {
+          return this._error(ERROR_UNVERIFIED_ACCOUNT, {
+            user: user
+          });
+        }
+
+        return this._fxAccounts.getKeys();
+      }
+    );
   }
-
 };
 
 FxAccountsManager.init();
--- a/services/fxaccounts/tests/xpcshell/test_manager.js
+++ b/services/fxaccounts/tests/xpcshell/test_manager.js
@@ -96,16 +96,17 @@ const kFxAccounts = fxAccounts;
 // and change it for a mock FxAccounts.
 FxAccountsManager._fxAccounts = {
   _reject: false,
   _getSignedInUserCalled: false,
   _setSignedInUserCalled: false,
 
   _error: 'error',
   _assertion: 'assertion',
+  _keys: 'keys',
   _signedInUser: null,
 
   _reset: function() {
     this._getSignedInUserCalled = false;
     this._setSignedInUserCalled = false;
     this._reject = false;
   },
 
@@ -134,16 +135,23 @@ FxAccountsManager._fxAccounts = {
   getSignedInUser: function() {
     this._getSignedInUserCalled = true;
     let deferred = Promise.defer();
     this._reject ? deferred.reject(this._error)
                  : deferred.resolve(this._signedInUser);
     return deferred.promise;
   },
 
+  getKeys: function() {
+    let deferred = Promise.defer();
+    this._reject ? deferred.reject(this._error)
+                 : deferred.resolve(this._keys);
+    return deferred.promise;
+  },
+
   resendVerificationEmail: function() {
     return this.getSignedInUser().then(data => {
       if (data) {
         return Promise.resolve(true);
       }
       throw new Error("Cannot resend verification email; no signed-in user");
     });
   },
@@ -894,8 +902,78 @@ add_test(function() {
   do_print("= fxaccounts:onlogout notification =");
   do_check_true(FxAccountsManager._activeSession != null);
   Services.obs.notifyObservers(null, ONLOGOUT_NOTIFICATION, null);
   do_execute_soon(function() {
     do_check_null(FxAccountsManager._activeSession);
     run_next_test();
   });
 });
+
+add_test(function(test_getKeys_sync_disabled) {
+  do_print("= getKeys sync disabled =");
+  Services.prefs.setBoolPref("services.sync.enabled", false);
+  FxAccountsManager.getKeys().then(
+    result => {
+      do_throw("Unexpected success");
+    },
+    error => {
+      do_check_eq(error, ERROR_SYNC_DISABLED);
+      Services.prefs.clearUserPref("services.sync.enabled");
+      run_next_test();
+    }
+  );
+});
+
+add_test(function(test_getKeys_no_session) {
+  do_print("= getKeys no session =");
+  Services.prefs.setBoolPref("services.sync.enabled", true);
+  FxAccountsManager._fxAccounts._signedInUser = null;
+  FxAccountsManager._activeSession = null;
+  FxAccountsManager.getKeys().then(
+    result => {
+      do_check_null(result);
+      FxAccountsManager._fxAccounts._reset();
+      Services.prefs.clearUserPref("services.sync.enabled");
+      run_next_test();
+    },
+    error => {
+      do_throw("Unexpected error: " + error);
+    }
+  );
+});
+
+add_test(function(test_getKeys_unverified_account) {
+  do_print("= getKeys unverified =");
+  Services.prefs.setBoolPref("services.sync.enabled", true);
+  FakeFxAccountsClient._verified = false;
+  FxAccountsManager.signIn("user@domain.org", "password").then(result => {
+    do_check_false(result.verified);
+    return FxAccountsManager.getKeys();
+  }).then(result => {
+      do_throw("Unexpected success");
+    },
+    error => {
+      do_check_eq(error.error, ERROR_UNVERIFIED_ACCOUNT);
+      FxAccountsManager._fxAccounts._reset();
+      Services.prefs.clearUserPref("services.sync.enabled");
+      FxAccountsManager.signOut().then(run_next_test)
+    }
+  );
+});
+
+add_test(function(test_getKeys_success) {
+  do_print("= getKeys success =");
+  Services.prefs.setBoolPref("services.sync.enabled", true);
+  FakeFxAccountsClient._verified = true;
+  FxAccountsManager.signIn("user@domain.org", "password").then(result => {
+    return FxAccountsManager.getKeys();
+  }).then(result => {
+      do_check_eq(result, FxAccountsManager._fxAccounts._keys);
+      FxAccountsManager._fxAccounts._reset();
+      Services.prefs.clearUserPref("services.sync.enabled");
+      run_next_test();
+    },
+    error => {
+      do_throw("Unexpected error " + error);
+    }
+  );
+});