tor-browser

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

commit fc938b0812fafe9b20a0c6f56c9dc91efa63f954
parent c3a2211fbe1d24bf77a4283a2c29b96fe1feba74
Author: Rebecca King <rking@mozilla.com>
Date:   Thu, 13 Nov 2025 21:03:00 +0000

Bug 1997469 - Add opted out state to IPProtectionService - r=ip-protection-reviewers,omc-reviewers,baku,mimi

Differential Revision: https://phabricator.services.mozilla.com/D271645

Diffstat:
Mbrowser/app/profile/firefox.js | 2++
Abrowser/components/ipprotection/IPPOptOutHelper.sys.mjs | 42++++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/ipprotection/IPProtection.sys.mjs | 9+++++++++
Mbrowser/components/ipprotection/IPProtectionHelpers.sys.mjs | 2++
Mbrowser/components/ipprotection/IPProtectionService.sys.mjs | 8++++++++
Mbrowser/components/ipprotection/moz.build | 1+
Mbrowser/components/ipprotection/tests/browser/browser.toml | 2++
Abrowser/components/ipprotection/tests/browser/browser_ipprotection_optout.js | 31+++++++++++++++++++++++++++++++
Mtoolkit/components/messaging-system/lib/SpecialMessageActions.sys.mjs | 1+
9 files changed, 98 insertions(+), 0 deletions(-)

diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js @@ -3509,6 +3509,8 @@ pref("browser.contextual-services.contextId.rust-component.enabled", true); // Pref to enable the IP protection feature pref("browser.ipProtection.enabled", false); +// Pref to track whether the user has opted out of using IP Protection +pref("browser.ipProtection.optedOut", false); // Pref to enable IP protection autostart pref("browser.ipProtection.autoStartEnabled", false); pref("browser.ipProtection.autoStartPrivateEnabled", false); diff --git a/browser/components/ipprotection/IPPOptOutHelper.sys.mjs b/browser/components/ipprotection/IPPOptOutHelper.sys.mjs @@ -0,0 +1,42 @@ +/* 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/. */ + +import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + IPProtectionService: + "resource:///modules/ipprotection/IPProtectionService.sys.mjs", +}); + +const OPTED_OUT_PREF = "browser.ipProtection.optedOut"; + +/** + * This class monitors the optedOut pref and if it sees an opted-out state, it + * sets the state on IPProtectionService + */ +class IPPOptedOutHelperSingleton { + constructor() { + XPCOMUtils.defineLazyPreferenceGetter( + this, + "optedOut", + OPTED_OUT_PREF, + false, + () => { + lazy.IPProtectionService.updateState(); + } + ); + } + + init() {} + + uninit() {} + + initOnStartupCompleted() {} +} + +const IPPOptOutHelper = new IPPOptedOutHelperSingleton(); + +export { IPPOptOutHelper }; diff --git a/browser/components/ipprotection/IPProtection.sys.mjs b/browser/components/ipprotection/IPProtection.sys.mjs @@ -15,6 +15,8 @@ ChromeUtils.defineESModuleGetters(lazy, { "resource:///modules/ipprotection/IPProtectionPanel.sys.mjs", IPProtectionService: "resource:///modules/ipprotection/IPProtectionService.sys.mjs", + IPProtectionStates: + "resource:///modules/ipprotection/IPProtectionService.sys.mjs", IPPProxyManager: "resource:///modules/ipprotection/IPPProxyManager.sys.mjs", IPPProxyStates: "resource:///modules/ipprotection/IPPProxyManager.sys.mjs", requestIdleCallback: "resource://gre/modules/Timer.sys.mjs", @@ -335,6 +337,13 @@ class IPProtectionWidget { event.type == "IPProtectionService:StateChanged" || event.type == "IPPProxyManager:StateChanged" ) { + if ( + lazy.IPProtectionService.state === lazy.IPProtectionStates.OPTED_OUT + ) { + lazy.CustomizableUI.removeWidgetFromArea(IPProtectionWidget.WIDGET_ID); + return; + } + let status = { isActive: lazy.IPPProxyManager.state === lazy.IPPProxyStates.ACTIVE, isError: diff --git a/browser/components/ipprotection/IPProtectionHelpers.sys.mjs b/browser/components/ipprotection/IPProtectionHelpers.sys.mjs @@ -26,6 +26,7 @@ import { IPPNimbusHelper } from "resource:///modules/ipprotection/IPPNimbusHelpe import { IPProtectionServerlist } from "resource:///modules/ipprotection/IPProtectionServerlist.sys.mjs"; import { IPPSignInWatcher } from "resource:///modules/ipprotection/IPPSignInWatcher.sys.mjs"; import { IPPStartupCache } from "resource:///modules/ipprotection/IPPStartupCache.sys.mjs"; +import { IPPOptOutHelper } from "resource:///modules/ipprotection/IPPOptOutHelper.sys.mjs"; import { IPPVPNAddonHelper } from "resource:///modules/ipprotection/IPPVPNAddonHelper.sys.mjs"; /** @@ -86,6 +87,7 @@ const IPPHelpers = [ new UIHelper(), IPPVPNAddonHelper, ...IPPAutoStartHelpers, + IPPOptOutHelper, IPPNimbusHelper, ]; diff --git a/browser/components/ipprotection/IPProtectionService.sys.mjs b/browser/components/ipprotection/IPProtectionService.sys.mjs @@ -12,6 +12,7 @@ ChromeUtils.defineESModuleGetters(lazy, { "resource:///modules/ipprotection/IPPEnrollAndEntitleManager.sys.mjs", IPPHelpers: "resource:///modules/ipprotection/IPProtectionHelpers.sys.mjs", IPPNimbusHelper: "resource:///modules/ipprotection/IPPNimbusHelper.sys.mjs", + IPPOptOutHelper: "resource:///modules/ipprotection/IPPOptOutHelper.sys.mjs", IPPSignInWatcher: "resource:///modules/ipprotection/IPPSignInWatcher.sys.mjs", IPPStartupCache: "resource:///modules/ipprotection/IPPStartupCache.sys.mjs", IPPVPNAddonHelper: @@ -33,6 +34,8 @@ const ENABLED_PREF = "browser.ipProtection.enabled"; * The user is not eligible (via nimbus) or still not signed in. No UI is available. * @property {string} UNAUTHENTICATED * The user is signed out but eligible (via nimbus). The panel should show the login view. + * @property {string} OPTED_OUT + * The user has opted out from using VPN. The toolbar icon and panel should not be visible. * @property {string} READY * Ready to be activated. * @@ -43,6 +46,7 @@ export const IPProtectionStates = Object.freeze({ UNINITIALIZED: "uninitialized", UNAVAILABLE: "unavailable", UNAUTHENTICATED: "unauthenticated", + OPTED_OUT: "optedout", READY: "ready", }); @@ -156,6 +160,10 @@ class IPProtectionServiceSingleton extends EventTarget { return IPProtectionStates.UNINITIALIZED; } + if (lazy.IPPOptOutHelper.optedOut) { + return IPProtectionStates.OPTED_OUT; + } + // Maybe we have to use the cached state, because we are not initialized yet. if (!lazy.IPPStartupCache.isStartupCompleted) { return lazy.IPPStartupCache.state; diff --git a/browser/components/ipprotection/moz.build b/browser/components/ipprotection/moz.build @@ -17,6 +17,7 @@ EXTRA_JS_MODULES.ipprotection += [ "IPPExceptionsManager.sys.mjs", "IPPNetworkErrorObserver.sys.mjs", "IPPNimbusHelper.sys.mjs", + "IPPOptOutHelper.sys.mjs", "IPPProxyManager.sys.mjs", "IPProtection.sys.mjs", "IPProtectionHelpers.sys.mjs", diff --git a/browser/components/ipprotection/tests/browser/browser.toml b/browser/components/ipprotection/tests/browser/browser.toml @@ -30,6 +30,8 @@ prefs = [ ["browser_ipprotection_message_bar.js"] +["browser_ipprotection_optout.js"] + ["browser_ipprotection_panel.js"] ["browser_ipprotection_proxy_errors.js"] diff --git a/browser/components/ipprotection/tests/browser/browser_ipprotection_optout.js b/browser/components/ipprotection/tests/browser/browser_ipprotection_optout.js @@ -0,0 +1,31 @@ +/* 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/. */ + +"use strict"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + IPProtectionWidget: "resource:///modules/ipprotection/IPProtection.sys.mjs", +}); + +/** + * Tests that setting the optedOut pref removes the toolbar button + */ +add_task(async function test_opt_out() { + let buttonBefore = document.getElementById(lazy.IPProtectionWidget.WIDGET_ID); + + Assert.ok( + BrowserTestUtils.isVisible(buttonBefore), + "ipprotection toolbar button should be present" + ); + + Services.prefs.setBoolPref("browser.ipProtection.optedOut", true); + + let buttonAfter = document.getElementById(lazy.IPProtectionWidget.WIDGET_ID); + + Assert.ok(!buttonAfter, "ipprotection toolbar button should not be present"); + + Services.prefs.clearUserPref("browser.ipProtection.optedOut"); +}); diff --git a/toolkit/components/messaging-system/lib/SpecialMessageActions.sys.mjs b/toolkit/components/messaging-system/lib/SpecialMessageActions.sys.mjs @@ -251,6 +251,7 @@ export const SpecialMessageActions = { "browser.crashReports.unsubmittedCheck.autoSubmit2", "browser.dataFeatureRecommendations.enabled", "browser.ipProtection.enabled", + "browser.ipProtection.optedOut", "browser.migrate.content-modal.about-welcome-behavior", "browser.migrate.content-modal.import-all.enabled", "browser.migrate.preferences-entrypoint.enabled",