Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Bug 680802: Installing a new add-on at the same time as installing a …

…new version of the app which uses new properties from install.rdf will fail. r=robstrong, a=LegNeato

--HG--
extra : transplant_source : %80%B5ZaZ%C9%A8%E2%22%F8%C4%E9Rp%BA%91B4%91%9B
  • Loading branch information...
commit 8402740c51cab501e0fbab2a3b69495e8f0ad1e1 1 parent 3526e4c
Dave Townsend Mossop authored
65 toolkit/mozapps/extensions/XPIProvider.jsm
@@ -1969,12 +1969,24 @@ var XPIProvider = {
1969 1969 aManifests[aLocation.name][id] = null;
1970 1970 let existingAddonID = id;
1971 1971
1972   - // Check for a cached AddonInternal for this add-on, it may contain
1973   - // updated compatibility information
1974 1972 let jsonfile = stagingDir.clone();
1975 1973 jsonfile.append(id + ".json");
  1974 +
  1975 + try {
  1976 + aManifests[aLocation.name][id] = loadManifestFromFile(stageDirEntry);
  1977 + }
  1978 + catch (e) {
  1979 + ERROR("Unable to read add-on manifest from " + stageDirEntry.path, e);
  1980 + // This add-on can't be installed so just remove it now
  1981 + seenFiles.push(stageDirEntry.leafName);
  1982 + seenFiles.push(jsonfile.leafName);
  1983 + continue;
  1984 + }
  1985 +
  1986 + // Check for a cached metadata for this add-on, it may contain updated
  1987 + // compatibility information
1976 1988 if (jsonfile.exists()) {
1977   - LOG("Found updated manifest for " + id + " in " + aLocation.name);
  1989 + LOG("Found updated metadata for " + id + " in " + aLocation.name);
1978 1990 let fis = Cc["@mozilla.org/network/file-input-stream;1"].
1979 1991 createInstance(Ci.nsIFileInputStream);
1980 1992 let json = Cc["@mozilla.org/dom/json;1"].
@@ -1982,13 +1994,14 @@ var XPIProvider = {
1982 1994
1983 1995 try {
1984 1996 fis.init(jsonfile, -1, 0, 0);
1985   - let addonObj = json.decodeFromStream(fis, jsonfile.fileSize);
1986   - aManifests[aLocation.name][id] = new AddonInternal();
1987   - aManifests[aLocation.name][id].fromJSON(addonObj);
1988   - existingAddonID = aManifests[aLocation.name][id].existingAddonID || id;
  1997 + let metadata = json.decodeFromStream(fis, jsonfile.fileSize);
  1998 + aManifests[aLocation.name][id].importMetadata(metadata);
1989 1999 }
1990 2000 catch (e) {
1991   - ERROR("Unable to read add-on manifest from " + jsonfile.path, e);
  2001 + // If some data can't be recovered from the cached metadata then it
  2002 + // is unlikely to be a problem big enough to justify throwing away
  2003 + // the install, just log and error and continue
  2004 + ERROR("Unable to read metadata from " + jsonfile.path, e);
1992 2005 }
1993 2006 finally {
1994 2007 fis.close();
@@ -1996,19 +2009,7 @@ var XPIProvider = {
1996 2009 }
1997 2010 seenFiles.push(jsonfile.leafName);
1998 2011
1999   - // If there was no cached AddonInternal then load it directly
2000   - if (!aManifests[aLocation.name][id]) {
2001   - try {
2002   - aManifests[aLocation.name][id] = loadManifestFromFile(stageDirEntry);
2003   - existingAddonID = aManifests[aLocation.name][id].existingAddonID || id;
2004   - }
2005   - catch (e) {
2006   - ERROR("Unable to read add-on manifest from " + stageDirEntry.path, e);
2007   - // This add-on can't be installed so just remove it now
2008   - seenFiles.push(stageDirEntry.leafName);
2009   - continue;
2010   - }
2011   - }
  2012 + existingAddonID = aManifests[aLocation.name][id].existingAddonID || id;
2012 2013
2013 2014 var oldBootstrap = null;
2014 2015 LOG("Processing install of " + id + " in " + aLocation.name);
@@ -6906,15 +6907,25 @@ AddonInternal.prototype = {
6906 6907 },
6907 6908
6908 6909 /**
6909   - * fromJSON should be called to set the properties of this AddonInternal to
6910   - * those from the passed in object. It is essentially the inverse of toJSON.
  6910 + * When an add-on install is pending its metadata will be cached in a file.
  6911 + * This method reads particular properties of that metadata that may be newer
  6912 + * than that in the install manifest, like compatibility information.
6911 6913 *
6912 6914 * @param aObj
6913   - * A JS object containing properties to be set on this AddonInternal
  6915 + * A JS object containing the cached metadata
6914 6916 */
6915   - fromJSON: function(aObj) {
6916   - for (let prop in aObj)
6917   - this[prop] = aObj[prop];
  6917 + importMetadata: function(aObj) {
  6918 + ["targetApplications", "userDisabled", "softDisabled", "existingAddonID",
  6919 + "sourceURI", "releaseNotesURI", "installDate", "updateDate",
  6920 + "applyBackgroundUpdates"].forEach(function(aProp) {
  6921 + if (!(aProp in aObj))
  6922 + return;
  6923 +
  6924 + this[aProp] = aObj[aProp];
  6925 + }, this);
  6926 +
  6927 + // Compatibility info may have changed so update appDisabled
  6928 + this.appDisabled = !isUsableAddon(this);
6918 6929 }
6919 6930 };
6920 6931
56 toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js
@@ -114,6 +114,34 @@ function run_test_1() {
114 114 Services.prefs.setIntPref("extensions.databaseSchema", 1);
115 115 db.close();
116 116
  117 + let jsonfile = gProfD.clone();
  118 + jsonfile.append("extensions");
  119 + jsonfile.append("staged");
  120 + jsonfile.append("addon3@tests.mozilla.org.json");
  121 + do_check_true(jsonfile.exists());
  122 +
  123 + // Remove an unnecessary property from the cached manifest
  124 + let fis = AM_Cc["@mozilla.org/network/file-input-stream;1"].
  125 + createInstance(AM_Ci.nsIFileInputStream);
  126 + let json = AM_Cc["@mozilla.org/dom/json;1"].
  127 + createInstance(AM_Ci.nsIJSON);
  128 + fis.init(jsonfile, -1, 0, 0);
  129 + let addonObj = json.decodeFromStream(fis, jsonfile.fileSize);
  130 + fis.close();
  131 + delete addonObj.optionsType;
  132 +
  133 + let stream = AM_Cc["@mozilla.org/network/file-output-stream;1"].
  134 + createInstance(AM_Ci.nsIFileOutputStream);
  135 + let converter = AM_Cc["@mozilla.org/intl/converter-output-stream;1"].
  136 + createInstance(AM_Ci.nsIConverterOutputStream);
  137 + stream.init(jsonfile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE |
  138 + FileUtils.MODE_TRUNCATE, FileUtils.PERMS_FILE,
  139 + 0);
  140 + converter.init(stream, "UTF-8", 0, 0x0000);
  141 + converter.writeString(JSON.stringify(addonObj));
  142 + converter.close();
  143 + stream.close();
  144 +
117 145 startupManager(false);
118 146
119 147 AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
@@ -221,6 +249,34 @@ function run_test_2() {
221 249 Services.prefs.setIntPref("extensions.databaseSchema", 1);
222 250 db.close();
223 251
  252 + let jsonfile = gProfD.clone();
  253 + jsonfile.append("extensions");
  254 + jsonfile.append("staged");
  255 + jsonfile.append("addon3@tests.mozilla.org.json");
  256 + do_check_true(jsonfile.exists());
  257 +
  258 + // Remove an unnecessary property from the cached manifest
  259 + let fis = AM_Cc["@mozilla.org/network/file-input-stream;1"].
  260 + createInstance(AM_Ci.nsIFileInputStream);
  261 + let json = AM_Cc["@mozilla.org/dom/json;1"].
  262 + createInstance(AM_Ci.nsIJSON);
  263 + fis.init(jsonfile, -1, 0, 0);
  264 + let addonObj = json.decodeFromStream(fis, jsonfile.fileSize);
  265 + fis.close();
  266 + delete addonObj.optionsType;
  267 +
  268 + let stream = AM_Cc["@mozilla.org/network/file-output-stream;1"].
  269 + createInstance(AM_Ci.nsIFileOutputStream);
  270 + let converter = AM_Cc["@mozilla.org/intl/converter-output-stream;1"].
  271 + createInstance(AM_Ci.nsIConverterOutputStream);
  272 + stream.init(jsonfile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE |
  273 + FileUtils.MODE_TRUNCATE, FileUtils.PERMS_FILE,
  274 + 0);
  275 + converter.init(stream, "UTF-8", 0, 0x0000);
  276 + converter.writeString(JSON.stringify(addonObj));
  277 + converter.close();
  278 + stream.close();
  279 +
224 280 gAppInfo.version = "2";
225 281 startupManager(true);
226 282

0 comments on commit 8402740

Please sign in to comment.
Something went wrong with that request. Please try again.