tor-browser

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

commit 7b4f02f92711c6de97bc6789914c15a40106c632
parent 24519257c6c245a1d6e2ed044d3e2a2715559a6d
Author: Emma Zuehlcke <emz@mozilla.com>
Date:   Tue,  2 Dec 2025 11:20:37 +0000

Bug 1971212 - Add ETP status card. r=fluent-reviewers,bvandersloot,bolsson,hjones

The advanced view (opened via the "Advanced settings" button) will be
implemented in Bug 1971444.

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

Diffstat:
Mbrowser/components/preferences/main.js | 33+++++++++++++++++++++++++++++++++
Mbrowser/components/preferences/privacy.inc.xhtml | 3++-
Mbrowser/components/preferences/privacy.js | 39+++++++++++++++++++++++++++++++++++++++
Mbrowser/components/preferences/tests/browser.toml | 2++
Abrowser/components/preferences/tests/browser_etp_status.js | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/locales-preview/privacyPreferences.ftl | 25+++++++++++++++++++++++++
6 files changed, 214 insertions(+), 1 deletion(-)

diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js @@ -2947,6 +2947,39 @@ SettingGroupManager.registerGroups({ }, ], }, + etpStatus: { + inProgress: true, + headingLevel: 2, + l10nId: "preferences-etp-status-header", + supportPage: "enhanced-tracking-protection", + iconSrc: "chrome://browser/skin/controlcenter/tracking-protection.svg", + items: [ + { + id: "etpStatusBoxGroup", + control: "moz-box-group", + items: [ + { + id: "etpStatusItem", + l10nId: "preferences-etp-level-standard", + control: "moz-box-item", + }, + { + id: "etpStatusAdvancedButton", + l10nId: "preferences-etp-status-advanced-button", + control: "moz-box-button", + }, + ], + }, + { + id: "protectionsDashboardLink", + l10nId: "preferences-etp-status-protections-dashboard-link", + control: "moz-box-link", + controlAttrs: { + href: "about:protections", + }, + }, + ], + }, }); /** diff --git a/browser/components/preferences/privacy.inc.xhtml b/browser/components/preferences/privacy.inc.xhtml @@ -14,7 +14,8 @@ <html:h1 data-l10n-id="privacy-header"/> </hbox> - +<!-- Enhanced Tracking Protection Status Section --> +<html:setting-group groupid="etpStatus" data-category="panePrivacy" data-subcategory="etpStatus" hidden="true"></html:setting-group> <!-- Tracking / Content Blocking --> <groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" aria-describedby="contentBlockingDescription" class="highlighting-group"> diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js @@ -2801,6 +2801,44 @@ Preferences.addSetting({ }, }); +Preferences.addSetting({ + id: "contentBlockingCategory", + pref: "browser.contentblocking.category", +}); + +Preferences.addSetting({ + id: "etpStatusBoxGroup", +}); + +Preferences.addSetting({ + id: "etpStatusItem", + deps: ["contentBlockingCategory"], + getControlConfig(config, { contentBlockingCategory }) { + // Display a different description and label depending on the content blocking category (= ETP level). + let categoryToL10nId = { + standard: "preferences-etp-level-standard", + strict: "preferences-etp-level-strict", + custom: "preferences-etp-level-custom", + }; + + return { + ...config, + l10nId: + categoryToL10nId[contentBlockingCategory.value] ?? + "preferences-etp-level-standard", + }; + }, +}); + +Preferences.addSetting({ + id: "etpStatusAdvancedButton", + // TODO: Bug 1971444 - Click action to switch to advanced subview. +}); + +Preferences.addSetting({ + id: "protectionsDashboardLink", +}); + function setEventListener(aId, aEventType, aCallback) { document .getElementById(aId) @@ -3362,6 +3400,7 @@ var gPrivacyPane = { initSettingGroup("permissions"); initSettingGroup("dnsOverHttps"); initSettingGroup("dnsOverHttpsAdvanced"); + initSettingGroup("etpStatus"); /* Initialize Content Blocking */ this.initContentBlocking(); diff --git a/browser/components/preferences/tests/browser.toml b/browser/components/preferences/tests/browser.toml @@ -107,6 +107,8 @@ skip-if = [ ["browser_etp_exceptions_dialog.js"] +["browser_etp_status.js"] + ["browser_experimental_features.js"] ["browser_experimental_features_filter.js"] diff --git a/browser/components/preferences/tests/browser_etp_status.js b/browser/components/preferences/tests/browser_etp_status.js @@ -0,0 +1,113 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + // Show the ETP status section in the privacy pane. + ["browser.settings-redesign.etpStatus.enabled", true], + // Ensure we start from ETP "standard". + ["browser.contentblocking.category", "standard"], + ], + }); +}); + +/** + * Helper for waiting for and asserting the ETP status item state. + * Can be called both when the item already changed or when we need to wait for the change. + * + * @param {Document} doc - The preferences document. + * @param {*} options - The expected ETP status item state. + * @param {string} options.l10nId - The expected l10nId attribute value. + * @param {string} options.description - The expected description attribute value. + */ +async function waitForAndAssertEtpStatusItemState(doc, { l10nId }) { + let etpStatusItem = doc.getElementById("etpStatusItem"); + Assert.ok( + BrowserTestUtils.isVisible(etpStatusItem), + "ETP status box item should be visible" + ); + + let condition = () => { + return etpStatusItem.getAttribute("data-l10n-id") == l10nId; + }; + if (!condition()) { + await BrowserTestUtils.waitForMutationCondition( + etpStatusItem, + { attributes: true, attributeFilter: ["data-l10n-id", "description"] }, + condition + ); + } + + Assert.equal(etpStatusItem.getAttribute("data-l10n-id"), l10nId); +} + +// Test that the ETP status section updates correctly when changing the ETP category. +add_task(async function test_status_categories() { + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); + let doc = gBrowser.contentDocument; + + await waitForAndAssertEtpStatusItemState(doc, { + l10nId: "preferences-etp-level-standard", + }); + + info("Switch to ETP `strict`"); + Services.prefs.setStringPref("browser.contentblocking.category", "strict"); + + await waitForAndAssertEtpStatusItemState(doc, { + l10nId: "preferences-etp-level-strict", + }); + + info("Switch to ETP `custom`"); + Services.prefs.setStringPref("browser.contentblocking.category", "custom"); + + await waitForAndAssertEtpStatusItemState(doc, { + l10nId: "preferences-etp-level-custom", + }); + + info("Switch back to default ETP `standard`"); + Services.prefs.clearUserPref("browser.contentblocking.category"); + + await waitForAndAssertEtpStatusItemState(doc, { + l10nId: "preferences-etp-level-standard", + }); + + gBrowser.removeCurrentTab(); +}); + +// Test that the protections dashboard link in the ETP status section opens the about:protections page. +add_task(async function test_protections_dashboard_link() { + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); + let doc = gBrowser.contentDocument; + + let protectionsDashboardLink = doc.getElementById("protectionsDashboardLink"); + + Assert.ok( + BrowserTestUtils.isVisible(protectionsDashboardLink), + "Protections dashboard link is visible." + ); + + let linkPromise = BrowserTestUtils.waitForNewTab( + gBrowser, + "about:protections" + ); + await BrowserTestUtils.synthesizeMouseAtCenter( + "#protectionsDashboardLink", + {}, + gBrowser.selectedBrowser + ); + let tab = await linkPromise; + + Assert.equal( + tab.linkedBrowser.currentURI.spec, + "about:protections", + "Protections dashboard link opened the about:protections page." + ); + + // about:protections tab. + BrowserTestUtils.removeTab(tab); + // Preferences tab. + gBrowser.removeCurrentTab(); +}); diff --git a/browser/locales-preview/privacyPreferences.ftl b/browser/locales-preview/privacyPreferences.ftl @@ -208,3 +208,28 @@ preferences-doh-custom-provider-label = preferences-doh-header2 = .heading = DNS over HTTPS + +## ETP status section + +preferences-etp-status-header = + .label = Enhanced Tracking Protection + .description = Some sites use trackers to learn what you do online. { -brand-short-name } blocks many of them automatically to protect your privacy while you browse. + +preferences-etp-level-standard = + .label = Standard (default) + .description = Blocks known trackers and cookies, helping protect your privacy without affecting most websites’ functionality. + +preferences-etp-level-strict = + .label = Strict + .description = Stronger protection, but may cause some sites or content to break. + +preferences-etp-level-custom = + .label = Custom + .description = Choose which trackers and scripts to block. + +preferences-etp-status-advanced-button = + .label = Advanced settings + +preferences-etp-status-protections-dashboard-link = + .label = View your personalized Protections Dashboard + .description = See how many creepers { -brand-short-name } has blocked for you, including social media trackers, fingerprinters, and cryptominers.