Bug 1526075 - Warn user and provide option to refresh tabs to apply content blocking changes. r=johannh,flod
authorErica Wright <ewright@mozilla.com>
Wed, 13 Mar 2019 14:57:40 +0000
changeset 524711 492c2ba4953f52eaa00b35fdf35312f89eceb18f
parent 524710 fffb4b5030daf853ff9d61453f3132c3295a6a3b
child 524712 5dc0ae1f1b48630aeee9ee07c2dcbda345ad3a2b
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjohannh, flod
bugs1526075
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1526075 - Warn user and provide option to refresh tabs to apply content blocking changes. r=johannh,flod When user changes a content blocking pref, warn them they need to refresh their tabs, and show them a button to do it. Differential Revision: https://phabricator.services.mozilla.com/D22600
browser/components/preferences/in-content/privacy.js
browser/components/preferences/in-content/privacy.xul
browser/components/preferences/in-content/tests/browser_contentblocking.js
browser/locales/en-US/browser/preferences/preferences.ftl
browser/themes/shared/incontentprefs/privacy.css
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -48,16 +48,19 @@ XPCOMUtils.defineLazyGetter(this, "Alert
 
 Preferences.addAll([
   // Content blocking / Tracking Protection
   { id: "privacy.trackingprotection.enabled", type: "bool" },
   { id: "privacy.trackingprotection.pbmode.enabled", type: "bool" },
   { id: "privacy.trackingprotection.fingerprinting.enabled", type: "bool" },
   { id: "privacy.trackingprotection.cryptomining.enabled", type: "bool" },
 
+  // Tracker list
+  { id: "urlclassifier.trackingTable", type: "string"},
+
   // Button prefs
   { id: "pref.privacy.disable_button.cookie_exceptions", type: "bool" },
   { id: "pref.privacy.disable_button.view_cookies", type: "bool" },
   { id: "pref.privacy.disable_button.change_blocklist", type: "bool" },
   { id: "pref.privacy.disable_button.tracking_protection_exceptions", type: "bool" },
 
   // Location Bar
   { id: "browser.urlbar.suggest.bookmark", type: "bool" },
@@ -459,16 +462,25 @@ var gPrivacyPane = {
     setEventListener("strictArrow", "command", this.toggleExpansion);
     setEventListener("customArrow", "command", this.toggleExpansion);
 
     Preferences.get("network.cookie.cookieBehavior").on("change",
       gPrivacyPane.readBlockCookies.bind(gPrivacyPane));
     Preferences.get("browser.contentblocking.category").on("change",
       gPrivacyPane.highlightCBCategory);
 
+    // If any relevant content blocking pref changes, show a warning that the changes will
+    // not be implemented until they refresh their tabs.
+    for (let pref of CONTENT_BLOCKING_PREFS) {
+      Preferences.get(pref).on("change", gPrivacyPane.notifyUserToReload);
+    }
+    for (let button of document.querySelectorAll(".reload-tabs-button")) {
+      button.addEventListener("command", gPrivacyPane.reloadAllTabs);
+    }
+
     let cryptoMinersOption = document.getElementById("contentBlockingCryptominersOption");
     let fingerprintersOption = document.getElementById("contentBlockingFingerprintersOption");
 
     cryptoMinersOption.hidden =
       !Services.prefs.getBoolPref("browser.contentblocking.cryptomining.preferences.ui.enabled");
     fingerprintersOption.hidden =
       !Services.prefs.getBoolPref("browser.contentblocking.fingerprinting.preferences.ui.enabled");
 
@@ -1008,16 +1020,35 @@ var gPrivacyPane = {
       case "all-third-parties":
         return Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN;
       default:
         return undefined;
     }
   },
 
   /**
+   * Reload all tabs in all windows.
+   */
+  reloadAllTabs() {
+    for (let win of window.BrowserWindowTracker.orderedWindows) {
+      let tabbrowser = win.getBrowser();
+      tabbrowser.reloadTabs(tabbrowser.tabs);
+    }
+  },
+
+  /**
+   * Show a warning to the user that they need to reload their tabs to apply the setting.
+   */
+  notifyUserToReload() {
+    for (let notification of document.querySelectorAll(".reload-tabs")) {
+      notification.hidden = false;
+    }
+  },
+
+  /**
    * Displays fine-grained, per-site preferences for cookies.
    */
   showCookieExceptions() {
     var params = {
       blockVisible: true,
       sessionVisible: true,
       allowVisible: true,
       prefilledHost: "",
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -70,20 +70,68 @@
                     <image class="content-blocking-trackers-image"/>
                     <label data-l10n-id="content-blocking-private-trackers"/>
                   </hbox>
                   <hbox class="extra-information-label">
                     <image class="content-blocking-cookies-image"/>
                     <label data-l10n-id="content-blocking-third-party-cookies"/>
                   </hbox>
                 </vbox>
+                <vbox class="content-blocking-warning reload-tabs" hidden="true">
+                  <hbox class="indent">
+                    <vbox>
+                      <spacer flex="1"/>
+                      <hbox>
+                        <vbox>
+                          <image class="content-blocking-info-image"/>
+                          <spacer flex="1"/>
+                        </vbox>
+                        <description>
+                          <html:span data-l10n-id="content-blocking-reload-description"></html:span>
+                        </description>
+                      </hbox>
+                      <spacer flex="1"/>
+                    </vbox>
+                    <vbox>
+                      <spacer flex="1"/>
+                      <button class="accessory-button reload-tabs-button"
+                              data-l10n-id="content-blocking-reload-tabs-button"/>
+                      <spacer flex="1"/>
+                    </vbox>
+                  </hbox>
+                </vbox>
               </vbox>
             </vbox>
             <vbox class="indent fallback-content-blocking-ui">
               <description data-l10n-id="content-blocking-standard-description"/>
+              <vbox class="content-blocking-extra-information">
+                <vbox class="content-blocking-warning reload-tabs" hidden="true">
+                  <hbox class="indent">
+                    <vbox>
+                      <spacer flex="1"/>
+                      <hbox>
+                        <vbox>
+                          <image class="content-blocking-info-image"/>
+                          <spacer flex="1"/>
+                        </vbox>
+                        <description>
+                          <html:span data-l10n-id="content-blocking-reload-description"></html:span>
+                        </description>
+                      </hbox>
+                      <spacer flex="1"/>
+                    </vbox>
+                    <vbox>
+                      <spacer flex="1"/>
+                      <button class="accessory-button reload-tabs-button"
+                              data-l10n-id="content-blocking-reload-tabs-button"/>
+                      <spacer flex="1"/>
+                    </vbox>
+                  </hbox>
+                </vbox>
+              </vbox>
             </vbox>
           </vbox>
           <vbox id="contentBlockingOptionStrict" class="content-blocking-category">
             <hbox>
               <radio id="strictRadio"
                      value="strict"
                      data-l10n-id="content-blocking-setting-strict"
                      flex="1"/>
@@ -100,16 +148,39 @@
                     <image class="content-blocking-trackers-image"/>
                     <label data-l10n-id="content-blocking-all-windows-trackers"/>
                   </hbox>
                   <hbox class="extra-information-label">
                     <image class="content-blocking-cookies-image"/>
                     <label data-l10n-id="content-blocking-third-party-cookies"/>
                   </hbox>
                 </vbox>
+                <vbox class="content-blocking-warning reload-tabs" hidden="true">
+                  <hbox class="indent">
+                    <vbox>
+                      <spacer flex="1"/>
+                      <hbox>
+                        <vbox>
+                          <image class="content-blocking-info-image"/>
+                          <spacer flex="1"/>
+                        </vbox>
+                        <description>
+                          <html:span data-l10n-id="content-blocking-reload-description"></html:span>
+                        </description>
+                      </hbox>
+                      <spacer flex="1"/>
+                    </vbox>
+                    <vbox>
+                      <spacer flex="1"/>
+                      <button class="accessory-button reload-tabs-button"
+                              data-l10n-id="content-blocking-reload-tabs-button"/>
+                      <spacer flex="1"/>
+                    </vbox>
+                  </hbox>
+                </vbox>
                 <vbox class="content-blocking-warning">
                   <vbox class="indent">
                     <hbox>
                       <image class="content-blocking-warning-image"/>
                       <label class="content-blocking-warning-title" data-l10n-id="content-blocking-warning-title"/>
                     </hbox>
                     <description class="indent">
                       <html:span class="tail-with-learn-more" data-l10n-id="content-blocking-warning-description"></html:span>
@@ -193,16 +264,39 @@
                 </hbox>
                 <hbox class="custom-option" id="contentBlockingFingerprintersOption">
                   <checkbox id="contentBlockingFingerprintersCheckbox"
                             class="content-blocking-checkbox" flex="1"
                             preference="privacy.trackingprotection.fingerprinting.enabled"
                             data-l10n-id="content-blocking-fingerprinters-label"
                             aria-describedby="contentBlockingCustomDesc"/>
                 </hbox>
+              <vbox class="content-blocking-warning reload-tabs" hidden="true">
+                <hbox class="indent">
+                  <vbox>
+                    <spacer flex="1"/>
+                    <hbox>
+                      <vbox>
+                        <image class="content-blocking-info-image"/>
+                        <spacer flex="1"/>
+                      </vbox>
+                      <description>
+                        <html:span data-l10n-id="content-blocking-reload-description"></html:span>
+                      </description>
+                    </hbox>
+                    <spacer flex="1"/>
+                  </vbox>
+                  <vbox>
+                    <spacer flex="1"/>
+                    <button class="accessory-button reload-tabs-button"
+                            data-l10n-id="content-blocking-reload-tabs-button"/>
+                    <spacer flex="1"/>
+                  </vbox>
+                </hbox>
+              </vbox>
               <vbox class="content-blocking-warning">
                 <vbox class="indent">
                   <hbox>
                     <image class="content-blocking-warning-image"/>
                     <label class="content-blocking-warning-title" data-l10n-id="content-blocking-warning-title"/>
                   </hbox>
                   <description class="indent">
                     <html:span class="tail-with-learn-more" data-l10n-id="content-blocking-warning-description"></html:span>
--- a/browser/components/preferences/in-content/tests/browser_contentblocking.js
+++ b/browser/components/preferences/in-content/tests/browser_contentblocking.js
@@ -11,26 +11,16 @@ const CAT_PREF = "browser.contentblockin
 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.
 add_task(async function testContentBlockingMainCategory() {
   let prefs = [
     [TP_PREF, false],
     [TP_PBM_PREF, true],
     [NCB_PREF, Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
@@ -408,9 +398,37 @@ add_task(async function testPolicyCatego
 
   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();
+
+  // Cleanup after this particular test.
+  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();
 });
+
+// Tests that changing a content blocking pref shows the content blocking warning
+// to reload tabs to apply changes.
+add_task(async function testContentBlockingReloadWarning() {
+  Services.prefs.setStringPref(CAT_PREF, "standard");
+  await openPreferencesViaOpenPreferencesAPI("privacy", {leaveOpen: true});
+  let doc = gBrowser.contentDocument;
+  let reloadWarnings = [...doc.querySelectorAll(".content-blocking-warning.reload-tabs")];
+  let allHidden = reloadWarnings.every((el) => el.hidden);
+  ok(allHidden, "all of the warnings to reload tabs are initially hidden");
+
+  Services.prefs.setStringPref(CAT_PREF, "strict");
+
+  let strictWarning = doc.querySelector("#contentBlockingOptionStrict .content-blocking-warning.reload-tabs");
+  ok(!BrowserTestUtils.is_hidden(strictWarning), "The warning in the strict section should be showing");
+
+  Services.prefs.setStringPref(CAT_PREF, "standard");
+  gBrowser.removeCurrentTab();
+});
--- a/browser/locales/en-US/browser/preferences/preferences.ftl
+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -849,16 +849,21 @@ content-blocking-private-trackers = Know
 content-blocking-third-party-cookies = Third-party tracking cookies
 content-blocking-all-windows-trackers = Known trackers in all windows
 content-blocking-all-third-party-cookies = All third-party cookies
 
 content-blocking-warning-title = Heads up!
 content-blocking-warning-description = Blocking content can cause some websites to break. It’s easy to disable blocking for sites you trust.
 content-blocking-learn-how = Learn how
 
+content-blocking-reload-description = You will need to reload your tabs to apply these changes.
+content-blocking-reload-tabs-button =
+  .label = Reload All Tabs
+  .accesskey = R
+
 content-blocking-trackers-label =
   .label = Trackers
   .accesskey = T
 content-blocking-tracking-protection-option-all-windows =
   .label = In all windows
   .accesskey = A
 content-blocking-option-private =
   .label = Only in Private Windows
--- a/browser/themes/shared/incontentprefs/privacy.css
+++ b/browser/themes/shared/incontentprefs/privacy.css
@@ -159,16 +159,63 @@
 .arrowhead.up {
   background-image: url("chrome://global/skin/icons/arrow-up-12.svg");
 }
 
 .arrowhead > .button-box {
   padding: 0 !important;
 }
 
+.content-blocking-category.expanded:not(.selected) .reload-tabs {
+  display: none;
+}
+
+.content-blocking-warning.reload-tabs description {
+  width: 318px;
+  margin-inline-end: 5px;
+}
+
+.content-blocking-warning.reload-tabs .indent {
+  min-height: 30px;
+}
+
+.content-blocking-warning.reload-tabs .content-blocking-info-image {
+  list-style-image: url(chrome://browser/skin/identity-icon.svg);
+  margin-top: 5px;
+  margin-inline-end: 8px;
+  margin-inline-start: 4px;
+}
+
+.reload-tabs-button {
+  -moz-context-properties: fill;
+  fill: currentColor;
+  max-height: 30px;
+  min-height: 30px;
+  padding: 0 20px;
+  list-style-image: url("chrome://browser/skin/reload.svg");
+  background-color: var(--blue-50);
+}
+
+.reload-tabs-button:not([disabled="true"]):hover {
+  background-color: var(--blue-60);
+}
+
+.reload-tabs-button:not([disabled="true"]):hover:active {
+  background-color: var(--blue-70);
+}
+
+.reload-tabs-button .button-icon {
+  margin: 0 6px;
+  color: white;
+}
+
+.reload-tabs-button .button-text {
+  color: white;
+}
+
 .content-blocking-category.expanded:not(.selected) .content-blocking-warning {
   background-color: var(--grey-90-a10);
 }
 
 .content-blocking-category.selected .arrowhead {
   display: none;
 }
 
@@ -205,16 +252,20 @@
 
 .content-blocking-warning {
   background-color: rgba(69, 161, 255, 0.2);
   border-radius: 4px;
   padding: 10px 0;
   margin: 10px 0;
 }
 
+.content-blocking-warning + .content-blocking-warning {
+  margin-top: 0;
+}
+
 .content-blocking-trackers-image {
   list-style-image: url("chrome://browser/skin/controlcenter/trackers-disabled.svg");
   margin-inline-end: 5px;
 }
 
 .content-blocking-cookies-image {
   list-style-image: url("chrome://browser/skin/controlcenter/3rdpartycookies-disabled.svg");
   margin-inline-end: 5px;