Bug 1556733 - [10.15] Multiple "Firefox Nightly Software Update" Mac OS X quarantine dialogs when performing a software update r=rstrong,spohl
authorHaik Aftandilian <haftandilian@mozilla.com>
Thu, 27 Jun 2019 02:51:45 +0000
changeset 543131 c35dfc59349855f1acfe97c5fc299ea10551b45b
parent 543130 c905c2290c3bb5c52a1a5b19118d0a044bfc9b4c
child 543132 89fbb2008b608b3b49f71ff5b6d73971d967e8d5
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrstrong, spohl
bugs1556733
milestone69.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 1556733 - [10.15] Multiple "Firefox Nightly Software Update" Mac OS X quarantine dialogs when performing a software update r=rstrong,spohl On Mac, remove the "com.apple.quarantine" extended attribute from the updater after it is copied to the staging area. Required on macOS 10.15 which has new restrictions on launching quarantined applications. Differential Revision: https://phabricator.services.mozilla.com/D35972
toolkit/xre/nsUpdateDriver.cpp
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -26,16 +26,17 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Printf.h"
 #include "mozilla/UniquePtr.h"
 #include "nsIObserverService.h"
 #include "nsNetCID.h"
 #include "mozilla/Services.h"
 
 #ifdef XP_MACOSX
+#  include <sys/xattr.h>
 #  include "nsILocalFileMac.h"
 #  include "nsCommandLineServiceMac.h"
 #  include "MacLaunchHelper.h"
 #  include "updaterfileutils_osx.h"
 #  include "mozilla/Monitor.h"
 #endif
 
 #if defined(XP_WIN)
@@ -52,16 +53,17 @@
 #  include <unistd.h>
 #  include <sys/wait.h>
 #endif
 
 using namespace mozilla;
 
 static LazyLogModule sUpdateLog("updatedriver");
 #define LOG(args) MOZ_LOG(sUpdateLog, mozilla::LogLevel::Debug, args)
+#define LOG_ENABLED() MOZ_LOG_TEST(sUpdateLog, mozilla::LogLevel::Debug)
 
 #ifdef XP_WIN
 #  define UPDATER_BIN "updater.exe"
 #  define MAINTENANCE_SVC_NAME L"MozillaMaintenance"
 #elif XP_MACOSX
 #  define UPDATER_BIN "org.mozilla.updater"
 #else
 #  define UPDATER_BIN "updater"
@@ -291,24 +293,49 @@ static bool CopyFileIntoUpdateDir(nsIFil
 
   // Make sure there is not an existing file in the target location.
   nsresult rv = updateDir->Clone(getter_AddRefs(file));
   if (NS_FAILED(rv)) return false;
   rv = file->AppendNative(leaf);
   if (NS_FAILED(rv)) return false;
   file->Remove(true);
 
+  // Destination path
+  nsCString targetFilePath;
+  rv = file->GetNativePath(targetFilePath);
+  if (NS_FAILED(rv)) return false;
+
   // Now, copy into the target location.
   rv = parentDir->Clone(getter_AddRefs(file));
   if (NS_FAILED(rv)) return false;
   rv = file->AppendNative(leaf);
   if (NS_FAILED(rv)) return false;
   rv = file->CopyToNative(updateDir, EmptyCString());
   if (NS_FAILED(rv)) return false;
 
+  // Remove the quarantine attribute. Starting with macOS 10.15, if the
+  // updater is quarantined, it will trigger a GateKeeper dialog when
+  // launched and fail to run. Firefox is configured to quarantine all
+  // written files by default.
+  int remove_rv = removexattr(targetFilePath.get(), "com.apple.quarantine", 0);
+  LOG(("Removing quarantine from %s: rv = %d", targetFilePath.get(),
+       remove_rv));
+
+  // Log quarantine status
+  if (LOG_ENABLED()) {
+    bool isQuarantined;
+    // getxattr returns -1 on error or, on success, the size of the value
+    // associated with the attribute. The com.apple.quarantine attribute
+    // can be set with a zero-length value so check for >= 0.
+    isQuarantined = (getxattr(targetFilePath.get(), "com.apple.quarantine",
+                              nullptr, 0, 0, 0) >= 0);
+    LOG(("Destination file %s is%s quarantined", targetFilePath.get(),
+         isQuarantined ? "" : " not"));
+  }
+
   return true;
 }
 
 static bool CopyUpdaterIntoUpdateDir(nsIFile* greDir, nsIFile* appDir,
                                      nsIFile* updateDir,
                                      nsCOMPtr<nsIFile>& updater) {
   // Copy the updater application from the GRE and the updater ini from the app.
   if (!CopyFileIntoUpdateDir(appDir, NS_LITERAL_CSTRING(UPDATER_APP),