backout 5a84a1907654 (bug 1042881) for causing app startup failures r=me
authorFabrice Desré <fabrice@mozilla.com>
Thu, 31 Jul 2014 12:14:03 -0700
changeset 197111 bdd901635243b877cdfc9b62729bc957e77b50b0
parent 197110 d29f619bb09d42f6b928887d00994d70f2b47875
child 197147 17396ce2587dee2bf5709bca37facab34bedc923
push id9353
push userfdesre@mozilla.com
push dateThu, 31 Jul 2014 19:15:41 +0000
treeherderb2g-inbound@bdd901635243 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1042881
milestone34.0a1
backs out5a84a1907654185e04a58a2d40654dd7c57b12bc
backout 5a84a1907654 (bug 1042881) for causing app startup failures r=me
b2g/chrome/content/shell.js
b2g/components/AlertsHelper.jsm
browser/modules/WebappManager.jsm
dom/activities/src/ActivitiesService.jsm
dom/apps/src/AppsUtils.jsm
dom/apps/src/PermissionsInstaller.jsm
dom/apps/src/Webapps.jsm
dom/messages/SystemMessagePermissionsChecker.jsm
mobile/android/chrome/content/WebappRT.js
mobile/android/chrome/content/aboutApps.js
mobile/android/modules/WebappManager.jsm
toolkit/devtools/server/actors/webapps.js
toolkit/webapps/NativeApp.jsm
webapprt/WebappManager.jsm
webapprt/WebappRT.jsm
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -797,18 +797,17 @@ var WebappsHelper = {
     json.mm = subject;
 
     switch(topic) {
       case "webapps-launch":
         DOMApplicationRegistry.getManifestFor(json.manifestURL).then((aManifest) => {
           if (!aManifest)
             return;
 
-          let manifest = new ManifestHelper(aManifest, json.origin,
-                                            json.manifestURL);
+          let manifest = new ManifestHelper(aManifest, json.origin);
           let payload = {
             timestamp: json.timestamp,
             url: manifest.fullLaunchPath(json.startPoint),
             manifestURL: json.manifestURL
           };
           shell.sendCustomEvent("webapps-launch", payload);
         });
         break;
--- a/b2g/components/AlertsHelper.jsm
+++ b/b2g/components/AlertsHelper.jsm
@@ -162,30 +162,30 @@ let AlertsHelper = {
   registerListener: function(alertId, cookie, alertListener) {
     this._listeners[alertId] = { observer: alertListener, cookie: cookie };
   },
 
   registerAppListener: function(uid, listener) {
     this._listeners[uid] = listener;
 
     appsService.getManifestFor(listener.manifestURL).then((manifest) => {
-      let app = appsService.getAppByManifestURL(listener.manifestURL);
-      let helper = new ManifestHelper(manifest, app.origin, app.manifestURL);
+      let helper = new ManifestHelper(manifest, listener.manifestURL);
       let getNotificationURLFor = function(messages) {
         if (!messages) {
           return null;
         }
 
         for (let i = 0; i < messages.length; i++) {
           let message = messages[i];
           if (message === kNotificationSystemMessageName) {
             return helper.fullLaunchPath();
           } else if (typeof message === "object" &&
                      kNotificationSystemMessageName in message) {
-            return helper.resolveURL(message[kNotificationSystemMessageName]);
+            return helper.resolveFromOrigin(
+              message[kNotificationSystemMessageName]);
           }
         }
 
         // No message found...
         return null;
       }
 
       listener.target = getNotificationURLFor(manifest.messages);
@@ -215,18 +215,17 @@ let AlertsHelper = {
     if (!manifestURL || !manifestURL.length) {
       send(null, null);
       return;
     }
 
     // If we have a manifest URL, get the icon and title from the manifest
     // to prevent spoofing.
     appsService.getManifestFor(manifestURL).then((manifest) => {
-      let app = appsService.getAppByManifestURL(manifestURL);
-      let helper = new ManifestHelper(manifest, app.origin, manifestURL);
+      let helper = new ManifestHelper(manifest, manifestURL);
       send(helper.name, helper.iconURLForSize(kNotificationIconSize));
     });
   },
 
   showAlertNotification: function(aMessage) {
     let data = aMessage.data;
     let currentListener = this._listeners[data.name];
     if (currentListener && currentListener.observer) {
--- a/browser/modules/WebappManager.jsm
+++ b/browser/modules/WebappManager.jsm
@@ -61,19 +61,17 @@ this.WebappManager = {
     if (aMessage.name == "Webapps:UpdateState") {
       if (data.error) {
         this.installations[manifestURL].reject(data.error);
       } else if (data.app.installState == "installed") {
         this.installations[manifestURL].resolve();
       }
     } else if (aMessage.name == "Webapps:Install:Return:OK" &&
                !data.isPackage) {
-      let manifest = new ManifestHelper(data.app.manifest,
-                                        data.app.origin,
-                                        data.app.manifestURL);
+      let manifest = new ManifestHelper(data.app.manifest, data.app.origin);
       if (!manifest.appcache_path) {
         this.installations[manifestURL].resolve();
       }
     } else if (aMessage.name == "Webapps:Install:Return:KO") {
       this.installations[manifestURL].reject(data.error);
     }
   },
 
@@ -169,18 +167,17 @@ this.WebappManager = {
               throw ex;
             }
           })
         );
       }
     };
 
     let requestingURI = chromeWin.makeURI(aData.from);
-    let app = aData.app;
-    let manifest = new ManifestHelper(jsonManifest, app.origin, app.manifestURL);
+    let manifest = new ManifestHelper(jsonManifest, aData.app.origin);
 
     let host;
     try {
       host = requestingURI.host;
     } catch(e) {
       host = requestingURI.spec;
     }
 
--- a/dom/activities/src/ActivitiesService.jsm
+++ b/dom/activities/src/ActivitiesService.jsm
@@ -289,20 +289,17 @@ let Activities = {
         let ids = aResults.options.map((aItem) => {
           return { id: reg._appIdForManifestURL(aItem.manifest) }
         });
 
         reg._readManifests(ids).then((aManifests) => {
           let results = [];
           aManifests.forEach((aManifest, i) => {
             let manifestURL = aResults.options[i].manifest;
-            // Not passing the origin is fine here since we only need
-            // helper.name which doesn't rely on url resolution.
-            let helper =
-              new ManifestHelper(aManifest.manifest, manifestURL, manifestURL);
+            let helper = new ManifestHelper(aManifest.manifest, manifestURL);
             results.push({
               manifestURL: manifestURL,
               iconURL: aResults.options[i].icon,
               appName: helper.name
             });
           });
 
           // Now fire success with the array of choices.
--- a/dom/apps/src/AppsUtils.jsm
+++ b/dom/apps/src/AppsUtils.jsm
@@ -19,18 +19,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "WebappOSUtils",
   "resource://gre/modules/WebappOSUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
   "resource://gre/modules/NetUtil.jsm");
 
 // Shared code for AppsServiceChild.jsm, Webapps.jsm and Webapps.js
 
-this.EXPORTED_SYMBOLS =
-  ["AppsUtils", "ManifestHelper", "isAbsoluteURI", "mozIApplication"];
+this.EXPORTED_SYMBOLS = ["AppsUtils", "ManifestHelper", "isAbsoluteURI", "mozIApplication"];
 
 function debug(s) {
   //dump("-*- AppsUtils.jsm: " + s + "\n");
 }
 
 this.isAbsoluteURI = function(aURI) {
   let foo = Services.io.newURI("http://foo", null, null);
   let bar = Services.io.newURI("http://bar", null, null);
@@ -369,18 +368,17 @@ this.AppsUtils = {
    * For now, only ensure app can't rename itself.
    */
   ensureSameAppName: function ensureSameAppName(aOldManifest, aNewManifest, aApp) {
     // Ensure that app name can't be updated
     aNewManifest.name = aApp.name;
 
     // Nor through localized names
     if ('locales' in aNewManifest) {
-      let defaultName =
-        new ManifestHelper(aOldManifest, aApp.origin, aApp.manifestURL).name;
+      let defaultName = new ManifestHelper(aOldManifest, aApp.origin).name;
       for (let locale in aNewManifest.locales) {
         let entry = aNewManifest.locales[locale];
         if (!entry.name) {
           continue;
         }
         // In case previous manifest didn't had a name,
         // we use the default app name
         let localizedName = defaultName;
@@ -590,35 +588,21 @@ this.AppsUtils = {
     // Convert the binary hash data to a hex string.
     return [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
   }
 }
 
 /**
  * Helper object to access manifest information with locale support
  */
-this.ManifestHelper = function(aManifest, aOrigin, aManifestURL) {
-  // If the app is packaged, we resolve uris against the origin.
-  // If it's not, against the manifest url.
-
-  if (!aOrigin || !aManifestURL) {
-    throw Error("ManifestHelper needs both origin and manifestURL");
-  }
-
-  this._baseURI = Services.io.newURI(
-    aOrigin.startsWith("app://") ? aOrigin : aManifestURL, null, null);
-
-  // We keep the manifest url in all cases since we need it to
-  // resolve the package path for packaged apps.
-  this._manifestURL = Services.io.newURI(aManifestURL, null, null);
-
+this.ManifestHelper = function(aManifest, aOrigin) {
+  this._origin = Services.io.newURI(aOrigin, null, null);
   this._manifest = aManifest;
-  let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"]
-                 .getService(Ci.nsIXULChromeRegistry)
-                 .QueryInterface(Ci.nsIToolkitChromeRegistry);
+  let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry)
+                                                          .QueryInterface(Ci.nsIToolkitChromeRegistry);
   let locale = chrome.getSelectedLocale("global").toLowerCase();
   this._localeRoot = this._manifest;
 
   if (this._manifest.locales && this._manifest.locales[locale]) {
     this._localeRoot = this._manifest.locales[locale];
   }
   else if (this._manifest.locales) {
     // try with the language part of the locale ("en" for en-GB) only
@@ -697,71 +681,71 @@ ManifestHelper.prototype = {
     let iconSizes = Object.keys(icons);
     if (iconSizes.length == 0) {
       return null;
     }
 
     iconSizes.sort((a, b) => a - b);
     let biggestIconSize = iconSizes.pop();
     let biggestIcon = icons[biggestIconSize];
-    let biggestIconURL = this._baseURI.resolve(biggestIcon);
+    let biggestIconURL = this._origin.resolve(biggestIcon);
 
     return biggestIconURL;
   },
 
   iconURLForSize: function(aSize) {
     let icons = this._localeProp("icons");
     if (!icons)
       return null;
     let dist = 100000;
     let icon = null;
     for (let size in icons) {
       let iSize = parseInt(size);
       if (Math.abs(iSize - aSize) < dist) {
-        icon = this._baseURI.resolve(icons[size]);
+        icon = this._origin.resolve(icons[size]);
         dist = Math.abs(iSize - aSize);
       }
     }
     return icon;
   },
 
   fullLaunchPath: function(aStartPoint) {
     // If no start point is specified, we use the root launch path.
     // In all error cases, we just return null.
     if ((aStartPoint || "") === "") {
-      return this._baseURI.resolve(this._localeProp("launch_path") || "");
+      return this._origin.resolve(this._localeProp("launch_path") || "");
     }
 
     // Search for the l10n entry_points property.
     let entryPoints = this._localeProp("entry_points");
     if (!entryPoints) {
       return null;
     }
 
     if (entryPoints[aStartPoint]) {
-      return this._baseURI.resolve(entryPoints[aStartPoint].launch_path || "");
+      return this._origin.resolve(entryPoints[aStartPoint].launch_path || "");
     }
 
     return null;
   },
 
-  resolveURL: function(aURI) {
+  resolveFromOrigin: function(aURI) {
     // This should be enforced higher up, but check it here just in case.
     if (isAbsoluteURI(aURI)) {
-      throw new Error("Webapps.jsm: non-relative URI passed to resolve");
+      throw new Error("Webapps.jsm: non-relative URI passed to resolveFromOrigin");
     }
-    return this._baseURI.resolve(aURI);
+    return this._origin.resolve(aURI);
   },
 
   fullAppcachePath: function() {
     let appcachePath = this._localeProp("appcache_path");
-    return this._baseURI.resolve(appcachePath ? appcachePath : "");
+    return this._origin.resolve(appcachePath ? appcachePath : "");
   },
 
   fullPackagePath: function() {
     let packagePath = this._localeProp("package_path");
-    return this._manifestURL.resolve(packagePath ? packagePath : "");
+    return this._origin.resolve(packagePath ? packagePath : "");
   },
 
   get role() {
     return this._manifest.role || "";
   }
 }
--- a/dom/apps/src/PermissionsInstaller.jsm
+++ b/dom/apps/src/PermissionsInstaller.jsm
@@ -54,18 +54,17 @@ this.PermissionsInstaller = {
    *        Indicates the app was just re-installed
    * @param function aOnError
    *        A function called if an error occurs
    * @returns void
    **/
   installPermissions: function installPermissions(aApp, aIsReinstall, aOnError,
                                                   aIsSystemUpdate) {
     try {
-      let newManifest =
-        new ManifestHelper(aApp.manifest, aApp.origin, aApp.manifestURL);
+      let newManifest = new ManifestHelper(aApp.manifest, aApp.origin);
       if (!newManifest.permissions && !aIsReinstall) {
         return;
       }
 
       if (aIsReinstall) {
         // Compare the original permissions against the new permissions
         // Remove any deprecated Permissions
 
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -384,18 +384,17 @@ this.DOMApplicationRegistry = {
         });
       });
     }
   },
 
   updateOfflineCacheForApp: function(aId) {
     let app = this.webapps[aId];
     this._readManifests([{ id: aId }]).then((aResult) => {
-      let manifest =
-        new ManifestHelper(aResult[0].manifest, app.origin, app.manifestURL);
+      let manifest = new ManifestHelper(aResult[0].manifest, app.origin);
       OfflineCacheInstaller.installCache({
         cachePath: app.cachePath,
         appId: aId,
         origin: Services.io.newURI(app.origin, null, null),
         localId: app.localId,
         appcache_path: manifest.fullAppcachePath()
       });
     });
@@ -671,47 +670,47 @@ this.DOMApplicationRegistry = {
       root = aManifest.entry_points[aEntryPoint];
     }
 
     if (!root.messages || !Array.isArray(root.messages) ||
         root.messages.length == 0) {
       return;
     }
 
-    let manifest = new ManifestHelper(aManifest, aApp.origin, aApp.manifestURL);
+    let manifest = new ManifestHelper(aManifest, aApp.origin);
     let launchPathURI = Services.io.newURI(manifest.fullLaunchPath(aEntryPoint), null, null);
     let manifestURI = Services.io.newURI(aApp.manifestURL, null, null);
     root.messages.forEach(function registerPages(aMessage) {
       let handlerPageURI = launchPathURI;
       let messageName;
       if (typeof(aMessage) === "object" && Object.keys(aMessage).length === 1) {
         messageName = Object.keys(aMessage)[0];
         let handlerPath = aMessage[messageName];
         // Resolve the handler path from origin. If |handler_path| is absent,
         // simply skip.
         let fullHandlerPath;
         try {
           if (handlerPath && handlerPath.trim()) {
-            fullHandlerPath = manifest.resolveURL(handlerPath);
+            fullHandlerPath = manifest.resolveFromOrigin(handlerPath);
           } else {
             throw new Error("Empty or blank handler path.");
           }
         } catch(e) {
           debug("system message handler path (" + handlerPath + ") is " +
                 "invalid, skipping. Error is: " + e);
           return;
         }
         handlerPageURI = Services.io.newURI(fullHandlerPath, null, null);
       } else {
         messageName = aMessage;
       }
 
       if (SystemMessagePermissionsChecker
             .isSystemMessagePermittedToRegister(messageName,
-                                                aApp.manifestURL,
+                                                aApp.origin,
                                                 aManifest)) {
         msgmgr.registerPage(messageName, handlerPageURI, manifestURI);
       }
     });
   },
 
   // |aEntryPoint| is either the entry_point name or the null in which case we
   // use the root of the manifest.
@@ -729,44 +728,44 @@ this.DOMApplicationRegistry = {
       return;
     }
 
     if ((typeof connections) !== "object") {
       debug("|connections| is not an object. Skipping: " + connections);
       return;
     }
 
-    let manifest = new ManifestHelper(aManifest, aApp.origin, aApp.manifestURL);
+    let manifest = new ManifestHelper(aManifest, aApp.origin);
     let launchPathURI = Services.io.newURI(manifest.fullLaunchPath(aEntryPoint),
                                            null, null);
     let manifestURI = Services.io.newURI(aApp.manifestURL, null, null);
 
     for (let keyword in connections) {
       let connection = connections[keyword];
 
       // Resolve the handler path from origin. If |handler_path| is absent,
       // use |launch_path| as default.
       let fullHandlerPath;
       let handlerPath = connection.handler_path;
       if (handlerPath) {
         try {
-          fullHandlerPath = manifest.resolveURL(handlerPath);
+          fullHandlerPath = manifest.resolveFromOrigin(handlerPath);
         } catch(e) {
           debug("Connection's handler path is invalid. Skipping: keyword: " +
                 keyword + " handler_path: " + handlerPath);
           continue;
         }
       }
       let handlerPageURI = fullHandlerPath
                            ? Services.io.newURI(fullHandlerPath, null, null)
                            : launchPathURI;
 
       if (SystemMessagePermissionsChecker
             .isSystemMessagePermittedToRegister("connection",
-                                                aApp.manifestURL,
+                                                aApp.origin,
                                                 aManifest)) {
         msgmgr.registerPage("connection", handlerPageURI, manifestURI);
       }
 
       interAppCommService.
         registerConnection(keyword,
                            handlerPageURI,
                            manifestURI,
@@ -808,26 +807,26 @@ this.DOMApplicationRegistry = {
     if (aEntryPoint && aManifest.entry_points[aEntryPoint]) {
       root = aManifest.entry_points[aEntryPoint];
     }
 
     if (!root.activities) {
       return activitiesToRegister;
     }
 
-    let manifest = new ManifestHelper(aManifest, aApp.origin, aApp.manifestURL);
+    let manifest = new ManifestHelper(aManifest, aApp.origin);
     for (let activity in root.activities) {
       let description = root.activities[activity];
       let href = description.href;
       if (!href) {
         href = manifest.launch_path;
       }
 
       try {
-        href = manifest.resolveURL(href);
+        href = manifest.resolveFromOrigin(href);
       } catch (e) {
         debug("Activity href (" + href + ") is invalid, skipping. " +
               "Error is: " + e);
         continue;
       }
 
       // Make a copy of the description object since we don't want to modify
       // the manifest itself, but need to register with a resolved URI.
@@ -847,17 +846,17 @@ this.DOMApplicationRegistry = {
                                     "description": newDesc });
       }
 
       let launchPathURI = Services.io.newURI(href, null, null);
       let manifestURI = Services.io.newURI(aApp.manifestURL, null, null);
 
       if (SystemMessagePermissionsChecker
             .isSystemMessagePermittedToRegister("activity",
-                                                aApp.manifestURL,
+                                                aApp.origin,
                                                 aManifest)) {
         msgmgr.registerPage("activity", launchPathURI, manifestURI);
       }
     }
     return activitiesToRegister;
   },
 
   // |aAppsToRegister| contains an array of apps to be registered, where
@@ -957,18 +956,17 @@ this.DOMApplicationRegistry = {
         let manifest = aResult.manifest;
         if (!manifest) {
           // If we can't load the manifest, we probably have a corrupted
           // registry. We delete the app since we can't do anything with it.
           delete this.webapps[aResult.id];
           return;
         }
 
-        let localeManifest =
-          new ManifestHelper(manifest, app.origin, app.manifestURL);
+        let localeManifest = new ManifestHelper(manifest, app.origin);
 
         app.name = manifest.name;
         app.csp = manifest.csp || "";
         app.role = localeManifest.role;
         if (app.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
           app.redirects = this.sanitizeRedirects(manifest.redirects);
         }
         this._registerSystemMessages(manifest, app);
@@ -1460,18 +1458,17 @@ this.DOMApplicationRegistry = {
                                  true);
 
     if (!file.exists()) {
       // This is a hosted app, let's check if it has an appcache
       // and download it.
       let results = yield this._readManifests([{ id: id }]);
 
       let jsonManifest = results[0].manifest;
-      let manifest =
-        new ManifestHelper(jsonManifest, app.origin, app.manifestURL);
+      let manifest = new ManifestHelper(jsonManifest, app.origin);
 
       if (manifest.appcache_path) {
         debug("appcache found");
         this.startOfflineCacheDownload(manifest, app, null, isUpdate);
       } else {
         // Hosted app with no appcache, nothing to do, but we fire a
         // downloaded event.
         debug("No appcache found, sending 'downloaded' for " + aManifestURL);
@@ -1495,17 +1492,17 @@ this.DOMApplicationRegistry = {
 
     let json = yield AppsUtils.loadJSONAsync(file.path);
     if (!json) {
       debug("startDownload: No update manifest found at " + file.path + " " +
             aManifestURL);
       throw new Error("MISSING_UPDATE_MANIFEST");
     }
 
-    let manifest = new ManifestHelper(json, app.origin, app.manifestURL);
+    let manifest = new ManifestHelper(json, app.manifestURL);
     let newApp = {
       manifestURL: aManifestURL,
       origin: app.origin,
       installOrigin: app.installOrigin,
       downloadSize: app.downloadSize
     };
 
     let newManifest, newId;
@@ -1806,18 +1803,17 @@ this.DOMApplicationRegistry = {
                   requestID: aData.requestID
                 });
               });
             } else {
               sendError("NOT_UPDATABLE");
             }
           }
         };
-        let helper =
-          new ManifestHelper(manifest, aData.origin, aData.manifestURL);
+        let helper = new ManifestHelper(manifest, aData.manifestURL);
         debug("onlyCheckAppCache - launch updateSvc.checkForUpdate for " +
               helper.fullAppcachePath());
         updateSvc.checkForUpdate(Services.io.newURI(helper.fullAppcachePath(), null, null),
                                  app.localId, false, updateObserver);
       });
       return;
     }
 
@@ -1989,18 +1985,17 @@ this.DOMApplicationRegistry = {
   updatePackagedApp: Task.async(function*(aData, aId, aApp, aNewManifest) {
     debug("updatePackagedApp");
 
     // Store the new update manifest.
     let dir = this._getAppDir(aId).path;
     let manFile = OS.Path.join(dir, "staged-update.webapp");
     yield this._writeFile(manFile, JSON.stringify(aNewManifest));
 
-    let manifest =
-      new ManifestHelper(aNewManifest, aApp.origin, aApp.manifestURL);
+    let manifest = new ManifestHelper(aNewManifest, aApp.manifestURL);
     // A package is available: set downloadAvailable to fire the matching
     // event.
     aApp.downloadAvailable = true;
     aApp.downloadSize = manifest.size;
     aApp.updateManifest = aNewManifest;
     yield this._saveApps();
 
     this.broadcastMessage("Webapps:UpdateState", {
@@ -2036,18 +2031,17 @@ this.DOMApplicationRegistry = {
 
       this.notifyUpdateHandlers(AppsUtils.cloneAppObject(aApp), aNewManifest);
 
       // Store the new manifest.
       let dir = this._getAppDir(aId).path;
       let manFile = OS.Path.join(dir, "manifest.webapp");
       yield this._writeFile(manFile, JSON.stringify(aNewManifest));
 
-      manifest =
-        new ManifestHelper(aNewManifest, aApp.origin, aApp.manifestURL);
+      manifest = new ManifestHelper(aNewManifest, aApp.origin);
 
       if (supportUseCurrentProfile()) {
         // Update the permissions for this app.
         PermissionsInstaller.installPermissions({
           manifest: aApp.manifest,
           origin: aApp.origin,
           manifestURL: aData.manifestURL
         }, true);
@@ -2056,18 +2050,17 @@ this.DOMApplicationRegistry = {
       this.updateDataStore(this.webapps[aId].localId, aApp.origin,
                            aApp.manifestURL, aApp.manifest);
 
       aApp.name = aNewManifest.name;
       aApp.csp = manifest.csp || "";
       aApp.role = manifest.role || "";
       aApp.updateTime = Date.now();
     } else {
-      manifest =
-        new ManifestHelper(aOldManifest, aApp.origin, aApp.manifestURL);
+      manifest = new ManifestHelper(aOldManifest, aApp.origin);
     }
 
     // Update the registry.
     this.webapps[aId] = aApp;
     yield this._saveApps();
 
     if (!manifest.appcache_path) {
       this.broadcastMessage("Webapps:UpdateState", {
@@ -2566,18 +2559,17 @@ this.DOMApplicationRegistry = {
     }
 
     let app = this._setupApp(aData, id);
 
     let jsonManifest = aData.isPackage ? app.updateManifest : app.manifest;
     yield this._writeManifestFile(id, aData.isPackage, jsonManifest);
 
     debug("app.origin: " + app.origin);
-    let manifest =
-      new ManifestHelper(jsonManifest, app.origin, app.manifestURL);
+    let manifest = new ManifestHelper(jsonManifest, app.origin);
 
     let appObject = this._cloneApp(aData, app, manifest, jsonManifest, id, localId);
 
     this.webapps[id] = appObject;
 
     // For package apps, the permissions are not in the mini-manifest, so
     // don't update the permissions yet.
     if (!aData.isPackage) {
@@ -2621,17 +2613,17 @@ this.DOMApplicationRegistry = {
       if (aData.app.localInstallPath) {
         dontNeedNetwork = true;
         jsonManifest.package_path = "file://" + aData.app.localInstallPath;
       }   
 #endif
 
       // origin for install apps is meaningless here, since it's app:// and this
       // can't be used to resolve package paths.
-      manifest = new ManifestHelper(jsonManifest, app.origin, app.manifestURL);
+      manifest = new ManifestHelper(jsonManifest, app.manifestURL);
 
       this.queuedPackageDownload[app.manifestURL] = {
         manifest: manifest,
         app: appObject,
         callback: aInstallSuccessCallback
       };
     }
 
--- a/dom/messages/SystemMessagePermissionsChecker.jsm
+++ b/dom/messages/SystemMessagePermissionsChecker.jsm
@@ -165,30 +165,28 @@ this.SystemMessagePermissionsChecker = {
     return object
   },
 
   /**
    * Check if the system message is permitted to be registered for the given
    * app at start-up based on the permissions claimed in the app's manifest.
    * @param string aSysMsgName
    *        The system messsage name.
-   * @param string aManifestURL
-   *        The app's manifest URL.
+   * @param string aOrigin
+   *        The app's origin.
    * @param object aManifest
    *        The app's manifest.
    * @returns bool
    *        Is permitted or not.
    **/
   isSystemMessagePermittedToRegister:
-    function isSystemMessagePermittedToRegister(aSysMsgName,
-                                                aManifestURL,
-                                                aManifest) {
+    function isSystemMessagePermittedToRegister(aSysMsgName, aOrigin, aManifest) {
     debug("isSystemMessagePermittedToRegister(): " +
           "aSysMsgName: " + aSysMsgName + ", " +
-          "aManifestURL: " + aManifestURL + ", " +
+          "aOrigin: " + aOrigin + ", " +
           "aManifest: " + JSON.stringify(aManifest));
 
     let permNames = this.getSystemMessagePermissions(aSysMsgName);
     if (permNames === null) {
       return false;
     }
 
     // Check to see if the 'webapp' is app/privileged/certified.
@@ -204,32 +202,30 @@ this.SystemMessagePermissionsChecker = {
       appStatus = "app";
       break;
     default:
       throw new Error("SystemMessagePermissionsChecker.jsm: " +
                       "Cannot decide the app's status. Install cancelled.");
       break;
     }
 
-    // It's ok here to not pass the origin to ManifestHelper since we only
-    // need the permission property and that doesn't depend on uri resolution.
-    let newManifest = new ManifestHelper(aManifest, aManifestURL, aManifestURL);
+    let newManifest = new ManifestHelper(aManifest, aOrigin);
 
     for (let permName in permNames) {
       // The app doesn't claim valid permissions for this sytem message.
       if (!newManifest.permissions || !newManifest.permissions[permName]) {
         debug("'" + aSysMsgName + "' isn't permitted by '" + permName + "'. " +
-              "Please add the permission for app: '" + aManifestURL + "'.");
+              "Please add the permission for app: '" + aOrigin + "'.");
         return false;
       }
       let permValue = PermissionsTable[permName][appStatus];
       if (permValue != Ci.nsIPermissionManager.PROMPT_ACTION &&
           permValue != Ci.nsIPermissionManager.ALLOW_ACTION) {
         debug("'" + aSysMsgName + "' isn't permitted by '" + permName + "'. " +
-              "Please add the permission for app: '" + aManifestURL + "'.");
+              "Please add the permission for app: '" + aOrigin + "'.");
         return false;
       }
 
       // Compare the expanded permission names between the ones in
       // app's manifest and the ones needed for system message.
       let expandedPermNames =
         expandPermissions(permName,
                           newManifest.permissions[permName].access);
--- a/mobile/android/chrome/content/WebappRT.js
+++ b/mobile/android/chrome/content/WebappRT.js
@@ -78,17 +78,17 @@ let WebappRT = {
   },
 
   getManifestFor: function (aUrl, aCallback) {
     let request = navigator.mozApps.mgmt.getAll();
     request.onsuccess = function() {
       let apps = request.result;
       for (let i = 0; i < apps.length; i++) {
         let app = apps[i];
-        let manifest = new ManifestHelper(app.manifest, app.origin, app.manifestURL);
+        let manifest = new ManifestHelper(app.manifest, app.origin);
 
         // if this is a path to the manifest, or the launch path, then we have a hit.
         if (app.manifestURL == aUrl || manifest.fullLaunchPath() == aUrl) {
           aCallback(manifest, app);
           return;
         }
       }
 
--- a/mobile/android/chrome/content/aboutApps.js
+++ b/mobile/android/chrome/content/aboutApps.js
@@ -100,17 +100,17 @@ function updateList() {
       addApplication(request.result[i]);
     if (request.result.length)
       document.getElementById("main-container").classList.remove("hidden");
   }
 }
 
 function addApplication(aApp) {
   let list = document.getElementById("appgrid");
-  let manifest = new ManifestHelper(aApp.manifest, aApp.origin, aApp.manifestURL);
+  let manifest = new ManifestHelper(aApp.manifest, aApp.origin);
 
   let container = document.createElement("div");
   container.className = "app list-item";
   container.setAttribute("contextmenu", "appmenu");
   container.setAttribute("id", "app-" + aApp.manifestURL);
   container.setAttribute("title", manifest.name);
 
   let img = document.createElement("img");
--- a/mobile/android/modules/WebappManager.jsm
+++ b/mobile/android/modules/WebappManager.jsm
@@ -174,33 +174,32 @@ this.WebappManager = {
   askInstall: function(aData) {
     let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
     file.initWithPath(aData.profilePath);
 
     this._deleteAppcachePath(aData.app.manifest);
 
     DOMApplicationRegistry.registryReady.then(() => {
       DOMApplicationRegistry.confirmInstall(aData, file, (function(aApp, aManifest) {
-        this._postInstall(aData.profilePath, aManifest, aData.app.origin,
-                          aData.app.apkPackageName, aData.app.manifestURL);
+        this._postInstall(aData.profilePath, aManifest, aData.app.origin, aData.app.apkPackageName);
       }).bind(this));
     });
   },
 
-  _postInstall: function(aProfilePath, aNewManifest, aOrigin, aApkPackageName, aManifestURL) {
+  _postInstall: function(aProfilePath, aNewManifest, aOrigin, aApkPackageName) {
     // aOrigin may now point to the app: url that hosts this app.
     sendMessageToJava({
       type: "Webapps:Postinstall",
       apkPackageName: aApkPackageName,
       origin: aOrigin,
     });
 
     let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
     file.initWithPath(aProfilePath);
-    let localeManifest = new ManifestHelper(aNewManifest, aOrigin, aManifestUrl);
+    let localeManifest = new ManifestHelper(aNewManifest, aOrigin);
     this.writeDefaultPrefs(file, localeManifest);
   },
 
   launch: function({ apkPackageName }) {
     debug("launch: " + apkPackageName);
 
     sendMessageToJava({
       type: "Webapps:Launch",
@@ -329,17 +328,17 @@ this.WebappManager = {
     if (aData.type == "hosted") {
       this._deleteAppcachePath(aData.manifest);
       let oldManifest = yield DOMApplicationRegistry.getManifestFor(aData.manifestURL);
       yield DOMApplicationRegistry.updateHostedApp(aData, aOldApp.id, aOldApp, oldManifest, aData.manifest);
     } else {
       yield this._autoUpdatePackagedApp(aData, aOldApp);
     }
 
-    this._postInstall(aData.profilePath, aData.manifest, aOldApp.origin, aOldApp.apkPackageName, aOldApp.manifestURL);
+    this._postInstall(aData.profilePath, aData.manifest, aOldApp.origin, aOldApp.apkPackageName);
   }).bind(this)); },
 
   _autoUpdatePackagedApp: Task.async(function*(aData, aOldApp) {
     debug("_autoUpdatePackagedApp: " + aData.manifestURL);
 
     if (aData.updateManifest && aData.zipFilePath) {
       aData.updateManifest.package_path = aData.zipFilePath;
     }
--- a/toolkit/devtools/server/actors/webapps.js
+++ b/toolkit/devtools/server/actors/webapps.js
@@ -278,18 +278,17 @@ WebappsActor.prototype = {
         Services.obs.notifyObservers(null, "webapps-installed",
           JSON.stringify({ manifestURL: aApp.manifestURL }));
 
         delete aApp.manifest;
         aDeferred.resolve({ appId: aId, path: aDir.path });
 
         // We can't have appcache for packaged apps.
         if (!aApp.origin.startsWith("app://")) {
-          reg.startOfflineCacheDownload(
-            new ManifestHelper(manifest, aApp.origin, aApp.manifestURL));
+          reg.startOfflineCacheDownload(new ManifestHelper(manifest, aApp.origin));
         }
       });
       // Cleanup by removing the temporary directory.
       if (aDir.exists())
         aDir.remove(true);
     });
   },
 
@@ -743,17 +742,17 @@ WebappsActor.prototype = {
     if (!app) {
       return { error: "wrongParameter",
                message: "No application for " + manifestURL };
     }
 
     let deferred = promise.defer();
 
     this._findManifestByURL(manifestURL).then(jsonManifest => {
-      let manifest = new ManifestHelper(jsonManifest, app.origin, manifestURL);
+      let manifest = new ManifestHelper(jsonManifest, app.origin);
       let iconURL = manifest.iconURLForSize(aRequest.size || 128);
       if (!iconURL) {
         deferred.resolve({
           error: "noIcon",
           message: "This app has no icon"
         });
         return;
       }
--- a/toolkit/webapps/NativeApp.jsm
+++ b/toolkit/webapps/NativeApp.jsm
@@ -52,18 +52,17 @@ const TMP_DIR = OS.Constants.Path.tmpDir
  *
  */
 function CommonNativeApp(aApp, aManifest, aCategories, aRegistryDir) {
   // Set the name property of the app object, otherwise
   // WebappOSUtils::getUniqueName won't work.
   aApp.name = aManifest.name;
   this.uniqueName = WebappOSUtils.getUniqueName(aApp);
 
-  let localeManifest =
-    new ManifestHelper(aManifest, aApp.origin, aApp.manifestURL);
+  let localeManifest = new ManifestHelper(aManifest, aApp.origin);
 
   this.appLocalizedName = localeManifest.name;
   this.appNameAsFilename = stripStringForFilename(aApp.name);
 
   if (aApp.updateManifest) {
     this.isPackaged = true;
   }
 
@@ -95,17 +94,17 @@ CommonNativeApp.prototype = {
   /**
    * This function reads and parses the data from the app
    * manifest and stores it in the NativeApp object.
    *
    * @param aManifest {Object} the manifest data provided by the web app
    *
    */
   _setData: function(aApp, aManifest) {
-    let manifest = new ManifestHelper(aManifest, aApp.origin, aApp.manifestURL);
+    let manifest = new ManifestHelper(aManifest, aApp.origin);
     let origin = Services.io.newURI(aApp.origin, null, null);
 
     this.iconURI = Services.io.newURI(manifest.biggestIconURL || DEFAULT_ICON_URL,
                                       null, null);
 
     if (manifest.developer) {
       if (manifest.developer.name) {
         let devName = manifest.developer.name.substr(0, 128);
--- a/webapprt/WebappManager.jsm
+++ b/webapprt/WebappManager.jsm
@@ -42,18 +42,17 @@ this.WebappManager = {
     let nativeApp = new NativeApp(aApp, aManifest,
                                   WebappRT.config.app.categories,
                                   WebappRT.config.registryDir);
     nativeApp.prepareUpdate(aApp, aManifest, aZipPath);
   },
 
   doInstall: function(data, window) {
     let jsonManifest = data.isPackage ? data.app.updateManifest : data.app.manifest;
-    let manifest =
-      new ManifestHelper(jsonManifest, data.app.origin, data.app.manifestURL);
+    let manifest = new ManifestHelper(jsonManifest, data.app.origin);
     let name = manifest.name;
     let bundle = Services.strings.createBundle("chrome://webapprt/locale/webapp.properties");
 
     let choice = Services.prompt.confirmEx(
       window,
       bundle.formatStringFromName("webapps.install.title", [name], 1),
       bundle.formatStringFromName("webapps.install.description", [name], 1),
       // Set both buttons to strings with the cancel button being default
--- a/webapprt/WebappRT.jsm
+++ b/webapprt/WebappRT.jsm
@@ -43,18 +43,17 @@ this.WebappRT = {
   },
 
   get launchURI() {
     return this.localeManifest.fullLaunchPath();
   },
 
   get localeManifest() {
     return new ManifestHelper(this.config.app.manifest,
-                              this.config.app.origin,
-                              this.config.app.manifestURL);
+                              this.config.app.origin);
   },
 
   get appID() {
     let manifestURL = this.config.app.manifestURL;
     if (!manifestURL) {
       return Ci.nsIScriptSecurityManager.NO_APP_ID;
     }