Bug 1834537 - Part 6: Simplify GCRuntime::checkAllocatorState a little r=sfink
[gecko.git] / ipc / glue / ProcessUtils_mac.mm
blob0f1d8ecbba68b16910436787f78e2e21e15ec7cd
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "ProcessUtils.h"
7 #include "nsObjCExceptions.h"
8 #include "nsCocoaUtils.h"
9 #include "nsString.h"
10 #include "mozilla/Sprintf.h"
12 #define UNDOCUMENTED_SESSION_CONSTANT ((int)-2)
14 namespace mozilla {
15 namespace ipc {
17 static void* sApplicationASN = NULL;
18 static void* sApplicationInfoItem = NULL;
20 void SetThisProcessName(const char* aProcessName) {
21   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
22   nsAutoreleasePool localPool;
24   if (!aProcessName || strcmp(aProcessName, "") == 0) {
25     return;
26   }
28   NSString* currentName =
29       [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:(NSString*)kCFBundleNameKey];
31   char formattedName[1024];
32   SprintfLiteral(formattedName, "%s %s", [currentName UTF8String], aProcessName);
34   aProcessName = formattedName;
36   // This function is based on Chrome/Webkit's and relies on potentially dangerous SPI.
37   typedef CFTypeRef (*LSGetASNType)();
38   typedef OSStatus (*LSSetInformationItemType)(int, CFTypeRef, CFStringRef, CFStringRef,
39                                                CFDictionaryRef*);
41   CFBundleRef launchServices = ::CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
42   if (!launchServices) {
43     NS_WARNING("Failed to set process name: Could not open LaunchServices bundle");
44     return;
45   }
47   if (!sApplicationASN) {
48     sApplicationASN =
49         ::CFBundleGetFunctionPointerForName(launchServices, CFSTR("_LSGetCurrentApplicationASN"));
50     if (!sApplicationASN) {
51       NS_WARNING("Failed to set process name: Could not get function pointer "
52                  "for LaunchServices");
53       return;
54     }
55   }
57   LSGetASNType getASNFunc = reinterpret_cast<LSGetASNType>(sApplicationASN);
59   if (!sApplicationInfoItem) {
60     sApplicationInfoItem = ::CFBundleGetFunctionPointerForName(
61         launchServices, CFSTR("_LSSetApplicationInformationItem"));
62   }
64   LSSetInformationItemType setInformationItemFunc =
65       reinterpret_cast<LSSetInformationItemType>(sApplicationInfoItem);
67   void* displayNameKeyAddr =
68       ::CFBundleGetDataPointerForName(launchServices, CFSTR("_kLSDisplayNameKey"));
70   CFStringRef displayNameKey = nil;
71   if (displayNameKeyAddr) {
72     displayNameKey = reinterpret_cast<CFStringRef>(*(CFStringRef*)displayNameKeyAddr);
73   }
75   // We need this to ensure we have a connection to the Process Manager, not
76   // doing so will silently fail and process name wont be updated.
77   ProcessSerialNumber psn;
78   if (::GetCurrentProcess(&psn) != noErr) {
79     return;
80   }
82   CFTypeRef currentAsn = getASNFunc ? getASNFunc() : nullptr;
84   if (!getASNFunc || !setInformationItemFunc || !displayNameKey || !currentAsn) {
85     NS_WARNING("Failed to set process name: Accessing launchServices failed");
86     return;
87   }
89   CFStringRef processName = ::CFStringCreateWithCString(nil, aProcessName, kCFStringEncodingASCII);
90   if (!processName) {
91     NS_WARNING("Failed to set process name: Could not create CFStringRef");
92     return;
93   }
95   OSErr err =
96       setInformationItemFunc(UNDOCUMENTED_SESSION_CONSTANT, currentAsn, displayNameKey, processName,
97                              nil);  // Optional out param
98   ::CFRelease(processName);
99   if (err != noErr) {
100     NS_WARNING("Failed to set process name: LSSetInformationItemType err");
101     return;
102   }
104   return;
105   NS_OBJC_END_TRY_ABORT_BLOCK;
108 }  // namespace ipc
109 }  // namespace mozilla