tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit c93446545b68a2c6def7832da661547d441bb3fc
parent 0303dcecad6003c2b682c16f7a9002a0f19c361d
Author: agoloman <agoloman@mozilla.com>
Date:   Thu,  2 Oct 2025 20:35:13 +0300

Revert "Bug 1992112 - IPProtectionService should not use UIState to check the sign-in flag, r=ip-protection-reviewers,rking" for causing bc failures @browser_startup.js.

This reverts commit f218375f33921491641c604b1b28454df6434da1.

Diffstat:
Dbrowser/components/ipprotection/IPPSignInWatcher.sys.mjs | 73-------------------------------------------------------------------------
Mbrowser/components/ipprotection/IPProtectionHelpers.sys.mjs | 43++++++++++++++++++++++++++++++++++++++++---
Mbrowser/components/ipprotection/IPProtectionPanel.sys.mjs | 13++++++++-----
Mbrowser/components/ipprotection/IPProtectionService.sys.mjs | 21++++++++++++++++++---
Mbrowser/components/ipprotection/moz.build | 1-
Mbrowser/components/ipprotection/tests/browser/head.js | 14++++++++------
Mbrowser/components/ipprotection/tests/xpcshell/test_IPProtectionPanel.js | 18++++++++++++------
Mbrowser/components/ipprotection/tests/xpcshell/test_IPProtectionService.js | 22++++++++++++++--------
Mbrowser/components/ipprotection/tests/xpcshell/test_IPProtectionStates.js | 36++++++++++++++++++++++++++----------
9 files changed, 126 insertions(+), 115 deletions(-)

diff --git a/browser/components/ipprotection/IPPSignInWatcher.sys.mjs b/browser/components/ipprotection/IPPSignInWatcher.sys.mjs @@ -1,73 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const lazy = {}; - -ChromeUtils.defineESModuleGetters(lazy, { - IPProtectionService: - "resource:///modules/ipprotection/IPProtectionService.sys.mjs", - UIState: "resource://services-sync/UIState.sys.mjs", -}); - -ChromeUtils.defineLazyGetter(lazy, "fxAccounts", () => { - return ChromeUtils.importESModule( - "resource://gre/modules/FxAccounts.sys.mjs" - ).getFxAccountsSingleton(); -}); - -/** - * This class monitors the Sign-In state and triggers the update of the service - * if needed. - */ -class IPPSignInWatcherSingleton { - #signedIn = false; - - get isSignedIn() { - return this.#signedIn; - } - - setSignedIn(signedIn) { - this.#signedIn = signedIn; - } - - /** - * Adds an observer for the FxA sign-in state. - */ - async init() { - this.fxaObserver = { - QueryInterface: ChromeUtils.generateQI([ - Ci.nsIObserver, - Ci.nsISupportsWeakReference, - ]), - - observe() { - let { status } = lazy.UIState.get(); - let signedIn = status == lazy.UIState.STATUS_SIGNED_IN; - if (signedIn !== IPPSignInWatcher.isSignedIn) { - IPPSignInWatcher.setSignedIn(signedIn); - lazy.IPProtectionService.updateState(); - } - }, - }; - - Services.obs.addObserver(this.fxaObserver, lazy.UIState.ON_UPDATE); - - const userData = await lazy.fxAccounts.getSignedInUser(); - this.#signedIn = (userData && userData.verified) || false; - } - - /** - * Removes the FxA sign-in state observer - */ - uninit() { - if (this.fxaObserver) { - Services.obs.removeObserver(this.fxaObserver, lazy.UIState.ON_UPDATE); - this.fxaObserver = null; - } - } -} - -const IPPSignInWatcher = new IPPSignInWatcherSingleton(); - -export { IPPSignInWatcher }; diff --git a/browser/components/ipprotection/IPProtectionHelpers.sys.mjs b/browser/components/ipprotection/IPProtectionHelpers.sys.mjs @@ -15,10 +15,9 @@ ChromeUtils.defineESModuleGetters(lazy, { IPProtectionStates: "resource:///modules/ipprotection/IPProtectionService.sys.mjs", NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", + UIState: "resource://services-sync/UIState.sys.mjs", }); -import { IPPSignInWatcher } from "resource:///modules/ipprotection/IPPSignInWatcher.sys.mjs"; - const VPN_ADDON_ID = "vpn@mozilla.com"; /** @@ -126,6 +125,44 @@ class VPNAddonHelper { } /** + * This class monitors the Sign-In state and triggers the update of the service + * if needed. + */ +class SignInStateHelper { + /** + * Adds an observer for the FxA sign-in state. + */ + init() { + this.fxaObserver = { + QueryInterface: ChromeUtils.generateQI([ + Ci.nsIObserver, + Ci.nsISupportsWeakReference, + ]), + + observe() { + let { status } = lazy.UIState.get(); + let signedIn = status == lazy.UIState.STATUS_SIGNED_IN; + if (signedIn !== lazy.IPProtectionService.signedIn) { + lazy.IPProtectionService.updateState(); + } + }, + }; + + Services.obs.addObserver(this.fxaObserver, lazy.UIState.ON_UPDATE); + } + + /** + * Removes the FxA sign-in state observer + */ + uninit() { + if (this.fxaObserver) { + Services.obs.removeObserver(this.fxaObserver, lazy.UIState.ON_UPDATE); + this.fxaObserver = null; + } + } +} + +/** * This class monitors the eligibility flag from Nimbus */ class EligibilityHelper { @@ -145,9 +182,9 @@ class EligibilityHelper { const IPPHelpers = [ new AccountResetHelper(), new EligibilityHelper(), + new SignInStateHelper(), new VPNAddonHelper(), new UIHelper(), - IPPSignInWatcher, ]; export { IPPHelpers }; diff --git a/browser/components/ipprotection/IPProtectionPanel.sys.mjs b/browser/components/ipprotection/IPProtectionPanel.sys.mjs @@ -12,7 +12,6 @@ ChromeUtils.defineESModuleGetters(lazy, { IPProtectionStates: "resource:///modules/ipprotection/IPProtectionService.sys.mjs", IPProtection: "resource:///modules/ipprotection/IPProtection.sys.mjs", - IPPSignInWatcher: "resource:///modules/ipprotection/IPPSignInWatcher.sys.mjs", }); import { @@ -110,11 +109,14 @@ export class IPProtectionPanel { constructor(window, variant = "") { this.handleEvent = this.#handleEvent.bind(this); - let { activatedAt: protectionEnabledSince, hasUpgraded } = - lazy.IPProtectionService; + let { + isSignedIn, + activatedAt: protectionEnabledSince, + hasUpgraded, + } = lazy.IPProtectionService; this.state = { - isSignedOut: !lazy.IPPSignInWatcher.isSignedIn, + isSignedOut: !isSignedIn, isProtectionEnabled: !!protectionEnabledSince, protectionEnabledSince, location: { @@ -357,6 +359,7 @@ export class IPProtectionPanel { } else if (event.type == "IPProtectionService:StateChanged") { let { state, + isSignedIn, activatedAt: protectionEnabledSince, hasUpgraded, } = lazy.IPProtectionService; @@ -365,7 +368,7 @@ export class IPProtectionPanel { lazy.IPProtectionService.errors.includes(ERRORS.GENERIC); this.setState({ - isSignedOut: !lazy.IPPSignInWatcher.isSignedIn, + isSignedOut: !isSignedIn, isProtectionEnabled: !!protectionEnabledSince, protectionEnabledSince, hasUpgraded, diff --git a/browser/components/ipprotection/IPProtectionService.sys.mjs b/browser/components/ipprotection/IPProtectionService.sys.mjs @@ -10,7 +10,7 @@ ChromeUtils.defineESModuleGetters(lazy, { GuardianClient: "resource:///modules/ipprotection/GuardianClient.sys.mjs", IPPHelpers: "resource:///modules/ipprotection/IPProtectionHelpers.sys.mjs", IPPProxyManager: "resource:///modules/ipprotection/IPPProxyManager.sys.mjs", - IPPSignInWatcher: "resource:///modules/ipprotection/IPPSignInWatcher.sys.mjs", + UIState: "resource://services-sync/UIState.sys.mjs", SpecialMessageActions: "resource://messaging-system/lib/SpecialMessageActions.sys.mjs", NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", @@ -76,6 +76,7 @@ class IPProtectionServiceSingleton extends EventTarget { errors = []; enrolling = null; + signedIn = null; guardian = null; proxyManager = null; @@ -142,7 +143,7 @@ class IPProtectionServiceSingleton extends EventTarget { } this.proxyManager = new lazy.IPPProxyManager(this.guardian); - await Promise.allSettled(this.#helpers.map(helper => helper.init())); + this.#helpers.forEach(helper => helper.init()); await this.#updateState(); } @@ -163,6 +164,7 @@ class IPProtectionServiceSingleton extends EventTarget { this.#entitlement = null; this.errors = []; this.enrolling = null; + this.signedIn = null; this.#helpers.forEach(helper => helper.uninit()); @@ -266,6 +268,7 @@ class IPProtectionServiceSingleton extends EventTarget { * Reset the statuses that are set based on a FxA account. */ resetAccount() { + this.signedIn = null; this.#entitlement = null; if (this.proxyManager?.active) { this.stop(false); @@ -274,6 +277,17 @@ class IPProtectionServiceSingleton extends EventTarget { } /** + * Checks if a user has signed in. + * + * @returns {boolean} + */ + get isSignedIn() { + let { status } = lazy.UIState.get(); + this.signedIn = status == lazy.UIState.STATUS_SIGNED_IN; + return this.signedIn; + } + + /** * Checks if the user has enrolled with FxA to use the proxy. * * @param { boolean } onlyCached - if true only the cached clients will be checked. @@ -422,8 +436,9 @@ class IPProtectionServiceSingleton extends EventTarget { // For non authenticated users, we can check if they are eligible (the UI // is shown and they have to login) or we don't know yet their current // enroll state (no UI is shown). + let signedIn = this.isSignedIn; let eligible = this.isEligible; - if (!lazy.IPPSignInWatcher.isSignedIn) { + if (!signedIn) { return !eligible ? IPProtectionStates.UNAVAILABLE : IPProtectionStates.UNAUTHENTICATED; diff --git a/browser/components/ipprotection/moz.build b/browser/components/ipprotection/moz.build @@ -20,7 +20,6 @@ EXTRA_JS_MODULES.ipprotection += [ "IPProtectionServerlist.sys.mjs", "IPProtectionService.sys.mjs", "IPProtectionUsage.sys.mjs", - "IPPSignInWatcher.sys.mjs", ] BROWSER_CHROME_MANIFESTS += [ diff --git a/browser/components/ipprotection/tests/browser/head.js b/browser/components/ipprotection/tests/browser/head.js @@ -13,10 +13,6 @@ const { IPProtectionService, IPProtectionStates } = ChromeUtils.importESModule( "resource:///modules/ipprotection/IPProtectionService.sys.mjs" ); -const { IPPSignInWatcher } = ChromeUtils.importESModule( - "resource:///modules/ipprotection/IPPSignInWatcher.sys.mjs" -); - const { HttpServer, HTTP_403 } = ChromeUtils.importESModule( "resource://testing-common/httpd.sys.mjs" ); @@ -27,6 +23,7 @@ const { NimbusTestUtils } = ChromeUtils.importESModule( ChromeUtils.defineESModuleGetters(this, { sinon: "resource://testing-common/Sinon.sys.mjs", + UIState: "resource://services-sync/UIState.sys.mjs", ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs", CustomizableUI: "moz-src:///browser/components/customizableui/CustomizableUI.sys.mjs", @@ -239,6 +236,7 @@ let DEFAULT_SERVICE_STATUS = { /* exported DEFAULT_SERVICE_STATUS */ let STUBS = { + UIState: undefined, isLinkedToGuardian: undefined, enroll: undefined, fetchUserInfo: undefined, @@ -269,7 +267,7 @@ add_setup(async function setupVPN() { }); function setupStubs(stubs = STUBS) { - stubs.isSignedIn = setupSandbox.stub(IPPSignInWatcher, "isSignedIn"); + stubs.UIState = setupSandbox.stub(UIState, "get"); stubs.isLinkedToGuardian = setupSandbox.stub( IPProtectionService.guardian, "isLinkedToGuardian" @@ -297,7 +295,11 @@ function setupService( stubs = STUBS ) { if (typeof isSignedIn != "undefined") { - stubs.isSignedIn.get(() => isSignedIn); + stubs.UIState.returns({ + status: isSignedIn + ? UIState.STATUS_SIGNED_IN + : UIState.STATUS_NOT_CONFIGURED, + }); } if (typeof isEnrolled != "undefined") { diff --git a/browser/components/ipprotection/tests/xpcshell/test_IPProtectionPanel.js b/browser/components/ipprotection/tests/xpcshell/test_IPProtectionPanel.js @@ -3,15 +3,15 @@ https://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; +const { UIState } = ChromeUtils.importESModule( + "resource://services-sync/UIState.sys.mjs" +); const { IPProtectionPanel } = ChromeUtils.importESModule( "resource:///modules/ipprotection/IPProtectionPanel.sys.mjs" ); const { IPProtectionService, IPProtectionStates } = ChromeUtils.importESModule( "resource:///modules/ipprotection/IPProtectionService.sys.mjs" ); -const { IPPSignInWatcher } = ChromeUtils.importESModule( - "resource:///modules/ipprotection/IPPSignInWatcher.sys.mjs" -); /** * A class that mocks the IP Protection panel. @@ -131,7 +131,9 @@ add_task(async function test_updateState() { */ add_task(async function test_IPProtectionPanel_signedIn() { let sandbox = sinon.createSandbox(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => true); + sandbox.stub(UIState, "get").returns({ + status: UIState.STATUS_SIGNED_IN, + }); sandbox .stub(IPProtectionService.guardian, "isLinkedToGuardian") .resolves(true); @@ -180,7 +182,9 @@ add_task(async function test_IPProtectionPanel_signedIn() { */ add_task(async function test_IPProtectionPanel_signedOut() { let sandbox = sinon.createSandbox(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => false); + sandbox.stub(UIState, "get").returns({ + status: UIState.STATUS_NOT_CONFIGURED, + }); let ipProtectionPanel = new IPProtectionPanel(); let fakeElement = new FakeIPProtectionPanelElement(); @@ -223,7 +227,9 @@ add_task(async function test_IPProtectionPanel_started_stopped() { fakeElement.isConnected = true; let sandbox = sinon.createSandbox(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => true); + sandbox.stub(UIState, "get").returns({ + status: UIState.STATUS_SIGNED_IN, + }); sandbox .stub(IPProtectionService.guardian, "isLinkedToGuardian") .resolves(true); diff --git a/browser/components/ipprotection/tests/xpcshell/test_IPProtectionService.js b/browser/components/ipprotection/tests/xpcshell/test_IPProtectionService.js @@ -12,8 +12,8 @@ const { ExtensionTestUtils } = ChromeUtils.importESModule( const { IPProtectionService, IPProtectionStates } = ChromeUtils.importESModule( "resource:///modules/ipprotection/IPProtectionService.sys.mjs" ); -const { IPPSignInWatcher } = ChromeUtils.importESModule( - "resource:///modules/ipprotection/IPPSignInWatcher.sys.mjs" +const { UIState } = ChromeUtils.importESModule( + "resource://services-sync/UIState.sys.mjs" ); do_get_profile(); @@ -31,7 +31,7 @@ ExtensionTestUtils.init(this); function setupStubs( sandbox, options = { - signedIn: true, + signedIn: UIState.STATUS_SIGNED_IN, isLinkedToGuardian: true, validProxyPass: true, entitlement: { @@ -41,7 +41,9 @@ function setupStubs( }, } ) { - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => options.signedIn); + sandbox.stub(UIState, "get").returns({ + status: options.signedIn, + }); sandbox .stub(IPProtectionService.guardian, "isLinkedToGuardian") .resolves(options.isLinkedToGuardian); @@ -172,7 +174,7 @@ add_task(async function test_IPProtectionService_updateState_signedIn() { await signedInEventPromise; - Assert.ok(IPPSignInWatcher.isSignedIn, "Should be signed in after update"); + Assert.ok(IPProtectionService.isSignedIn, "Should be signed in after update"); IPProtectionService.uninit(); sandbox.restore(); @@ -187,7 +189,9 @@ add_task(async function test_IPProtectionService_updateState_signedOut() { await IPProtectionService.init(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => false); + UIState.get.returns({ + status: UIState.STATUS_NOT_CONFIGURED, + }); let signedOutEventPromise = waitForEvent( IPProtectionService, @@ -201,7 +205,7 @@ add_task(async function test_IPProtectionService_updateState_signedOut() { await signedOutEventPromise; Assert.ok( - !IPPSignInWatcher.isSignedIn, + !IPProtectionService.isSignedIn, "Should not be signed in after update" ); @@ -291,7 +295,9 @@ add_task(async function test_IPProtectionService_hasUpgraded_signed_out() { await IPProtectionService.init(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => false); + UIState.get.returns({ + status: UIState.STATUS_NOT_CONFIGURED, + }); let signedOutEventPromise = waitForEvent( IPProtectionService, diff --git a/browser/components/ipprotection/tests/xpcshell/test_IPProtectionStates.js b/browser/components/ipprotection/tests/xpcshell/test_IPProtectionStates.js @@ -6,8 +6,8 @@ https://creativecommons.org/publicdomain/zero/1.0/ */ const { IPProtectionService, IPProtectionStates } = ChromeUtils.importESModule( "resource:///modules/ipprotection/IPProtectionService.sys.mjs" ); -const { IPPSignInWatcher } = ChromeUtils.importESModule( - "resource:///modules/ipprotection/IPPSignInWatcher.sys.mjs" +const { UIState } = ChromeUtils.importESModule( + "resource://services-sync/UIState.sys.mjs" ); do_get_profile(); @@ -53,7 +53,9 @@ add_task(async function test_IPProtectionStates_uninitialized() { */ add_task(async function test_IPProtectionStates_uninitialized() { let sandbox = sinon.createSandbox(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => false); + sandbox.stub(UIState, "get").returns({ + status: UIState.STATUS_STATUS_NOT_CONFIGURED, + }); sandbox .stub(IPProtectionService.guardian, "isLinkedToGuardian") .resolves(false); @@ -85,7 +87,9 @@ add_task(async function test_IPProtectionStates_uninitialized() { */ add_task(async function test_IPProtectionStates_unauthenticated() { let sandbox = sinon.createSandbox(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => true); + sandbox.stub(UIState, "get").returns({ + status: UIState.STATUS_SIGNED_IN, + }); sandbox .stub(IPProtectionService.guardian, "isLinkedToGuardian") .resolves(false); @@ -108,7 +112,9 @@ add_task(async function test_IPProtectionStates_unauthenticated() { "IP Protection service should no longer be unauthenticated" ); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => false); + UIState.get.returns({ + status: UIState.STATUS_STATUS_NOT_CONFIGURED, + }); await IPProtectionService.updateState(); @@ -127,7 +133,9 @@ add_task(async function test_IPProtectionStates_unauthenticated() { */ add_task(async function test_IPProtectionStates_enrolling() { let sandbox = sinon.createSandbox(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => true); + sandbox.stub(UIState, "get").returns({ + status: UIState.STATUS_SIGNED_IN, + }); sandbox .stub(IPProtectionService.guardian, "isLinkedToGuardian") .resolves(false); @@ -166,7 +174,9 @@ add_task(async function test_IPProtectionStates_enrolling() { */ add_task(async function test_IPProtectionStates_ready() { let sandbox = sinon.createSandbox(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => true); + sandbox.stub(UIState, "get").returns({ + status: UIState.STATUS_SIGNED_IN, + }); sandbox .stub(IPProtectionService.guardian, "isLinkedToGuardian") .resolves(true); @@ -184,7 +194,9 @@ add_task(async function test_IPProtectionStates_ready() { "IP Protection service should be ready" ); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => false); + UIState.get.returns({ + status: UIState.STATUS_STATUS_NOT_CONFIGURED, + }); await IPProtectionService.updateState(); @@ -203,7 +215,9 @@ add_task(async function test_IPProtectionStates_ready() { */ add_task(async function test_IPProtectionStates_active() { let sandbox = sinon.createSandbox(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => true); + sandbox.stub(UIState, "get").returns({ + status: UIState.STATUS_SIGNED_IN, + }); sandbox .stub(IPProtectionService.guardian, "isLinkedToGuardian") .resolves(true); @@ -254,7 +268,9 @@ add_task(async function test_IPProtectionStates_active() { */ add_task(async function test_IPProtectionStates_error() { let sandbox = sinon.createSandbox(); - sandbox.stub(IPPSignInWatcher, "isSignedIn").get(() => true); + sandbox.stub(UIState, "get").returns({ + status: UIState.STATUS_SIGNED_IN, + }); sandbox .stub(IPProtectionService.guardian, "isLinkedToGuardian") .resolves(true);