Bug 1077529 - Update Trusted Hosted Apps r=fabrice
authorZoran Jovanovic <zoran.jovanovic@sonymobile.com>
Tue, 14 Oct 2014 12:28:16 -0700
changeset 210378 35da15d147c53d3dfe82d1e5f2ec3c3500816fdb
parent 210377 5eb54b0e4e07ecda78dd4e6d16ede7bd70f5b912
child 210379 9d39a8c6310900a6afbbf63d409d1194af0be173
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersfabrice
bugs1077529
milestone36.0a1
Bug 1077529 - Update Trusted Hosted Apps r=fabrice Verify manifest of trusted hosted app on update instead of just overwriting it. --- dom/apps/TrustedHostedAppsUtils.jsm | 8 ++++---- dom/apps/Webapps.jsm | 26 +++++++++++++++++++++----- 2 files changed, 25 insertions(+), 9 deletions(-)
dom/apps/TrustedHostedAppsUtils.jsm
dom/apps/Webapps.jsm
--- a/dom/apps/TrustedHostedAppsUtils.jsm
+++ b/dom/apps/TrustedHostedAppsUtils.jsm
@@ -249,24 +249,24 @@ this.TrustedHostedAppsUtils = {
     ]).then(([aManifestStream, aSignatureStream]) => {
       this._verifySignedFile(aManifestStream, aSignatureStream, certDb)
         .then(deferred.resolve, deferred.reject);
     }, deferred.reject);
 
     return deferred.promise;
   },
 
-  verifyManifest: function(aData) {
+  verifyManifest: function(aApp, aAppId, aManifest) {
     return new Promise((resolve, reject) => {
       // sanity check on manifest host's CA (proper CA check with
       // pinning is done by regular networking code)
-      if (!this.isHostPinned(aData.app.manifestURL)) {
+      if (!this.isHostPinned(aApp.manifestURL)) {
         reject("TRUSTED_APPLICATION_HOST_CERTIFICATE_INVALID");
         return;
       }
-      if (!this.verifyCSPWhiteList(aData.app.manifest.csp)) {
+      if (!this.verifyCSPWhiteList(aManifest.csp)) {
         reject("TRUSTED_APPLICATION_WHITELIST_VALIDATION_FAILED");
         return;
       }
-      this.verifySignedManifest(aData.app, aData.appId).then(resolve, reject);
+      this.verifySignedManifest(aApp, aAppId).then(resolve, reject);
     });
   }
 };
--- a/dom/apps/Webapps.jsm
+++ b/dom/apps/Webapps.jsm
@@ -1996,18 +1996,34 @@ this.DOMApplicationRegistry = {
                   manifestURL: app.manifestURL,
                   requestID: aData.requestID
                 });
               });
             }
           } else {
             // Update only the appcache if the manifest has not changed
             // based on the hash value.
-            this.updateHostedApp(aData, id, app, oldManifest,
-                                 oldHash == hash ? null : manifest);
+            if (oldHash == hash) {
+              debug("Update - oldhash");
+              this.updateHostedApp(aData, id, app, oldManifest, null);
+              return;
+            }
+
+            // For hosted apps and hosted apps with appcache, use the
+            // manifest "as is".
+            if (this.kTrustedHosted !== this.appKind(app, app.manifest)) {
+              this.updateHostedApp(aData, id, app, oldManifest, manifest);
+              return;
+            }
+
+            // For trusted hosted apps, verify the manifest before
+            // installation.
+            TrustedHostedAppsUtils.verifyManifest(app, id, manifest)
+              .then(() => this.updateHostedApp(aData, id, app, oldManifest, manifest),
+                sendError);
           }
         }
       } else if (xhr.status == 304) {
         // The manifest has not changed.
         if (isPackage) {
           app.lastCheckedUpdate = Date.now();
           this._saveApps().then(() => {
             // If the app is a packaged app, we just send a 'downloadapplied'
@@ -2321,18 +2337,18 @@ this.DOMApplicationRegistry = {
     // in which case we don't need to load it.
     if (app.manifest) {
       if (checkManifest()) {
         debug("Installed manifest check OK");
         if (this.kTrustedHosted !== this.appKind(app, app.manifest)) {
           installApp();
           return;
         }
-        TrustedHostedAppsUtils.verifyManifest(aData)
-        	.then(installApp, sendError);
+        TrustedHostedAppsUtils.verifyManifest(aData.app, aData.appId, app.manifest)
+          .then(installApp, sendError);
       } else {
         debug("Installed manifest check failed");
         // checkManifest() sends error before return
       }
       return;
     }
 
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
@@ -2356,17 +2372,17 @@ this.DOMApplicationRegistry = {
           debug("Downloaded manifest check OK");
           app.etag = xhr.getResponseHeader("Etag");
           if (this.kTrustedHosted !== this.appKind(app, app.manifest)) {
             installApp();
             return;
           }
 
           debug("App kind: " + this.kTrustedHosted);
-          TrustedHostedAppsUtils.verifyManifest(aData)
+          TrustedHostedAppsUtils.verifyManifest(aData.app, aData.appId, app.manifest)
             .then(installApp, sendError);
           return;
         } else {
           debug("Downloaded manifest check failed");
           // checkManifest() sends error before return
         }
       } else {
         sendError("MANIFEST_URL_ERROR");