Bug 999190 - Part 1 - Detect fxa deletion on sync auth error. r=markh

This commit is contained in:
Edouard Oger 2015-09-02 16:44:00 +02:00
parent 0181411d9d
commit dfbb27ab2f
4 changed files with 90 additions and 14 deletions

View File

@ -31,6 +31,7 @@ Cu.import("resource://services-sync/browserid_identity.js");
Cu.import("resource://testing-common/services/common/logging.js");
Cu.import("resource://testing-common/services/sync/fakeservices.js");
Cu.import("resource://gre/modules/FxAccounts.jsm");
Cu.import("resource://gre/modules/FxAccountsClient.jsm");
Cu.import("resource://gre/modules/FxAccountsCommon.js");
Cu.import("resource://gre/modules/Promise.jsm");
@ -191,6 +192,18 @@ this.configureFxAccountIdentity = function(authService,
};
fxa = new FxAccounts(MockInternal);
let MockFxAccountsClient = function() {
FxAccountsClient.apply(this);
};
MockFxAccountsClient.prototype = {
__proto__: FxAccountsClient.prototype,
accountStatus() {
return Promise.resolve(true);
}
};
let mockFxAClient = new MockFxAccountsClient();
fxa.internal._fxAccountsClient = mockFxAClient;
let mockTSC = { // TokenServerClient
getTokenFromBrowserIDAssertion: function(uri, assertion, cb) {
config.fxaccount.token.uid = config.username;

View File

@ -184,7 +184,7 @@ this.BrowserIDManager.prototype = {
// Reset the world before we do anything async.
this.whenReadyToAuthenticate = Promise.defer();
this.whenReadyToAuthenticate.promise.then(null, (err) => {
this.whenReadyToAuthenticate.promise.catch(err => {
this._log.error("Could not authenticate", err);
});
@ -240,14 +240,25 @@ this.BrowserIDManager.prototype = {
Services.obs.notifyObservers(null, "weave:service:setup-complete", null);
Weave.Utils.nextTick(Weave.Service.sync, Weave.Service);
}
}).then(null, err => {
this._shouldHaveSyncKeyBundle = true; // but we probably don't have one...
this.whenReadyToAuthenticate.reject(err);
}).catch(err => {
let authErr = err; // note that we must reject with this error and not a
// subsequent one
// report what failed...
this._log.error("Background fetch for key bundle failed", err);
this._log.error("Background fetch for key bundle failed", authErr);
// check if the account still exists
this._fxaService.accountStatus().then(exists => {
if (!exists) {
return fxAccounts.signOut(true);
}
}).catch(err => {
this._log.error("Error while trying to determine FXA existence", err);
}).then(() => {
this._shouldHaveSyncKeyBundle = true; // but we probably don't have one...
this.whenReadyToAuthenticate.reject(authErr)
});
});
// and we are done - the fetch continues on in the background...
}).then(null, err => {
}).catch(err => {
this._log.error("Processing logged in account", err);
});
},
@ -595,7 +606,7 @@ this.BrowserIDManager.prototype = {
}
return token;
})
.then(null, err => {
.catch(err => {
// TODO: unify these errors - we need to handle errors thrown by
// both tokenserverclient and hawkclient.
// A tokenserver error thrown based on a bad response.

View File

@ -35,7 +35,10 @@ let MockFxAccountsClient = function() {
FxAccountsClient.apply(this);
};
MockFxAccountsClient.prototype = {
__proto__: FxAccountsClient.prototype
__proto__: FxAccountsClient.prototype,
accountStatus() {
return Promise.resolve(true);
}
};
function MockFxAccounts() {
@ -83,6 +86,47 @@ add_task(function test_initialializeWithCurrentIdentity() {
}
);
add_task(function test_initialializeWithAuthErrorAndDeletedAccount() {
_("Verify sync unpair after initializeWithCurrentIdentity with auth error + account deleted");
browseridManager._fxaService.internal.initialize();
let fetchTokenForUserCalled = false;
let accountStatusCalled = false;
let MockFxAccountsClient = function() {
FxAccountsClient.apply(this);
};
MockFxAccountsClient.prototype = {
__proto__: FxAccountsClient.prototype,
accountStatus() {
accountStatusCalled = true;
return Promise.resolve(false);
}
};
let mockFxAClient = new MockFxAccountsClient();
browseridManager._fxaService.internal._fxAccountsClient = mockFxAClient;
let oldFetchTokenForUser = browseridManager._fetchTokenForUser;
browseridManager._fetchTokenForUser = function() {
fetchTokenForUserCalled = true;
return Promise.reject(false);
}
yield browseridManager.initializeWithCurrentIdentity();
yield Assert.rejects(browseridManager.whenReadyToAuthenticate.promise,
"should reject due to an auth error");
do_check_true(fetchTokenForUserCalled);
do_check_true(accountStatusCalled);
do_check_false(browseridManager.account);
do_check_false(browseridManager._token);
do_check_false(browseridManager.hasValidToken());
do_check_false(browseridManager.account);
browseridManager._fetchTokenForUser = oldFetchTokenForUser;
});
add_task(function test_initialializeWithNoKeys() {
_("Verify start after initializeWithCurrentIdentity without kA, kB or keyFetchToken");
let identityConfig = makeIdentityConfig();
@ -646,7 +690,17 @@ function* initializeIdentityWithHAWKResponseFactory(config, cbGetResponse) {
callback.call(this);
},
get: function(callback) {
this.response = cbGetResponse("get", null, this._uri, this._credentials, this._extra);
// Skip /status requests (browserid_identity checks if the account still
// exists after an auth error)
if (this._uri.startsWith("http://mockedserver:9999/account/status")) {
this.response = {
status: 200,
headers: {"content-type": "application/json"},
body: JSON.stringify({exists: true}),
};
} else {
this.response = cbGetResponse("get", null, this._uri, this._credentials, this._extra);
}
callback.call(this);
}
}

View File

@ -1,3 +1,6 @@
// We change this pref before anything else initializes
Services.prefs.setCharPref("identity.fxaccounts.auth.uri", "http://localhost");
// Test the FxAMigration module
Cu.import("resource://services-sync/FxaMigrator.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
@ -80,12 +83,7 @@ function configureLegacySync() {
return [engine, server];
}
function configureFxa() {
Services.prefs.setCharPref("identity.fxaccounts.auth.uri", "http://localhost");
}
add_task(function *testMigration() {
configureFxa();
// when we do a .startOver we want the new provider.
let oldValue = Services.prefs.getBoolPref("services.sync-testing.startOverKeepIdentity");