tor-browser

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

commit d8491f82adc36bfa37686e026f73a63a4ad47780
parent bfd944f556c8c4a200fc3a2418913f43bbed176a
Author: kpatenio <kpatenio@mozilla.com>
Date:   Thu, 11 Dec 2025 22:30:17 +0000

Bug 2004518 — remove site inclusions and exceptions mode pref use for IP Protection settings r=ip-protection-reviewers,fluent-reviewers,akulyk,bolsson,rking

This patch updates the Firefox VPN section in about:preferences to:
- manage site exclusions only
- remove radio buttons to choose between "all" and "select" protection modes
- remove site inclusions controls
- slightly edit some strings. The strings still need content approval, but I felt that it made sense to change strings mentioning "site inclusions" and "select" protection mode

Tests were also updated to no longer check for site inclusions or mode pref switching.

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

Diffstat:
Mbrowser/components/ipprotection/tests/browser/browser.toml | 2--
Dbrowser/components/ipprotection/tests/browser/browser_exceptions_dialog.js | 209-------------------------------------------------------------------------------
Mbrowser/components/preferences/dialogs/permissions.js | 20+-------------------
Mbrowser/components/preferences/main.js | 31++++++-------------------------
Mbrowser/components/preferences/privacy.js | 36++++++++----------------------------
Mbrowser/components/preferences/tests/browser.toml | 2++
Abrowser/components/preferences/tests/browser_capability_filter.js | 225+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/preferences/tests/browser_privacy_ipprotection.js | 152++++---------------------------------------------------------------------------
Mbrowser/locales-preview/ipProtection.ftl | 16++--------------
9 files changed, 250 insertions(+), 443 deletions(-)

diff --git a/browser/components/ipprotection/tests/browser/browser.toml b/browser/components/ipprotection/tests/browser/browser.toml @@ -14,8 +14,6 @@ prefs = [ ["browser_IPProtectionService.js"] -["browser_exceptions_dialog.js"] - ["browser_guardian_client.js"] ["browser_ipprotection_content.js"] diff --git a/browser/components/ipprotection/tests/browser/browser_exceptions_dialog.js b/browser/components/ipprotection/tests/browser/browser_exceptions_dialog.js @@ -1,209 +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 https://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const { IPPExceptionsManager } = ChromeUtils.importESModule( - "resource:///modules/ipprotection/IPPExceptionsManager.sys.mjs" -); - -const MODE_PREF = "browser.ipProtection.exceptionsMode"; -const ALL_MODE = "all"; -const SELECT_MODE = "select"; -const ONBOARDING_MESSAGE_MASK_PREF = - "browser.ipProtection.onboardingMessageMask"; - -const PERM_NAME = "ipp-vpn"; - -/** - * Opens the ipp-vpn permission dialog with a set capabilityFilter. - * - * @param {Browser} browser - * The current browser instance. - * @param {1 | 2} capabilityFilter - * Ci.nsIPermissionManager.DENY_ACTION or Ci.nsIPermissionManager.ALLOW_ACTION - * @returns {Window} The dialog window. - */ -async function openDialog(browser, capabilityFilter) { - let params = { - hideStatusColumn: true, - prefilledHost: "", - permissionType: PERM_NAME, - capabilityFilter, - }; - - let dialogLoaded = TestUtils.topicObserved("subdialog-loaded"); - - browser.contentWindow.gSubDialog.open( - "chrome://browser/content/preferences/dialogs/permissions.xhtml", - { features: "resizable=yes" }, - params - ); - - let [dialogWin] = await dialogLoaded; - return dialogWin; -} - -function addMockPrincipalToIPPVPN(site, capability) { - let principal = - Services.scriptSecurityManager.createContentPrincipalFromOrigin(site); - Services.perms.addFromPrincipal(principal, PERM_NAME, capability); -} - -/** - * If MODE_PREF === "all", adds 2 exclusions and 1 inclusion. - * If MODE === "select", adds 2 inclusions and 1 exclusion. - * - * Once permissions have been set up, return an array of site origins - * that we expect to be displayed in the dialog. - * Eg. If our mode is "all", we expect the 2 site origins to be displayed - * when our dialog is filtered to show exclusions only. - * - * @param {"all" | "select"} mode - * The site exceptions mode - * @returns {Array<string>} - * An array of site origins that we expect to be displayed in the dialog - * - * @see MODE_PREF - */ -function setupTestExceptions(mode) { - const site1 = "https://www.example.com"; - const site2 = "https://www.another.example.com"; - const site3 = "https://www.shouldbeignored.example.org"; - - let expectedCapability; - let unexpectedCapability; - - if (mode === ALL_MODE) { - expectedCapability = Ci.nsIPermissionManager.DENY_ACTION; - unexpectedCapability = Ci.nsIPermissionManager.ALLOW_ACTION; - } else { - expectedCapability = Ci.nsIPermissionManager.ALLOW_ACTION; - unexpectedCapability = Ci.nsIPermissionManager.DENY_ACTION; - } - - // Let's add 2 exclusions if mode === "all", OR 2 inclusions if mode === "select" - addMockPrincipalToIPPVPN(site1, expectedCapability); - addMockPrincipalToIPPVPN(site2, expectedCapability); - - // And let's add 1 inclusion if mode === "all", OR 2 exceptions if mode === "select" - addMockPrincipalToIPPVPN(site3, unexpectedCapability); - - // Before we test our dialog, let's double check that exceptions were loaded correctly. - let expectedExceptions = Services.perms - .getAllByTypes([PERM_NAME]) - .filter(perm => perm.capability === expectedCapability); - let unexpectedExceptions = Services.perms - .getAllByTypes([PERM_NAME]) - .filter(perm => perm.capability === unexpectedCapability); - - let expectedTypeName = mode === ALL_MODE ? "exclusions" : "inclusions"; - let unexpectedTypeName = mode === ALL_MODE ? "inclusion" : "exclusion"; - - Assert.equal( - expectedExceptions.length, - 2, - `There should be 2 ${expectedTypeName}` - ); - Assert.equal( - unexpectedExceptions.length, - 1, - `There should be 1 ${unexpectedTypeName}` - ); - - return expectedExceptions.map(permission => permission.principal.prePath); -} - -/** - * Opens the permissions dialog for ipp-vpn permissions with a capabilityFilter. - * If our filter is set to DENY, then tests that only site exclusions / principals - * with DENY capability are listed. - * If our filter is set to ALLOW, then tests that only site inclusions / principals - * with ALLOW capability are listed. - * - * @param {Array<string>} expectedSites - * An array of site origins that we expect to be displayed in the dialog. - * @param {1 | 2} capabilityFilter - * Ci.nsIPermissionManager.DENY_ACTION or Ci.nsIPermissionManager.ALLOW_ACTION - */ -async function testExceptionsInDialog(expectedSites, capabilityFilter) { - await BrowserTestUtils.withNewTab("about:preferences", async browser => { - let dialog = await openDialog(browser, capabilityFilter); - Assert.ok(dialog, "Dialog was found"); - - let permissionsBox = dialog.document.getElementById("permissionsBox"); - - // Wait for all exceptions to load - await BrowserTestUtils.waitForMutationCondition( - permissionsBox, - { childList: true, subtree: true }, - () => { - return permissionsBox.itemCount === 2; - } - ); - - let numberOfExceptions = permissionsBox.itemCount; - Assert.equal( - numberOfExceptions, - 2, - "There should be 2 inclusions in the dialog" - ); - - let displayedSites = Array.from(permissionsBox.children).map(entry => - entry.getAttribute("origin") - ); - Assert.ok( - displayedSites.includes(expectedSites[0]), - `${expectedSites[0]} was displayed in the dialog as an exception` - ); - Assert.ok( - displayedSites.includes(expectedSites[1]), - `${expectedSites[1]} was displayed in the dialog as an exception` - ); - }); -} - -function cleanupExceptions() { - Services.perms.removeByType(PERM_NAME); -} - -/** - * Tests that we can filter the permissions dialog to only show - * exclusions. - */ -add_task(async function test_filter_dialog_exclusions_only() { - await SpecialPowers.pushPrefEnv({ - set: [[MODE_PREF, ALL_MODE]], - }); - - let exclusions = setupTestExceptions(ALL_MODE); - - const capabilityFilter = Ci.nsIPermissionManager.DENY_ACTION; - - await testExceptionsInDialog(exclusions, capabilityFilter); - - cleanupExceptions(); - await SpecialPowers.popPrefEnv(); - Services.prefs.clearUserPref(ONBOARDING_MESSAGE_MASK_PREF); -}); - -/** - * Tests that we can filter the permissions dialog to only show - * inclusions. - */ -add_task(async function test_filter_dialog_inclusions_only() { - await SpecialPowers.pushPrefEnv({ - set: [[MODE_PREF, SELECT_MODE]], - }); - - let inclusions = setupTestExceptions(SELECT_MODE); - - const capabilityFilter = Ci.nsIPermissionManager.ALLOW_ACTION; - - await testExceptionsInDialog(inclusions, capabilityFilter); - - cleanupExceptions(); - await SpecialPowers.popPrefEnv(); - Services.prefs.clearUserPref(ONBOARDING_MESSAGE_MASK_PREF); -}); diff --git a/browser/components/preferences/dialogs/permissions.js b/browser/components/preferences/dialogs/permissions.js @@ -111,25 +111,7 @@ var gPermissionManager = { let permissionsText = document.getElementById("permissionsText"); - let l10n; - - // For ipp-vpn, we want to override strings based on capability. - // Valid capabilities for this permission are ALLOW and DENY. - if (this._type === "ipp-vpn") { - if (params.capabilityFilter === Ci.nsIPermissionManager.ALLOW_ACTION) { - l10n = { - window: "ip-protection-exceptions-dialog-window", - description: "ip-protection-inclusions-desc", - }; - } else { - l10n = { - window: "ip-protection-exceptions-dialog-window", - description: "ip-protection-exclusions-desc", - }; - } - } else { - l10n = permissionExceptionsL10n[this._type]; - } + let l10n = permissionExceptionsL10n[this._type]; document.l10n.setAttributes(permissionsText, l10n.description); document.l10n.setAttributes(document.documentElement, l10n.window); diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js @@ -2319,36 +2319,17 @@ SettingGroupManager.registerGroups({ supportPage: "ip-protection", items: [ { - id: "ipProtectionExceptionsMode", + id: "ipProtectionExceptions", l10nId: "ip-protection-site-exceptions", - control: "moz-radio-group", + control: "moz-fieldset", controlAttrs: { ".headingLevel": 3, }, - options: [ - { - id: "ipProtectionExceptionRadioAll", - value: "all", - l10nId: "ip-protection-site-exceptions-all-sites-radio", - items: [ - { - id: "ipProtectionExceptionAllListButton", - l10nId: "ip-protection-site-exceptions-all-sites-button", - control: "moz-box-button", - }, - ], - }, + items: [ { - id: "ipProtectionExceptionRadioSelect", - value: "select", - l10nId: "ip-protection-site-exceptions-select-sites-radio", - items: [ - { - id: "ipProtectionExceptionSelectListButton", - l10nId: "ip-protection-site-exceptions-select-sites-button", - control: "moz-box-button", - }, - ], + 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 @@ -202,7 +202,6 @@ Preferences.addAll([ // Firefox VPN { id: "browser.ipProtection.variant", type: "string" }, { id: "browser.ipProtection.features.siteExceptions", type: "bool" }, - { id: "browser.ipProtection.exceptionsMode", type: "string" }, { id: "browser.ipProtection.features.autoStart", type: "bool" }, { id: "browser.ipProtection.autoStartEnabled", type: "bool" }, { id: "browser.ipProtection.autoStartPrivateEnabled", type: "bool" }, @@ -1419,10 +1418,8 @@ Preferences.addSetting({ id: "ipProtectionSiteExceptionsFeatureEnabled", pref: "browser.ipProtection.features.siteExceptions", }); -// This setting also affects the radio group for site exceptions Preferences.addSetting({ - id: "ipProtectionExceptionsMode", - pref: "browser.ipProtection.exceptionsMode", + id: "ipProtectionExceptions", deps: ["ipProtectionVisible", "ipProtectionSiteExceptionsFeatureEnabled"], visible: ({ ipProtectionVisible, @@ -1430,11 +1427,15 @@ Preferences.addSetting({ }) => ipProtectionVisible.value && ipProtectionSiteExceptionsFeatureEnabled.value, }); + Preferences.addSetting({ id: "ipProtectionExceptionAllListButton", - deps: ["ipProtectionVisible", "ipProtectionExceptionsMode"], - visible: ({ ipProtectionVisible, ipProtectionExceptionsMode }) => - ipProtectionVisible.value && ipProtectionExceptionsMode.value == "all", + deps: ["ipProtectionVisible", "ipProtectionSiteExceptionsFeatureEnabled"], + visible: ({ + ipProtectionVisible, + ipProtectionSiteExceptionsFeatureEnabled, + }) => + ipProtectionVisible.value && ipProtectionSiteExceptionsFeatureEnabled.value, onUserClick() { let params = { blockVisible: true, @@ -1452,27 +1453,6 @@ Preferences.addSetting({ }, }); Preferences.addSetting({ - id: "ipProtectionExceptionSelectListButton", - deps: ["ipProtectionVisible", "ipProtectionExceptionsMode"], - visible: ({ ipProtectionVisible, ipProtectionExceptionsMode }) => - ipProtectionVisible.value && ipProtectionExceptionsMode.value == "select", - onUserClick() { - let params = { - allowVisible: true, - hideStatusColumn: true, - prefilledHost: "", - permissionType: "ipp-vpn", - capabilityFilter: Ci.nsIPermissionManager.ALLOW_ACTION, - }; - - gSubDialog.open( - "chrome://browser/content/preferences/dialogs/permissions.xhtml", - { features: "resizable=yes" }, - params - ); - }, -}); -Preferences.addSetting({ id: "ipProtectionAutoStartFeatureEnabled", pref: "browser.ipProtection.features.autoStart", get: prefVal => prefVal, diff --git a/browser/components/preferences/tests/browser.toml b/browser/components/preferences/tests/browser.toml @@ -53,6 +53,8 @@ support-files = ["browser_bug1184989_prevent_scrolling_when_preferences_flipped. ["browser_bug1579418.js"] +["browser_capability_filter.js"] + ["browser_cert_export.js"] ["browser_change_app_handler.js"] diff --git a/browser/components/preferences/tests/browser_capability_filter.js b/browser/components/preferences/tests/browser_capability_filter.js @@ -0,0 +1,225 @@ +/* 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 https://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const ONBOARDING_MESSAGE_MASK_PREF = + "browser.ipProtection.onboardingMessageMask"; + +/** + * Opens the dialog for a specified permission type with a set capabilityFilter. + * + * @param {Browser} browser + * The current browser instance. + * @param {1 | 2} capabilityFilter + * 1 for Ci.nsIPermissionManager.ALLOW_ACTION or 2 for Ci.nsIPermissionManager.DENY_ACTION. + * @returns {Window} The dialog window. + */ +async function openDialogWithFilter(permissionType, browser, capabilityFilter) { + let params = { + hideStatusColumn: true, + prefilledHost: "", + permissionType, + capabilityFilter, + }; + + let dialogLoaded = TestUtils.topicObserved("subdialog-loaded"); + + browser.contentWindow.gSubDialog.open( + "chrome://browser/content/preferences/dialogs/permissions.xhtml", + { features: "resizable=yes" }, + params + ); + + let [dialogWin] = await dialogLoaded; + return dialogWin; +} + +function addMockPrincipal(permissionType, site, capability) { + let principal = + Services.scriptSecurityManager.createContentPrincipalFromOrigin(site); + Services.perms.addFromPrincipal(principal, permissionType, capability); +} + +/** + * Returns an array of 2 sites origins that match the specified permission capability + * action and 1 site origin that does not match the capability action. + * + * @param {string} permissionType + * The name of the permission type. + * @param {1 | 2} capabilityToFilter + * 1 for Ci.nsIPermissionManager.ALLOW_ACTION or 2 for Ci.nsIPermissionManager.DENY_ACTION. + * @returns {Array<string>} + * An array of site origins. + * + * @see MODE_PREF + */ +function getMockSiteOrigins(permissionType, capabilityToFilter) { + const site1 = "https://www.example.com"; + const site2 = "https://www.another.example.com"; + const site3 = "https://www.shouldbeignored.example.org"; + + const DENY_ACTION = Ci.nsIPermissionManager.DENY_ACTION; + const ALLOW_ACTION = Ci.nsIPermissionManager.ALLOW_ACTION; + + let expectedCapability; + let unexpectedCapability; + + if (capabilityToFilter === DENY_ACTION) { + expectedCapability = DENY_ACTION; + unexpectedCapability = ALLOW_ACTION; + } else { + expectedCapability = ALLOW_ACTION; + unexpectedCapability = DENY_ACTION; + } + + // Let's add 2 permissions of the specified capability + addMockPrincipal(permissionType, site1, expectedCapability); + addMockPrincipal(permissionType, site2, expectedCapability); + + // And let's add 1 permission opposite of the specified capability. + // Eg. if capabilityFilter is ALLOW_ACTION, then the 1 opposite permission has DENY_ACTION. + addMockPrincipal(permissionType, site3, unexpectedCapability); + + // Before we test our dialog, let's double check that permissions were loaded correctly. + let expectedSites = Services.perms + .getAllByTypes([permissionType]) + .filter(perm => perm.capability === expectedCapability); + let unexpectedSites = Services.perms + .getAllByTypes([permissionType]) + .filter(perm => perm.capability === unexpectedCapability); + + let expectedTypeName = + capabilityToFilter === ALLOW_ACTION ? "ALLOW_ACTION" : "DENY_ACTION"; + let unexpectedTypeName = + capabilityToFilter === ALLOW_ACTION ? "DENY_ACTION" : "ALLOW_ACTION"; + + Assert.equal( + expectedSites.length, + 2, + `There should be 2 permissions with ${expectedTypeName}` + ); + Assert.equal( + unexpectedSites.length, + 1, + `There should be 1 permission with ${unexpectedTypeName}` + ); + + let sites = [ + expectedSites.map(permission => permission.principal.prePath), + unexpectedSites.map(permission => permission.principal.prePath), + ].flat(); + + return sites; +} + +/** + * Opens the permissions dialog with a capabilityFilter and checks that only sites with + * the specified capability action are displayed. + * + * @param {Array<string>} sitesArray + * An array of site origins. + * @param {1 | 2} capabilityFilter + * 1 for Ci.nsIPermissionManager.ALLOW_ACTION or 2 for Ci.nsIPermissionManager.DENY_ACTION. + */ +async function testFilteredPermissionsInDialog( + permissionType, + sitesArray, + capabilityFilter +) { + await BrowserTestUtils.withNewTab("about:preferences", async browser => { + let dialog = await openDialogWithFilter( + permissionType, + browser, + capabilityFilter + ); + Assert.ok(dialog, "Dialog was found"); + + let permissionsBox = dialog.document.getElementById("permissionsBox"); + + // Wait for all permissions to load + await BrowserTestUtils.waitForMutationCondition( + permissionsBox, + { childList: true, subtree: true }, + () => { + return permissionsBox.itemCount === 2; + } + ); + + let numberOfPermissions = permissionsBox.itemCount; + Assert.equal( + numberOfPermissions, + 2, + "There should be 2 permissions in the dialog" + ); + + let displayedSites = Array.from(permissionsBox.children).map(entry => + entry.getAttribute("origin") + ); + Assert.ok( + displayedSites.includes(sitesArray[0]), + `${sitesArray[0]} was displayed in the dialog` + ); + Assert.ok( + displayedSites.includes(sitesArray[1]), + `${sitesArray[1]} was displayed in the dialog` + ); + Assert.ok( + !displayedSites.includes(sitesArray[2]), + `${sitesArray[2]} was not displayed in the dialog` + ); + }); +} + +function cleanupPermissions(permissionType) { + Services.perms.removeByType(permissionType); +} + +/** + * Tests that we can filter the permissions dialog to only show + * permissions with DENY_ACTION capability. + */ +add_task(async function test_filter_dialog_DENY_ACTION_only() { + // capabilityFilter isn't exclusive to any permission type. + // Let's use ipp-vpn as an example to test the filter. + const permissionType = "ipp-vpn"; + const capabilityFilter = Ci.nsIPermissionManager.DENY_ACTION; + + let sites = getMockSiteOrigins(permissionType, capabilityFilter); + + await testFilteredPermissionsInDialog( + permissionType, + sites, + capabilityFilter + ); + + cleanupPermissions(permissionType); + // Since we're using ipp-vpn for this test, clear any prefs related to the permission. + // We can remove this line if we change the permission type. + Services.prefs.clearUserPref(ONBOARDING_MESSAGE_MASK_PREF); +}); + +/** + * Tests that we can filter the permissions dialog to only show + * permissions with ALLOW_ACTION capability. + */ +add_task(async function test_filter_dialog_ALLOW_ACTION_only() { + // capabilityFilter isn't exclusive to any permission type. + // Let's use ipp-vpn as an example to test the filter. + const permissionType = "ipp-vpn"; + const capabilityFilter = Ci.nsIPermissionManager.ALLOW_ACTION; + + let sites = getMockSiteOrigins(permissionType, capabilityFilter); + + await testFilteredPermissionsInDialog( + permissionType, + sites, + capabilityFilter + ); + + cleanupPermissions(permissionType); + // Since we're using ipp-vpn for this test, clear any prefs related to the permission. + // We can remove this line if we change the permission type. + Services.prefs.clearUserPref(ONBOARDING_MESSAGE_MASK_PREF); +}); diff --git a/browser/components/preferences/tests/browser_privacy_ipprotection.js b/browser/components/preferences/tests/browser_privacy_ipprotection.js @@ -8,7 +8,6 @@ const FEATURE_PREF = "browser.ipProtection.variant"; const SITE_EXCEPTIONS_FEATURE_PREF = "browser.ipProtection.features.siteExceptions"; -const MODE_PREF = "browser.ipProtection.exceptionsMode"; const AUTOSTART_FEATURE_ENABLED_PREF = "browser.ipProtection.features.autoStart"; const AUTOSTART_PREF = "browser.ipProtection.autoStartEnabled"; @@ -19,7 +18,6 @@ const SECTION_ID = "dataIPProtectionGroup"; async function setupVpnPrefs({ feature, siteExceptions = false, - mode = "all", autostartFeatureEnabled = false, autostart = false, autostartprivate = false, @@ -28,7 +26,6 @@ async function setupVpnPrefs({ set: [ [FEATURE_PREF, feature], [SITE_EXCEPTIONS_FEATURE_PREF, siteExceptions], - [MODE_PREF, mode], [AUTOSTART_FEATURE_ENABLED_PREF, autostartFeatureEnabled], [AUTOSTART_PREF, autostart], [AUTOSTART_PRIVATE_PREF, autostartprivate], @@ -68,8 +65,8 @@ add_task( } ); -// Test the site exceptions controls load correctly with mode set to "all" -add_task(async function test_exceptions_load_with_all_mode() { +// Test the site exceptions controls load correctly. +add_task(async function test_exceptions_settings() { await setupVpnPrefs({ feature: "beta", siteExceptions: true }); await BrowserTestUtils.withNewTab( @@ -82,155 +79,18 @@ add_task(async function test_exceptions_load_with_all_mode() { is_element_visible(section, "#dataIPProtectionGroup is shown"); is_element_visible(settingGroup, "ipprotection setting group is shown"); - let siteExceptionsRadioGroup = settingGroup?.querySelector( - "#ipProtectionExceptionsMode" - ); - is_element_visible( - siteExceptionsRadioGroup, - "Site exceptions radio group is shown" - ); - - let exceptionAllRadioButton = siteExceptionsRadioGroup?.querySelector( - "#ipProtectionExceptionRadioAll" - ); - let exceptionSelectRadioButton = siteExceptionsRadioGroup?.querySelector( - "#ipProtectionExceptionRadioSelect" - ); - Assert.ok( - exceptionAllRadioButton?.checked, - "The 'all' radio button should be checked" - ); - Assert.ok( - !exceptionSelectRadioButton?.checked, - "The 'select' radio button should not be checked" + let siteExceptionsGroup = settingGroup?.querySelector( + "#ipProtectionExceptions" ); + is_element_visible(siteExceptionsGroup, "Site exceptions group is shown"); - let exceptionAllListButton = siteExceptionsRadioGroup?.querySelector( + let exceptionAllListButton = siteExceptionsGroup?.querySelector( "#ipProtectionExceptionAllListButton" ); - let exceptionSelectListButton = siteExceptionsRadioGroup?.querySelector( - "#ipProtectionExceptionSelectListButton" - ); is_element_visible( exceptionAllListButton, "Button for list of exclusions is shown" ); - is_element_hidden( - exceptionSelectListButton, - "Button for list of inclusions is hidden" - ); - } - ); -}); - -// Test the site exceptions controls load correctly with mode set to "select" -add_task(async function test_exceptions_with_select_mode() { - await setupVpnPrefs({ - feature: "beta", - siteExceptions: true, - mode: "select", - }); - - 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 siteExceptionsRadioGroup = settingGroup?.querySelector( - "#ipProtectionExceptionsMode" - ); - is_element_visible( - siteExceptionsRadioGroup, - "Site exceptions radio group is shown" - ); - - let exceptionAllRadioButton = siteExceptionsRadioGroup?.querySelector( - "#ipProtectionExceptionRadioAll" - ); - let exceptionSelectRadioButton = siteExceptionsRadioGroup?.querySelector( - "#ipProtectionExceptionRadioSelect" - ); - Assert.ok( - !exceptionAllRadioButton?.checked, - "The 'all' radio button should not be checked" - ); - Assert.ok( - exceptionSelectRadioButton?.checked, - "The 'select' radio button should be checked" - ); - - let exceptionAllListButton = siteExceptionsRadioGroup?.querySelector( - "#ipProtectionExceptionAllListButton" - ); - let exceptionSelectListButton = siteExceptionsRadioGroup?.querySelector( - "#ipProtectionExceptionSelectListButton" - ); - is_element_hidden( - exceptionAllListButton, - "Button for list of exclusions is hidden" - ); - is_element_visible( - exceptionSelectListButton, - "Button for list of inclusions is shown" - ); - } - ); -}); - -// Test the site exceptions controls and pref update correctly after selecting another mode option. -add_task(async function test_exceptions_change_mode_and_buttons() { - 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 siteExceptionsRadioGroup = settingGroup?.querySelector( - "#ipProtectionExceptionsMode" - ); - is_element_visible( - siteExceptionsRadioGroup, - "Site exceptions radio group is shown" - ); - - let exceptionAllRadioButton = siteExceptionsRadioGroup?.querySelector( - "#ipProtectionExceptionRadioAll" - ); - let exceptionSelectRadioButton = siteExceptionsRadioGroup?.querySelector( - "#ipProtectionExceptionRadioSelect" - ); - - // Change mode by clicking "select" button - exceptionSelectRadioButton.click(); - - Assert.ok( - !exceptionAllRadioButton?.checked, - "The 'all' radio button should not be checked" - ); - Assert.ok( - exceptionSelectRadioButton?.checked, - "The 'select' radio button should be checked" - ); - - let mode = Services.prefs.getStringPref(MODE_PREF); - Assert.equal( - mode, - "select", - `Mode should now be "select" instead of "all"` - ); - - Services.prefs.clearUserPref(MODE_PREF); } ); }); diff --git a/browser/locales-preview/ipProtection.ftl b/browser/locales-preview/ipProtection.ftl @@ -102,12 +102,9 @@ ip-protection-description = ip-protection-learn-more = Learn more ip-protection-site-exceptions = - .label = Where to use VPN - .description = Use VPN for all websites except ones you choose, or for select specific ones. -ip-protection-site-exceptions-all-sites-radio = - .label = All websites (default) + .label = Site specific settings ip-protection-site-exceptions-all-sites-button = - .label = { -firefox-vpn-brand-name } is off for these websites + .label = Manage website settings .description = No websites added yet ip-protection-autostart = @@ -122,20 +119,11 @@ ip-protection-contact-support-link = ip-protection-upgrade-link = .label = Upgrade to { -mozilla-vpn-brand-name } -# "Select" is an adjective here to describe a setting that allows running the VPN on certain sites only. -# Not to be confused with the action of selecting a site, which is not at all applicable to this setting. -ip-protection-site-exceptions-select-sites-radio = - .label = Select websites -ip-protection-site-exceptions-select-sites-button = - .label = { -firefox-vpn-brand-name } is on for these websites - .description = No websites added yet - ## IP Protection dialogs ip-protection-exceptions-dialog-window = .title = Where to use { -firefox-vpn-brand-name } ip-protection-exclusions-desc = Use VPN for all websites except ones on this list. Add websites to this list by turning { -firefox-vpn-brand-name } on or off for any site in the VPN panel. -ip-protection-inclusions-desc = Use VPN only for select websites. Add websites to this list by turning { -firefox-vpn-brand-name } on or off for any site in the VPN panel. ipprotection-site-settings-title = .title = VPN site settings