forked from mirrors/gecko-dev
MozReview-Commit-ID: EjyAssqiQk8 --HG-- extra : rebase_source : cbfc8d4474b6c3d46eb21374e33fd3341403444f
165 lines
4.6 KiB
JavaScript
165 lines
4.6 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
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/osfile.jsm");
|
|
|
|
// We grab some additional stuff via backstage passes.
|
|
var {AccountState} = Cu.import("resource://gre/modules/FxAccounts.jsm", {});
|
|
|
|
function promiseNotification(topic) {
|
|
return new Promise(resolve => {
|
|
let observe = () => {
|
|
Services.obs.removeObserver(observe, topic);
|
|
resolve();
|
|
}
|
|
Services.obs.addObserver(observe, topic, false);
|
|
});
|
|
}
|
|
|
|
// A storage manager that doesn't actually write anywhere.
|
|
function MockStorageManager() {
|
|
}
|
|
|
|
MockStorageManager.prototype = {
|
|
promiseInitialized: Promise.resolve(),
|
|
|
|
initialize(accountData) {
|
|
this.accountData = accountData;
|
|
},
|
|
|
|
finalize() {
|
|
return Promise.resolve();
|
|
},
|
|
|
|
getAccountData() {
|
|
return Promise.resolve(this.accountData);
|
|
},
|
|
|
|
updateAccountData(updatedFields) {
|
|
for (let [name, value] of Object.entries(updatedFields)) {
|
|
if (value == null) {
|
|
delete this.accountData[name];
|
|
} else {
|
|
this.accountData[name] = value;
|
|
}
|
|
}
|
|
return Promise.resolve();
|
|
},
|
|
|
|
deleteAccountData() {
|
|
this.accountData = null;
|
|
return Promise.resolve();
|
|
}
|
|
}
|
|
|
|
|
|
// Just enough mocks so we can avoid hawk etc.
|
|
function MockFxAccountsClient() {
|
|
this._email = "nobody@example.com";
|
|
this._verified = false;
|
|
|
|
this.accountStatus = function(uid) {
|
|
let deferred = Promise.defer();
|
|
deferred.resolve(!!uid && (!this._deletedOnServer));
|
|
return deferred.promise;
|
|
};
|
|
|
|
this.signOut = function() { return Promise.resolve(); };
|
|
this.registerDevice = function() { return Promise.resolve(); };
|
|
this.updateDevice = function() { return Promise.resolve(); };
|
|
this.signOutAndDestroyDevice = function() { return Promise.resolve(); };
|
|
this.getDeviceList = function() { return Promise.resolve(); };
|
|
|
|
FxAccountsClient.apply(this);
|
|
}
|
|
|
|
MockFxAccountsClient.prototype = {
|
|
__proto__: FxAccountsClient.prototype
|
|
}
|
|
|
|
function MockFxAccounts(device = {}) {
|
|
return new FxAccounts({
|
|
fxAccountsClient: new MockFxAccountsClient(),
|
|
newAccountState(credentials) {
|
|
// we use a real accountState but mocked storage.
|
|
let storage = new MockStorageManager();
|
|
storage.initialize(credentials);
|
|
return new AccountState(storage);
|
|
},
|
|
_getDeviceName() {
|
|
return "mock device name";
|
|
},
|
|
fxaPushService: {
|
|
registerPushEndpoint() {
|
|
return new Promise((resolve) => {
|
|
resolve({
|
|
endpoint: "http://mochi.test:8888"
|
|
});
|
|
});
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function* createMockFxA() {
|
|
let fxa = new MockFxAccounts();
|
|
let credentials = {
|
|
email: "foo@example.com",
|
|
uid: "1234@lcip.org",
|
|
assertion: "foobar",
|
|
sessionToken: "dead",
|
|
kA: "beef",
|
|
kB: "cafe",
|
|
verified: true
|
|
};
|
|
yield fxa.setSignedInUser(credentials);
|
|
return fxa;
|
|
}
|
|
|
|
// The tests.
|
|
function run_test() {
|
|
run_next_test();
|
|
}
|
|
|
|
add_task(function* testCacheStorage() {
|
|
let fxa = yield createMockFxA();
|
|
|
|
// Hook what the impl calls to save to disk.
|
|
let cas = fxa.internal.currentAccountState;
|
|
let origPersistCached = cas._persistCachedTokens.bind(cas)
|
|
cas._persistCachedTokens = function() {
|
|
return origPersistCached().then(() => {
|
|
Services.obs.notifyObservers(null, "testhelper-fxa-cache-persist-done", null);
|
|
});
|
|
};
|
|
|
|
let promiseWritten = promiseNotification("testhelper-fxa-cache-persist-done");
|
|
let tokenData = {token: "token1", somethingelse: "something else"};
|
|
let scopeArray = ["foo", "bar"];
|
|
cas.setCachedToken(scopeArray, tokenData);
|
|
deepEqual(cas.getCachedToken(scopeArray), tokenData);
|
|
|
|
deepEqual(cas.oauthTokens, {"bar|foo": tokenData});
|
|
// wait for background write to complete.
|
|
yield promiseWritten;
|
|
|
|
// Check the token cache made it to our mocked storage.
|
|
deepEqual(cas.storageManager.accountData.oauthTokens, {"bar|foo": tokenData});
|
|
|
|
// Drop the token from the cache and ensure it is removed from the json.
|
|
promiseWritten = promiseNotification("testhelper-fxa-cache-persist-done");
|
|
yield cas.removeCachedToken("token1");
|
|
deepEqual(cas.oauthTokens, {});
|
|
yield promiseWritten;
|
|
deepEqual(cas.storageManager.accountData.oauthTokens, {});
|
|
|
|
// sign out and the token storage should end up with null.
|
|
let storageManager = cas.storageManager; // .signOut() removes the attribute.
|
|
yield fxa.signOut( /* localOnly = */ true);
|
|
deepEqual(storageManager.accountData, null);
|
|
});
|