Bug 915480 - Get the installation path of web apps in a more precise way. r=myk
authorMarco Castelluccio <mar.castelluccio@studenti.unina.it>
Tue, 01 Oct 2013 08:06:57 -0400
changeset 149501 0029abd9afdd16d7f58a889018cf7fcacdfd1c9c
parent 149500 c62f55756420ec0447d7c1a8033cdb16c3b5ef3c
child 149502 73aee2b3959fc157f02fcbbce3357e9a780a499d
push id2909
push userryanvm@gmail.com
push dateTue, 01 Oct 2013 21:24:54 +0000
treeherderfx-team@6290d3169a3f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmyk
bugs915480
milestone27.0a1
Bug 915480 - Get the installation path of web apps in a more precise way. r=myk
toolkit/webapps/WebappOSUtils.jsm
--- a/toolkit/webapps/WebappOSUtils.jsm
+++ b/toolkit/webapps/WebappOSUtils.jsm
@@ -50,44 +50,53 @@ this.WebappOSUtils = {
    * The new format ensures a readable and unique name for an app by combining
    * its name with a hash of its manifest URL.  The old format uses its origin,
    * which is only unique until we support multiple apps per origin.
    */
   getLaunchTarget: function(aApp) {
     let uniqueName = this.getUniqueName(aApp);
 
 #ifdef XP_WIN
+    let isOldNamingScheme = false;
     let appRegKey;
     try {
       let open = CC("@mozilla.org/windows-registry-key;1",
                     "nsIWindowsRegKey", "open");
       appRegKey = open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
                        "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" +
                        uniqueName, Ci.nsIWindowsRegKey.ACCESS_READ);
     } catch (ex) {
+      // Fall back to the old installation naming scheme
       try {
         appRegKey = open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
                          "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" +
                          aApp.origin, Ci.nsIWindowsRegKey.ACCESS_READ);
+        isOldNamingScheme = true;
       } catch (ex) {
         return null;
       }
     }
 
     let appFilename, installLocation;
     try {
       appFilename = appRegKey.readStringValue("AppFilename");
       installLocation = appRegKey.readStringValue("InstallLocation");
     } catch (ex) {
       return null;
     } finally {
       appRegKey.close();
     }
 
     installLocation = installLocation.substring(1, installLocation.length - 1);
+
+    if (isOldNamingScheme &&
+        !this.isOldInstallPathValid(aApp, installLocation)) {
+      return null;
+    }
+
     let initWithPath = CC("@mozilla.org/file/local;1",
                           "nsILocalFile", "initWithPath");
     let launchTarget = initWithPath(installLocation);
     launchTarget.append(appFilename + ".exe");
 
     return launchTarget;
 #elifdef XP_MACOSX
     let mwaUtils = Cc["@mozilla.org/widget/mac-web-app-utils;1"]
@@ -95,41 +104,45 @@ this.WebappOSUtils = {
 
     try {
       let path;
       if (path = mwaUtils.pathForAppWithIdentifier(uniqueName)) {
         return [ uniqueName, path ];
       }
     } catch(ex) {}
 
+    // Fall back to the old installation naming scheme
     try {
       let path;
-      if (path = mwaUtils.pathForAppWithIdentifier(aApp.origin)) {
+      if ((path = mwaUtils.pathForAppWithIdentifier(aApp.origin)) &&
+           this.isOldInstallPathValid(aApp, path)) {
         return [ aApp.origin, path ];
       }
     } catch(ex) {}
 
     return [ null, null ];
 #elifdef XP_UNIX
     let exeFile = Services.dirsvc.get("Home", Ci.nsIFile);
     exeFile.append("." + uniqueName);
     exeFile.append("webapprt-stub");
 
+    // Fall back to the old installation naming scheme
     if (!exeFile.exists()) {
       exeFile = Services.dirsvc.get("Home", Ci.nsIFile);
 
       let origin = Services.io.newURI(aApp.origin, null, null);
       let installDir = "." + origin.scheme + ";" +
                        origin.host +
                        (origin.port != -1 ? ";" + origin.port : "");
 
       exeFile.append(installDir);
       exeFile.append("webapprt-stub");
 
-      if (!exeFile.exists()) {
+      if (!exeFile.exists() ||
+          !this.isOldInstallPathValid(aApp, exeFile.parent.path)) {
         return null;
       }
     }
 
     return exeFile;
 #endif
   },
 
@@ -268,16 +281,34 @@ this.WebappOSUtils = {
     }
 
     return true;
 #endif
 #endif
   },
 
   /**
+   * Returns true if the given install path (in the old naming scheme) actually
+   * belongs to the given application.
+   */
+  isOldInstallPathValid: function(aApp, aInstallPath) {
+    // Applications with an origin that starts with "app" are packaged apps and
+    // packaged apps have never been installed using the old naming scheme.
+    // After bug 910465, we'll have a better way to check if an app is
+    // packaged.
+    if (aApp.origin.startsWith("app")) {
+      return false;
+    }
+
+    // Bug 915480: We could check the app name from the manifest to
+    // better verify the installation path.
+    return true;
+  },
+
+  /**
    * Checks if the given app is locally installed.
    */
   isLaunchable: function(aApp) {
     let uniqueName = this.getUniqueName(aApp);
 
 #ifdef XP_WIN
     if (!this.getLaunchTarget(aApp)) {
       return false;
@@ -303,31 +334,40 @@ this.WebappOSUtils = {
     if (xdg_data_home_env) {
       desktopINI = new FileUtils.File(xdg_data_home_env);
     } else {
       desktopINI = FileUtils.getFile("Home", [".local", "share"]);
     }
     desktopINI.append("applications");
     desktopINI.append("owa-" + uniqueName + ".desktop");
 
+    // Fall back to the old installation naming scheme
     if (!desktopINI.exists()) {
       if (xdg_data_home_env) {
         desktopINI = new FileUtils.File(xdg_data_home_env);
       } else {
         desktopINI = FileUtils.getFile("Home", [".local", "share"]);
       }
 
       let origin = Services.io.newURI(aApp.origin, null, null);
       let oldUniqueName = origin.scheme + ";" +
                           origin.host +
                           (origin.port != -1 ? ";" + origin.port : "");
 
       desktopINI.append("owa-" + oldUniqueName + ".desktop");
 
-      return desktopINI.exists();
+      if (!desktopINI.exists()) {
+        return false;
+      }
+
+      let installDir = Services.dirsvc.get("Home", Ci.nsIFile);
+      installDir.append("." + origin.scheme + ";" + origin.host +
+                        (origin.port != -1 ? ";" + origin.port : ""));
+
+      return isOldInstallPathValid(aApp, installDir.path);
     }
 
     return true;
 #endif
   },
 
   /**
    * Sanitize the filename (accepts only a-z, 0-9, - and _)