tor-browser

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

commit e93c6d84bd469982d3adc588767cbca3b449db7e
parent d731e585dcd76b8aa314fcf28f456921c27ce26e
Author: Fred Chasen <fchasen@mozilla.com>
Date:   Wed, 22 Oct 2025 16:02:25 +0000

Bug 1993605 - Prevent re-adding IP Protection toolbar when it has been removed by the user. r=ip-protection-reviewers,Gijs

Adds a `browser.ipProtection.added` pref to track when the toolbar item has been added and prevent changing the location after it has been set.

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

Diffstat:
Mbrowser/app/profile/firefox.js | 1+
Mbrowser/components/ipprotection/IPProtection.sys.mjs | 13++++++++++---
Mbrowser/components/ipprotection/tests/browser/browser_ipprotection_toolbar.js | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/ipprotection/tests/browser/head.js | 1+
4 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js @@ -3502,6 +3502,7 @@ pref("browser.ipProtection.domainExclusions", ""); pref("browser.ipProtection.domainInclusions", ""); pref("browser.ipProtection.log", false); pref("browser.ipProtection.guardian.endpoint", "https://vpn.mozilla.org/"); +pref("browser.ipProtection.added", false); // Pref to enable aboug:glean redesign. pref("about.glean.redesign.enabled", false); diff --git a/browser/components/ipprotection/IPProtection.sys.mjs b/browser/components/ipprotection/IPProtection.sys.mjs @@ -39,6 +39,7 @@ class IPProtectionWidget { static ENABLED_PREF = "browser.ipProtection.enabled"; static VARIANT_PREF = "browser.ipProtection.variant"; + static ADDED_PREF = "browser.ipProtection.added"; #inited = false; created = false; @@ -121,7 +122,7 @@ class IPProtectionWidget { const onBeforeCreated = this.#onBeforeCreated.bind(this); const onCreated = this.#onCreated.bind(this); const onDestroyed = this.#onDestroyed.bind(this); - lazy.CustomizableUI.createWidget({ + const item = { id: IPProtectionWidget.WIDGET_ID, l10nId: "ipprotection-button", type: "view", @@ -131,7 +132,8 @@ class IPProtectionWidget { onBeforeCreated, onCreated, onDestroyed, - }); + }; + lazy.CustomizableUI.createWidget(item); this.#placeWidget(); @@ -142,12 +144,16 @@ class IPProtectionWidget { * Places the widget in the nav bar, next to the FxA widget. */ #placeWidget() { + let wasAddedToToolbar = Services.prefs.getBoolPref( + IPProtectionWidget.ADDED_PREF, + false + ); let alreadyPlaced = lazy.CustomizableUI.getPlacementOfWidget( IPProtectionWidget.WIDGET_ID, false, true ); - if (alreadyPlaced) { + if (wasAddedToToolbar || alreadyPlaced) { return; } @@ -161,6 +167,7 @@ class IPProtectionWidget { lazy.CustomizableUI.AREA_NAVBAR, pos ); + Services.prefs.setBoolPref(IPProtectionWidget.ADDED_PREF, true); } /** diff --git a/browser/components/ipprotection/tests/browser/browser_ipprotection_toolbar.js b/browser/components/ipprotection/tests/browser/browser_ipprotection_toolbar.js @@ -259,3 +259,52 @@ add_task(async function toolbar_placement_customized() { start.position ); }); + +/** + * Tests that toolbar widget can be removed and will not be re-added. + */ +add_task(async function toolbar_removed() { + setupService({ + isSignedIn: true, + isEnrolled: true, + }); + + let start = CustomizableUI.getPlacementOfWidget(IPProtectionWidget.WIDGET_ID); + Assert.equal( + start.area, + CustomizableUI.AREA_NAVBAR, + "IP Protection widget is initially added to the nav bar" + ); + + // Remove from the toolbar + CustomizableUI.removeWidgetFromArea(IPProtectionWidget.WIDGET_ID); + + let end = CustomizableUI.getPlacementOfWidget(IPProtectionWidget.WIDGET_ID); + Assert.equal(end, null, "IP Protection widget is removed"); + + // Disable the feature + await cleanupExperiment(); + + const waitForStateChange = BrowserTestUtils.waitForEvent( + lazy.IPProtectionService, + "IPProtectionService:StateChanged", + false, + () => lazy.IPProtectionService.state === lazy.IPProtectionStates.READY + ); + + // Reenable the feature + await setupExperiment(); + + await waitForStateChange; + + let restored = CustomizableUI.getPlacementOfWidget( + IPProtectionWidget.WIDGET_ID + ); + Assert.equal(restored, null, "IP Protection widget is still removed"); + + CustomizableUI.addWidgetToArea( + IPProtectionWidget.WIDGET_ID, + start.area, + start.position + ); +}); diff --git a/browser/components/ipprotection/tests/browser/head.js b/browser/components/ipprotection/tests/browser/head.js @@ -265,6 +265,7 @@ add_setup(async function setupVPN() { setupSandbox.restore(); cleanupExperiment(); CustomizableUI.reset(); + Services.prefs.clearUserPref(IPProtectionWidget.ADDED_PREF); }); });