tor-browser

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

commit 6e53e5a0c186680163c48b9d64061cccaf3d5143
parent 0f4eb845cab77bf323f497af8cba3d2643c03a6b
Author: kpatenio <kpatenio@mozilla.com>
Date:   Thu,  8 Jan 2026 23:39:43 +0000

Bug 1998827 — update site exclusions control to show the correct number of excluded sites. r=ip-protection-reviewers,fluent-reviewers,mconley,bolsson,fchasen

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

Diffstat:
Mbrowser/components/preferences/main.js | 1-
Mbrowser/components/preferences/privacy.js | 34++++++++++++++++++++++++++++++++++
Mbrowser/components/preferences/tests/browser_privacy_ipprotection.js | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/locales-preview/ipProtection.ftl | 9++++++++-
4 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js @@ -2850,7 +2850,6 @@ SettingGroupManager.registerGroups({ items: [ { id: "ipProtectionExceptionAllListButton", - l10nId: "ip-protection-site-exceptions-all-sites-button", control: "moz-box-button", }, ], diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js @@ -1458,6 +1458,22 @@ Preferences.addSetting({ Preferences.addSetting({ id: "ipProtectionExceptionAllListButton", deps: ["ipProtectionVisible", "ipProtectionSiteExceptionsFeatureEnabled"], + setup(emitChange) { + let permObserver = { + observe(subject, topic, _data) { + if (subject && topic === "perm-changed") { + let permission = subject.QueryInterface(Ci.nsIPermission); + if (permission.type === "ipp-vpn") { + emitChange(); + } + } + }, + }; + Services.obs.addObserver(permObserver, "perm-changed"); + return () => { + Services.obs.removeObserver(permObserver, "perm-changed"); + }; + }, visible: ({ ipProtectionVisible, ipProtectionSiteExceptionsFeatureEnabled, @@ -1478,6 +1494,24 @@ Preferences.addSetting({ params ); }, + getControlConfig(config) { + let l10nId = "ip-protection-site-exceptions-all-sites-button"; + + let savedExceptions = Services.perms.getAllByTypes(["ipp-vpn"]); + let numberOfExclusions = savedExceptions.filter( + perm => perm.capability === Ci.nsIPermissionManager.DENY_ACTION + ).length; + + let l10nArgs = { + count: numberOfExclusions, + }; + + return { + ...config, + l10nId, + l10nArgs, + }; + }, }); Preferences.addSetting({ id: "ipProtectionAutoStartFeatureEnabled", diff --git a/browser/components/preferences/tests/browser_privacy_ipprotection.js b/browser/components/preferences/tests/browser_privacy_ipprotection.js @@ -201,6 +201,101 @@ add_task(async function test_exclusions_add_button() { ); }); +// Test that we show the correct number of site exclusions +add_task(async function test_exclusions_count() { + const PERM_NAME = "ipp-vpn"; + await setupVpnPrefs({ feature: "beta", siteExceptions: true }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:preferences#privacy" }, + async function (browser) { + let section = browser.contentDocument.getElementById(SECTION_ID); + let settingGroup = section.querySelector( + `setting-group[groupid="ipprotection"]` + ); + is_element_visible(section, "#dataIPProtectionGroup is shown"); + is_element_visible(settingGroup, "ipprotection setting group is shown"); + + let siteExceptionsGroup = settingGroup?.querySelector( + "#ipProtectionExceptions" + ); + is_element_visible(siteExceptionsGroup, "Site exceptions group is shown"); + + let exceptionAllListButton = siteExceptionsGroup?.querySelector( + "#ipProtectionExceptionAllListButton" + ); + is_element_visible( + exceptionAllListButton, + "Button for list of exclusions is shown" + ); + + let sitesCountUpdatedPromise = BrowserTestUtils.waitForMutationCondition( + exceptionAllListButton, + { attributes: true, attributeFilter: ["data-l10n-args"] }, + () => { + let args = exceptionAllListButton.getAttribute("data-l10n-args"); + return args && JSON.parse(args)?.count === 0; + } + ); + + // Clear ipp-vpn to start with 0 exclusions + Services.perms.removeByType(PERM_NAME); + + await sitesCountUpdatedPromise; + + Assert.ok(true, "Should show 0 exclusions initially"); + + // Now test with 1 exclusion + sitesCountUpdatedPromise = BrowserTestUtils.waitForMutationCondition( + exceptionAllListButton, + { attributes: true, attributeFilter: ["data-l10n-args"] }, + () => { + let args = exceptionAllListButton.getAttribute("data-l10n-args"); + return args && JSON.parse(args)?.count === 1; + } + ); + let site1 = "https://example.com"; + let principal1 = + Services.scriptSecurityManager.createContentPrincipalFromOrigin(site1); + Services.perms.addFromPrincipal( + principal1, + PERM_NAME, + Services.perms.DENY_ACTION + ); + + await sitesCountUpdatedPromise; + + Assert.ok(true, "Should show 1 exclusion after adding the first site"); + + // Now test with 2 exclusions + sitesCountUpdatedPromise = BrowserTestUtils.waitForMutationCondition( + exceptionAllListButton, + { attributes: true, attributeFilter: ["data-l10n-args"] }, + () => { + let args = exceptionAllListButton.getAttribute("data-l10n-args"); + return args && JSON.parse(args)?.count === 2; + } + ); + let site2 = "https://example.org"; + let principal2 = + Services.scriptSecurityManager.createContentPrincipalFromOrigin(site2); + Services.perms.addFromPrincipal( + principal2, + PERM_NAME, + Services.perms.DENY_ACTION + ); + + await sitesCountUpdatedPromise; + + Assert.ok(true, "Should show 2 exclusions after adding the second site"); + + // Clean up + Services.perms.removeByType(PERM_NAME); + Services.prefs.clearUserPref(ONBOARDING_MESSAGE_MASK_PREF); + } + ); +}); + // Test that autostart checkboxes exist and map to the correct preferences add_task(async function test_autostart_checkboxes() { await setupVpnPrefs({ diff --git a/browser/locales-preview/ipProtection.ftl b/browser/locales-preview/ipProtection.ftl @@ -108,9 +108,16 @@ ip-protection-learn-more = Learn more ip-protection-site-exceptions = .label = Site specific settings + +# Variables: +# $count (number) - The number of sites saved as VPN exclusions. ip-protection-site-exceptions-all-sites-button = .label = Manage website settings - .description = No websites added yet + .description = + { $count -> + [one] { $count } website + *[other] { $count } websites + } ip-protection-autostart = .label = Turn on VPN automatically