Bug 821211 - Information presented to the user from the mini-manifest is not verified to exactly match the information in the manifest within the JAR file. r=ferjm, a=blocking-basecamp
authorFabrice Desré <fabrice@mozilla.com>
Wed, 19 Dec 2012 11:37:13 -0800
changeset 119054 80bb6b8d8359b09be61463f453fcd969d5378cb0
parent 119053 c3213cfcb816ddef600e25d64ea6e2efd1d368b1
child 119055 f6e5cd97800c323164ab1c986916d5145190d8c5
push id3050
push userryanvm@gmail.com
push dateSun, 23 Dec 2012 20:25:31 +0000
treeherdermozilla-aurora@c6679926db37 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersferjm, blocking-basecamp
bugs821211
milestone19.0a2
Bug 821211 - Information presented to the user from the mini-manifest is not verified to exactly match the information in the manifest within the JAR file. r=ferjm, a=blocking-basecamp
dom/apps/src/AppsUtils.jsm
dom/apps/src/Webapps.jsm
--- a/dom/apps/src/AppsUtils.jsm
+++ b/dom/apps/src/AppsUtils.jsm
@@ -260,16 +260,73 @@ this.AppsUtils = {
 
     let buildID = Services.appinfo.platformBuildID;
 
     aPrefBranch.setCharPref("gecko.mstone", mstone);
     aPrefBranch.setCharPref("gecko.buildID", buildID);
 
     return ((mstone != savedmstone) || (buildID != savedBuildID));
   },
+
+  /**
+   * Check if two manifests have the same set of properties and that the
+   * values of these properties are the same, in each locale.
+   * Manifests here are raw json ones.
+   */
+  compareManifests: function compareManifests(aManifest1, aManifest2) {
+    // 1. check if we have the same locales in both manifests.
+    let locales1 = [];
+    let locales2 = [];
+    if (aManifest1.locales) {
+      for (let locale in aManifest1.locales) {
+        locales1.push(locale);
+      }
+    }
+    if (aManifest2.locales) {
+      for (let locale in aManifest2.locales) {
+        locales2.push(locale);
+      }
+    }
+    if (locales1.sort().join() !== locales2.sort().join()) {
+      return false;
+    }
+
+    // Helper function to check the app name and developer information for
+    // two given roots.
+    let checkNameAndDev = function(aRoot1, aRoot2) {
+      let name1 = aRoot1.name;
+      let name2 = aRoot2.name;
+      if (name1 !== name2) {
+        return false;
+      }
+
+      let dev1 = aRoot1.developer;
+      let dev2 = aRoot2.developer;
+      if ((dev1 && !dev2) || (dev2 && !dev1)) {
+        return false;
+      }
+
+      return (dev1.name === dev2.name && dev1.url === dev2.url);
+    }
+
+    // 2. For each locale, check if the name and dev info are the same.
+    if (!checkNameAndDev(aManifest1, aManifest2)) {
+      return false;
+    }
+
+    for (let locale in aManifest1.locales) {
+      if (!checkNameAndDev(aManifest1.locales[locale],
+                           aManifest2.locales[locale])) {
+        return false;
+      }
+    }
+
+    // Nothing failed.
+    return true;
+  }
 }
 
 /**
  * Helper object to access manifest information with locale support
  */
 this.ManifestHelper = function(aManifest, aOrigin) {
   this._origin = Services.io.newURI(aOrigin, null, null);
   this._manifest = aManifest;
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -1851,16 +1851,21 @@ this.DOMApplicationRegistry = {
               // Obtain a converter to read from a UTF-8 encoded input stream.
               let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
                                 .createInstance(Ci.nsIScriptableUnicodeConverter);
               converter.charset = "UTF-8";
 
               let manifest = JSON.parse(converter.ConvertToUnicode(NetUtil.readInputStreamToString(istream,
                                                                    istream.available()) || ""));
 
+              if (!AppsUtils.compareManifests(manifest,
+                                              aManifest._manifest)) {
+                throw "MANIFEST_MISMATCH";
+              }
+
               if (!AppsUtils.checkManifest(manifest)) {
                 throw "INVALID_MANIFEST";
               }
 
               if (!AppsUtils.checkInstallAllowed(manifest, aApp.installOrigin)) {
                 throw "INSTALL_FROM_DENIED";
               }