Bug 1505331 - Port bug 1458308 to TB: (update-prefs) Move update prefs out of profile. r=jorgk,mkmelin
authoraceman <acelists@atlas.sk>
Sat, 10 Nov 2018 09:53:00 +1300
changeset 33703 7ac42d333c2085e6df3ca99d470e2ed9937cdadd
parent 33702 77212297c915ec15d690788eeac94a726d6319c3
child 33704 fbd01a6e230fec49fd193f983ed9842747fe9c3c
push id388
push userclokep@gmail.com
push dateMon, 28 Jan 2019 20:54:56 +0000
reviewersjorgk, mkmelin
bugs1505331, 1458308
Bug 1505331 - Port bug 1458308 to TB: (update-prefs) Move update prefs out of profile. r=jorgk,mkmelin
mail/app/profile/all-thunderbird.js
mail/base/content/aboutDialog-appUpdater.js
mail/components/preferences/advanced.inc.xul
mail/components/preferences/advanced.js
mail/locales/en-US/messenger/preferences/preferences.ftl
--- a/mail/app/profile/all-thunderbird.js
+++ b/mail/app/profile/all-thunderbird.js
@@ -70,19 +70,25 @@ pref("app.update.cert.maxErrors", 5);
 
 pref("app.update.certs.1.issuerName", "CN=DigiCert SHA2 Secure Server CA,O=DigiCert Inc,C=US");
 pref("app.update.certs.1.commonName", "aus5.mozilla.org");
 
 pref("app.update.certs.2.issuerName", "CN=thawte SSL CA - G2,O=\"thawte, Inc.\",C=US");
 pref("app.update.certs.2.commonName", "aus5.mozilla.org");
 
 // If set to true, the Update Service will automatically download updates when
-// app updates are enabled per the app.update.enabled preference and if the user
-// can apply updates.
-pref("app.update.auto", true);
+// user can apply updates. This pref is no longer used on Windows, except as the
+// default value to migrate to the new location that this data is now stored
+// (which is in a file in the update directory). Because of this, this pref
+// should no longer be used directly. Instead,
+// nsIUpdateService::getAutoUpdateIsEnabled and
+// nsIUpdateService::setAutoUpdateIsEnabled should be used.
+#ifndef XP_WIN
+ pref("app.update.auto", true);
+#endif
 
 // If set to true, the Update Service will present no UI for any event.
 pref("app.update.silent", false);
 
 // If set to true, the Update Service will apply updates in the background
 // when it finishes downloading them. Disabled in bug 1397862.
 pref("app.update.staging.enabled", false);
 
--- a/mail/base/content/aboutDialog-appUpdater.js
+++ b/mail/base/content/aboutDialog-appUpdater.js
@@ -20,16 +20,17 @@ function onUnload(aEvent) {
   gAppUpdater.removeDownloadListener();
   gAppUpdater = null;
 }
 
 
 function appUpdater()
 {
   this.updateDeck = document.getElementById("updateDeck");
+  this.promiseAutoUpdateSetting = null;
 
   // Hide the update deck when there is already an update window open to avoid
   // syncing issues between them.
   if (Services.wm.getMostRecentWindow("Update:Wizard")) {
     this.updateDeck.hidden = true;
     return;
   }
 
@@ -68,16 +69,19 @@ function appUpdater()
   }
 
   if (this.isDownloading) {
     this.startDownload();
     // selectPanel("downloading") is called from setupDownloadingUI().
     return;
   }
 
+  // We might need this value later, so start loading it from the disk now.
+  this.promiseAutoUpdateSetting = this.aus.getAutoUpdateIsEnabled();
+
   // That leaves the options
   // "Check for updates, but let me choose whether to install them", and
   // "Automatically install updates".
   // In both cases, we check for updates without asking.
   // In the "let me choose" case, we ask before downloading though, in onCheckComplete.
   this.checkForUpdates();
 }
 
@@ -125,25 +129,16 @@ appUpdater.prototype =
   },
 
   // true when updating in background is enabled.
   get backgroundUpdateEnabled() {
     return !this.updateDisabledByPolicy &&
            gAppUpdater.aus.canStageUpdates;
   },
 
-  // true when updating is automatic.
-  get updateAuto() {
-    try {
-      return Services.prefs.getBoolPref("app.update.auto");
-    }
-    catch (e) { }
-    return true; // Thunderbird default is true
-  },
-
   /**
    * Sets the panel of the updateDeck.
    *
    * @param  aChildID
    *         The id of the deck's child to select, e.g. "apply".
    */
   selectPanel: function(aChildID) {
     let panel = document.getElementById(aChildID);
@@ -251,20 +246,26 @@ appUpdater.prototype =
         return;
       }
 
       if (!gAppUpdater.aus.canApplyUpdates) {
         gAppUpdater.selectPanel("manualUpdate");
         return;
       }
 
-      if (gAppUpdater.updateAuto) // automatically download and install
-        gAppUpdater.startDownload();
-      else // ask
-        gAppUpdater.selectPanel("downloadAndInstall");
+      if (this.promiseAutoUpdateSetting == null) {
+        this.promiseAutoUpdateSetting = this.aus.getAutoUpdateIsEnabled();
+      }
+      this.promiseAutoUpdateSetting.then(updateAuto => {
+        if (updateAuto) { // automatically download and install
+          gAppUpdater.startDownload();
+        } else { // ask
+          gAppUpdater.selectPanel("downloadAndInstall");
+        }
+      });
     },
 
     /**
      * See nsIUpdateService.idl
      */
     onError: function(aRequest, aUpdate) {
       // Errors in the update check are treated as no updates found. If the
       // update check fails repeatedly without a success the user will be
--- a/mail/components/preferences/advanced.inc.xul
+++ b/mail/components/preferences/advanced.inc.xul
@@ -74,19 +74,16 @@
       <preference id="browser.cache.disk.capacity"
                   name="browser.cache.disk.capacity" type="int"/>
       <preference id="browser.cache.disk.smart_size.enabled"
                   name="browser.cache.disk.smart_size.enabled"
                   inverted="true"
                   type="bool"/>
 #ifdef MOZ_UPDATER
       <!-- Update tab -->
-      <preference id="app.update.auto"
-                  name="app.update.auto"
-                  type="bool"/>
       <preference id="app.update.disable_button.showUpdateHistory"
                   name="app.update.disable_button.showUpdateHistory"
                   type="bool"/>
 
 #ifdef MOZ_MAINTENANCE_SERVICE
       <preference id="app.update.service.enabled"
                   name="app.update.service.enabled"
                   type="bool"/>
@@ -468,22 +465,23 @@
                 </hbox>
                 <hbox id="unsupportedSystem" align="center">
                   <label>&update.unsupported.start;</label><label id="unsupportedLink" class="text-link">&update.unsupported.linkText;</label><label>&update.unsupported.end;</label>
                 </hbox>
               </deck>
             </vbox>
             <separator/>
             <radiogroup id="updateRadioGroup"
-                        align="start"
-                        oncommand="gAdvancedPane.updateWritePrefs();">
-              <radio value="auto"
+                        align="start">
+              <radio id="autoDesktop"
+                     value="true"
                      label="&updateAuto.label;"
                      accesskey="&updateAuto.accesskey;"/>
-              <radio value="checkOnly"
+              <radio id="manualDesktop"
+                     value="false"
                      label="&updateCheck.label;"
                      accesskey="&updateCheck.accesskey;"/>
             </radiogroup>
           </groupbox>
 
 #ifdef MOZ_MAINTENANCE_SERVICE
           <separator/>
           <checkbox id="useService"
--- a/mail/components/preferences/advanced.js
+++ b/mail/components/preferences/advanced.js
@@ -9,24 +9,35 @@
 // Load DownloadUtils module for convertByteUnits
 ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm");
 ChromeUtils.import("resource://gre/modules/Localization.jsm");
 
+XPCOMUtils.defineLazyServiceGetters(this, {
+  gAUS: ["@mozilla.org/updates/update-service;1", "nsIApplicationUpdateService"],
+});
+
+const AUTO_UPDATE_CHANGED_TOPIC = "auto-update-config-change";
+
 var gAdvancedPane = {
   mPane: null,
   mInitialized: false,
   mShellServiceWorking: false,
   mBundle: null,
   requestingLocales: null,
 
   init() {
+    function setEventListener(aId, aEventType, aCallback) {
+      document.getElementById(aId)
+        .addEventListener(aEventType, aCallback.bind(gAdvancedPane));
+    }
+
     this.mPane = document.getElementById("paneAdvanced");
     this.updateCompactOptions();
     this.mBundle = document.getElementById("bundlePreferences");
     this.formatLocaleSetLabels();
 
     if (Services.prefs.getBoolPref("intl.multilingual.enabled")) {
       this.initMessengerLocale();
     }
@@ -85,32 +96,68 @@ var gAdvancedPane = {
         document.getElementById("alwaysCheckDefault").checked = false;
       }
       if (document.getElementById("checkDefaultButton"))
         document.getElementById("checkDefaultButton").disabled = true;
       this.mShellServiceWorking = false;
     }
 
     if (AppConstants.MOZ_UPDATER) {
+      gAppUpdater = new appUpdater(); // eslint-disable-line no-global-assign
+      if (Services.policies && !Services.policies.isAllowed("appUpdate")) {
+          document.getElementById("updateAllowDescription").hidden = true;
+          document.getElementById("updateRadioGroup").hidden = true;
+        if (AppConstants.MOZ_MAINTENANCE_SERVICE) {
+          document.getElementById("useService").hidden = true;
+        }
+      } else {
+        // Start with no option selected since we are still reading the value
+        document.getElementById("autoDesktop").removeAttribute("selected");
+        document.getElementById("manualDesktop").removeAttribute("selected");
+        // Start reading the correct value from the disk
+        this.updateReadPrefs();
+        setEventListener("updateRadioGroup", "command",
+                         gAdvancedPane.updateWritePrefs);
+      }
+
       let distroId = Services.prefs.getCharPref("distribution.id", "");
       if (distroId) {
         let distroVersion = Services.prefs.getCharPref("distribution.version");
 
         let distroIdField = document.getElementById("distributionId");
         distroIdField.value = distroId + " - " + distroVersion;
         distroIdField.style.display = "block";
 
         let distroAbout = Services.prefs.getStringPref("distribution.about", "");
         if (distroAbout) {
           let distroField = document.getElementById("distribution");
           distroField.value = distroAbout;
           distroField.style.display = "block";
         }
       }
 
+      if (AppConstants.MOZ_MAINTENANCE_SERVICE) {
+        // Check to see if the maintenance service is installed.
+        // If it isn't installed, don't show the preference at all.
+        let installed;
+        try {
+          let wrk = Cc["@mozilla.org/windows-registry-key;1"]
+                    .createInstance(Ci.nsIWindowsRegKey);
+          wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
+                   "SOFTWARE\\Mozilla\\MaintenanceService",
+                   wrk.ACCESS_READ | wrk.WOW64_64);
+          installed = wrk.readIntValue("Installed");
+          wrk.close();
+        } catch (e) {
+        }
+        if (installed != 1) {
+          document.getElementById("useService").hidden = true;
+        }
+      }
+
       let version = AppConstants.MOZ_APP_VERSION_DISPLAY;
 
       // Include the build ID and display warning if this is an "a#" (nightly) build
       if (/a\d+$/.test(version)) {
         let buildID = Services.appinfo.appBuildID;
         let year = buildID.slice(0, 4);
         let month = buildID.slice(4, 6);
         let day = buildID.slice(6, 8);
@@ -134,18 +181,23 @@ var gAdvancedPane = {
         if (relNotesPrefType != Services.prefs.PREF_INVALID) {
           let relNotesURL = Services.urlFormatter.formatURLPref("app.releaseNotesURL");
           if (relNotesURL != "about:blank") {
             relNotesLink.href = relNotesURL;
             relNotesLink.hidden = false;
           }
         }
       }
+      // Initialize Application section.
 
-      gAppUpdater = new appUpdater(); // eslint-disable-line no-global-assign
+      // Listen for window unload so we can remove our preference observers.
+      window.addEventListener("unload", this);
+
+      Services.obs.addObserver(this, AUTO_UPDATE_CHANGED_TOPIC);
+
     }
 
     this.mInitialized = true;
   },
 
   tabSelectionChanged() {
     if (this.mInitialized) {
       document.getElementById("mail.preferences.advanced.selectedTabIndex")
@@ -257,76 +309,66 @@ var gAdvancedPane = {
   clearCache() {
     try {
       Services.cache2.clear();
     } catch (ex) {}
     this.updateActualCacheSize();
   },
 
   /**
-   * Selects the item of the radiogroup based on the pref values and locked
-   * states.
-   *
-   * UI state matrix for update preference conditions
-   *
-   * UI Components:                              Preferences
-   * Radiogroup                                  i   = app.update.auto
+   * Selects the correct item in the update radio group
    */
-  updateReadPrefs() {
-    let autoPref = document.getElementById("app.update.auto");
-    let radiogroup = document.getElementById("updateRadioGroup");
-
-    if (autoPref.value)
-      radiogroup.value = "auto";      // Automatically install updates
-    else
-      radiogroup.value = "checkOnly"; // Check, but let me choose
-
-    let canCheck = Cc["@mozilla.org/updates/update-service;1"].
-                     getService(Ci.nsIApplicationUpdateService).
-                     canCheckForUpdates;
-
-    // canCheck is false if the binary platform or OS version is not known.
-    // A locked pref is sufficient to disable the radiogroup.
-    radiogroup.disabled = !canCheck || autoPref.locked;
-
-    if (AppConstants.MOZ_MAINTENANCE_SERVICE) {
-      // Check to see if the maintenance service is installed.
-      // If it is don't show the preference at all.
-      let installed;
+  async updateReadPrefs() {
+    if (AppConstants.MOZ_UPDATER &&
+        (!Services.policies || Services.policies.isAllowed("appUpdate"))) {
+      let radiogroup = document.getElementById("updateRadioGroup");
+      radiogroup.disabled = true;
       try {
-        let wrk = Cc["@mozilla.org/windows-registry-key;1"]
-                    .createInstance(Ci.nsIWindowsRegKey);
-        wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
-                 "SOFTWARE\\Mozilla\\MaintenanceService",
-                 wrk.ACCESS_READ | wrk.WOW64_64);
-        installed = wrk.readIntValue("Installed");
-        wrk.close();
-      } catch (e) { }
-      if (installed != 1) {
-        document.getElementById("useService").hidden = true;
+        let enabled = await gAUS.getAutoUpdateIsEnabled();
+        radiogroup.value = enabled;
+        radiogroup.disabled = false;
+      } catch (error) {
+        Cu.reportError(error);
       }
     }
   },
 
   /**
-   * Sets the pref values based on the selected item of the radiogroup.
+   * Writes the value of the update radio group to the disk
    */
-  updateWritePrefs() {
-    let autoPref = document.getElementById("app.update.auto");
-    let radiogroup = document.getElementById("updateRadioGroup");
-    switch (radiogroup.value) {
-      case "auto":      // Automatically install updates
-        autoPref.value = true;
-        break;
-      case "checkOnly": // Check, but but let me choose
-        autoPref.value = false;
-        break;
+  async updateWritePrefs() {
+    if (AppConstants.MOZ_UPDATER &&
+        (!Services.policies || Services.policies.isAllowed("appUpdate"))) {
+      let radiogroup = document.getElementById("updateRadioGroup");
+      let updateAutoValue = (radiogroup.value == "true");
+      radiogroup.disabled = true;
+      try {
+        await gAUS.setAutoUpdateIsEnabled(updateAutoValue);
+        radiogroup.disabled = false;
+      } catch (error) {
+        Cu.reportError(error);
+        await this.updateReadPrefs();
+        await this.reportUpdatePrefWriteError(error);
+      }
     }
   },
 
+  async reportUpdatePrefWriteError(error) {
+    let [title, message] = await document.l10n.formatValues([
+      {id: "update-pref-write-failure-title"},
+      {id: "update-pref-write-failure-message", args: {path: error.path}},
+    ]);
+
+    // Set up the Ok Button
+    let buttonFlags = (Services.prompt.BUTTON_POS_0 *
+                       Services.prompt.BUTTON_TITLE_OK);
+    Services.prompt.confirmEx(window, title, message, buttonFlags,
+                              null, null, null, null, {});
+  },
+
   showUpdates() {
     gSubDialog.open("chrome://mozapps/content/update/history.xul");
   },
 
   updateCompactOptions(aCompactEnabled) {
     document.getElementById("offlineCompactFolderMin").disabled =
       !document.getElementById("offlineCompactFolder").checked ||
       document.getElementById("mail.purge_threshhold_mb").locked;
@@ -597,9 +639,39 @@ var gAdvancedPane = {
       return;
     }
     let locales = Array.from(new Set([
       locale,
       ...Services.locale.requestedLocales,
     ]).values());
     this.showConfirmLanguageChangeMessageBar(locales);
   },
+
+  destroy() {
+    window.removeEventListener("unload", this);
+
+    Services.obs.removeObserver(this, AUTO_UPDATE_CHANGED_TOPIC);
+  },
+
+  // nsISupports
+
+  QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver]),
+
+  // nsIObserver
+
+  async observe(aSubject, aTopic, aData) {
+    if (aTopic == AUTO_UPDATE_CHANGED_TOPIC) {
+      if (aData != "true" && aData != "false") {
+        throw new Error("Invalid preference value for app.update.auto");
+      }
+      document.getElementById("updateRadioGroup").value = aData;
+    }
+  },
+
+  // EventListener
+
+  handleEvent(aEvent) {
+    if (aEvent.type == "unload") {
+      this.destroy();
+    }
+  },
+
 };
--- a/mail/locales/en-US/messenger/preferences/preferences.ftl
+++ b/mail/locales/en-US/messenger/preferences/preferences.ftl
@@ -3,8 +3,14 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 choose-messenger-language-description = Choose the languages used to display menus, messages, and notifications from { -brand-short-name }.
 manage-messenger-languages-button =
   .label = Set Alternatives…
   .accesskey = l
 confirm-messenger-language-change-description = Restart { -brand-short-name } to apply these changes
 confirm-messenger-language-change-button = Apply and Restart
+
+update-pref-write-failure-title = Write Failure
+
+# Variables:
+#   $path (String) - Path to the configuration file
+update-pref-write-failure-message = Unable to save preference. Could not write to file: { $path }