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"
10 #include "mozilla/Sprintf.h"
12 #define UNDOCUMENTED_SESSION_CONSTANT ((int)-2)
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) {
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,
41 CFBundleRef launchServices = ::CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
42 if (!launchServices) {
43 NS_WARNING("Failed to set process name: Could not open LaunchServices bundle");
47 if (!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");
57 LSGetASNType getASNFunc = reinterpret_cast<LSGetASNType>(sApplicationASN);
59 if (!sApplicationInfoItem) {
60 sApplicationInfoItem = ::CFBundleGetFunctionPointerForName(
61 launchServices, CFSTR("_LSSetApplicationInformationItem"));
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);
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) {
82 CFTypeRef currentAsn = getASNFunc ? getASNFunc() : nullptr;
84 if (!getASNFunc || !setInformationItemFunc || !displayNameKey || !currentAsn) {
85 NS_WARNING("Failed to set process name: Accessing launchServices failed");
89 CFStringRef processName = ::CFStringCreateWithCString(nil, aProcessName, kCFStringEncodingASCII);
91 NS_WARNING("Failed to set process name: Could not create CFStringRef");
96 setInformationItemFunc(UNDOCUMENTED_SESSION_CONSTANT, currentAsn, displayNameKey, processName,
97 nil); // Optional out param
98 ::CFRelease(processName);
100 NS_WARNING("Failed to set process name: LSSetInformationItemType err");
105 NS_OBJC_END_TRY_ABORT_BLOCK;
109 } // namespace mozilla