Bug 1374039 - Port bug 394984 to TB [Enable any admin user on OSX to update Firefox, front-end and updater changes]. r=philipp
authorRichard Marti <richard.marti@gmail.com>
Sun, 18 Jun 2017 10:12:50 +0200
changeset 29604 cc50be271afa15352c702fd9d61f923932f7ff0c
parent 29603 89f6848383e34cf869621b12001ddffa60ec8bc2
child 29605 8e63fdcf0e3c856af2314679f0968c0fed2bc656
push id378
push userclokep@gmail.com
push dateMon, 13 Nov 2017 18:45:35 +0000
reviewersphilipp
bugs1374039, 394984
Bug 1374039 - Port bug 394984 to TB [Enable any admin user on OSX to update Firefox, front-end and updater changes]. r=philipp
mail/app/Makefile.in
mail/app/macbuild/Contents/Info.plist.in
mail/base/content/aboutDialog-appUpdater.js
mail/installer/package-manifest.in
--- a/mail/app/Makefile.in
+++ b/mail/app/Makefile.in
@@ -148,13 +148,18 @@ tools repackage:: $(PROGRAM)
 	sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(MOZ_MACBUNDLE_NAME)/$(LPROJ)/InfoPlist.strings
 	rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Resources
 	rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS
 	$(RM) $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS/$(PROGRAM)
 	rsync -aL $(PROGRAM) $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS
 	$(MKDIR) -p $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Library/Spotlight
 	rsync -a --copy-unsafe-links $(DIST)/package/thunderbird.mdimporter $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Library/Spotlight
 	cp -RL $(DIST)/branding/thunderbird.icns $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Resources/thunderbird.icns
+	$(MKDIR) -p $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Library/LaunchServices
+ifdef MOZ_UPDATER
+	mv -f $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Library/LaunchServices
+	ln -s ../../../../Library/LaunchServices/org.mozilla.updater $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater
+endif
 	printf APPLMOZM > $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/PkgInfo
 endif
 
 # Note that anything you do to dist/ down here isn't going to make it into the
 # Mac build, since it's already been copied over to the .app, above.
--- a/mail/app/macbuild/Contents/Info.plist.in
+++ b/mail/app/macbuild/Contents/Info.plist.in
@@ -58,16 +58,21 @@
         <key>LSMinimumSystemVersion</key>
         <string>10.9.0</string>
         <key>NSSupportsAutomaticGraphicsSwitching</key>
         <true/>
 	<key>NSDisablePersistence</key>
 	<true/>
         <key>NSPrincipalClass</key>
         <string>GeckoNSApplication</string>
+	<key>SMPrivilegedExecutables</key>
+	<dict>
+		<key>org.mozilla.updater</key>
+		<string>identifier "org.mozilla.updater" and ((anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9]) or (anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] and certificate leaf[field.1.2.840.113635.100.6.1.13] and certificate leaf[subject.OU] = "43AQ936H96"))</string>
+	</dict>
 	<key>UTExportedTypeDeclarations</key>
 	<array>
 		<dict>
 			<key>UTTypeIdentifier</key>
 			<string>com.mozilla.thunderbird.mozeml</string>
 			<key>UTTypeReferenceURL</key>
 			<string>http://www.mozilla.com/Thunderbird</string>
 			<key>UTTypeDescription</key>
--- a/mail/base/content/aboutDialog-appUpdater.js
+++ b/mail/base/content/aboutDialog-appUpdater.js
@@ -3,16 +3,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Note: this file is included in aboutDialog.xul and preferences/advanced.xul
 // if MOZ_UPDATER is defined.
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
 
+const PREF_APP_UPDATE_CANCELATIONS_OSX = "app.update.cancelations.osx";
+const PREF_APP_UPDATE_ELEVATE_NEVER    = "app.update.elevate.never";
+
 var gAppUpdater;
 
 function onUnload(aEvent) {
   if (gAppUpdater.isChecking)
     gAppUpdater.checker.stopChecking(Components.interfaces.nsIUpdateChecker.CURRENT_CHECK);
   // Safe to call even when there isn't a download in progress.
   gAppUpdater.removeDownloadListener();
   gAppUpdater = null;
@@ -69,17 +72,18 @@ function appUpdater()
     // selectPanel("downloading") is called from setupDownloadingUI().
     return;
   }
 
   // Honor the "Never check for updates" option by not only disabling background
   // update checks, but also in the About dialog, by presenting a
   // "Check for updates" button.
   // If updates are found, the user is then asked if he wants to "Update to <version>".
-  if (!this.updateEnabled) {
+  if (!this.updateEnabled ||
+      Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ELEVATE_NEVER)) {
     this.selectPanel("checkForUpdates");
     return;
   }
 
   // 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.
@@ -91,21 +95,23 @@ appUpdater.prototype =
 {
   // true when there is an update check in progress.
   isChecking: false,
 
   // true when there is an update already staged / ready to be applied.
   get isPending() {
     if (this.update) {
       return this.update.state == "pending" ||
-             this.update.state == "pending-service";
+             this.update.state == "pending-service" ||
+             this.update.state == "pending-elevate";
     }
     return this.um.activeUpdate &&
            (this.um.activeUpdate.state == "pending" ||
-            this.um.activeUpdate.state == "pending-service");
+            this.um.activeUpdate.state == "pending-service" ||
+            this.um.activeUpdate.state == "pending-elevate");
   },
 
   // true when there is an update already installed in the background.
   get isApplied() {
     if (this.update) {
       return this.update.state == "applied" ||
              this.update.state == "applied-service";
     }
@@ -185,51 +191,60 @@ appUpdater.prototype =
       this.updateDeck.selectedPanel = panel;
     }
   },
 
   /**
    * Check for updates
    */
   checkForUpdates: function() {
+    // Clear prefs that could prevent a user from discovering available updates.
+    if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CANCELATIONS_OSX)) {
+      Services.prefs.clearUserPref(PREF_APP_UPDATE_CANCELATIONS_OSX);
+    }
+    if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ELEVATE_NEVER)) {
+      Services.prefs.clearUserPref(PREF_APP_UPDATE_ELEVATE_NEVER);
+    }
     this.selectPanel("checkingForUpdates");
     this.isChecking = true;
     this.checker.checkForUpdates(this.updateCheckListener, true);
     // after checking, onCheckComplete() is called
   },
 
   /**
    * Handles oncommand for the "Restart to Update" button
    * which is presented after the download has been downloaded.
    */
   buttonRestartAfterDownload: function() {
-    if (!this.isPending && !this.isApplied)
+    if (!this.isPending && !this.isApplied) {
       return;
+    }
 
-      // Notify all windows that an application quit has been requested.
-      let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"].
-                       createInstance(Components.interfaces.nsISupportsPRBool);
-      Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
-
-      // Something aborted the quit process.
-      if (cancelQuit.data)
-        return;
+    // Notify all windows that an application quit has been requested.
+    let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"].
+                     createInstance(Components.interfaces.nsISupportsPRBool);
+    Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
 
-      let appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].
-                       getService(Components.interfaces.nsIAppStartup);
+    // Something aborted the quit process.
+    if (cancelQuit.data) {
+      return;
+    }
+
+    let appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].
+                     getService(Components.interfaces.nsIAppStartup);
 
-      // If already in safe mode restart in safe mode (bug 327119)
-      if (Services.appinfo.inSafeMode) {
-        appStartup.restartInSafeMode(Components.interfaces.nsIAppStartup.eAttemptQuit);
-        return;
-      }
+    // If already in safe mode restart in safe mode (bug 327119)
+    if (Services.appinfo.inSafeMode) {
+      appStartup.restartInSafeMode(Components.interfaces.nsIAppStartup.eAttemptQuit);
+      return;
+    }
 
-      appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit |
-                      Components.interfaces.nsIAppStartup.eRestart);
-    },
+    appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit |
+                    Components.interfaces.nsIAppStartup.eRestart);
+  },
 
   /**
    * Implements nsIUpdateCheckListener. The methods implemented by
    * nsIUpdateCheckListener are in a different scope from nsIIncrementalDownload
    * to make it clear which are used by each interface.
    */
   updateCheckListener: {
     /**
@@ -356,17 +371,18 @@ appUpdater.prototype =
       if (this.backgroundUpdateEnabled) {
         this.selectPanel("applying");
         let update = this.um.activeUpdate;
         let self = this;
         Services.obs.addObserver(function selectPanelOnUpdate(aSubject, aTopic, aData) {
           // Update the UI when the background updater is finished
           let status = aData;
           if (status == "applied" || status == "applied-service" ||
-              status == "pending" || status == "pending-service") {
+              status == "pending" || status == "pending-service" ||
+              status == "pending-elevate") {
             // If the update is successfully applied, or if the updater has
             // fallen back to non-staged updates, show the "Restart to Update"
             // button.
             self.selectPanel("apply");
           } else if (status == "failed") {
             // Background update has failed, let's show the UI responsible for
             // prompting the user to update manually.
             self.selectPanel("downloadFailed");
--- a/mail/installer/package-manifest.in
+++ b/mail/installer/package-manifest.in
@@ -35,16 +35,17 @@
 #ifndef XP_MACOSX
 #define UNIX_BUT_NOT_MAC
 #endif
 #endif
 
 #ifdef XP_MACOSX
 ; Mac bundle stuff
 @APPNAME@/Contents/Info.plist
+@APPNAME@/Contents/Library/LaunchServices
 @APPNAME@/Contents/PkgInfo
 @APPNAME@/Contents/Library/Spotlight/thunderbird.mdimporter/
 @RESPATH@/thunderbird.icns
 @RESPATH@/@LPROJ_ROOT@.lproj/*
 #endif
 
 [@AB_CD@]
 @RESPATH@/chrome/@AB_CD@@JAREXT@