tor-browser

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

commit 41f13be6d202fe196fe99846ece781c917c1f0a0
parent 89f3915515e59b0e38a040e983fdf95e8c4f8e22
Author: Emma Zuehlcke <emz@mozilla.com>
Date:   Mon, 22 Dec 2025 10:51:42 +0000

Bug 2003471 - Split up browser_etp_customize to avoid timeouts. r=hjones

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

Diffstat:
Mbrowser/components/preferences/tests/browser.toml | 4+++-
Mbrowser/components/preferences/tests/browser_etp_advanced.js | 75++-------------------------------------------------------------------------
Dbrowser/components/preferences/tests/browser_etp_customize.js | 388-------------------------------------------------------------------------------
Abrowser/components/preferences/tests/browser_etp_customize_1.js | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abrowser/components/preferences/tests/browser_etp_customize_2.js | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/preferences/tests/head.js | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 421 insertions(+), 462 deletions(-)

diff --git a/browser/components/preferences/tests/browser.toml b/browser/components/preferences/tests/browser.toml @@ -111,7 +111,9 @@ skip-if = [ ["browser_etp_advanced.js"] -["browser_etp_customize.js"] +["browser_etp_customize_1.js"] + +["browser_etp_customize_2.js"] ["browser_etp_exceptions_dialog.js"] diff --git a/browser/components/preferences/tests/browser_etp_advanced.js b/browser/components/preferences/tests/browser_etp_advanced.js @@ -12,83 +12,12 @@ const CONVENIENCE_PREF = const PERMISSIONS_DIALOG_URL = "chrome://browser/content/preferences/dialogs/permissions.xhtml"; -function getControl(doc, id) { - let control = doc.getElementById(id); - ok(control, `Control ${id} exists`); - return control; -} - -function synthesizeClick(el) { - let target = el.buttonEl ?? el.inputEl ?? el; - target.scrollIntoView({ block: "center" }); - EventUtils.synthesizeMouseAtCenter(target, {}, target.ownerGlobal); -} - -function getControlWrapper(doc, id) { - return getControl(doc, id).closest("setting-control"); -} - -async function clickBaselineCheckboxWithConfirm( - doc, - controlId, - prefName, - expectedValue, - buttonNumClick -) { - let checkbox = getControl(doc, controlId); - - let promptPromise = PromptTestUtils.handleNextPrompt( - gBrowser.selectedBrowser, - { modalType: Services.prompt.MODAL_TYPE_CONTENT }, - { buttonNumClick } - ); - - let prefChangePromise = null; - if (buttonNumClick === 1) { - prefChangePromise = waitForAndAssertPrefState( - prefName, - expectedValue, - `${prefName} updated` - ); - } - - synthesizeClick(checkbox); - - await promptPromise; - - if (prefChangePromise) { - await prefChangePromise; - } - - is( - checkbox.checked, - expectedValue, - `Checkbox ${controlId} should be ${expectedValue}` - ); - - return checkbox; -} - add_setup(async function () { await SpecialPowers.pushPrefEnv({ set: [["browser.settings-redesign.enabled", true]], }); }); -async function openEtpPage() { - await openPreferencesViaOpenPreferencesAPI("etp", { leaveOpen: true }); - let doc = gBrowser.contentDocument; - await BrowserTestUtils.waitForCondition( - () => doc.getElementById("contentBlockingCategoryRadioGroup"), - "Wait for the ETP advanced radio group to render" - ); - return { - win: gBrowser.contentWindow, - doc, - tab: gBrowser.selectedTab, - }; -} - // Verifies category radios reflect pref changes and the customize entry point navigates correctly. add_task(async function test_etp_category_radios_and_customize_navigation() { await SpecialPowers.pushPrefEnv({ @@ -198,7 +127,7 @@ add_task(async function test_strict_baseline_checkbox_requires_confirmation() { ok(baselineCheckbox.checked, "Baseline checkbox starts checked"); info("Cancel the confirmation dialog and ensure checkbox stays checked"); - await clickBaselineCheckboxWithConfirm( + await clickEtpBaselineCheckboxWithConfirm( doc, "etpAllowListBaselineEnabled", BASELINE_PREF, @@ -211,7 +140,7 @@ add_task(async function test_strict_baseline_checkbox_requires_confirmation() { ); info("Confirm the dialog to disable the baseline allow list"); - await clickBaselineCheckboxWithConfirm( + await clickEtpBaselineCheckboxWithConfirm( doc, "etpAllowListBaselineEnabled", BASELINE_PREF, diff --git a/browser/components/preferences/tests/browser_etp_customize.js b/browser/components/preferences/tests/browser_etp_customize.js @@ -1,388 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -const CAT_PREF = "browser.contentblocking.category"; -const BASELINE_PREF = "privacy.trackingprotection.allow_list.baseline.enabled"; -const CONVENIENCE_PREF = - "privacy.trackingprotection.allow_list.convenience.enabled"; -const COOKIE_BEHAVIOR_PREF = "network.cookie.cookieBehavior"; -const TP_PREF = "privacy.trackingprotection.enabled"; -const TP_PBM_PREF = "privacy.trackingprotection.pbmode.enabled"; -const CRYPTOMINING_PREF = "privacy.trackingprotection.cryptomining.enabled"; -const FINGERPRINTING_PREF = "privacy.trackingprotection.fingerprinting.enabled"; -const SUSPECT_FP_PREF = "privacy.fingerprintingProtection"; -const SUSPECT_FP_PBM_PREF = "privacy.fingerprintingProtection.pbmode"; - -add_setup(async function () { - await SpecialPowers.pushPrefEnv({ - set: [["browser.settings-redesign.enabled", true]], - }); -}); - -function getControl(doc, id) { - let control = doc.getElementById(id); - ok(control, `Control ${id} exists`); - return control; -} - -function synthesizeClick(el) { - let target = el.buttonEl ?? el.inputEl ?? el; - target.scrollIntoView({ block: "center" }); - EventUtils.synthesizeMouseAtCenter(target, {}, target.ownerGlobal); -} - -async function openEtpCustomizePage() { - await openPreferencesViaOpenPreferencesAPI("etpCustomize", { - leaveOpen: true, - }); - let doc = gBrowser.contentDocument; - await BrowserTestUtils.waitForCondition( - () => doc.getElementById("etpAllowListBaselineEnabledCustom"), - "Wait for the ETP customize controls to render" - ); - return { - win: gBrowser.contentWindow, - doc, - }; -} - -async function changeMozSelectValue(selectEl, value) { - let control = selectEl.control; - let changePromise = waitForSettingControlChange(control); - selectEl.value = value; - selectEl.dispatchEvent(new Event("change", { bubbles: true })); - await changePromise; -} - -async function clickBaselineCheckboxWithConfirm( - doc, - controlId, - prefName, - expectedValue, - buttonNumClick -) { - let checkbox = getControl(doc, controlId); - - let promptPromise = PromptTestUtils.handleNextPrompt( - gBrowser.selectedBrowser, - { modalType: Services.prompt.MODAL_TYPE_CONTENT }, - { buttonNumClick } - ); - - let prefChangePromise = null; - if (buttonNumClick === 1) { - prefChangePromise = waitForAndAssertPrefState( - prefName, - expectedValue, - `${prefName} updated` - ); - } - - synthesizeClick(checkbox); - - await promptPromise; - if (prefChangePromise) { - await prefChangePromise; - } - - is( - checkbox.checked, - expectedValue, - `Checkbox ${controlId} should be ${expectedValue}` - ); - - return checkbox; -} - -// Confirms reset buttons drive the category pref and enable/disable appropriately. -add_task(async function test_etp_reset_buttons_update_category() { - await SpecialPowers.pushPrefEnv({ - set: [[CAT_PREF, "standard"]], - }); - - let { doc } = await openEtpCustomizePage(); - let standardButton = getControl(doc, "etpResetStandardButton"); - let strictButton = getControl(doc, "etpResetStrictButton"); - - ok(standardButton.disabled, "Standard reset button disabled on standard"); - ok(!strictButton.disabled, "Strict reset button enabled"); - - let prefChange = waitForAndAssertPrefState( - CAT_PREF, - "strict", - "ETP category pref switched to strict" - ); - synthesizeClick(strictButton); - await prefChange; - - ok(strictButton.disabled, "Strict reset button disabled after use"); - ok( - !standardButton.disabled, - "Standard reset button enabled after switching to strict" - ); - - prefChange = waitForAndAssertPrefState( - CAT_PREF, - "standard", - "ETP category pref switched back to standard" - ); - synthesizeClick(standardButton); - await prefChange; - - gBrowser.removeCurrentTab(); -}); - -// Mirrors legacy allow list checkbox behavior and confirmation prompts in the custom pane. -add_task(async function test_custom_allow_list_controls_match_old_behavior() { - await SpecialPowers.pushPrefEnv({ - set: [ - [CAT_PREF, "custom"], - [BASELINE_PREF, true], - [CONVENIENCE_PREF, true], - ], - }); - - let { doc } = await openEtpCustomizePage(); - let baselineCheckbox = getControl(doc, "etpAllowListBaselineEnabledCustom"); - let convenienceCheckbox = getControl( - doc, - "etpAllowListConvenienceEnabledCustom" - ); - - ok(baselineCheckbox.checked, "Custom baseline checkbox starts checked"); - - await clickBaselineCheckboxWithConfirm( - doc, - "etpAllowListBaselineEnabledCustom", - BASELINE_PREF, - false, - 1 - ); - - ok( - !Services.prefs.getBoolPref(BASELINE_PREF), - "Baseline pref disabled from custom controls" - ); - ok( - convenienceCheckbox.parentDisabled, - "Custom convenience checkbox disabled when baseline unchecked" - ); - - let baselinePrefChange = waitForAndAssertPrefState( - BASELINE_PREF, - true, - "Baseline pref restored" - ); - synthesizeClick(baselineCheckbox); - await baselinePrefChange; - await BrowserTestUtils.waitForCondition( - () => !convenienceCheckbox.parentDisabled, - "Custom convenience checkbox enabled once baseline rechecked" - ); - - gBrowser.removeCurrentTab(); -}); - -// Validates the cookie toggle/select wiring for custom mode. -add_task(async function test_custom_cookie_controls() { - let defaults = Services.prefs.getDefaultBranch(""); - let defaultCookieBehavior = defaults.getIntPref(COOKIE_BEHAVIOR_PREF); - - await SpecialPowers.pushPrefEnv({ - set: [ - [CAT_PREF, "custom"], - [COOKIE_BEHAVIOR_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT], - ], - }); - - let { doc } = await openEtpCustomizePage(); - let cookieToggle = getControl(doc, "etpCustomCookiesEnabled"); - let cookieSelect = getControl(doc, "cookieBehavior"); - - ok( - !cookieToggle.pressed, - "Cookie toggle starts disabled when behavior is accept" - ); - - let prefChange = waitForAndAssertPrefState( - COOKIE_BEHAVIOR_PREF, - defaultCookieBehavior, - "Enabling cookie toggle restores default behavior" - ); - synthesizeClick(cookieToggle.buttonEl); - await prefChange; - - ok(cookieToggle.pressed, "Cookie toggle is pressed when enabled"); - - info("Select a stricter cookie behavior through the dropdown"); - let newBehavior = Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN.toString(); - await changeMozSelectValue(cookieSelect, newBehavior); - is( - Services.prefs.getIntPref(COOKIE_BEHAVIOR_PREF), - Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN, - "Cookie behavior pref updated from moz-select" - ); - - prefChange = waitForAndAssertPrefState( - COOKIE_BEHAVIOR_PREF, - Ci.nsICookieService.BEHAVIOR_ACCEPT, - "Disabling cookie toggle accepts all cookies" - ); - synthesizeClick(cookieToggle.buttonEl); - await prefChange; - - ok(!cookieToggle.pressed, "Cookie toggle reflects disabled state"); - - gBrowser.removeCurrentTab(); -}); - -// Checks tracking protection toggle and scope dropdown interactions. -add_task(async function test_custom_tracking_protection_controls() { - await SpecialPowers.pushPrefEnv({ - set: [ - [CAT_PREF, "custom"], - [TP_PREF, false], - [TP_PBM_PREF, true], - ], - }); - - let { doc } = await openEtpCustomizePage(); - let tpToggle = getControl(doc, "etpCustomTrackingProtectionEnabled"); - let tpContext = getControl(doc, "etpCustomTrackingProtectionEnabledContext"); - - ok(tpToggle.pressed, "Tracking protection toggle starts enabled"); - - let prefChange = TestUtils.waitForPrefChange( - TP_PBM_PREF, - value => value === false - ); - synthesizeClick(tpToggle.buttonEl); - await prefChange; - - ok(!tpToggle.pressed, "Tracking protection toggle reflects disabled state"); - ok( - !Services.prefs.getBoolPref(TP_PREF), - "All-windows tracking protection pref remains false" - ); - - prefChange = TestUtils.waitForPrefChange( - TP_PBM_PREF, - value => value === true - ); - synthesizeClick(tpToggle.buttonEl); - await prefChange; - ok(tpToggle.pressed, "Tracking protection toggle enabled again"); - ok( - !Services.prefs.getBoolPref(TP_PREF), - "All-windows tracking protection pref still false after re-enabling toggle" - ); - - info("Switch context to protect all windows"); - await changeMozSelectValue(tpContext, "all"); - ok( - Services.prefs.getBoolPref(TP_PREF), - "Tracking protection pref enabled for all windows" - ); - ok( - Services.prefs.getBoolPref(TP_PBM_PREF), - "Tracking protection PBM pref stays enabled" - ); - - info("Switch back to private windows only"); - await changeMozSelectValue(tpContext, "pbmOnly"); - ok( - !Services.prefs.getBoolPref(TP_PREF), - "All windows pref disabled when choosing private only" - ); - ok( - Services.prefs.getBoolPref(TP_PBM_PREF), - "Private windows pref stays enabled" - ); - - gBrowser.removeCurrentTab(); -}); - -// Covers cryptomining/fingerprinting toggles and suspect protection context behavior. -add_task(async function test_custom_fingerprinting_controls() { - await SpecialPowers.pushPrefEnv({ - set: [ - [CAT_PREF, "custom"], - [CRYPTOMINING_PREF, false], - [FINGERPRINTING_PREF, false], - [SUSPECT_FP_PREF, false], - [SUSPECT_FP_PBM_PREF, false], - ], - }); - - let { doc } = await openEtpCustomizePage(); - let cryptoToggle = getControl(doc, "etpCustomCryptominingProtectionEnabled"); - let knownFpToggle = getControl( - doc, - "etpCustomKnownFingerprintingProtectionEnabled" - ); - let suspectFpToggle = getControl( - doc, - "etpCustomSuspectFingerprintingProtectionEnabled" - ); - let suspectContext = getControl( - doc, - "etpCustomSuspectFingerprintingProtectionEnabledContext" - ); - - info("Enable cryptomining protection"); - let prefChange = waitForAndAssertPrefState( - CRYPTOMINING_PREF, - true, - "Cryptomining pref enabled" - ); - synthesizeClick(cryptoToggle.buttonEl); - await prefChange; - - info("Enable known fingerprinting protection"); - prefChange = waitForAndAssertPrefState( - FINGERPRINTING_PREF, - true, - "Fingerprinting pref enabled" - ); - synthesizeClick(knownFpToggle.buttonEl); - await prefChange; - - info("Enable suspect fingerprinting protection"); - prefChange = TestUtils.waitForPrefChange( - SUSPECT_FP_PBM_PREF, - value => value === true - ); - synthesizeClick(suspectFpToggle.buttonEl); - await prefChange; - ok( - !Services.prefs.getBoolPref(SUSPECT_FP_PREF), - "All-windows suspect fingerprinting pref remains false after toggle" - ); - - info("Switch suspect protection context to all windows"); - await changeMozSelectValue(suspectContext, "all"); - ok( - Services.prefs.getBoolPref(SUSPECT_FP_PREF), - "All-windows suspect fingerprinting pref enabled" - ); - ok( - Services.prefs.getBoolPref(SUSPECT_FP_PBM_PREF), - "PBM suspect fingerprinting pref remains enabled" - ); - - info("Disable suspect protection through the toggle"); - prefChange = TestUtils.waitForPrefChange( - SUSPECT_FP_PBM_PREF, - value => value === false - ); - synthesizeClick(suspectFpToggle.buttonEl); - await prefChange; - ok( - !Services.prefs.getBoolPref(SUSPECT_FP_PREF), - "All-window suspect pref disabled after toggle off" - ); - - gBrowser.removeCurrentTab(); -}); diff --git a/browser/components/preferences/tests/browser_etp_customize_1.js b/browser/components/preferences/tests/browser_etp_customize_1.js @@ -0,0 +1,102 @@ +/* Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const CAT_PREF = "browser.contentblocking.category"; +const BASELINE_PREF = "privacy.trackingprotection.allow_list.baseline.enabled"; +const CONVENIENCE_PREF = + "privacy.trackingprotection.allow_list.convenience.enabled"; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["browser.settings-redesign.enabled", true]], + }); +}); + +add_task(async function test_etp_reset_buttons_update_category() { + await SpecialPowers.pushPrefEnv({ + set: [[CAT_PREF, "standard"]], + }); + + let { doc } = await openEtpCustomizePage(); + let standardButton = getControl(doc, "etpResetStandardButton"); + let strictButton = getControl(doc, "etpResetStrictButton"); + + ok(standardButton.disabled, "Standard reset button disabled on standard"); + ok(!strictButton.disabled, "Strict reset button enabled"); + + let prefChange = waitForAndAssertPrefState( + CAT_PREF, + "strict", + "ETP category pref switched to strict" + ); + synthesizeClick(strictButton); + await prefChange; + + ok(strictButton.disabled, "Strict reset button disabled after use"); + ok( + !standardButton.disabled, + "Standard reset button enabled after switching to strict" + ); + + prefChange = waitForAndAssertPrefState( + CAT_PREF, + "standard", + "ETP category pref switched back to standard" + ); + synthesizeClick(standardButton); + await prefChange; + + gBrowser.removeCurrentTab(); +}); + +add_task(async function test_custom_allow_list_controls_match_old_behavior() { + await SpecialPowers.pushPrefEnv({ + set: [ + [CAT_PREF, "custom"], + [BASELINE_PREF, true], + [CONVENIENCE_PREF, true], + ], + }); + + let { doc } = await openEtpCustomizePage(); + let baselineCheckbox = getControl(doc, "etpAllowListBaselineEnabledCustom"); + let convenienceCheckbox = getControl( + doc, + "etpAllowListConvenienceEnabledCustom" + ); + + ok(baselineCheckbox.checked, "Custom baseline checkbox starts checked"); + + await clickEtpBaselineCheckboxWithConfirm( + doc, + "etpAllowListBaselineEnabledCustom", + BASELINE_PREF, + false, + 1 + ); + + ok( + !Services.prefs.getBoolPref(BASELINE_PREF), + "Baseline pref disabled from custom controls" + ); + ok( + convenienceCheckbox.parentDisabled, + "Custom convenience checkbox disabled when baseline unchecked" + ); + + let baselinePrefChange = waitForAndAssertPrefState( + BASELINE_PREF, + true, + "Baseline pref restored" + ); + synthesizeClick(baselineCheckbox); + await baselinePrefChange; + await BrowserTestUtils.waitForCondition( + () => !convenienceCheckbox.parentDisabled, + "Custom convenience checkbox enabled once baseline rechecked" + ); + + gBrowser.removeCurrentTab(); +}); diff --git a/browser/components/preferences/tests/browser_etp_customize_2.js b/browser/components/preferences/tests/browser_etp_customize_2.js @@ -0,0 +1,220 @@ +/* Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const CAT_PREF = "browser.contentblocking.category"; +const COOKIE_BEHAVIOR_PREF = "network.cookie.cookieBehavior"; +const TP_PREF = "privacy.trackingprotection.enabled"; +const TP_PBM_PREF = "privacy.trackingprotection.pbmode.enabled"; +const CRYPTOMINING_PREF = "privacy.trackingprotection.cryptomining.enabled"; +const FINGERPRINTING_PREF = "privacy.trackingprotection.fingerprinting.enabled"; +const SUSPECT_FP_PREF = "privacy.fingerprintingProtection"; +const SUSPECT_FP_PBM_PREF = "privacy.fingerprintingProtection.pbmode"; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["browser.settings-redesign.enabled", true]], + }); +}); + +// Checks tracking protection toggle and scope dropdown interactions. +add_task(async function test_custom_cookie_controls() { + let defaults = Services.prefs.getDefaultBranch(""); + let defaultCookieBehavior = defaults.getIntPref(COOKIE_BEHAVIOR_PREF); + + await SpecialPowers.pushPrefEnv({ + set: [ + [CAT_PREF, "custom"], + [COOKIE_BEHAVIOR_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT], + ], + }); + + let { doc } = await openEtpCustomizePage(); + let cookieToggle = getControl(doc, "etpCustomCookiesEnabled"); + let cookieSelect = getControl(doc, "cookieBehavior"); + + ok( + !cookieToggle.pressed, + "Cookie toggle starts disabled when behavior is accept" + ); + + let prefChange = waitForAndAssertPrefState( + COOKIE_BEHAVIOR_PREF, + defaultCookieBehavior, + "Enabling cookie toggle restores default behavior" + ); + synthesizeClick(cookieToggle.buttonEl); + await prefChange; + + ok(cookieToggle.pressed, "Cookie toggle is pressed when enabled"); + + info("Select a stricter cookie behavior through the dropdown"); + let newBehavior = Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN.toString(); + await changeMozSelectValue(cookieSelect, newBehavior); + is( + Services.prefs.getIntPref(COOKIE_BEHAVIOR_PREF), + Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN, + "Cookie behavior pref updated from moz-select" + ); + + prefChange = waitForAndAssertPrefState( + COOKIE_BEHAVIOR_PREF, + Ci.nsICookieService.BEHAVIOR_ACCEPT, + "Disabling cookie toggle accepts all cookies" + ); + synthesizeClick(cookieToggle.buttonEl); + await prefChange; + + ok(!cookieToggle.pressed, "Cookie toggle reflects disabled state"); + + gBrowser.removeCurrentTab(); +}); + +add_task(async function test_custom_tracking_protection_controls() { + await SpecialPowers.pushPrefEnv({ + set: [ + [CAT_PREF, "custom"], + [TP_PREF, false], + [TP_PBM_PREF, true], + ], + }); + + let { doc } = await openEtpCustomizePage(); + let tpToggle = getControl(doc, "etpCustomTrackingProtectionEnabled"); + let tpContext = getControl(doc, "etpCustomTrackingProtectionEnabledContext"); + + ok(tpToggle.pressed, "Tracking protection toggle starts enabled"); + + let prefChange = TestUtils.waitForPrefChange( + TP_PBM_PREF, + value => value === false + ); + synthesizeClick(tpToggle.buttonEl); + await prefChange; + + ok(!tpToggle.pressed, "Tracking protection toggle reflects disabled state"); + ok( + !Services.prefs.getBoolPref(TP_PREF), + "All-windows tracking protection pref remains false" + ); + + prefChange = TestUtils.waitForPrefChange( + TP_PBM_PREF, + value => value === true + ); + synthesizeClick(tpToggle.buttonEl); + await prefChange; + ok(tpToggle.pressed, "Tracking protection toggle enabled again"); + ok( + !Services.prefs.getBoolPref(TP_PREF), + "All-windows tracking protection pref still false after re-enabling toggle" + ); + + info("Switch context to protect all windows"); + await changeMozSelectValue(tpContext, "all"); + ok( + Services.prefs.getBoolPref(TP_PREF), + "Tracking protection pref enabled for all windows" + ); + ok( + Services.prefs.getBoolPref(TP_PBM_PREF), + "Tracking protection PBM pref stays enabled" + ); + + info("Switch back to private windows only"); + await changeMozSelectValue(tpContext, "pbmOnly"); + ok( + !Services.prefs.getBoolPref(TP_PREF), + "All windows pref disabled when choosing private only" + ); + ok( + Services.prefs.getBoolPref(TP_PBM_PREF), + "Private windows pref stays enabled" + ); + + gBrowser.removeCurrentTab(); +}); + +// Covers cryptomining/fingerprinting toggles and suspect protection context behavior. +add_task(async function test_custom_fingerprinting_controls() { + await SpecialPowers.pushPrefEnv({ + set: [ + [CAT_PREF, "custom"], + [CRYPTOMINING_PREF, false], + [FINGERPRINTING_PREF, false], + [SUSPECT_FP_PREF, false], + [SUSPECT_FP_PBM_PREF, false], + ], + }); + + let { doc } = await openEtpCustomizePage(); + let cryptoToggle = getControl(doc, "etpCustomCryptominingProtectionEnabled"); + let knownFpToggle = getControl( + doc, + "etpCustomKnownFingerprintingProtectionEnabled" + ); + let suspectFpToggle = getControl( + doc, + "etpCustomSuspectFingerprintingProtectionEnabled" + ); + let suspectContext = getControl( + doc, + "etpCustomSuspectFingerprintingProtectionEnabledContext" + ); + + info("Enable cryptomining protection"); + let prefChange = waitForAndAssertPrefState( + CRYPTOMINING_PREF, + true, + "Cryptomining pref enabled" + ); + synthesizeClick(cryptoToggle.buttonEl); + await prefChange; + + info("Enable known fingerprinting protection"); + prefChange = waitForAndAssertPrefState( + FINGERPRINTING_PREF, + true, + "Fingerprinting pref enabled" + ); + synthesizeClick(knownFpToggle.buttonEl); + await prefChange; + + info("Enable suspect fingerprinting protection"); + prefChange = TestUtils.waitForPrefChange( + SUSPECT_FP_PBM_PREF, + value => value === true + ); + synthesizeClick(suspectFpToggle.buttonEl); + await prefChange; + ok( + !Services.prefs.getBoolPref(SUSPECT_FP_PREF), + "All-windows suspect fingerprinting pref remains false after toggle" + ); + + info("Switch suspect protection context to all windows"); + await changeMozSelectValue(suspectContext, "all"); + ok( + Services.prefs.getBoolPref(SUSPECT_FP_PREF), + "All-windows suspect fingerprinting pref enabled" + ); + ok( + Services.prefs.getBoolPref(SUSPECT_FP_PBM_PREF), + "PBM suspect fingerprinting pref remains enabled" + ); + + info("Disable suspect protection through the toggle"); + prefChange = TestUtils.waitForPrefChange( + SUSPECT_FP_PBM_PREF, + value => value === false + ); + synthesizeClick(suspectFpToggle.buttonEl); + await prefChange; + ok( + !Services.prefs.getBoolPref(SUSPECT_FP_PREF), + "All-window suspect pref disabled after toggle off" + ); + + gBrowser.removeCurrentTab(); +}); diff --git a/browser/components/preferences/tests/head.js b/browser/components/preferences/tests/head.js @@ -734,3 +734,97 @@ async function waitForPaneChange(paneId) { : `pane${paneId[0].toUpperCase()}${paneId.substring(1)}`; is(event.detail.category, expectId, "Loaded the correct pane"); } + +function getControl(doc, id) { + let control = doc.getElementById(id); + ok(control, `Control ${id} exists`); + return control; +} + +function synthesizeClick(el) { + let target = el.buttonEl ?? el.inputEl ?? el; + target.scrollIntoView({ block: "center" }); + EventUtils.synthesizeMouseAtCenter(target, {}, target.ownerGlobal); +} + +function getControlWrapper(doc, id) { + return getControl(doc, id).closest("setting-control"); +} + +async function openEtpPage() { + await openPreferencesViaOpenPreferencesAPI("etp", { leaveOpen: true }); + let doc = gBrowser.contentDocument; + await BrowserTestUtils.waitForCondition( + () => doc.getElementById("contentBlockingCategoryRadioGroup"), + "Wait for the ETP advanced radio group to render" + ); + return { + win: gBrowser.contentWindow, + doc, + tab: gBrowser.selectedTab, + }; +} + +async function openEtpCustomizePage() { + await openPreferencesViaOpenPreferencesAPI("etpCustomize", { + leaveOpen: true, + }); + let doc = gBrowser.contentDocument; + await BrowserTestUtils.waitForCondition( + () => doc.getElementById("etpAllowListBaselineEnabledCustom"), + "Wait for the ETP customize controls to render" + ); + return { + win: gBrowser.contentWindow, + doc, + }; +} + +async function changeMozSelectValue(selectEl, value) { + let control = selectEl.control; + let changePromise = waitForSettingControlChange(control); + selectEl.value = value; + selectEl.dispatchEvent(new Event("change", { bubbles: true })); + await changePromise; +} + +async function clickEtpBaselineCheckboxWithConfirm( + doc, + controlId, + prefName, + expectedValue, + buttonNumClick +) { + let checkbox = getControl(doc, controlId); + + let promptPromise = PromptTestUtils.handleNextPrompt( + gBrowser.selectedBrowser, + { modalType: Services.prompt.MODAL_TYPE_CONTENT }, + { buttonNumClick } + ); + + let prefChangePromise = null; + if (buttonNumClick === 1) { + prefChangePromise = waitForAndAssertPrefState( + prefName, + expectedValue, + `${prefName} updated` + ); + } + + synthesizeClick(checkbox); + + await promptPromise; + + if (prefChangePromise) { + await prefChangePromise; + } + + is( + checkbox.checked, + expectedValue, + `Checkbox ${controlId} should be ${expectedValue}` + ); + + return checkbox; +}