tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ProcessUtils_mac.mm (3947B)


      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/. */
      4 
      5 #include "ProcessUtils.h"
      6 
      7 #include "nsObjCExceptions.h"
      8 #include "nsCocoaUtils.h"
      9 #include "nsString.h"
     10 #include "mozilla/Sprintf.h"
     11 
     12 #define UNDOCUMENTED_SESSION_CONSTANT ((int)-2)
     13 
     14 namespace mozilla {
     15 namespace ipc {
     16 
     17 static void* sApplicationASN = NULL;
     18 static void* sApplicationInfoItem = NULL;
     19 
     20 //
     21 // Sets the process name to the concatenation of the bundlekCFBundleNameKey
     22 // value and the 'aProcessName' argument. If aProcessName is the empty string,
     23 // the process name will be set to just the kCFBundleNameKey value.
     24 //
     25 void SetThisProcessName(const char* aProcessName) {
     26  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
     27  nsAutoreleasePool localPool;
     28 
     29  if (!aProcessName) {
     30    return;
     31  }
     32 
     33  NSString* currentName = [[[NSBundle mainBundle] localizedInfoDictionary]
     34      objectForKey:(NSString*)kCFBundleNameKey];
     35 
     36  char formattedName[1024];
     37  if (strcmp(aProcessName, "") == 0) {
     38    SprintfLiteral(formattedName, "%s", [currentName UTF8String]);
     39  } else {
     40    SprintfLiteral(formattedName, "%s %s", [currentName UTF8String],
     41                   aProcessName);
     42  }
     43 
     44  aProcessName = formattedName;
     45 
     46  // This function is based on Chrome/Webkit's and relies on potentially
     47  // dangerous SPI.
     48  typedef CFTypeRef (*LSGetASNType)();
     49  typedef OSStatus (*LSSetInformationItemType)(int, CFTypeRef, CFStringRef,
     50                                               CFStringRef, CFDictionaryRef*);
     51 
     52  CFBundleRef launchServices =
     53      ::CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
     54  if (!launchServices) {
     55    NS_WARNING(
     56        "Failed to set process name: Could not open LaunchServices bundle");
     57    return;
     58  }
     59 
     60  if (!sApplicationASN) {
     61    sApplicationASN = ::CFBundleGetFunctionPointerForName(
     62        launchServices, CFSTR("_LSGetCurrentApplicationASN"));
     63    if (!sApplicationASN) {
     64      NS_WARNING("Failed to set process name: Could not get function pointer "
     65                 "for LaunchServices");
     66      return;
     67    }
     68  }
     69 
     70  LSGetASNType getASNFunc = reinterpret_cast<LSGetASNType>(sApplicationASN);
     71 
     72  if (!sApplicationInfoItem) {
     73    sApplicationInfoItem = ::CFBundleGetFunctionPointerForName(
     74        launchServices, CFSTR("_LSSetApplicationInformationItem"));
     75  }
     76 
     77  LSSetInformationItemType setInformationItemFunc =
     78      reinterpret_cast<LSSetInformationItemType>(sApplicationInfoItem);
     79 
     80  void* displayNameKeyAddr = ::CFBundleGetDataPointerForName(
     81      launchServices, CFSTR("_kLSDisplayNameKey"));
     82 
     83  CFStringRef displayNameKey = nil;
     84  if (displayNameKeyAddr) {
     85    displayNameKey =
     86        reinterpret_cast<CFStringRef>(*(CFStringRef*)displayNameKeyAddr);
     87  }
     88 
     89  // We need this to ensure we have a connection to the Process Manager, not
     90  // doing so will silently fail and process name wont be updated.
     91  ProcessSerialNumber psn;
     92  if (::GetCurrentProcess(&psn) != noErr) {
     93    return;
     94  }
     95 
     96  CFTypeRef currentAsn = getASNFunc ? getASNFunc() : nullptr;
     97 
     98  if (!getASNFunc || !setInformationItemFunc || !displayNameKey ||
     99      !currentAsn) {
    100    NS_WARNING("Failed to set process name: Accessing launchServices failed");
    101    return;
    102  }
    103 
    104  CFStringRef processName =
    105      ::CFStringCreateWithCString(nil, aProcessName, kCFStringEncodingASCII);
    106  if (!processName) {
    107    NS_WARNING("Failed to set process name: Could not create CFStringRef");
    108    return;
    109  }
    110 
    111  OSErr err = setInformationItemFunc(UNDOCUMENTED_SESSION_CONSTANT, currentAsn,
    112                                     displayNameKey, processName,
    113                                     nil);  // Optional out param
    114  ::CFRelease(processName);
    115  if (err != noErr) {
    116    NS_WARNING("Failed to set process name: LSSetInformationItemType err");
    117    return;
    118  }
    119 
    120  return;
    121  NS_OBJC_END_TRY_ABORT_BLOCK;
    122 }
    123 
    124 }  // namespace ipc
    125 }  // namespace mozilla