Bug 1499470 - Provide option to opt-out of add-on recommendations r=mixedpuppy,flod,Gijs
authorMark Striemer <mstriemer@mozilla.com>
Fri, 30 Nov 2018 14:19:04 +0000
changeset 505513 2c9bc41949eeec1b16efebb7704b104cf31aead3
parent 505512 6d3b77d3edc407d8d1740c56e7cb3ae139fbd4dd
child 505514 fedf8f5b79e57be608f1bf82f6bbe4728692f42b
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmixedpuppy, flod, Gijs
bugs1499470
milestone65.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 1499470 - Provide option to opt-out of add-on recommendations r=mixedpuppy,flod,Gijs Differential Revision: https://phabricator.services.mozilla.com/D13168
browser/app/profile/firefox.js
browser/components/preferences/in-content/privacy.js
browser/components/preferences/in-content/privacy.xul
browser/locales/en-US/browser/preferences/preferences.ftl
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1788,13 +1788,13 @@ pref("prio.publicKeyB", "26E6674E65425B8
 pref("toolkit.coverage.enabled", false);
 pref("toolkit.coverage.endpoint.base", "https://coverage.mozilla.org");
 // Whether or not Prio-encoded Telemetry will be sent along with the main ping.
 #if defined(NIGHTLY_BUILD) && defined(MOZ_LIBPRIO)
 pref("prio.enabled", true);
 #endif
 
 // Discovery prefs
-pref("browser.discovery.enabled", false);
+pref("browser.discovery.enabled", true);
 pref("browser.discovery.containers.enabled", true);
 pref("browser.discovery.sites", "addons.mozilla.org");
 
 pref("browser.engagement.recent_visited_origins.expiry", 86400); // 24 * 60 * 60 (24 hours in seconds)
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -24,16 +24,18 @@ const PREF_UPLOAD_ENABLED = "datareporti
 
 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";
 
+const PREF_ADDON_RECOMMENDATIONS_ENABLED = "browser.discovery.enabled";
+
 XPCOMUtils.defineLazyGetter(this, "AlertsServiceDND", function() {
   try {
     let alertsService = Cc["@mozilla.org/alerts-service;1"]
       .getService(Ci.nsIAlertsService)
       .QueryInterface(Ci.nsIAlertsDoNotDisturb);
     // This will throw if manualDoNotDisturb isn't implemented.
     alertsService.manualDoNotDisturb;
     return alertsService;
@@ -119,16 +121,17 @@ Preferences.addAll([
 
 ]);
 
 // Study opt out
 if (AppConstants.MOZ_DATA_REPORTING) {
   Preferences.addAll([
     // Preference instances for prefs that we need to monitor while the page is open.
     { id: PREF_OPT_OUT_STUDIES_ENABLED, type: "bool" },
+    { id: PREF_ADDON_RECOMMENDATIONS_ENABLED, type: "bool" },
     { id: PREF_UPLOAD_ENABLED, type: "bool" },
   ]);
 }
 
 // Data Choices tab
 if (AppConstants.NIGHTLY_BUILD) {
   Preferences.add({ id: "browser.chrome.errorReporter.enabled", type: "bool" });
 }
@@ -136,16 +139,45 @@ if (AppConstants.MOZ_CRASHREPORTER) {
   Preferences.add({ id: "browser.crashReports.unsubmittedCheck.autoSubmit2", type: "bool" });
 }
 
 function setEventListener(aId, aEventType, aCallback) {
   document.getElementById(aId)
     .addEventListener(aEventType, aCallback.bind(gPrivacyPane));
 }
 
+function dataCollectionCheckboxHandler({checkbox, pref, matchPref = () => true, isDisabled = () => false}) {
+  function updateCheckbox() {
+    let collectionEnabled = Services.prefs.getBoolPref(PREF_UPLOAD_ENABLED, false);
+
+    if (collectionEnabled && matchPref()) {
+      if (Services.prefs.getBoolPref(pref, false)) {
+        checkbox.setAttribute("checked", "true");
+      } else {
+        checkbox.removeAttribute("checked");
+      }
+      checkbox.setAttribute("preference", pref);
+    } else {
+      checkbox.removeAttribute("preference");
+      checkbox.removeAttribute("checked");
+    }
+
+    // We can't use checkbox.disabled here because the XBL binding may not be present,
+    // in which case setting the property won't work properly.
+    if (!collectionEnabled || Services.prefs.prefIsLocked(pref) || isDisabled()) {
+      checkbox.setAttribute("disabled", "true");
+    } else {
+      checkbox.removeAttribute("disabled");
+    }
+  }
+
+  Preferences.get(PREF_UPLOAD_ENABLED).on("change", updateCheckbox);
+  updateCheckbox();
+}
+
 var gPrivacyPane = {
   _pane: null,
 
   /**
    * Whether the prompt to restart Firefox should appear when changing the autostart pref.
    */
   _shouldPromptForRestart: true,
 
@@ -378,16 +410,17 @@ var gPrivacyPane = {
       }
       if (AppConstants.MOZ_CRASHREPORTER) {
         this.initSubmitCrashes();
       }
       this.initSubmitHealthReport();
       setEventListener("submitHealthReportBox", "command",
         gPrivacyPane.updateSubmitHealthReport);
       this.initOptOutStudyCheckbox();
+      this.initAddonRecommendationsCheckbox();
     }
     this._initA11yState();
     let signonBundle = document.getElementById("signonBundle");
     let pkiBundle = document.getElementById("pkiBundle");
     appendSearchKeywords("showPasswords", [
       signonBundle.getString("loginsDescriptionAll2"),
     ]);
     appendSearchKeywords("viewSecurityDevicesButton", [
@@ -1531,69 +1564,53 @@ var gPrivacyPane = {
 
 
   /**
    * Initialize the opt-out-study preference checkbox into about:preferences and
    * handles events coming from the UI for it.
    */
   initOptOutStudyCheckbox(doc) {
     const allowedByPolicy = Services.policies.isAllowed("Shield");
-    const checkbox = document.getElementById("optOutStudiesEnabled");
-
-    function updateStudyCheckboxState() {
-      // The checkbox should be disabled if any of the below are true. This
-      // prevents the user from changing the value in the box.
-      //
-      // * the policy forbids shield
-      // * the Shield Study preference is locked
-      // * the FHR pref is false
-      //
-      // The checkbox should match the value of the preference only if all of
-      // these are true. Otherwise, the checkbox should remain unchecked. This
-      // is because in these situations, Shield studies are always disabled, and
-      // so showing a checkbox would be confusing.
-      //
-      // * the policy allows Shield
-      // * the FHR pref is true
-      // * Normandy is enabled
-
-      const checkboxMatchesPref = (
-        allowedByPolicy &&
-        Services.prefs.getBoolPref(PREF_UPLOAD_ENABLED, false) &&
-        Services.prefs.getBoolPref(PREF_NORMANDY_ENABLED, false)
-      );
 
-      if (checkboxMatchesPref) {
-        if (Services.prefs.getBoolPref(PREF_OPT_OUT_STUDIES_ENABLED, false)) {
-          checkbox.setAttribute("checked", "checked");
-        } else {
-          checkbox.removeAttribute("checked");
-        }
-        checkbox.setAttribute("preference", PREF_OPT_OUT_STUDIES_ENABLED);
-      } else {
-        checkbox.removeAttribute("preference");
-        checkbox.removeAttribute("checked");
-      }
+    // The checkbox should be disabled if any of the below are true. This
+    // prevents the user from changing the value in the box.
+    //
+    // * the policy forbids shield
+    // * the Shield Study preference is locked
+    // * the FHR pref is false
+    //
+    // The checkbox should match the value of the preference only if all of
+    // these are true. Otherwise, the checkbox should remain unchecked. This
+    // is because in these situations, Shield studies are always disabled, and
+    // so showing a checkbox would be confusing.
+    //
+    // * the policy allows Shield
+    // * the FHR pref is true
+    // * Normandy is enabled
+    dataCollectionCheckboxHandler({
+      checkbox: document.getElementById("optOutStudiesEnabled"),
+      matchPref: () => (
+        allowedByPolicy &&
+        Services.prefs.getBoolPref(PREF_NORMANDY_ENABLED, false)
+      ),
+      isDisabled: () => !allowedByPolicy,
+      pref: PREF_OPT_OUT_STUDIES_ENABLED,
+    });
+  },
 
-      const isDisabled = (
-        !allowedByPolicy ||
-        Services.prefs.prefIsLocked(PREF_OPT_OUT_STUDIES_ENABLED) ||
-        !Services.prefs.getBoolPref(PREF_UPLOAD_ENABLED, false)
-      );
+  initAddonRecommendationsCheckbox() {
+    // Setup the learn more link.
+    const url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "personalized-addons";
+    document.getElementById("addonRecommendationLearnMore").setAttribute("href", url);
 
-      // We can't use checkbox.disabled here because the XBL binding may not be present,
-      // in which case setting the property won't work properly.
-      if (isDisabled) {
-        checkbox.setAttribute("disabled", "true");
-      } else {
-        checkbox.removeAttribute("disabled");
-      }
-    }
-    Preferences.get(PREF_UPLOAD_ENABLED).on("change", updateStudyCheckboxState);
-    updateStudyCheckboxState();
+    // Setup the checkbox.
+    dataCollectionCheckboxHandler({
+      checkbox: document.getElementById("addonRecommendationEnabled"),
+      pref: PREF_ADDON_RECOMMENDATIONS_ENABLED,
+    });
   },
 
   observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "sitedatamanager:updating-sites":
         // While updating, we want to disable this section and display loading message until updated
         this.toggleSiteData(false);
         this.showSiteDataLoading();
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -694,16 +694,25 @@
                     class="tail-with-learn-more"
                     data-l10n-id="collection-studies"/>
           <label id="viewShieldStudies"
                  href="about:studies"
                  useoriginprincipal="true"
                  class="learnMore text-link"
                  data-l10n-id="collection-studies-link"/>
         </hbox>
+
+        <hbox align="center">
+          <checkbox id="addonRecommendationEnabled"
+                    class="tail-with-learn-more"
+                    data-l10n-id="addon-recommendations"/>
+          <label id="addonRecommendationLearnMore"
+                 class="learnMore text-link"
+                 data-l10n-id="addon-recommendations-link"/>
+        </hbox>
       </vbox>
     </description>
 #ifndef MOZ_TELEMETRY_REPORTING
   <description id="TelemetryDisabledDesc"
     class="indent tip-caption" control="telemetryGroup"
     data-l10n-id="collection-health-report-disabled"/>
 #endif
 
--- a/browser/locales/en-US/browser/preferences/preferences.ftl
+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -948,16 +948,20 @@ collection-health-report =
     .label = Allow { -brand-short-name } to send technical and interaction data to { -vendor-short-name }
     .accesskey = r
 collection-health-report-link = Learn more
 
 collection-studies =
     .label = Allow { -brand-short-name } to install and run studies
 collection-studies-link = View { -brand-short-name } studies
 
+addon-recommendations =
+    .label = Allow { -brand-short-name } to make personalized extension recommendations
+addon-recommendations-link = Learn more
+
 # This message is displayed above disabled data sharing options in developer builds
 # or builds with no Telemetry support available.
 collection-health-report-disabled = Data reporting is disabled for this build configuration
 
 collection-browser-errors =
     .label = Allow { -brand-short-name } to send browser error reports (including error messages) to { -vendor-short-name }
     .accesskey = b
 collection-browser-errors-link = Learn more