commit 60cb4824d57267f5b7f18543ab356ae56a672aae
parent 443bc3032282afa636188c99bbe39c1827983c66
Author: Emma Zuehlcke <emz@mozilla.com>
Date: Thu, 18 Dec 2025 17:00:38 +0000
Bug 1971445 - Create ETP > Custom > Customize settings in config-based prefs. r=fluent-reviewers,hjones,bvandersloot,bolsson,desktop-theme-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D274317
Diffstat:
6 files changed, 459 insertions(+), 9 deletions(-)
diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js
@@ -3516,7 +3516,7 @@ SettingGroupManager.registerGroups({
supportPage: "enhanced-tracking-protection",
items: [
{
- id: "contentBlockingCategory",
+ id: "contentBlockingCategoryRadioGroup",
control: "moz-radio-group",
options: [
{
@@ -3581,6 +3581,148 @@ SettingGroupManager.registerGroups({
},
],
},
+ etpReset: {
+ inProgress: true,
+ headingLevel: 2,
+ l10nId: "preferences-etp-reset",
+ items: [
+ {
+ id: "etpResetButtonGroup",
+ control: "div",
+ items: [
+ {
+ id: "etpResetStandardButton",
+ control: "moz-button",
+ l10nId: "preferences-etp-reset-standard-button",
+ },
+ {
+ id: "etpResetStrictButton",
+ control: "moz-button",
+ l10nId: "preferences-etp-reset-strict-button",
+ },
+ ],
+ },
+ ],
+ },
+ etpCustomize: {
+ inProgress: true,
+ headingLevel: 2,
+ l10nId: "preferences-etp-custom-control-group",
+ items: [
+ {
+ id: "etpAllowListBaselineEnabledCustom",
+ l10nId: "content-blocking-baseline-exceptions-3",
+ supportPage: "manage-enhanced-tracking-protection-exceptions",
+ control: "moz-checkbox",
+ items: [
+ {
+ id: "etpAllowListConvenienceEnabledCustom",
+ l10nId: "content-blocking-convenience-exceptions-3",
+ control: "moz-checkbox",
+ },
+ ],
+ },
+ {
+ id: "etpCustomCookiesEnabled",
+ l10nId: "preferences-etp-custom-cookies-enabled",
+ control: "moz-toggle",
+ items: [
+ {
+ id: "cookieBehavior",
+ l10nId: "preferences-etp-custom-cookie-behavior",
+ control: "moz-select",
+ options: [
+ {
+ value: Ci.nsICookieService.BEHAVIOR_ACCEPT.toString(),
+ l10nId: "preferences-etpc-custom-cookie-behavior-accept-all",
+ },
+ {
+ value: Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER.toString(),
+ l10nId: "sitedata-option-block-cross-site-trackers",
+ },
+ {
+ value:
+ Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN.toString(),
+ l10nId: "sitedata-option-block-cross-site-cookies2",
+ },
+ {
+ value: Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN.toString(),
+ l10nId: "sitedata-option-block-unvisited",
+ },
+ {
+ value: Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN.toString(),
+ l10nId: "sitedata-option-block-all-cross-site-cookies",
+ },
+ {
+ value: Ci.nsICookieService.BEHAVIOR_REJECT.toString(),
+ l10nId: "sitedata-option-block-all",
+ },
+ ],
+ },
+ ],
+ },
+ {
+ id: "etpCustomTrackingProtectionEnabled",
+ l10nId: "preferences-etp-custom-tracking-protection-enabled",
+ control: "moz-toggle",
+ items: [
+ {
+ id: "etpCustomTrackingProtectionEnabledContext",
+ l10nId:
+ "preferences-etp-custom-tracking-protection-enabled-context",
+ control: "moz-select",
+ options: [
+ {
+ value: "all",
+ l10nId:
+ "content-blocking-tracking-protection-option-all-windows",
+ },
+ {
+ value: "pbmOnly",
+ l10nId: "content-blocking-option-private",
+ },
+ ],
+ },
+ ],
+ },
+ {
+ id: "etpCustomCryptominingProtectionEnabled",
+ l10nId: "preferences-etp-custom-crypto-mining-protection-enabled",
+ control: "moz-toggle",
+ },
+ {
+ id: "etpCustomKnownFingerprintingProtectionEnabled",
+ l10nId:
+ "preferences-etp-custom-known-fingerprinting-protection-enabled",
+ control: "moz-toggle",
+ },
+ {
+ id: "etpCustomSuspectFingerprintingProtectionEnabled",
+ l10nId:
+ "preferences-etp-custom-suspect-fingerprinting-protection-enabled",
+ control: "moz-toggle",
+ items: [
+ {
+ id: "etpCustomSuspectFingerprintingProtectionEnabledContext",
+ l10nId:
+ "preferences-etp-custom-suspect-fingerprinting-protection-enabled-context",
+ control: "moz-select",
+ options: [
+ {
+ value: "all",
+ l10nId:
+ "content-blocking-tracking-protection-option-all-windows",
+ },
+ {
+ value: "pbmOnly",
+ l10nId: "content-blocking-option-private",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
manageAddresses: {
items: [
{
diff --git a/browser/components/preferences/preferences.js b/browser/components/preferences/preferences.js
@@ -290,6 +290,11 @@ const CONFIG_PANES = Object.freeze({
l10nId: "preferences-etp-header",
groupIds: ["etpBanner", "etpAdvanced"],
},
+ etpCustomize: {
+ parent: "etp",
+ l10nId: "preferences-etp-customize-header",
+ groupIds: ["etpReset", "etpCustomize"],
+ },
manageAddresses: {
parent: "privacy",
l10nId: "autofill-addresses-manage-addresses-title",
diff --git a/browser/components/preferences/privacy.inc.xhtml b/browser/components/preferences/privacy.inc.xhtml
@@ -18,7 +18,7 @@
<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">
+<groupbox id="trackingGroup" data-category="panePrivacy" data-srd-groupid="etpBanner" hidden="true" aria-describedby="contentBlockingDescription" class="highlighting-group">
<label id="contentBlockingHeader"><html:h2 data-l10n-id="content-blocking-enhanced-tracking-protection"/></label>
<html:setting-group groupid="securityPrivacyStatus"/>
<vbox data-subcategory="trackingprotection">
diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js
@@ -2787,11 +2787,44 @@ Preferences.addSetting({
},
});
+function shouldDisableETPCategoryControls() {
+ let policy = Services.policies.getActivePolicies();
+ return policy?.EnableTrackingProtection?.Locked || policy?.Cookies?.Locked;
+}
+
Preferences.addSetting({
id: "contentBlockingCategory",
pref: "browser.contentblocking.category",
});
+// We need a separate setting for the radio group for custom disable behavior.
+// Setter and getter simply write to the pref.
+Preferences.addSetting({
+ id: "contentBlockingCategoryRadioGroup",
+ deps: ["contentBlockingCategory"],
+ get(_, { contentBlockingCategory }) {
+ return contentBlockingCategory.value;
+ },
+ set(value, { contentBlockingCategory }) {
+ contentBlockingCategory.value = value;
+ },
+ getControlConfig(config, _, setting) {
+ if (!shouldDisableETPCategoryControls()) {
+ return config;
+ }
+
+ let { options } = config;
+
+ // If ETP level is set to custom keep the radio button enabled so the "customize" button works even when the category selection itself is locked.
+ for (let option of options) {
+ option.disabled =
+ option.id != "etpLevelCustom" || setting.value != "custom";
+ }
+
+ return config;
+ },
+});
+
Preferences.addSetting({
id: "etpStatusBoxGroup",
});
@@ -2897,6 +2930,227 @@ Preferences.addSetting({
},
});
+Preferences.addSetting({
+ id: "etpResetButtonGroup",
+});
+
+Preferences.addSetting({
+ id: "etpResetStandardButton",
+ deps: ["contentBlockingCategory"],
+ onUserClick(_, { contentBlockingCategory }) {
+ contentBlockingCategory.value = "standard";
+ },
+ disabled({ contentBlockingCategory }) {
+ return (
+ contentBlockingCategory.value == "standard" ||
+ shouldDisableETPCategoryControls()
+ );
+ },
+});
+
+Preferences.addSetting({
+ id: "etpResetStrictButton",
+ deps: ["contentBlockingCategory"],
+ onUserClick(_, { contentBlockingCategory }) {
+ contentBlockingCategory.value = "strict";
+ },
+ disabled({ contentBlockingCategory }) {
+ return (
+ contentBlockingCategory.value == "strict" ||
+ shouldDisableETPCategoryControls()
+ );
+ },
+});
+
+Preferences.addSetting({
+ id: "etpAllowListBaselineEnabledCustom",
+ pref: "privacy.trackingprotection.allow_list.baseline.enabled",
+});
+
+Preferences.addSetting({
+ id: "etpAllowListConvenienceEnabledCustom",
+ pref: "privacy.trackingprotection.allow_list.convenience.enabled",
+});
+
+Preferences.addSetting({
+ id: "etpCustomCookiesEnabled",
+ deps: ["cookieBehavior"],
+ disabled: ({ cookieBehavior }) => {
+ return cookieBehavior.locked;
+ },
+ get(_, { cookieBehavior }) {
+ return cookieBehavior.value != Ci.nsICookieService.BEHAVIOR_ACCEPT;
+ },
+ set(value, { cookieBehavior }) {
+ if (!value) {
+ cookieBehavior.value = Ci.nsICookieService.BEHAVIOR_ACCEPT;
+ } else {
+ // When the user enabled cookie blocking, set the cookie behavior to the default.
+ cookieBehavior.value = cookieBehavior.pref.defaultValue;
+ }
+ },
+});
+
+Preferences.addSetting({
+ id: "trackingProtectionEnabled",
+ pref: "privacy.trackingprotection.enabled",
+});
+
+Preferences.addSetting({
+ id: "trackingProtectionEnabledPBM",
+ pref: "privacy.trackingprotection.pbmode.enabled",
+});
+
+Preferences.addSetting({
+ id: "etpCustomTrackingProtectionEnabledContext",
+ deps: ["trackingProtectionEnabled", "trackingProtectionEnabledPBM"],
+ get(_, { trackingProtectionEnabled, trackingProtectionEnabledPBM }) {
+ if (trackingProtectionEnabled.value && trackingProtectionEnabledPBM.value) {
+ return "all";
+ } else if (trackingProtectionEnabledPBM) {
+ return "pbmOnly";
+ }
+ return null;
+ },
+ set(value, { trackingProtectionEnabled, trackingProtectionEnabledPBM }) {
+ if (value == "all") {
+ trackingProtectionEnabled.value = true;
+ trackingProtectionEnabledPBM.value = true;
+ } else if (value == "pbmOnly") {
+ trackingProtectionEnabled.value = false;
+ trackingProtectionEnabledPBM.value = true;
+ }
+ },
+});
+
+Preferences.addSetting({
+ id: "etpCustomTrackingProtectionEnabled",
+ deps: ["trackingProtectionEnabled", "trackingProtectionEnabledPBM"],
+ disabled: ({ trackingProtectionEnabled, trackingProtectionEnabledPBM }) => {
+ return (
+ trackingProtectionEnabled.locked || trackingProtectionEnabledPBM.locked
+ );
+ },
+ get(_, { trackingProtectionEnabled, trackingProtectionEnabledPBM }) {
+ return (
+ trackingProtectionEnabled.value || trackingProtectionEnabledPBM.value
+ );
+ },
+ set(value, { trackingProtectionEnabled, trackingProtectionEnabledPBM }) {
+ if (value) {
+ trackingProtectionEnabled.value = false;
+ trackingProtectionEnabledPBM.value = true;
+ } else {
+ trackingProtectionEnabled.value = false;
+ trackingProtectionEnabledPBM.value = false;
+ }
+ },
+});
+
+Preferences.addSetting({
+ id: "etpCustomCryptominingProtectionEnabled",
+ pref: "privacy.trackingprotection.cryptomining.enabled",
+});
+
+Preferences.addSetting({
+ id: "etpCustomKnownFingerprintingProtectionEnabled",
+ pref: "privacy.trackingprotection.fingerprinting.enabled",
+});
+
+Preferences.addSetting({
+ id: "etpCustomFingerprintingProtectionEnabled",
+ pref: "privacy.fingerprintingProtection",
+});
+
+Preferences.addSetting({
+ id: "etpCustomFingerprintingProtectionEnabledPBM",
+ pref: "privacy.fingerprintingProtection.pbmode",
+});
+
+Preferences.addSetting({
+ id: "etpCustomSuspectFingerprintingProtectionEnabled",
+ deps: [
+ "etpCustomFingerprintingProtectionEnabled",
+ "etpCustomFingerprintingProtectionEnabledPBM",
+ ],
+ disabled({
+ etpCustomFingerprintingProtectionEnabled,
+ etpCustomFingerprintingProtectionEnabledPBM,
+ }) {
+ return (
+ etpCustomFingerprintingProtectionEnabled.locked ||
+ etpCustomFingerprintingProtectionEnabledPBM.locked
+ );
+ },
+ get(
+ _,
+ {
+ etpCustomFingerprintingProtectionEnabled,
+ etpCustomFingerprintingProtectionEnabledPBM,
+ }
+ ) {
+ return (
+ etpCustomFingerprintingProtectionEnabled.value ||
+ etpCustomFingerprintingProtectionEnabledPBM.value
+ );
+ },
+ set(
+ value,
+ {
+ etpCustomFingerprintingProtectionEnabled,
+ etpCustomFingerprintingProtectionEnabledPBM,
+ }
+ ) {
+ if (value) {
+ etpCustomFingerprintingProtectionEnabled.value = false;
+ etpCustomFingerprintingProtectionEnabledPBM.value = true;
+ } else {
+ etpCustomFingerprintingProtectionEnabled.value = false;
+ etpCustomFingerprintingProtectionEnabledPBM.value = false;
+ }
+ },
+});
+
+Preferences.addSetting({
+ id: "etpCustomSuspectFingerprintingProtectionEnabledContext",
+ deps: [
+ "etpCustomFingerprintingProtectionEnabled",
+ "etpCustomFingerprintingProtectionEnabledPBM",
+ ],
+ get(
+ _,
+ {
+ etpCustomFingerprintingProtectionEnabled,
+ etpCustomFingerprintingProtectionEnabledPBM,
+ }
+ ) {
+ if (
+ etpCustomFingerprintingProtectionEnabled.value &&
+ etpCustomFingerprintingProtectionEnabledPBM.value
+ ) {
+ return "all";
+ } else if (etpCustomFingerprintingProtectionEnabledPBM) {
+ return "pbmOnly";
+ }
+ return null;
+ },
+ set(
+ value,
+ {
+ etpCustomFingerprintingProtectionEnabled,
+ etpCustomFingerprintingProtectionEnabledPBM,
+ }
+ ) {
+ if (value == "all") {
+ etpCustomFingerprintingProtectionEnabled.value = true;
+ etpCustomFingerprintingProtectionEnabledPBM.value = true;
+ } else if (value == "pbmOnly") {
+ etpCustomFingerprintingProtectionEnabled.value = false;
+ etpCustomFingerprintingProtectionEnabledPBM.value = true;
+ }
+ },
+});
+
function setEventListener(aId, aEventType, aCallback) {
document
.getElementById(aId)
@@ -3015,13 +3269,7 @@ var gPrivacyPane = {
Services.obs.notifyObservers(window, "privacy-pane-tp-ui-updated");
}
- let policy = Services.policies.getActivePolicies();
- if (
- policy &&
- ((policy.EnableTrackingProtection &&
- policy.EnableTrackingProtection.Locked) ||
- (policy.Cookies && policy.Cookies.Locked))
- ) {
+ if (shouldDisableETPCategoryControls()) {
setInputsDisabledState(true);
}
if (tPPrefisLocked) {
@@ -3461,6 +3709,8 @@ var gPrivacyPane = {
initSettingGroup("etpStatus");
initSettingGroup("etpBanner");
initSettingGroup("etpAdvanced");
+ initSettingGroup("etpReset");
+ initSettingGroup("etpCustomize");
/* Initialize Content Blocking */
this.initContentBlocking();
diff --git a/browser/locales-preview/privacyPreferences.ftl b/browser/locales-preview/privacyPreferences.ftl
@@ -255,3 +255,51 @@ preferences-etp-level-warning-message =
preferences-etp-manage-exceptions-button =
.label = Manage exceptions
.description = Manage websites where Enhanced Tracking Protection is disabled.
+
+preferences-etp-customize-header =
+ .heading = Customize privacy protection
+ .description = Aut voluptates deleniti ut. Aut et praesentium voluptas dolore nostrum occaecati.
+
+preferences-etp-reset =
+ .label = Reset
+ .description = Aut voluptates deleniti ut. Aut et praesentium voluptas dolore nostrum occaecati. Fugit soluta dolor aut soluta sapiente ut vel.
+
+
+preferences-etp-reset-standard-button =
+ .label = Reset to standard
+
+preferences-etp-reset-strict-button =
+ .label = Reset to strict
+
+preferences-etp-custom-control-group =
+ .label = Tracking protection
+
+preferences-etp-custom-cookies-enabled =
+ .label = Cookies
+ .description = Description
+
+preferences-etp-custom-cookie-behavior =
+ .aria-label = { preferences-etp-custom-cookies-enabled.label }
+
+preferences-etpc-custom-cookie-behavior-accept-all =
+ .label = Allow all cookies
+
+preferences-etp-custom-tracking-protection-enabled =
+ .label = Tracking content
+ .description = Description
+
+preferences-etp-custom-tracking-protection-enabled-context =
+ .aria-label = { preferences-etp-custom-tracking-protection-enabled.label }
+
+preferences-etp-custom-crypto-mining-protection-enabled =
+ .label = Cryptominers
+
+preferences-etp-custom-known-fingerprinting-protection-enabled =
+ .label = Known fingerprinters
+
+preferences-etp-custom-suspect-fingerprinting-protection-enabled =
+ .label = Suspected fingerprinters
+ .description = Description
+
+preferences-etp-custom-suspect-fingerprinting-protection-enabled-context =
+ .aria-label = { preferences-etp-custom-suspect-fingerprinting-protection-enabled.label }
diff --git a/browser/themes/shared/preferences/preferences.css b/browser/themes/shared/preferences/preferences.css
@@ -1551,6 +1551,11 @@ setting-group[groupid="home"] {
--promo-image-position: top;
}
+#etpResetButtonGroup {
+ display: flex;
+ gap: var(--space-small);
+}
+
#addresses-list-header,
#payments-list-header {
--box-label-font-weight: var(--heading-font-weight);