From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../tests/xpcshell/test_oauth_token_storage.js | 177 +++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 services/fxaccounts/tests/xpcshell/test_oauth_token_storage.js (limited to 'services/fxaccounts/tests/xpcshell/test_oauth_token_storage.js') diff --git a/services/fxaccounts/tests/xpcshell/test_oauth_token_storage.js b/services/fxaccounts/tests/xpcshell/test_oauth_token_storage.js new file mode 100644 index 0000000000..5a41cd4571 --- /dev/null +++ b/services/fxaccounts/tests/xpcshell/test_oauth_token_storage.js @@ -0,0 +1,177 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { FxAccounts } = ChromeUtils.importESModule( + "resource://gre/modules/FxAccounts.sys.mjs" +); +const { FxAccountsClient } = ChromeUtils.importESModule( + "resource://gre/modules/FxAccountsClient.sys.mjs" +); + +// We grab some additional stuff via backstage passes. +var { AccountState } = ChromeUtils.importESModule( + "resource://gre/modules/FxAccounts.sys.mjs" +); + +function promiseNotification(topic) { + return new Promise(resolve => { + let observe = () => { + Services.obs.removeObserver(observe, topic); + resolve(); + }; + Services.obs.addObserver(observe, topic); + }); +} + +// 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) { + return Promise.resolve(!!uid && !this._deletedOnServer); + }; + + 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 = {}; +Object.setPrototypeOf( + MockFxAccountsClient.prototype, + 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", + }); + }); + }, + }, + }); +} + +async function createMockFxA() { + let fxa = new MockFxAccounts(); + let credentials = { + email: "foo@example.com", + uid: "1234@lcip.org", + sessionToken: "dead", + kSync: "beef", + kXCS: "cafe", + kExtSync: "bacon", + kExtKbHash: "cheese", + verified: true, + }; + await fxa._internal.setSignedInUser(credentials); + return fxa; +} + +// The tests. + +add_task(async function testCacheStorage() { + let fxa = await 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"); + }); + }; + + 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. + await 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"); + await cas.removeCachedToken("token1"); + deepEqual(cas.oauthTokens, {}); + await 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. + await fxa.signOut(/* localOnly = */ true); + deepEqual(storageManager.accountData, null); +}); -- cgit v1.2.3