Bug 772600. Create WebappOSUtils to host platform-specific webapps code and implement native app launch. r=felipe
authorDan Walkowski <dwalkowski@mozilla.com>
Sat, 14 Jul 2012 01:09:39 -0700
changeset 104180 4cffe2b37d0c95dde87ec2a96f5bf8d34eb3a670
parent 104179 827cfcf5a41b01b25693d29e546d14a51556d4b0
child 104199 38812f58ea22baac2edb13406744d6315c036280
push id1316
push userakeybl@mozilla.com
push dateMon, 27 Aug 2012 22:37:00 +0000
treeherdermozilla-beta@db4b09302ee2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfelipe
bugs772600
milestone16.0a1
first release with
nightly linux32
4cffe2b37d0c / 16.0a1 / 20120716030546 / files
nightly linux64
4cffe2b37d0c / 16.0a1 / 20120716030546 / files
nightly mac
4cffe2b37d0c / 16.0a1 / 20120716030546 / files
nightly win32
4cffe2b37d0c / 16.0a1 / 20120716030546 / files
nightly win64
4cffe2b37d0c / 16.0a1 / 20120716030546 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 772600. Create WebappOSUtils to host platform-specific webapps code and implement native app launch. r=felipe Windows part by Tim Abraldes and Linux part by Marco Castelluccio
dom/apps/src/Webapps.jsm
toolkit/Makefile.in
toolkit/webapps/Makefile.in
toolkit/webapps/WebappOSUtils.jsm
widget/cocoa/nsMacWebAppUtils.mm
widget/nsIMacWebAppUtils.idl
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -9,16 +9,17 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 
 let EXPORTED_SYMBOLS = ["DOMApplicationRegistry", "DOMApplicationManifest"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/WebappOSUtils.jsm");
 
 const WEBAPP_RUNTIME = Services.appinfo.ID == "webapprt@mozilla.org";
 
 XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
   Cu.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
@@ -166,17 +167,17 @@ let DOMApplicationRegistry = {
         break;
       case "Webapps:GetSelf":
         this.getSelf(msg);
         break;
       case "Webapps:Uninstall":
         this.uninstall(msg);
         break;
       case "Webapps:Launch":
-        Services.obs.notifyObservers(this, "webapps-launch", JSON.stringify(msg));
+        WebappOSUtils.launch(msg);
         break;
       case "Webapps:GetInstalled":
         this.getInstalled(msg);
         break;
       case "Webapps:GetNotInstalled":
         this.getNotInstalled(msg);
         break;
       case "Webapps:GetAll":
--- a/toolkit/Makefile.in
+++ b/toolkit/Makefile.in
@@ -19,16 +19,17 @@ PARALLEL_DIRS = \
   mozapps/extensions \
   mozapps/handling \
   mozapps/preferences \
   mozapps/plugins \
   mozapps/shared \
   obsolete \
   profile \
   themes \
+  webapps \
   $(NULL)
 
 DIRS += \
   mozapps/update \
   $(NULL)
 
 ifdef MOZ_MAINTENANCE_SERVICE
 DIRS += \
new file mode 100644
--- /dev/null
+++ b/toolkit/webapps/Makefile.in
@@ -0,0 +1,18 @@
+# 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/.
+
+DEPTH     = ../..
+topsrcdir = @top_srcdir@
+srcdir    = @srcdir@
+VPATH     = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+EXTRA_PP_JS_MODULES = \
+	WebappOSUtils.jsm \
+	$(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/toolkit/webapps/WebappOSUtils.jsm
@@ -0,0 +1,81 @@
+/* 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/. */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const CC = Components.Constructor;
+
+let EXPORTED_SYMBOLS = ["WebappOSUtils"];
+
+let WebappOSUtils = {
+  launch: function(aData) {
+#ifdef XP_WIN
+    let appRegKey;
+    try {
+      let open = CC("@mozilla.org/windows-registry-key;1",
+                    "nsIWindowsRegKey", "open");
+      let initWithPath = CC("@mozilla.org/file/local;1",
+                            "nsILocalFile", "initWithPath");
+      let initProcess = CC("@mozilla.org/process/util;1",
+                           "nsIProcess", "init");
+
+      appRegKey = open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                       "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" +
+                       aData.origin, Ci.nsIWindowsRegKey.ACCESS_READ);
+
+      let launchTarget = initWithPath(appRegKey.readStringValue("InstallLocation"));
+      launchTarget.append(appRegKey.readStringValue("AppFilename") + ".exe");
+
+      let process = initProcess(launchTarget);
+      process.runwAsync([], 0);
+    } catch (e) {
+      return false;
+    } finally {
+      if (appRegKey) {
+        appRegKey.close();
+      }
+    }
+
+    return true;
+#elifdef XP_MACOSX
+    let mwaUtils = Cc["@mozilla.org/widget/mac-web-app-utils;1"]
+                    .createInstance(Ci.nsIMacWebAppUtils);
+    let appPath;
+    try {
+      appPath = mwaUtils.pathForAppWithIdentifier(aData.origin);
+    } catch (e) {}
+
+    if (appPath) {
+      mwaUtils.launchAppWithIdentifier(aData.origin);
+      return true;
+    }
+
+    return false;
+#elifdef XP_UNIX
+    let origin = Services.io.newURI(aData.origin, null, null);
+    let installDir = "." + origin.scheme + ";" + origin.host;
+    if (origin.port != -1)
+      installDir += ";" + origin.port;
+
+    let exeFile = Services.dirsvc.get("Home", Ci.nsIFile);
+    exeFile.append(installDir);
+    exeFile.append("webapprt-stub");
+
+    try {
+      if (exeFile.exists()) {
+        let process = Cc["@mozilla.org/process/util;1"]
+                        .createInstance(Ci.nsIProcess);
+        process.init(exeFile);
+        process.runAsync([], 0);
+        return true;
+      }
+    } catch (e) {}
+
+    return false;
+#else
+    Services.obs.notifyObservers(this, "webapps-launch", JSON.stringify(aData));
+    return true;
+#endif
+  }
+}
--- a/widget/cocoa/nsMacWebAppUtils.mm
+++ b/widget/cocoa/nsMacWebAppUtils.mm
@@ -32,8 +32,27 @@ NS_IMETHODIMP nsMacWebAppUtils::PathForA
     nsCocoaUtils::GetStringForNSString(temp, outPath);
   }
 
   [ap release];
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
+
+NS_IMETHODIMP nsMacWebAppUtils::LaunchAppWithIdentifier(const nsAString& bundleIdentifier) {
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
+
+  // Note this might return false, meaning the app wasnt launched for some reason. 
+  BOOL success = [[NSWorkspace sharedWorkspace] launchAppWithBundleIdentifier:
+                        [NSString stringWithCharacters:((nsString)bundleIdentifier).get() length:((nsString)bundleIdentifier).Length()]
+                        options: nil
+                        additionalEventParamDescriptor: nil
+                        launchIdentifier: NULL];
+
+
+  [ap release];
+  return NS_OK;
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
--- a/widget/nsIMacWebAppUtils.idl
+++ b/widget/nsIMacWebAppUtils.idl
@@ -12,9 +12,14 @@ interface nsIMacWebAppUtils;
 
 [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);
 
+  /**
+   * Launch the app with the given identifier, if it exists.
+   */
+  void launchAppWithIdentifier(in AString bundleIdentifier);
+
 };