Bug 756308. Implement MacWebAppUtils to allow callers to locate and manipulate native webapps on Mac. r=josh
authorDan Walkowski <dwalkowski@mozilla.com>
Wed, 20 Jun 2012 17:19:13 -0700
changeset 97198 50cd7af728914f5b52299a3332d8e70dcbe0b191
parent 97197 d047caf12f049233ef030514367839c7209e5b91
child 97199 99038d3c6360cc893fa613cf9c26706f9cd53400
push id10932
push userfelipc@gmail.com
push dateThu, 21 Jun 2012 01:39:31 +0000
treeherdermozilla-inbound@50cd7af72891 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjosh
bugs756308
milestone16.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 756308. Implement MacWebAppUtils to allow callers to locate and manipulate native webapps on Mac. r=josh
widget/Makefile.in
widget/cocoa/Makefile.in
widget/cocoa/nsMacWebAppUtils.h
widget/cocoa/nsMacWebAppUtils.mm
widget/cocoa/nsWidgetFactory.mm
widget/nsIMacWebAppUtils.idl
widget/nsWidgetsCID.h
widget/tests/unit/test_macwebapputils.js
widget/tests/unit/xpcshell.ini
--- a/widget/Makefile.in
+++ b/widget/Makefile.in
@@ -138,16 +138,17 @@ XPIDLSRCS	+= nsIPrintSettingsWin.idl \
 		nsIJumpListBuilder.idl \
 		nsIJumpListItem.idl \
 		$(NULL)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 XPIDLSRCS +=	nsIMacDockSupport.idl \
 		nsIStandaloneNativeMenu.idl \
+		nsIMacWebAppUtils.idl \
 		$(NULL)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 XPIDLSRCS	+= nsIRwsService.idl
 endif
 
 EXPORTS		:= $(addprefix $(srcdir)/, $(EXPORTS))
--- a/widget/cocoa/Makefile.in
+++ b/widget/cocoa/Makefile.in
@@ -57,16 +57,17 @@ CMMSRCS = \
   nsDeviceContextSpecX.mm \
   nsPrintDialogX.mm \
   nsPrintOptionsX.mm \
   nsPrintSettingsX.mm \
   nsIdleServiceX.mm \
   TextInputHandler.mm \
   nsMacDockSupport.mm \
   nsStandaloneNativeMenu.mm \
+  nsMacWebAppUtils.mm \
   GfxInfo.mm \
   WidgetTraceEvent.mm \
   $(NULL)
 
 ifeq (x86_64,$(TARGET_CPU))
 CMMSRCS += ComplexTextInputPanel.mm
 endif
 
new file mode 100644
--- /dev/null
+++ b/widget/cocoa/nsMacWebAppUtils.h
@@ -0,0 +1,21 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef _MAC_WEB_APP_UTILS_H_
+#define _MAC_WEB_APP_UTILS_H_
+
+#include "nsIMacWebAppUtils.h"
+
+#define NS_MACWEBAPPUTILS_CONTRACTID "@mozilla.org/widget/mac-web-app-utils;1"
+#define NS_MACWEBAPPUTILS_COMPONENT_CLASSNAME "Mac Web Application Utils"
+
+class nsMacWebAppUtils : public nsIMacWebAppUtils {
+public:
+  nsMacWebAppUtils() {}
+  virtual ~nsMacWebAppUtils() {}
+  
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIMACWEBAPPUTILS
+};
+
+#endif //_MAC_WEB_APP_UTILS_H_
new file mode 100644
--- /dev/null
+++ b/widget/cocoa/nsMacWebAppUtils.mm
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#import <Cocoa/Cocoa.h>
+
+#include "nsMacWebAppUtils.h"
+#include "nsObjCExceptions.h"
+#include "nsCOMPtr.h"
+#include "nsCocoaUtils.h"
+#include "nsString.h"
+
+// Find the path to the app with the given bundleIdentifier, if any.
+// Note that the OS will return the path to the newest binary, if there is more than one.
+// The determination of 'newest' is complex and beyond the scope of this comment.
+
+NS_IMPL_ISUPPORTS1(nsMacWebAppUtils, nsIMacWebAppUtils)
+
+NS_IMETHODIMP nsMacWebAppUtils::PathForAppWithIdentifier(const nsAString& bundleIdentifier, nsAString& outPath) {
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  outPath.Truncate();
+
+  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
+
+  //note that the result of this expression might be nil, meaning no matching app was found. 
+  NSString* temp = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:
+                        [NSString stringWithCharacters:((nsString)bundleIdentifier).get() length:((nsString)bundleIdentifier).Length()]];
+
+  if (temp) {
+    // Copy out the resultant absolute path into outPath if non-nil.
+    nsCocoaUtils::GetStringForNSString(temp, outPath);
+  }
+
+  [ap release];
+  return NS_OK;
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
--- a/widget/cocoa/nsWidgetFactory.mm
+++ b/widget/cocoa/nsWidgetFactory.mm
@@ -57,16 +57,19 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeM
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
 
 #include "nsNativeThemeCocoa.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeThemeCocoa)
 
 #include "nsMacDockSupport.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacDockSupport)
 
+#include "nsMacWebAppUtils.h"
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacWebAppUtils)
+
 #include "nsStandaloneNativeMenu.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStandaloneNativeMenu)
 
 #include "GfxInfo.h"
 namespace mozilla {
 namespace widget {
 // This constructor should really be shared with all platforms.
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init)
@@ -90,16 +93,17 @@ NS_DEFINE_NAMED_CID(NS_THEMERENDERER_CID
 NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_DEVICE_CONTEXT_SPEC_CID);
 NS_DEFINE_NAMED_CID(NS_PRINTSESSION_CID);
 NS_DEFINE_NAMED_CID(NS_PRINTSETTINGSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_PRINTDIALOGSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_NATIVEMENUSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_MACDOCKSUPPORT_CID);
+NS_DEFINE_NAMED_CID(NS_MACWEBAPPUTILS_CID);
 NS_DEFINE_NAMED_CID(NS_STANDALONENATIVEMENU_CID);
 NS_DEFINE_NAMED_CID(NS_GFXINFO_CID);
 
 
 static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
   { &kNS_WINDOW_CID, false, NULL, nsCocoaWindowConstructor },
   { &kNS_POPUP_CID, false, NULL, nsCocoaWindowConstructor },
   { &kNS_CHILD_CID, false, NULL, nsChildViewConstructor },
@@ -116,16 +120,17 @@ static const mozilla::Module::CIDEntry k
   { &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerCocoaConstructor },
   { &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecXConstructor },
   { &kNS_PRINTSESSION_CID, false, NULL, nsPrintSessionConstructor },
   { &kNS_PRINTSETTINGSSERVICE_CID, false, NULL, nsPrintOptionsXConstructor },
   { &kNS_PRINTDIALOGSERVICE_CID, false, NULL, nsPrintDialogServiceXConstructor },
   { &kNS_IDLE_SERVICE_CID, false, NULL, nsIdleServiceXConstructor },
   { &kNS_NATIVEMENUSERVICE_CID, false, NULL, nsNativeMenuServiceXConstructor },
   { &kNS_MACDOCKSUPPORT_CID, false, NULL, nsMacDockSupportConstructor },
+  { &kNS_MACWEBAPPUTILS_CID, false, NULL, nsMacWebAppUtilsConstructor },
   { &kNS_STANDALONENATIVEMENU_CID, false, NULL, nsStandaloneNativeMenuConstructor },
   { &kNS_GFXINFO_CID, false, NULL, mozilla::widget::GfxInfoConstructor },
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
   { "@mozilla.org/widgets/window/mac;1", &kNS_WINDOW_CID },
   { "@mozilla.org/widgets/popup/mac;1", &kNS_POPUP_CID },
@@ -143,16 +148,17 @@ static const mozilla::Module::ContractID
   { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
   { "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID },
   { "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID },
   { "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },
   { NS_PRINTDIALOGSERVICE_CONTRACTID, &kNS_PRINTDIALOGSERVICE_CID },
   { "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID },
   { "@mozilla.org/widget/nativemenuservice;1", &kNS_NATIVEMENUSERVICE_CID },
   { "@mozilla.org/widget/macdocksupport;1", &kNS_MACDOCKSUPPORT_CID },
+  { "@mozilla.org/widget/mac-web-app-utils;1", &kNS_MACWEBAPPUTILS_CID },
   { "@mozilla.org/widget/standalonenativemenu;1", &kNS_STANDALONENATIVEMENU_CID },
   { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID },
   { NULL }
 };
 
 static void
 nsWidgetCocoaModuleDtor()
 {
new file mode 100644
--- /dev/null
+++ b/widget/nsIMacWebAppUtils.idl
@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface nsIMacWebAppUtils;
+
+/**
+ * Allow MozApps API to locate and manipulate natively installed apps
+ */
+
+[scriptable, uuid(e9096367-ddd9-45e4-b762-49c0c18b7119)]
+interface nsIMacWebAppUtils : nsISupports {
+  /**
+   * Find the path for an app with the given signature.
+   */
+  AString pathForAppWithIdentifier(in AString bundleIdentifier);
+
+};
--- a/widget/nsWidgetsCID.h
+++ b/widget/nsWidgetsCID.h
@@ -124,16 +124,20 @@
 // {F72C5DC4-5A12-47be-BE28-AB105F33B08F}
 #define NS_WIN_JUMPLISTLINK_CID \
 { 0xf72c5dc4, 0x5a12, 0x47be, { 0xbe, 0x28, 0xab, 0x10, 0x5f, 0x33, 0xb0, 0x8f } }
 
 // {B16656B2-5187-498f-ABF4-56346126BFDB}
 #define NS_WIN_JUMPLISTSHORTCUT_CID \
 { 0xb16656b2, 0x5187, 0x498f, { 0xab, 0xf4, 0x56, 0x34, 0x61, 0x26, 0xbf, 0xdb } }
 
+// {e9096367-ddd9-45e4-b762-49c0c18b7119}
+#define NS_MACWEBAPPUTILS_CID \
+{ 0xe9096367, 0xddd9, 0x45e4, { 0xb7, 0x62, 0x49, 0xc0, 0xc1, 0x8b, 0x71, 0x19 } }
+
 //-----------------------------------------------------------
 //Printing
 //-----------------------------------------------------------
 #define NS_DEVICE_CONTEXT_SPEC_CID \
 { 0xd3f69889, 0xe13a, 0x4321, \
 { 0x98, 0x0c, 0xa3, 0x93, 0x32, 0xe2, 0x1f, 0x34 } }
 
 #define NS_PRINTSETTINGSSERVICE_CID \
new file mode 100644
--- /dev/null
+++ b/widget/tests/unit/test_macwebapputils.js
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//Basic tests to verify that MacWebAppUtils works
+
+let Ci = Components.interfaces;
+let Cc = Components.classes;
+let Cu = Components.utils;
+let Cr = Components.results;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+function test_find_app()
+{
+  var mwaUtils = Cc["@mozilla.org/widget/mac-web-app-utils;1"].
+  createInstance(Ci.nsIMacWebAppUtils);
+  let sig = "com.apple.TextEdit";
+
+  let path;
+  path = mwaUtils.pathForAppWithIdentifier(sig);
+  do_print("TextEdit path: " + path + "\n");
+  do_check_neq(path, "");
+}
+
+function test_dont_find_fake_app()
+{
+  var mwaUtils = Cc["@mozilla.org/widget/mac-web-app-utils;1"].
+  createInstance(Ci.nsIMacWebAppUtils);
+  let sig = "calliope.penitentiary.dramamine";
+
+  let path;
+  path = mwaUtils.pathForAppWithIdentifier(sig);
+  do_check_eq(path, "");
+}
+
+
+function run_test()
+{
+  test_find_app();
+  test_dont_find_fake_app();
+}
--- a/widget/tests/unit/xpcshell.ini
+++ b/widget/tests/unit/xpcshell.ini
@@ -1,5 +1,7 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_taskbar_jumplistitems.js]
+[test_macwebapputils.js]
+skip-if = os != "mac"