diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm index 41b9bca1808f..c13ccff84f33 100644 --- a/browser/components/BrowserGlue.jsm +++ b/browser/components/BrowserGlue.jsm @@ -3100,6 +3100,15 @@ var ContentBlockingCategoriesPrefs = { } else { Services.prefs.setStringPref(this.PREF_CB_CATEGORY, "custom"); } + + // If there is a custom policy which changes a related pref, then put the user in custom so + // they still have access to other content blocking prefs, and to keep our default definitions + // from changing. + let policy = Services.policies.getActivePolicies(); + if (policy && (policy.EnableTrackingProtection || + policy.Cookies)) { + Services.prefs.setStringPref(this.PREF_CB_CATEGORY, "custom"); + } }, updateCBCategory() { diff --git a/browser/components/preferences/in-content/privacy.js b/browser/components/preferences/in-content/privacy.js index 80dd6612e4ff..87cee621ace3 100644 --- a/browser/components/preferences/in-content/privacy.js +++ b/browser/components/preferences/in-content/privacy.js @@ -21,6 +21,12 @@ const PREF_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled"; const TRACKING_PROTECTION_KEY = "websites.trackingProtectionMode"; const TRACKING_PROTECTION_PREFS = ["privacy.trackingprotection.enabled", "privacy.trackingprotection.pbmode.enabled"]; +const CONTENT_BLOCKING_PREFS = ["privacy.trackingprotection.enabled", + "privacy.trackingprotection.pbmode.enabled", + "network.cookie.cookieBehavior", + "privacy.trackingprotection.fingerprinting.enabled", + "privacy.trackingprotection.cryptomining.enabled", + "urlclassifier.trackingTable"]; const PREF_OPT_OUT_STUDIES_ENABLED = "app.shield.optoutstudies.enabled"; const PREF_NORMANDY_ENABLED = "app.normandy.enabled"; @@ -178,25 +184,28 @@ var gPrivacyPane = { * Update the tracking protection UI to deal with extension control. */ _updateTrackingProtectionUI() { - let isLocked = TRACKING_PROTECTION_PREFS.some( + let cBPrefisLocked = CONTENT_BLOCKING_PREFS.some( + pref => Services.prefs.prefIsLocked(pref)); + let tPPrefisLocked = TRACKING_PROTECTION_PREFS.some( pref => Services.prefs.prefIsLocked(pref)); function setInputsDisabledState(isControlled) { - let disabled = isLocked || isControlled; + let tpDisabled = tPPrefisLocked || isControlled; + let disabled = cBPrefisLocked || isControlled; let tpCheckbox = document.getElementById("contentBlockingTrackingProtectionCheckbox"); // Only enable the TP menu if Detect All Trackers is enabled. - document.getElementById("trackingProtectionMenu").disabled = disabled || + document.getElementById("trackingProtectionMenu").disabled = tpDisabled || !tpCheckbox.checked; - tpCheckbox.disabled = disabled; + tpCheckbox.disabled = tpDisabled; - document.getElementById("standardRadio").disabled = isControlled; - document.getElementById("strictRadio").disabled = isControlled; - document.getElementById("contentBlockingOptionStrict").classList.toggle("disabled", isControlled); - document.getElementById("contentBlockingOptionStandard").classList.toggle("disabled", isControlled); + document.getElementById("standardRadio").disabled = disabled; + document.getElementById("strictRadio").disabled = disabled; + document.getElementById("contentBlockingOptionStrict").classList.toggle("disabled", disabled); + document.getElementById("contentBlockingOptionStandard").classList.toggle("disabled", disabled); let arrowButtons = document.querySelectorAll("button.arrowhead"); for (let button of arrowButtons) { - button.disabled = isControlled; + button.disabled = disabled; } // Notify observers that the TP UI has been updated. @@ -212,7 +221,12 @@ var gPrivacyPane = { document.getElementById("contentBlockingCategories").toggleAttribute("fallback-ui", defaults.getIntPref("network.cookie.cookieBehavior") === Ci.nsICookieService.BEHAVIOR_ACCEPT); - if (isLocked) { + let policy = Services.policies.getActivePolicies(); + if (policy && ((policy.EnableTrackingProtection && policy.EnableTrackingProtection.Locked) || + (policy.Cookies && policy.Cookies.Locked))) { + setInputsDisabledState(true); + } + if (tPPrefisLocked) { // An extension can't control this setting if either pref is locked. hideControllingExtension(TRACKING_PROTECTION_KEY); setInputsDisabledState(false); diff --git a/browser/components/preferences/in-content/tests/browser_contentblocking.js b/browser/components/preferences/in-content/tests/browser_contentblocking.js index af855290b4bf..89c00bf84407 100644 --- a/browser/components/preferences/in-content/tests/browser_contentblocking.js +++ b/browser/components/preferences/in-content/tests/browser_contentblocking.js @@ -11,6 +11,21 @@ const CAT_PREF = "browser.contentblocking.category"; const FP_PREF = "privacy.trackingprotection.fingerprinting.enabled"; const CM_PREF = "privacy.trackingprotection.cryptomining.enabled"; +const { + EnterprisePolicyTesting, + PoliciesPrefTracker, +} = ChromeUtils.import("resource://testing-common/EnterprisePolicyTesting.jsm", null); + +registerCleanupFunction(async function policies_headjs_finishWithCleanSlate() { + if (Services.policies.status != Ci.nsIEnterprisePolicies.INACTIVE) { + await EnterprisePolicyTesting.setupPolicyEngineWithJson(""); + } + is(Services.policies.status, Ci.nsIEnterprisePolicies.INACTIVE, "Engine is inactive at the end of the test"); + + EnterprisePolicyTesting.resetRunOnceState(); + PoliciesPrefTracker.stop(); +}); + requestLongerTimeout(2); // Tests that the content blocking main category checkboxes have the correct default state. @@ -355,3 +370,47 @@ add_task(async function testCustomOptionsVisibility() { Services.prefs.clearUserPref("browser.contentblocking.cryptomining.preferences.ui.enabled"); Services.prefs.clearUserPref("browser.contentblocking.fingerprinting.preferences.ui.enabled"); }); + +// Checks that adding a custom enterprise policy will put the user in the custom category. +// Other categories will be disabled. +add_task(async function testPolicyCategorization() { + Services.prefs.setStringPref(CAT_PREF, "standard"); + is(Services.prefs.getStringPref(CAT_PREF), "standard", `${CAT_PREF} starts on standard`); + is(Services.prefs.getBoolPref(TP_PREF), false, `${TP_PREF} starts on false`); + PoliciesPrefTracker.start(); + + await EnterprisePolicyTesting.setupPolicyEngineWithJson({ + policies: {"EnableTrackingProtection": { + "Value": true, + }, + }, + }); + EnterprisePolicyTesting.checkPolicyPref(TP_PREF, true, false); + is(Services.prefs.getStringPref(CAT_PREF), "custom", `${CAT_PREF} has been set to custom`); + + Services.prefs.setStringPref(CAT_PREF, "standard"); + is(Services.prefs.getStringPref(CAT_PREF), "standard", `${CAT_PREF} starts on standard`); + is(Services.prefs.getIntPref(NCB_PREF), 4, `${NCB_PREF} starts on 4`); + + let uiUpdatedPromise = TestUtils.topicObserved("privacy-pane-tp-ui-updated"); + await EnterprisePolicyTesting.setupPolicyEngineWithJson({ + policies: {"Cookies": { + "AcceptThirdParty": "never", + "Locked": true, + }, + }, + }); + await openPreferencesViaOpenPreferencesAPI("privacy", {leaveOpen: true}); + await uiUpdatedPromise; + + EnterprisePolicyTesting.checkPolicyPref(NCB_PREF, 1, true); + is(Services.prefs.getStringPref(CAT_PREF), "custom", `${CAT_PREF} has been set to custom`); + + let doc = gBrowser.contentDocument; + let strictRadioOption = doc.getElementById("strictRadio"); + let standardRadioOption = doc.getElementById("standardRadio"); + is(strictRadioOption.disabled, true, "the strict option is disabled"); + is(standardRadioOption.disabled, true, "the standard option is disabled"); + + gBrowser.removeCurrentTab(); +});