Bug 557226 - Mac plugins now reflect plugin name; r=smichaud
authorBenoit Girard <b56girard@gmail.com>
Sun, 15 Aug 2010 23:02:38 -0400
changeset 71908 f29f165edae601ef78119356954e03a0d5489515
parent 71907 34e102b130e9007ff1ecd05338cd39f3303f102f
child 71909 012e21b5705736afad47fca86f7925faff9bdf0d
push id283
push userb56girard@gmail.com
push dateTue, 28 Jun 2011 14:40:41 +0000
treeherdermozilla-inbound@f29f165edae6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmichaud
bugs557226
milestone7.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 557226 - Mac plugins now reflect plugin name; r=smichaud
dom/plugins/ipc/PluginModuleChild.cpp
dom/plugins/ipc/PluginUtilsOSX.h
dom/plugins/ipc/PluginUtilsOSX.mm
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -249,16 +249,25 @@ PluginModuleChild::Init(const std::strin
     mInitializeFunc =
         (NP_PLUGININIT)PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
     NS_ENSURE_TRUE(mInitializeFunc, false);
 #else
 
 #  error Please copy the initialization code from nsNPAPIPlugin.cpp
 
 #endif
+
+#ifdef XP_MACOSX
+    nsPluginInfo info = nsPluginInfo();
+    rv = pluginFile.GetPluginInfo(info, &mLibrary);
+    if (rv == NS_OK) {
+        mozilla::plugins::PluginUtilsOSX::SetProcessName(info.fName);
+    }
+#endif
+
     return true;
 }
 
 #if defined(MOZ_WIDGET_GTK2)
 typedef void (*GObjectDisposeFn)(GObject*);
 typedef gboolean (*GtkWidgetScrollEventFn)(GtkWidget*, GdkEventScroll*);
 typedef void (*GtkPlugEmbeddedFn)(GtkPlug*);
 
--- a/dom/plugins/ipc/PluginUtilsOSX.h
+++ b/dom/plugins/ipc/PluginUtilsOSX.h
@@ -53,12 +53,13 @@ void InvokeNativeEventLoop();
 
 // Need to call back and send a cocoa draw event to the plugin.
 typedef void (*DrawPluginFunc) (CGContextRef, void*, nsIntRect aUpdateRect);
 
 void* GetCGLayer(DrawPluginFunc aFunc, void* aPluginInstance);
 void ReleaseCGLayer(void* cgLayer);
 void Repaint(void* cgLayer, nsIntRect aRect);
 
+bool SetProcessName(const char* aProcessName);
 
 } // namespace PluginUtilsOSX
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/ipc/PluginUtilsOSX.mm
+++ b/dom/plugins/ipc/PluginUtilsOSX.mm
@@ -38,16 +38,19 @@
   * ***** END LICENSE BLOCK ***** */
 
 #import <AppKit/AppKit.h>
 #import <QuartzCore/QuartzCore.h>
 #include "PluginUtilsOSX.h"
 
 // Remove definitions for try/catch interfering with ObjCException macros.
 #include "nsObjCExceptions.h"
+#include "nsCocoaUtils.h"
+
+#include "nsDebug.h"
 
 using namespace mozilla::plugins::PluginUtilsOSX;
 
 @interface CGBridgeLayer : CALayer {
   DrawPluginFunc mDrawFunc;
   void* mPluginInstance;
   nsIntRect mUpdateRect;
 }
@@ -163,8 +166,104 @@ NPError mozilla::plugins::PluginUtilsOSX
 }
 
 void mozilla::plugins::PluginUtilsOSX::InvokeNativeEventLoop()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
   ::CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, true);
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
+
+
+#define UNDOCUMENTED_SESSION_CONSTANT ((int)-2)
+static void *mozilla::plugins::PluginUtilsOSX::sApplicationASN = NULL;
+static void *mozilla::plugins::PluginUtilsOSX::sApplicationInfoItem = NULL;
+
+bool mozilla::plugins::PluginUtilsOSX::SetProcessName(const char* aProcessName) {
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
+  nsAutoreleasePool localPool;
+
+  if (!aProcessName || strcmp(aProcessName, "") == 0) {
+    return false;
+  }
+
+  NSString *currentName = [[[NSBundle mainBundle] localizedInfoDictionary] 
+                              objectForKey:(NSString *)kCFBundleNameKey];
+
+  char formattedName[1024];
+  snprintf(formattedName, sizeof(formattedName), 
+      "%s (%s)", [currentName UTF8String], aProcessName);
+
+  aProcessName = formattedName;
+
+  // This function is based on Chrome/Webkit's and relies on potentially dangerous SPI.
+  typedef CFTypeRef (*LSGetASNType)();
+  typedef OSStatus (*LSSetInformationItemType)(int, CFTypeRef,
+                                               CFStringRef, 
+                                               CFStringRef,
+                                               CFDictionaryRef*);
+
+  CFBundleRef launchServices = ::CFBundleGetBundleWithIdentifier(
+                                          CFSTR("com.apple.LaunchServices"));
+  if (!launchServices) {
+    NS_WARNING("Failed to set process name: Could not open LaunchServices bundle");
+    return false;
+  }
+
+  if (!sApplicationASN) {
+    sApplicationASN = ::CFBundleGetFunctionPointerForName(launchServices, 
+                                            CFSTR("_LSGetCurrentApplicationASN"));
+  }
+
+  LSGetASNType getASNFunc = reinterpret_cast<LSGetASNType>
+                                          (sApplicationASN);
+
+  if (!sApplicationInfoItem) {
+    sApplicationInfoItem = ::CFBundleGetFunctionPointerForName(launchServices, 
+                                            CFSTR("_LSSetApplicationInformationItem"));
+  }
+
+  LSSetInformationItemType setInformationItemFunc 
+                                          = reinterpret_cast<LSSetInformationItemType>
+                                          (sApplicationInfoItem);
+
+  void * displayNameKeyAddr = ::CFBundleGetDataPointerForName(launchServices,
+                                          CFSTR("_kLSDisplayNameKey"));
+
+  CFStringRef displayNameKey = nil;
+  if (displayNameKeyAddr) {
+    displayNameKey = reinterpret_cast<CFStringRef>(*(CFStringRef*)displayNameKeyAddr);
+  }
+
+  // Rename will fail without this
+  ProcessSerialNumber psn;
+  if (::GetCurrentProcess(&psn) != noErr) {
+    return false;
+  }
+
+  CFTypeRef currentAsn = getASNFunc();
+
+  if (!getASNFunc || !setInformationItemFunc || 
+      !displayNameKey || !currentAsn) {
+    NS_WARNING("Failed to set process name: Accessing launchServices failed");
+    return false;
+  }
+
+  CFStringRef processName = ::CFStringCreateWithCString(nil, 
+                                                        aProcessName, 
+                                                        kCFStringEncodingASCII);
+  if (!processName) {
+    NS_WARNING("Failed to set process name: Could not create CFStringRef");
+    return false;
+  }
+
+  OSErr err = setInformationItemFunc(UNDOCUMENTED_SESSION_CONSTANT, currentAsn,
+                                     displayNameKey, processName,
+                                     nil); // Optional out param
+  ::CFRelease(processName);
+  if (err != noErr) {
+    NS_WARNING("Failed to set process name: LSSetInformationItemType err");
+    return false;
+  }
+
+  return true;
+  NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
+}