Bug 1542316: Allow new instances to be launched if the path to the application bundle is different than currently running instances on macOS. r=spohl
authorYuri <mozilla@yuriydev.com>
Thu, 25 Apr 2019 11:46:31 -0400
changeset 530243 9cddd0efaf16b0e57c04e0a69e2b90735353cad3
parent 530242 29ada9b1cec2bb8ff8a1e80b0348644fa7192d30
child 530244 387aebeb7e8819e828f5c279db4d57dcdf42cf70
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersspohl
bugs1542316
milestone68.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 1542316: Allow new instances to be launched if the path to the application bundle is different than currently running instances on macOS. r=spohl
toolkit/xre/nsNativeAppSupportCocoa.mm
--- a/toolkit/xre/nsNativeAppSupportCocoa.mm
+++ b/toolkit/xre/nsNativeAppSupportCocoa.mm
@@ -62,17 +62,25 @@ nsresult GetNativeWindowPointerFromDOMWi
 // was specified in either of these processes), making the original process handle
 // the arguments passed to this handler.
 void remoteClientNotificationCallback(CFNotificationCenterRef aCenter, void* aObserver,
                                       CFStringRef aName, const void* aObject,
                                       CFDictionaryRef aUserInfo) {
   // Autorelease pool to prevent memory leaks, in case there is no outer pool.
   mozilla::MacAutoreleasePool pool;
   NSDictionary* userInfoDict = (__bridge NSDictionary*)aUserInfo;
-  if (userInfoDict && [userInfoDict objectForKey:@"commandLineArgs"]) {
+  if (userInfoDict && [userInfoDict objectForKey:@"commandLineArgs"] &&
+      [userInfoDict objectForKey:@"senderPath"]) {
+
+    NSString* senderPath = [userInfoDict objectForKey:@"senderPath"];
+    if (![senderPath isEqual:[[NSBundle mainBundle] bundlePath]]) {
+      // The caller is not the process at the same path as we are at. Skipping.
+      return;
+    }
+
     NSArray* args = [userInfoDict objectForKey:@"commandLineArgs"];
     nsCOMPtr<nsICommandLineRunner> cmdLine(new nsCommandLine());
 
     // Converting Objective-C array into a C array,
     // which nsICommandLineRunner understands.
     int argc = [args count];
     const char** argv = new const char*[argc];
     for (int i = 0; i < argc; i++) {
@@ -196,26 +204,38 @@ NS_IMETHODIMP nsNativeAppSupportCocoa::S
   // current user.
   NSString* notificationName = [[[NSBundle mainBundle] bundleIdentifier]
       stringByAppendingString:@".distributedNotification.commandLineArgs"];
 
   BOOL runningInstanceFound = NO;
   if (!shallProceedLikeNoRemote) {
     // We check for other running instances only if -no-remote was not specified.
     // The check is needed so the marAppApplyUpdateSuccess.js test doesn't fail on next call.
-    runningInstanceFound =
-        [[NSRunningApplication
-            runningApplicationsWithBundleIdentifier:[[NSBundle mainBundle] bundleIdentifier]]
-            count] > 1;
+    NSArray* appsWithMatchingId = [NSRunningApplication runningApplicationsWithBundleIdentifier:
+                                    [[NSBundle mainBundle] bundleIdentifier]];
+    NSString* currentAppBundlePath = [[NSBundle mainBundle] bundlePath];
+    NSRunningApplication* currentApp = [NSRunningApplication currentApplication];
+    for (NSRunningApplication* app in appsWithMatchingId) {
+      if ([currentAppBundlePath isEqual:[[app bundleURL] path]] &&
+          ![currentApp isEqual:app]) {
+        runningInstanceFound = YES;
+        break;
+      }
+    }
   }
 
   if (!shallProceedLikeNoRemote && !mozillaRestarting && runningInstanceFound) {
     // There is another instance of this app already running!
     NSArray* arguments = [[NSProcessInfo processInfo] arguments];
-    CFDictionaryRef userInfoDict = (__bridge CFDictionaryRef) @{@"commandLineArgs" : arguments};
+    NSString* senderPath = [[NSBundle mainBundle] bundlePath];
+    CFDictionaryRef userInfoDict = (__bridge CFDictionaryRef) @{@"commandLineArgs" :
+                                                                  arguments,
+                                                                @"senderPath":
+                                                                  senderPath
+                                                                };
 
     // This code is shared between Firefox, Thunderbird and other Mozilla products.
     // So we need a notification name that is unique to the product, so we
     // do not send a notification to Firefox from Thunderbird and so on. I am using
     // bundle Id (assuming all Mozilla products come wrapped in .app bundles) -
     // it should be unique
     // (e.g., org.mozilla.firefox.distributedNotification.commandLineArgs for Firefox).
     // We also need to make sure the notifications are "local" to the current user,