commit b55b57caba523eacf6dfd35b6e69a6de48c05348
parent f5038bfe19515c12c73c8124dec668fc2e115b36
Author: Sammy Khamis <skhamis@mozilla.com>
Date: Wed, 31 Dec 2025 21:36:15 +0000
Bug 2008264 - Dont destroy session if user is already logged in r=bdk
Differential Revision: https://phabricator.services.mozilla.com/D277716
Diffstat:
2 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/services/fxaccounts/FxAccountsWebChannel.sys.mjs b/services/fxaccounts/FxAccountsWebChannel.sys.mjs
@@ -667,8 +667,17 @@ FxAccountsWebChannelHelpers.prototype = {
accountData.requestedServices = JSON.stringify(requestedServices);
this.setPreviousAccountHashPref(accountData.uid);
- await this._fxAccounts._internal.setSignedInUser(accountData);
- log.debug("Webchannel finished logging a user in.");
+
+ // For scenarios like user is logged in via third-party but wants
+ // to enable sync (password) the server will send an additional login command
+ // we need to ensure we don't destroy the existing session
+ if (signedInUser && signedInUser.uid === accountData.uid) {
+ await this._fxAccounts._internal.updateUserAccountData(accountData);
+ log.debug("Webchannel finished updating already logged in user.");
+ } else {
+ await this._fxAccounts._internal.setSignedInUser(accountData);
+ log.debug("Webchannel finished logging a user in.");
+ }
},
/**
diff --git a/services/fxaccounts/tests/xpcshell/test_web_channel.js b/services/fxaccounts/tests/xpcshell/test_web_channel.js
@@ -657,6 +657,65 @@ add_task(async function test_helpers_login_another_user_signed_in() {
Assert.ok(helpers._disconnect.called);
});
+// The FxA server sends the `login` command after the user is signed in
+// when upgrading from third-party auth to password + sync
+add_task(async function test_helpers_login_same_user_signed_in() {
+ let updateUserAccountDataCalled = false;
+ let setSignedInUserCalled = false;
+
+ let helpers = new FxAccountsWebChannelHelpers({
+ fxAccounts: {
+ getSignedInUser() {
+ return Promise.resolve({
+ uid: "testuser",
+ email: "testuser@testuser.com",
+ });
+ },
+ _internal: {
+ updateUserAccountData(accountData) {
+ updateUserAccountDataCalled = true;
+ Assert.equal(accountData.email, "testuser@testuser.com");
+ Assert.equal(accountData.uid, "testuser");
+ return Promise.resolve();
+ },
+ setSignedInUser() {
+ setSignedInUserCalled = true;
+ return Promise.resolve();
+ },
+ },
+ telemetry: {
+ recordConnection: sinon.spy(),
+ },
+ },
+ weaveXPCOM: {
+ whenLoaded() {},
+ Weave: {
+ Service: {
+ configure() {},
+ },
+ },
+ },
+ });
+ helpers._disconnect = sinon.spy();
+
+ await helpers.login({
+ uid: "testuser",
+ email: "testuser@testuser.com",
+ verifiedCanLinkAccount: true,
+ customizeSync: false,
+ });
+
+ Assert.ok(
+ updateUserAccountDataCalled,
+ "updateUserAccountData should be called"
+ );
+ Assert.ok(!setSignedInUserCalled, "setSignedInUser should not be called");
+ Assert.ok(!helpers._disconnect.called, "_disconnect should not be called");
+ Assert.ok(
+ helpers._fxAccounts.telemetry.recordConnection.calledWith([], "webchannel")
+ );
+});
+
add_task(async function test_helpers_login_with_customize_sync() {
let helpers = new FxAccountsWebChannelHelpers({
fxAccounts: {
@@ -710,6 +769,10 @@ add_task(async function test_helpers_persist_requested_services() {
accountData = newAccountData;
return accountData;
},
+ async updateUserAccountData(updatedFields) {
+ accountData = { ...accountData, ...updatedFields };
+ return accountData;
+ },
},
async getSignedInUser() {
return accountData;