Bug 809094 - Move data upload choices to Advanced pref pane, add FHR option; r=gavin, gps, a=akeybl
authorMike Connor <mconnor@mozilla.com>
Thu, 03 Jan 2013 23:45:15 -0500
changeset 127228 293ee495f43996875a933b95a744e25be754ab5b
parent 127227 509fb1a9021b6bd213c7f30a109d4211a6f56501
child 127229 50db9b596a5dade0f225b4eaa1a59b3cebbbd153
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin, gps, akeybl
bugs809094
milestone20.0a2
Bug 809094 - Move data upload choices to Advanced pref pane, add FHR option; r=gavin, gps, a=akeybl
browser/app/profile/firefox.js
browser/components/preferences/advanced.js
browser/components/preferences/advanced.xul
browser/components/preferences/in-content/advanced.js
browser/components/preferences/in-content/advanced.xul
browser/components/preferences/in-content/tests/Makefile.in
browser/components/preferences/in-content/tests/browser_healthreport.js
browser/components/preferences/tests/Makefile.in
browser/components/preferences/tests/browser_healthreport.js
browser/locales/en-US/chrome/browser/preferences/advanced.dtd
services/healthreport/healthreport-prefs.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -852,16 +852,20 @@ pref("browser.zoom.updateBackgroundTabs"
 
 // The breakpad report server to link to in about:crashes
 pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/");
 
 // Override submission of plugin hang reports to a different processing server
 pref("toolkit.crashreporter.pluginHangSubmitURL",
      "https://hang-reports.mozilla.org/submit");
 
+// URL for "Learn More" for Crash Reporter
+pref("toolkit.crashreporter.infoURL",
+     "http://www.mozilla.com/legal/privacy/firefox.html#crash-reporter");
+
 // base URL for web-based support pages
 pref("app.support.baseURL", "http://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/");
 
 // Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
 pref("security.alternate_certificate_error_page", "certerror");
 
 // Whether to start the private browsing mode at application startup
 pref("browser.privatebrowsing.autostart", false);
--- a/browser/components/preferences/advanced.js
+++ b/browser/components/preferences/advanced.js
@@ -43,19 +43,21 @@ var gAdvancedPane = {
 
 #ifdef MOZ_UPDATER
     this.updateReadPrefs();
 #endif
     this.updateOfflineApps();
 #ifdef MOZ_CRASHREPORTER
     this.initSubmitCrashes();
 #endif
-#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
     this.initTelemetry();
+#ifdef MOZ_SERVICES_HEALTHREPORT
+    this.initSubmitHealthReport();
 #endif
+
     this.updateActualCacheSize("disk");
     this.updateActualCacheSize("offline");
 
     // Notify observers that the UI is now ready
     Services.obs.notifyObservers(window, "advanced-pane-loaded", null);
   },
 
   /**
@@ -125,89 +127,164 @@ var gAdvancedPane = {
    */
   writeCheckSpelling: function ()
   {
     var checkbox = document.getElementById("checkSpelling");
     return checkbox.checked ? (this._storedSpellCheck == 2 ? 2 : 1) : 0;
   },
 
   /**
+   * When the user toggles the layers.acceleration.disabled pref,
+   * sync its new value to the gfx.direct2d.disabled pref too.
+   */
+  updateHardwareAcceleration: function()
+  {
+#ifdef XP_WIN
+    var fromPref = document.getElementById("layers.acceleration.disabled");
+    var toPref = document.getElementById("gfx.direct2d.disabled");
+    toPref.value = fromPref.value;
+#endif
+  },
+
+  // DATA CHOICES TAB
+
+  /**
+   * Set up or hide the Learn More links for various data collection options
+   */
+  _setupLearnMoreLink: function (pref, element) {
+    // set up the Learn More link with the correct URL
+    let url = Services.prefs.getCharPref(pref);
+    let el = document.getElementById(element);
+
+    if (url) {
+      el.setAttribute("href", url);
+    } else {
+      el.setAttribute("hidden", "true");
+    }
+  },
+
+  /**
    *
    */
   initSubmitCrashes: function ()
   {
     var checkbox = document.getElementById("submitCrashesBox");
     try {
       var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"].
                getService(Components.interfaces.nsICrashReporter);
       checkbox.checked = cr.submitReports;
     } catch (e) {
       checkbox.style.display = "none";
     }
+    this._setupLearnMoreLink("toolkit.crashreporter.infoURL", "crashReporterLearnMore");
   },
 
   /**
    *
    */
   updateSubmitCrashes: function ()
   {
     var checkbox = document.getElementById("submitCrashesBox");
     try {
       var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"].
                getService(Components.interfaces.nsICrashReporter);
       cr.submitReports = checkbox.checked;
     } catch (e) { }
   },
 
-#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
+
   /**
    * When telemetry is opt-out, verify if the user explicitly rejected the
    * telemetry prompt, and if so reflect his choice in the current preference
    * value. This doesn't cover the case where the user refused telemetry in the
    * prompt but later enabled it in preferences in builds before the fix for
    * bug 737600.
+   *
+   * In all cases, set up the Learn More link sanely
    */
   initTelemetry: function ()
   {
+#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
     const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabledPreRelease";
     let enabled = Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED);
     let rejected = false;
     try {
       rejected = Services.prefs.getBoolPref("toolkit.telemetry.rejected");
     } catch (e) {}
     if (enabled && rejected) {
       Services.prefs.setBoolPref(PREF_TELEMETRY_ENABLED, false);
     }
+#endif
+#ifdef MOZ_TELEMETRY_REPORTING
+    this._setupLearnMoreLink("toolkit.telemetry.infoURL", "telemetryLearnMore");
+#endif
   },
-#endif
 
   /**
    * When the user toggles telemetry, update the rejected value as well, so we
    * know he expressed a choice, and don't re-prompt inadvertently.
    */
   telemetryEnabledChanged: function (event)
   {
     let rejected = document.getElementById("toolkit.telemetry.rejected");
     rejected.value = !event.target.value;
     let displayed = document.getElementById("toolkit.telemetry.prompted");
     displayed.value = @MOZ_TELEMETRY_DISPLAY_REV@;
   },
 
+#ifdef MOZ_SERVICES_HEALTHREPORT
   /**
-   * When the user toggles the layers.acceleration.disabled pref,
-   * sync its new value to the gfx.direct2d.disabled pref too.
+   * Initialize the health report service reference and checkbox.
+   */
+  initSubmitHealthReport: function () {
+    this._setupLearnMoreLink("healthreport.infoURL", "FHRLearnMore");
+
+    let reporter = Components.classes["@mozilla.org/healthreport/service;1"]
+                                     .getService(Components.interfaces.nsISupports)
+                                     .wrappedJSObject
+                                     .reporter;
+
+    let checkbox = document.getElementById("submitHealthReportBox");
+
+    if (!reporter) {
+      checkbox.setAttribute("disabled", "true");
+      return;
+    }
+
+    checkbox.checked = reporter.dataSubmissionPolicyAccepted;
+  },
+
+  /**
+   * Update the health report policy acceptance with state from checkbox.
    */
-  updateHardwareAcceleration: function()
-  {
-#ifdef XP_WIN
-    var fromPref = document.getElementById("layers.acceleration.disabled");
-    var toPref = document.getElementById("gfx.direct2d.disabled");
-    toPref.value = fromPref.value;
+  updateSubmitHealthReport: function () {
+    let reporter = Components.classes["@mozilla.org/healthreport/service;1"]
+                                     .getService(Components.interfaces.nsISupports)
+                                     .wrappedJSObject
+                                     .reporter;
+
+    if (!reporter) {
+      return;
+    }
+
+    let checkbox = document.getElementById("submitHealthReportBox");
+
+    let accepted = reporter.dataSubmissionPolicyAccepted;
+
+    if (checkbox.checked && !accepted) {
+      reporter.recordPolicyAcceptance("pref-checkbox-checked");
+      return;
+    }
+
+    if (!checkbox.checked && accepted) {
+      reporter.recordPolicyRejection("pref-checkbox-unchecked");
+      return;
+    }
+  },
 #endif
-  },
 
   // NETWORK TAB
 
   /*
    * Preferences:
    *
    * browser.cache.disk.capacity
    * - the size of the browser cache in KB
--- a/browser/components/preferences/advanced.xul
+++ b/browser/components/preferences/advanced.xul
@@ -45,16 +45,18 @@
                   name="browser.shell.checkDefaultBrowser"
                   type="bool"/>
 
       <preference id="pref.general.disable_button.default_browser"
                   name="pref.general.disable_button.default_browser"
                   type="bool"/>
 #endif
 
+      <!-- Data Choices tab -->
+
 #ifdef MOZ_TELEMETRY_REPORTING
       <preference id="toolkit.telemetry.enabled"
 #ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
                   name="toolkit.telemetry.enabledPreRelease"
 #else
                   name="toolkit.telemetry.enabled"
 #endif
                   onchange="gAdvancedPane.telemetryEnabledChanged(event);"
@@ -69,22 +71,22 @@
       <preference id="toolkit.telemetry.rejected"
                   name="toolkit.telemetry.rejected"
                   type="bool"/>
 #endif
 
       <!-- Network tab -->
       <preference id="browser.cache.disk.capacity"     name="browser.cache.disk.capacity"     type="int"/>
       <preference id="browser.offline-apps.notify"     name="browser.offline-apps.notify"     type="bool"/>
- 
+
       <preference id="browser.cache.disk.smart_size.enabled"
                   name="browser.cache.disk.smart_size.enabled"
                   inverted="true"
                   type="bool"/>
- 
+
      <!-- Update tab -->
 #ifdef MOZ_UPDATER
       <preference id="app.update.enabled"              name="app.update.enabled"              type="bool"/>
       <preference id="app.update.auto"                 name="app.update.auto"                 type="bool"/>
       <preference id="app.update.mode"                 name="app.update.mode"                 type="int"/>
 
       <preference id="app.update.disable_button.showUpdateHistory"
                   name="app.update.disable_button.showUpdateHistory"
@@ -110,29 +112,30 @@
                   type="bool"/>
       <preference id="security.OCSP.disable_button.managecrl"
                   name="security.OCSP.disable_button.managecrl"
                   type="bool"/>
       <preference id="security.disable_button.openDeviceManager"
                   name="security.disable_button.openDeviceManager"
                   type="bool"/>
     </preferences>
-    
+
 #ifdef HAVE_SHELL_SERVICE
     <stringbundle id="bundleShell" src="chrome://browser/locale/shellservice.properties"/>
     <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
 #endif
 
     <script type="application/javascript" src="chrome://browser/content/preferences/advanced.js"/>
 
     <tabbox id="advancedPrefs" flex="1"
             onselect="gAdvancedPane.tabSelectionChanged();">
 
       <tabs id="tabsElement">
         <tab id="generalTab" label="&generalTab.label;" helpTopic="prefs-advanced-general"/>
+        <tab id="dataChoicesTab" label="&dataChoicesTab.label;" helpTopic="prefs-advanced-data-choices"/>
         <tab id="networkTab" label="&networkTab.label;" helpTopic="prefs-advanced-network"/>
         <tab id="updateTab" label="&updateTab.label;"  helpTopic="prefs-advanced-update"/>
         <tab id="encryptionTab" label="&encryptionTab.label;" helpTopic="prefs-advanced-encryption"/>
       </tabs>
 
       <tabpanels flex="1">
 
         <!-- General -->
@@ -175,47 +178,98 @@
             <checkbox id="checkSpelling"
                       label="&checkSpelling.label;"
                       accesskey="&checkSpelling.accesskey;"
                       onsyncfrompreference="return gAdvancedPane.readCheckSpelling();"
                       onsynctopreference="return gAdvancedPane.writeCheckSpelling();"
                       preference="layout.spellcheckDefault"/>
           </groupbox>
 
+#ifdef HAVE_SHELL_SERVICE
           <!-- System Defaults -->
           <groupbox id="systemDefaultsGroup" orient="vertical">
             <caption label="&systemDefaults.label;"/>
 
-#ifdef HAVE_SHELL_SERVICE
             <checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
                       label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;"
                       flex="1"/>
             <hbox class="indent">
               <deck id="setDefaultPane">
                 <button id="setDefaultButton"
                         label="&setDefault.label;" accesskey="&setDefault.accesskey;"
                         oncommand="gAdvancedPane.setDefaultBrowser();"
                         preference="pref.general.disable_button.default_browser"/>
                 <description>&isDefault.label;</description>
               </deck>
             </hbox>
-#ifdef MOZ_CRASHREPORTER
-            <checkbox id="submitCrashesBox" flex="1"
-                      oncommand="gAdvancedPane.updateSubmitCrashes();"
-                      label="&submitCrashes.label;" accesskey="&submitCrashes.accesskey;"/>
+          </groupbox>
+#endif
+        </tabpanel>
+
+#ifndef MOZ_TELEMETRY_REPORTING
+#ifndef MOZ_SERVICES_HEALTHREPORT
+#ifndef MOZ_CRASHREPORTER
+#define HIDE_DATACHOICES
+#endif
 #endif
 #endif
+#ifndef HIDE_DATACHOICES
+        <!-- Data Choices -->
+        <tabpanel id="dataChoicesPanel" orient="vertical">
 #ifdef MOZ_TELEMETRY_REPORTING
-            <checkbox id="submitTelemetryBox" flex="1"
-                      preference="toolkit.telemetry.enabled"
-                      label="&submitTelemetry.label;" accesskey="&submitTelemetry.accesskey;"/>
+          <groupbox>
+            <caption label="&telemetrySection.label;"/>
+            <description>&telemetryDesc.label;</description>
+            <hbox>
+              <checkbox id="submitTelemetryBox"
+                        preference="toolkit.telemetry.enabled"
+                        label="&enableTelemetry.label;"
+                        accesskey="&enableTelemetry.accesskey;"/>
+              <spacer flex="1"/>
+              <label id="telemetryLearnMore"
+                     class="text-link"
+                     value="&telemetryLearnMore.label;"/>
+            </hbox>
+          </groupbox>
 #endif
+#ifdef MOZ_SERVICES_HEALTHREPORT
+          <groupbox>
+            <caption label="&FHRSection.label;"/>
+            <description>&FHRDesc.label;</description>
+            <hbox>
+              <checkbox id="submitHealthReportBox"
+                        oncommand="gAdvancedPane.updateSubmitHealthReport();"
+                        label="&enableFHR.label;"
+                        accesskey="&enableFHR.accesskey;"/>
+              <spacer flex="1"/>
+              <label id="FHRLearnMore"
+                     class="text-link"
+                     value="&FHRLearnMore.label;"/>
+            </hbox>
           </groupbox>
+#endif
+#ifdef MOZ_CRASHREPORTER
+          <groupbox>
+            <caption label="&crashReporterSection.label;"/>
+            <description>&crashReporterDesc.label;</description>
+            <hbox>
+              <checkbox id="submitCrashesBox"
+                        oncommand="gAdvancedPane.updateSubmitCrashes();"
+                        label="&enableCrashReporter.label;"
+                        accesskey="&enableCrashReporter.accesskey;"/>
+
+              <spacer flex="1"/>
+              <label id="crashReporterLearnMore"
+                     class="text-link"
+                     value="&crashReporterLearnMore.label;"/>
+            </hbox>
+          </groupbox>
+#endif
         </tabpanel>
-
+#endif
         <!-- Network -->
         <tabpanel id="networkPanel" orient="vertical">
 
           <!-- Connection -->
           <groupbox id="connectionGroup">
             <caption label="&connection.label;"/>
 
             <hbox align="center">
@@ -234,21 +288,21 @@
               <label id="actualDiskCacheSize" flex="1"/>
               <button id="clearCacheButton" icon="clear"
                       label="&clearCacheNow.label;" accesskey="&clearCacheNow.accesskey;"
                       oncommand="gAdvancedPane.clearCache();"/>
             </hbox>
             <checkbox preference="browser.cache.disk.smart_size.enabled"
                       id="allowSmartSize" flex="1"
                       onsyncfrompreference="return gAdvancedPane.readSmartSizeEnabled();"
-                      label="&overrideSmartCacheSize.label;" 
+                      label="&overrideSmartCacheSize.label;"
                       accesskey="&overrideSmartCacheSize.accesskey;"/>
             <hbox align="center" class="indent">
               <label id="useCacheBefore" control="cacheSize"
-                     accesskey="&limitCacheSizeBefore.accesskey;" 
+                     accesskey="&limitCacheSizeBefore.accesskey;"
                      value="&limitCacheSizeBefore.label;"/>
               <textbox id="cacheSize" type="number" size="4" max="1024"
                        preference="browser.cache.disk.capacity"
                        onsyncfrompreference="return gAdvancedPane.readCacheSize();"
                        onsynctopreference="return gAdvancedPane.writeCacheSize();"
                        aria-labelledby="useCacheBefore cacheSize useCacheAfter"/>
               <label id="useCacheAfter" flex="1">&limitCacheSizeAfter.label;</label>
             </hbox>
@@ -283,17 +337,17 @@
                          aria-labelledby="offlineAppsListLabel"
                          onselect="gAdvancedPane.offlineAppSelected(event);">
                 </listbox>
               </vbox>
               <vbox pack="end">
                 <button id="offlineAppsListRemove"
                         disabled="true"
                         label="&offlineAppsListRemove.label;"
-                        accesskey="&offlineAppsListRemove.accesskey;" 
+                        accesskey="&offlineAppsListRemove.accesskey;"
                         oncommand="gAdvancedPane.removeOfflineApp();"/>
               </vbox>
             </hbox>
           </groupbox>
         </tabpanel>
 
         <!-- Update -->
         <tabpanel id="updatePanel" orient="vertical">
@@ -384,38 +438,38 @@
             <!--
               The values on these radio buttons may look like l12y issues, but
               they're not - this preference uses *those strings* as its values.
               I KID YOU NOT.
             -->
             <radiogroup id="certSelection" orient="horizontal" preftype="string"
                         preference="security.default_personal_cert"
                         aria-labelledby="CertGroupCaption CertSelectionDesc">
-              <radio label="&certs.auto;" accesskey="&certs.auto.accesskey;" 
+              <radio label="&certs.auto;" accesskey="&certs.auto.accesskey;"
                      value="Select Automatically"/>
-              <radio label="&certs.ask;" accesskey="&certs.ask.accesskey;" 
+              <radio label="&certs.ask;" accesskey="&certs.ask.accesskey;"
                      value="Ask Every Time"/>
             </radiogroup>
 
             <separator/>
 
 #ifdef XP_MACOSX
             <vbox>
 #endif
             <hbox>
               <button id="viewCertificatesButton"
-                      label="&viewCerts.label;" accesskey="&viewCerts.accesskey;" 
+                      label="&viewCerts.label;" accesskey="&viewCerts.accesskey;"
                       oncommand="gAdvancedPane.showCertificates();"
                       preference="security.disable_button.openCertManager"/>
               <button id="viewCRLButton"
-                      label="&viewCRLs.label;" accesskey="&viewCRLs.accesskey;" 
+                      label="&viewCRLs.label;" accesskey="&viewCRLs.accesskey;"
                       oncommand="gAdvancedPane.showCRLs();"
                       preference="security.OCSP.disable_button.managecrl"/>
               <button id="verificationButton"
-                      label="&verify2.label;" accesskey="&verify2.accesskey;" 
+                      label="&verify2.label;" accesskey="&verify2.accesskey;"
                       oncommand="gAdvancedPane.showOCSP();"/>
 #ifdef XP_MACOSX
             </hbox>
             <hbox>
 #endif
               <button id="viewSecurityDevicesButton"
                       label="&viewSecurityDevices.label;" accesskey="&viewSecurityDevices.accesskey;"
                       oncommand="gAdvancedPane.showSecurityDevices();"
--- a/browser/components/preferences/in-content/advanced.js
+++ b/browser/components/preferences/in-content/advanced.js
@@ -34,18 +34,19 @@ var gAdvancedPane = {
 #endif
 #ifdef MOZ_UPDATER
     this.updateReadPrefs();
 #endif
     this.updateOfflineApps();
 #ifdef MOZ_CRASHREPORTER
     this.initSubmitCrashes();
 #endif
-#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
     this.initTelemetry();
+#ifdef MOZ_SERVICES_HEALTHREPORT
+    this.initSubmitHealthReport();
 #endif
     this.updateActualCacheSize("disk");
     this.updateActualCacheSize("offline");
   },
 
   /**
    * Stores the identity of the current tab in preferences so that the selected
    * tab can be persisted between openings of the preferences window.
@@ -112,21 +113,55 @@ var gAdvancedPane = {
    * unchanged and represents a value not strictly allowed in UI.
    */
   writeCheckSpelling: function ()
   {
     var checkbox = document.getElementById("checkSpelling");
     return checkbox.checked ? (this._storedSpellCheck == 2 ? 2 : 1) : 0;
   },
 
+
+  /**
+   * When the user toggles the layers.acceleration.disabled pref,
+   * sync its new value to the gfx.direct2d.disabled pref too.
+   */
+  updateHardwareAcceleration: function()
+  {
+#ifdef XP_WIN
+    var fromPref = document.getElementById("layers.acceleration.disabled");
+    var toPref = document.getElementById("gfx.direct2d.disabled");
+    toPref.value = fromPref.value;
+#endif
+  },
+
+  // DATA CHOICES TAB
+
+  /**
+   * Set up or hide the Learn More links for various data collection options
+   */
+  _setupLearnMoreLink: function (pref, element) {
+    // set up the Learn More link with the correct URL
+    let url = Services.prefs.getCharPref(pref);
+    let el = document.getElementById(element);
+
+    if (url) {
+      el.setAttribute("href", url);
+    } else {
+      el.setAttribute("hidden", "true");
+    }
+  },
+
   /**
    *
    */
   initSubmitCrashes: function ()
   {
+    this._setupLearnMoreLink("toolkit.crashreporter.infoURL",
+                             "crashReporterLearnMore");
+
     var checkbox = document.getElementById("submitCrashesBox");
     try {
       var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"].
                getService(Components.interfaces.nsICrashReporter);
       checkbox.checked = cr.submitReports;
     } catch (e) {
       checkbox.style.display = "none";
     }
@@ -140,62 +175,106 @@ var gAdvancedPane = {
     var checkbox = document.getElementById("submitCrashesBox");
     try {
       var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"].
                getService(Components.interfaces.nsICrashReporter);
       cr.submitReports = checkbox.checked;
     } catch (e) { }
   },
 
-#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
   /**
    * When telemetry is opt-out, verify if the user explicitly rejected the
    * telemetry prompt, and if so reflect his choice in the current preference
    * value. This doesn't cover the case where the user refused telemetry in the
    * prompt but later enabled it in preferences in builds before the fix for
    * bug 737600.
+   *
+   * In all cases, set up the Learn More link sanely.
    */
   initTelemetry: function ()
   {
+#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
     const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabledPreRelease";
     let enabled = Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED);
     let rejected = false;
     try {
       rejected = Services.prefs.getBoolPref("toolkit.telemetry.rejected");
     } catch (e) {}
     if (enabled && rejected) {
       Services.prefs.setBoolPref(PREF_TELEMETRY_ENABLED, false);
     }
+#endif
+#ifdef MOZ_TELEMETRY_REPORTING
+    this._setupLearnMoreLink("toolkit.telemetry.infoURL", "telemetryLearnMore");
+#endif
   },
-#endif
+
 
   /**
    * When the user toggles telemetry, update the rejected value as well, so we
    * know he expressed a choice, and don't re-prompt inadvertently.
    */
   telemetryEnabledChanged: function (event)
   {
     let rejected = document.getElementById("toolkit.telemetry.rejected");
     rejected.value = !event.target.value;
     let displayed = document.getElementById("toolkit.telemetry.prompted");
     displayed.value = @MOZ_TELEMETRY_DISPLAY_REV@;
   },
 
+#ifdef MOZ_SERVICES_HEALTHREPORT
   /**
-   * When the user toggles the layers.acceleration.disabled pref,
-   * sync its new value to the gfx.direct2d.disabled pref too.
+   * Initialize the health report service reference and checkbox.
+   */
+  initSubmitHealthReport: function () {
+    this._setupLearnMoreLink("healthreport.infoURL", "FHRLearnMore");
+
+    let reporter = Components.classes["@mozilla.org/healthreport/service;1"]
+                                     .getService(Components.interfaces.nsISupports)
+                                     .wrappedJSObject
+                                     .reporter;
+
+    let checkbox = document.getElementById("submitHealthReportBox");
+
+    if (!reporter) {
+      checkbox.setAttribute("disabled", "true");
+      return;
+    }
+
+    checkbox.checked = reporter.dataSubmissionPolicyAccepted;
+  },
+
+  /**
+   * Update the health report policy acceptance with state from checkbox.
    */
-  updateHardwareAcceleration: function()
-  {
-#ifdef XP_WIN
-    var fromPref = document.getElementById("layers.acceleration.disabled");
-    var toPref = document.getElementById("gfx.direct2d.disabled");
-    toPref.value = fromPref.value;
+  updateSubmitHealthReport: function () {
+    let reporter = Components.classes["@mozilla.org/healthreport/service;1"]
+                                     .getService(Components.interfaces.nsISupports)
+                                     .wrappedJSObject
+                                     .reporter;
+
+    if (!reporter) {
+      return;
+    }
+
+    let checkbox = document.getElementById("submitHealthReportBox");
+
+    let accepted = reporter.dataSubmissionPolicyAccepted;
+
+    if (checkbox.checked && !accepted) {
+      reporter.recordPolicyAcceptance("pref-checkbox-checked");
+      return;
+    }
+
+    if (!checkbox.checked && accepted) {
+      reporter.recordPolicyRejection("pref-checkbox-unchecked");
+      return;
+    }
+  },
 #endif
-  },
 
   // NETWORK TAB
 
   /*
    * Preferences:
    *
    * browser.cache.disk.capacity
    * - the size of the browser cache in KB
--- a/browser/components/preferences/in-content/advanced.xul
+++ b/browser/components/preferences/in-content/advanced.xul
@@ -147,16 +147,17 @@
 </hbox>
 
 <tabbox id="advancedPrefs" flex="1"
         data-category="paneAdvanced" hidden="true"
         onselect="gAdvancedPane.tabSelectionChanged();">
 
   <tabs id="tabsElement">
     <tab id="generalTab" label="&generalTab.label;" helpTopic="prefs-advanced-general"/>
+    <tab id="dataChoicesTab" label="&dataChoicesTab.label;" helpTopic="prefs-advanced-data-choices"/>
     <tab id="networkTab" label="&networkTab.label;" helpTopic="prefs-advanced-network"/>
     <tab id="updateTab" label="&updateTab.label;"  helpTopic="prefs-advanced-update"/>
     <tab id="encryptionTab" label="&encryptionTab.label;" helpTopic="prefs-advanced-encryption"/>
   </tabs>
 
   <tabpanels flex="1">
 
     <!-- General -->
@@ -196,46 +197,97 @@
                   preference="layers.acceleration.disabled"/>
         <checkbox id="checkSpelling"
                   label="&checkSpelling.label;"
                   accesskey="&checkSpelling.accesskey;"
                   onsyncfrompreference="return gAdvancedPane.readCheckSpelling();"
                   onsynctopreference="return gAdvancedPane.writeCheckSpelling();"
                   preference="layout.spellcheckDefault"/>
       </groupbox>
+#ifdef HAVE_SHELL_SERVICE
       <!-- System Defaults -->
       <groupbox id="systemDefaultsGroup" orient="vertical">
         <caption label="&systemDefaults.label;"/>
 
-#ifdef HAVE_SHELL_SERVICE
         <checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
-                      label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;"
-                      flex="1"/>
+                  label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;"
+                  flex="1"/>
         <hbox class="indent">
           <deck id="setDefaultPane">
             <button id="setDefaultButton"
                     label="&setDefault.label;" accesskey="&setDefault.accesskey;"
                     oncommand="gAdvancedPane.setDefaultBrowser();"
                     preference="pref.general.disable_button.default_browser"/>
             <description>&isDefault.label;</description>
           </deck>
         </hbox>
-#ifdef MOZ_CRASHREPORTER
-        <checkbox id="submitCrashesBox" flex="1"
-                  oncommand="gAdvancedPane.updateSubmitCrashes();"
-                  label="&submitCrashes.label;" accesskey="&submitCrashes.accesskey;"/>
+      </groupbox>
+#endif
+    </tabpanel>
+#ifndef MOZ_TELEMETRY_REPORTING
+#ifndef MOZ_SERVICES_HEALTHREPORT
+#ifndef MOZ_CRASHREPORTER
+#define HIDE_DATACHOICES
+#endif
 #endif
 #endif
+#ifndef HIDE_DATACHOICES
+    <!-- Data Choices -->
+    <tabpanel id="dataChoicesPanel" orient="vertical">
 #ifdef MOZ_TELEMETRY_REPORTING
-        <checkbox id="submitTelemetryBox" flex="1"
-                  preference="toolkit.telemetry.enabled"
-                  label="&submitTelemetry.label;" accesskey="&submitTelemetry.accesskey;"/>
+      <groupbox>
+        <caption label="&telemetrySection.label;"/>
+        <description>&telemetryDesc.label;</description>
+        <hbox>
+          <checkbox id="submitTelemetryBox"
+                    preference="toolkit.telemetry.enabled"
+                    label="&enableTelemetry.label;"
+                    accesskey="&enableTelemetry.accesskey;"/>
+          <spacer flex="1"/>
+          <label id="telemetryLearnMore"
+                 class="text-link"
+                 value="&telemetryLearnMore.label;"/>
+        </hbox>
+      </groupbox>
 #endif
+#ifdef MOZ_SERVICES_HEALTHREPORT
+      <groupbox>
+        <caption label="&FHRSection.label;"/>
+        <description>&FHRDesc.label;</description>
+        <hbox>
+          <checkbox id="submitHealthReportBox"
+                    oncommand="gAdvancedPane.updateSubmitHealthReport();"
+                    label="&enableFHR.label;"
+                    accesskey="&enableFHR.accesskey;"/>
+          <spacer flex="1"/>
+          <label id="FHRLearnMore"
+                 class="text-link"
+                 value="&FHRLearnMore.label;"/>
+        </hbox>
       </groupbox>
+#endif
+#ifdef MOZ_CRASHREPORTER
+      <groupbox>
+        <caption label="&crashReporterSection.label;"/>
+        <description>&crashReporterDesc.label;</description>
+        <hbox>
+          <checkbox id="submitCrashesBox"
+                    oncommand="gAdvancedPane.updateSubmitCrashes();"
+                    label="&enableCrashReporter.label;"
+                    accesskey="&enableCrashReporter.accesskey;"/>
+
+          <spacer flex="1"/>
+          <label id="crashReporterLearnMore"
+                 class="text-link"
+                 value="&crashReporterLearnMore.label;"/>
+        </hbox>
+      </groupbox>
+#endif
     </tabpanel>
+#endif
 
     <!-- Network -->
     <tabpanel id="networkPanel" orient="vertical">
 
       <!-- Connection -->
       <groupbox id="connectionGroup">
         <caption label="&connection.label;"/>
 
--- a/browser/components/preferences/in-content/tests/Makefile.in
+++ b/browser/components/preferences/in-content/tests/Makefile.in
@@ -38,10 +38,14 @@ else
     browser_privacypane_1.js \
     browser_privacypane_3.js \
     browser_privacypane_4.js \
     browser_privacypane_5.js \
     browser_privacypane_8.js \
     $(NULL)
 endif
 
+ifdef MOZ_SERVICES_HEALTHREPORT
+_BROWSER_FILES += browser_healthreport.js
+endif
+
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_healthreport.js
@@ -0,0 +1,45 @@
+/* Any copyright is dedicated to the Public Domain.
+* http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function test() {
+  waitForExplicitFinish();
+  resetPreferences();
+  registerCleanupFunction(resetPreferences);
+  open_preferences(runTest);
+}
+
+function runTest(win) {
+  let doc = win.document;
+
+  win.gotoPref("paneAdvanced");
+  let advancedPrefs = doc.getElementById("advancedPrefs");
+  let dataChoicesTab = doc.getElementById("dataChoicesTab");
+  advancedPrefs.selectedTab = dataChoicesTab;
+
+  let checkbox = doc.getElementById("submitHealthReportBox");
+  ok(checkbox);
+  is(checkbox.checked, false, "Health Report checkbox is unchecked on app first run.");
+
+  let reporter = Components.classes["@mozilla.org/healthreport/service;1"]
+                                   .getService(Components.interfaces.nsISupports)
+                                   .wrappedJSObject
+                                   .reporter;
+  ok(reporter);
+  is(reporter.dataSubmissionPolicyAccepted, false, "Data submission policy not accepted.");
+
+  checkbox.checked = true;
+  checkbox.doCommand();
+  is(reporter.dataSubmissionPolicyAccepted, true, "Checking checkbox accepts data submission policy.");
+  checkbox.checked = false;
+  checkbox.doCommand();
+  is(reporter.dataSubmissionPolicyAccepted, false, "Unchecking checkbox opts out of data submission.");
+
+  win.close();
+  finish();
+}
+
+function resetPreferences() {
+  Services.prefs.clearUserPref("healthreport.policy.dataSubmissionPolicyAccepted");
+}
--- a/browser/components/preferences/tests/Makefile.in
+++ b/browser/components/preferences/tests/Makefile.in
@@ -38,10 +38,14 @@ else
     browser_privacypane_1.js \
     browser_privacypane_3.js \
     browser_privacypane_4.js \
     browser_privacypane_5.js \
     browser_privacypane_8.js \
     $(NULL)
 endif
 
+ifdef MOZ_SERVICES_HEALTHREPORT
+_BROWSER_FILES += browser_healthreport.js
+endif
+
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/tests/browser_healthreport.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+* http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function test() {
+  waitForExplicitFinish();
+  resetPreferences();
+  registerCleanupFunction(resetPreferences);
+
+  function observer(win, topic, data) {
+    Services.obs.removeObserver(observer, "advanced-pane-loaded");
+    runTest(win);
+  }
+  Services.obs.addObserver(observer, "advanced-pane-loaded", false);
+  openDialog("chrome://browser/content/preferences/preferences.xul", "Preferences",
+             "chrome,titlebar,toolbar,centerscreen,dialog=no", "paneAdvanced");
+}
+
+function runTest(win) {
+  let doc = win.document;
+
+  //win.gotoPref("paneAdvanced");
+  //let advancedPrefs = doc.getElementById("advancedPrefs");
+  //let dataChoicesTab = doc.getElementById("dataChoicesTab");
+  //advancedPrefs.selectedTab = dataChoicesTab;
+
+  let checkbox = doc.getElementById("submitHealthReportBox");
+  ok(checkbox);
+  is(checkbox.checked, false, "Health Report checkbox is unchecked on app first run.");
+
+  let reporter = Components.classes["@mozilla.org/healthreport/service;1"]
+                                   .getService(Components.interfaces.nsISupports)
+                                   .wrappedJSObject
+                                   .reporter;
+  ok(reporter);
+  is(reporter.dataSubmissionPolicyAccepted, false, "Data submission policy not accepted.");
+
+  checkbox.checked = true;
+  checkbox.doCommand();
+  is(reporter.dataSubmissionPolicyAccepted, true, "Checking checkbox accepts data submission policy.");
+  checkbox.checked = false;
+  checkbox.doCommand();
+  is(reporter.dataSubmissionPolicyAccepted, false, "Unchecking checkbox opts out of data submission.");
+
+  win.close();
+  finish();
+}
+
+function resetPreferences() {
+  Services.prefs.clearUserPref("healthreport.policy.dataSubmissionPolicyAccepted");
+}
--- a/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
@@ -27,20 +27,36 @@
 <!ENTITY checkSpelling.accesskey         "t">
 
 <!ENTITY systemDefaults.label            "System Defaults">
 <!ENTITY alwaysCheckDefault.label        "Always check to see if &brandShortName; is the default browser on startup"><!--XXX-->
 <!ENTITY alwaysCheckDefault.accesskey    "w">
 <!ENTITY setDefault.label                "Make &brandShortName; the default browser">
 <!ENTITY setDefault.accesskey            "d">
 <!ENTITY isDefault.label                 "&brandShortName; is currently your default browser">
-<!ENTITY submitCrashes.label             "Submit crash reports">
-<!ENTITY submitCrashes.accesskey         "S">
-<!ENTITY submitTelemetry.label           "Submit performance data">
-<!ENTITY submitTelemetry.accesskey       "P">
+
+<!ENTITY dataChoicesTab.label            "Data Choices">
+
+<!ENTITY FHRSection.label                "Firefox Health Report">
+<!ENTITY FHRDesc.label                   "Helps you understand your browser performance and shares data with &vendorShortName; about your browser health">
+<!ENTITY enableFHR.label                 "Enable Firefox Health Report">
+<!ENTITY enableFHR.accesskey             "F">
+<!ENTITY FHRLearnMore.label              "Learn More">
+
+<!ENTITY telemetrySection.label          "Telemetry">
+<!ENTITY telemetryDesc.label             "Shares performance, usage, hardware and customization data about your browser with &vendorShortName; to help us make &brandShortName; better">
+<!ENTITY enableTelemetry.label           "Enable Telemetry">
+<!ENTITY enableTelemetry.accesskey       "T">
+<!ENTITY telemetryLearnMore.label        "Learn More">
+
+<!ENTITY crashReporterSection.label      "Crash Reporter">
+<!ENTITY crashReporterDesc.label         "&brandShortName; submits crash reports to help &vendorShortName; make your browser more stable and secure">
+<!ENTITY enableCrashReporter.label       "Enable Crash Reporter">
+<!ENTITY enableCrashReporter.accesskey   "C">
+<!ENTITY crashReporterLearnMore.label    "Learn More">
 
 <!ENTITY networkTab.label                "Network">
 
 <!ENTITY connection.label                "Connection">
 
 <!ENTITY connectionDesc.label            "Configure how &brandShortName; connects to the Internet">
 <!ENTITY connectionSettings.label        "Settingsā€¦">
 <!ENTITY connectionSettings.accesskey    "e">
--- a/services/healthreport/healthreport-prefs.js
+++ b/services/healthreport/healthreport-prefs.js
@@ -16,9 +16,9 @@ pref("healthreport.policy.dataSubmission
 pref("healthreport.policy.firstRunTime", "0");
 pref("healthreport.policy.lastDataSubmissionFailureTime", "0");
 pref("healthreport.policy.lastDataSubmissionRequestedTime", "0");
 pref("healthreport.policy.lastDataSubmissionSuccessfulTime", "0");
 pref("healthreport.policy.nextDataSubmissionTime", "0");
 pref("healthreport.service.enabled", true);
 pref("healthreport.service.loadDelayMsec", 10000);
 pref("healthreport.service.providerCategories", "healthreport-js-provider");
-
+pref("healthreport.infoURL", "http://www.mozilla.org/legal/privacy/firefox.html#health-report");