Bug 1476217 - Part 5 - Disable content blocking sub-controls when content blocking is disabled. r=jaws draft
authorJohann Hofmann <jhofmann@mozilla.com>
Wed, 01 Aug 2018 15:27:13 +0200
changeset 825737 598c88dd38de453d03fb2cb93486986b23f0979a
parent 825736 05de3f8c154924b7dc81fc519df47b3a5b5ed1a6
push id118155
push userjhofmann@mozilla.com
push dateThu, 02 Aug 2018 06:20:22 +0000
reviewersjaws
bugs1476217
milestone63.0a1
Bug 1476217 - Part 5 - Disable content blocking sub-controls when content blocking is disabled. r=jaws MozReview-Commit-ID: 2WIqsabEXWw
browser/components/preferences/in-content/privacy.js
browser/components/preferences/in-content/tests/browser_contentblocking.js
browser/themes/shared/incontentprefs/preferences.inc.css
browser/themes/shared/incontentprefs/privacy.css
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -18,16 +18,19 @@ ChromeUtils.defineModuleGetter(this, "Lo
 ChromeUtils.defineModuleGetter(this, "SiteDataManager",
   "resource:///modules/SiteDataManager.jsm");
 
 ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingUiEnabled",
                                       "browser.contentblocking.ui.enabled");
 
+XPCOMUtils.defineLazyPreferenceGetter(this, "contentBlockingEnabled",
+                                      "browser.contentblocking.enabled");
+
 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 PREF_OPT_OUT_STUDIES_ENABLED = "app.shield.optoutstudies.enabled";
 const PREF_NORMANDY_ENABLED = "app.normandy.enabled";
@@ -176,17 +179,19 @@ var gPrivacyPane = {
    */
   _updateTrackingProtectionUI() {
     let isLocked = TRACKING_PROTECTION_PREFS.some(
       pref => Services.prefs.prefIsLocked(pref));
 
     function setInputsDisabledState(isControlled) {
       let disabled = isLocked || isControlled;
       if (contentBlockingUiEnabled) {
-        document.getElementById("trackingProtectionMenu").disabled = disabled;
+        // Only enable the TP menu if content blocking is enabled.
+        document.getElementById("trackingProtectionMenu").disabled = disabled ||
+          !contentBlockingEnabled;
       } else {
         document.querySelectorAll("#trackingProtectionRadioGroup > radio")
           .forEach((element) => {
             element.disabled = disabled;
           });
         document.querySelector("#trackingProtectionDesc > label")
           .disabled = disabled;
       }
@@ -487,26 +492,55 @@ var gPrivacyPane = {
     }
   },
 
   /**
    * Updates the preferences UI to reflect the browser.contentblocking.enabled pref.
    * This affects the button to toggle the pref and the disabled state of the dependent controls.
    */
   updateContentBlockingToggle() {
-    let enabled = Services.prefs.getBoolPref("browser.contentblocking.enabled");
-    let onOrOff = enabled ? "on" : "off";
+    let onOrOff = contentBlockingEnabled ? "on" : "off";
     let contentBlockingToggle = document.getElementById("contentBlockingToggle");
     let contentBlockingToggleLabel = document.getElementById("contentBlockingToggleLabel");
 
     document.l10n.setAttributes(contentBlockingToggle,
       "content-blocking-toggle-" + onOrOff);
-    contentBlockingToggle.setAttribute("aria-pressed", enabled);
+    contentBlockingToggle.setAttribute("aria-pressed", contentBlockingEnabled);
     document.l10n.setAttributes(contentBlockingToggleLabel,
       "content-blocking-toggle-label-" + onOrOff);
+
+    this.updateContentBlockingControls();
+  },
+
+  /**
+   * Changes the disabled state of controls that depend on the browser.contentblocking.enabled pref.
+   */
+  updateContentBlockingControls() {
+    let dependentControls = [
+      "#content-blocking-categories-label",
+      ".content-blocking-icon",
+      ".content-blocking-category-menu",
+      ".content-blocking-category-name",
+      "#changeBlockListLink",
+    ];
+
+    for (let selector of dependentControls) {
+      let controls = document.querySelectorAll(selector);
+
+      for (let control of controls) {
+        if (contentBlockingEnabled) {
+          control.removeAttribute("disabled");
+        } else {
+          control.setAttribute("disabled", "true");
+        }
+      }
+    }
+
+    // Need to make sure we account for pref locking/extension overrides when enabling the TP menu.
+    this._updateTrackingProtectionUI();
   },
 
   // TRACKING PROTECTION MODE
 
   /**
    * Selects the right item of the Tracking Protection radiogroup.
    */
   trackingProtectionReadPrefs() {
--- a/browser/components/preferences/in-content/tests/browser_contentblocking.js
+++ b/browser/components/preferences/in-content/tests/browser_contentblocking.js
@@ -141,8 +141,70 @@ add_task(async function testContentBlock
   }
 
   ok(Services.prefs.prefHasUserValue(TP_PREF), "did not reset the TP pref");
 
   await extension.unload();
 
   gBrowser.removeCurrentTab();
 });
+
+// Checks that the granular controls are disabled or enabled depending on the master pref for CB.
+add_task(async function testContentBlockingDependentControls() {
+  SpecialPowers.pushPrefEnv({set: [
+    [CB_UI_PREF, true],
+  ]});
+
+  let dependentControls = [
+    "#content-blocking-categories-label",
+    ".content-blocking-icon",
+    ".content-blocking-category-menu",
+    ".content-blocking-category-name",
+    "#changeBlockListLink",
+  ];
+
+  function checkControlState(doc) {
+    let enabled = Services.prefs.getBoolPref(CB_PREF);
+    for (let selector of dependentControls) {
+      let controls = doc.querySelectorAll(selector);
+      for (let control of controls) {
+        if (enabled) {
+          ok(!control.hasAttribute("disabled"), `${selector} is enabled because CB is on.`);
+        } else {
+          is(control.getAttribute("disabled"), "true", `${selector} is disabled because CB is off`);
+        }
+      }
+    }
+  }
+
+  Services.prefs.setBoolPref(CB_PREF, true);
+
+  await openPreferencesViaOpenPreferencesAPI("privacy", {leaveOpen: true});
+  let doc = gBrowser.contentDocument;
+
+  is(Services.prefs.getBoolPref(CB_PREF), true, "Content Blocking is on");
+  checkControlState(doc);
+
+  gBrowser.removeCurrentTab();
+
+  Services.prefs.setBoolPref(CB_PREF, false);
+
+  await openPreferencesViaOpenPreferencesAPI("privacy", {leaveOpen: true});
+  doc = gBrowser.contentDocument;
+
+  is(Services.prefs.getBoolPref(CB_PREF), false, "Content Blocking is off");
+  checkControlState(doc);
+
+  let contentBlockingToggle = doc.getElementById("contentBlockingToggle");
+  contentBlockingToggle.click();
+
+  is(Services.prefs.getBoolPref(CB_PREF), true, "Content Blocking is on");
+  checkControlState(doc);
+
+  contentBlockingToggle.click();
+
+  is(Services.prefs.getBoolPref(CB_PREF), false, "Content Blocking is off");
+  checkControlState(doc);
+
+  Services.prefs.clearUserPref("browser.contentblocking.enabled");
+  gBrowser.removeCurrentTab();
+});
+
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -436,16 +436,20 @@ button > hbox > label {
 #tabsElement {
   margin-inline-end: 4px; /* add the 4px end-margin of other elements */
 }
 
 .text-link {
   margin-bottom: 0;
 }
 
+.text-link[disabled="true"] {
+  pointer-events: none;
+}
+
 #showUpdateHistory {
   margin-inline-start: 0;
 }
 
 /**
  * Dialog
  */
 
--- a/browser/themes/shared/incontentprefs/privacy.css
+++ b/browser/themes/shared/incontentprefs/privacy.css
@@ -8,16 +8,20 @@
 .permission-icon {
   height: 20px;
   width: 20px;
   vertical-align: middle;
   -moz-context-properties: fill;
   fill: currentColor;
 }
 
+.content-blocking-icon[disabled] {
+  fill: GrayText;
+}
+
 .geo-icon {
   list-style-image: url(chrome://browser/skin/notification-icons/geo.svg);
 }
 
 .camera-icon {
   list-style-image: url(chrome://browser/skin/notification-icons/camera.svg);
 }