зеркало из https://github.com/mozilla/gecko-dev.git
Bug 814136 - Part 2: Changes on the package installation code to check that a version number and package identifier are provided for signed apps. r=bsmith, r=fabrice, a=overholt
This commit is contained in:
Родитель
5fe054e26d
Коммит
ede24a9dfb
|
@ -43,6 +43,11 @@ AppsService.prototype = {
|
|||
return DOMApplicationRegistry.getAppLocalIdByManifestURL(aManifestURL);
|
||||
},
|
||||
|
||||
getAppLocalIdByStoreId: function getAppLocalIdByStoreId(aStoreId) {
|
||||
debug("getAppLocalIdByStoreId( " + aStoreId + " )");
|
||||
return DOMApplicationRegistry.getAppLocalIdByStoreId(aStoreId);
|
||||
},
|
||||
|
||||
getAppByLocalId: function getAppByLocalId(aLocalId) {
|
||||
debug("getAppByLocalId( " + aLocalId + " )");
|
||||
return DOMApplicationRegistry.getAppByLocalId(aLocalId);
|
||||
|
|
|
@ -83,6 +83,11 @@ this.DOMApplicationRegistry = {
|
|||
return AppsUtils.getCSPByLocalId(this.webapps, aLocalId);
|
||||
},
|
||||
|
||||
getAppLocalIdByStoreId: function(aStoreId) {
|
||||
debug("getAppLocalIdByStoreId:" + aStoreId);
|
||||
return AppsUtils.getAppLocalIdByStoreId(this.webapps, aStoreId);
|
||||
},
|
||||
|
||||
getAppByLocalId: function getAppByLocalId(aLocalId) {
|
||||
debug("getAppByLocalId " + aLocalId);
|
||||
let app = this.localIdIndex[aLocalId];
|
||||
|
|
|
@ -90,7 +90,9 @@ this.AppsUtils = {
|
|||
packageHash: aApp.packageHash,
|
||||
staged: aApp.staged,
|
||||
installerAppId: aApp.installerAppId || Ci.nsIScriptSecurityManager.NO_APP_ID,
|
||||
installerIsBrowser: !!aApp.installerIsBrowser
|
||||
installerIsBrowser: !!aApp.installerIsBrowser,
|
||||
storeId: aApp.storeId || "",
|
||||
storeVersion: aApp.storeVersion || 0
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -126,6 +128,17 @@ this.AppsUtils = {
|
|||
return Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||
},
|
||||
|
||||
getAppLocalIdByStoreId: function(aApps, aStoreId) {
|
||||
debug("getAppLocalIdByStoreId:" + aStoreId);
|
||||
for (let id in aApps) {
|
||||
if (aApps[id].storeId == aStoreId) {
|
||||
return aApps[id].localId;
|
||||
}
|
||||
}
|
||||
|
||||
return Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||
},
|
||||
|
||||
getCSPByLocalId: function getCSPByLocalId(aApps, aLocalId) {
|
||||
debug("getCSPByLocalId " + aLocalId);
|
||||
for (let id in aApps) {
|
||||
|
|
|
@ -148,6 +148,14 @@ this.DOMApplicationRegistry = {
|
|||
app.installState = "installed";
|
||||
}
|
||||
|
||||
// Default storeId to "" and storeVersion to 0
|
||||
if (this.webapps[id].storeId === undefined) {
|
||||
this.webapps[id].storeId = "";
|
||||
}
|
||||
if (this.webapps[id].storeVersion === undefined) {
|
||||
this.webapps[id].storeVersion = 0;
|
||||
}
|
||||
|
||||
// At startup we can't be downloading, and the $TMP directory
|
||||
// will be empty so we can't just apply a staged update.
|
||||
app.downloading = false;
|
||||
|
@ -2078,6 +2086,39 @@ this.DOMApplicationRegistry = {
|
|||
app: app });
|
||||
}
|
||||
|
||||
// aStoreId must be a string of the form
|
||||
// <installOrigin>#<storeId from ids.json>
|
||||
// aStoreVersion must be a positive integer.
|
||||
function checkForStoreIdMatch(aStoreId, aStoreVersion) {
|
||||
// Things to check:
|
||||
// 1. if it's a update:
|
||||
// a. We should already have this storeId
|
||||
// b. The manifestURL for the stored app should be the same one we're
|
||||
// updating
|
||||
// c. And finally the version of the update should be higher than the one
|
||||
// on the already installed package
|
||||
// 2. else
|
||||
// a. We should not have this storeId on the list
|
||||
// We're currently launching WRONG_APP_STORE_ID for all the mismatch kind of
|
||||
// errors, and APP_STORE_VERSION_ROLLBACK for the version error.
|
||||
|
||||
// Does an app with this storeID exist already?
|
||||
let appId = self.getAppLocalIdByStoreId(aStoreId);
|
||||
let isInstalled = appId != Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||
if (aIsUpdate) {
|
||||
if (!isInstalled || (app.localId !== appId)) {
|
||||
// If we don't have the storeId on track already, this
|
||||
// cannot be an update
|
||||
throw "WRONG_APP_STORE_ID";
|
||||
}
|
||||
if (app.storeVersion >= aStoreVersion) {
|
||||
throw "APP_STORE_VERSION_ROLLBACK";
|
||||
}
|
||||
} else if (isInstalled) {
|
||||
throw "WRONG_APP_STORE_ID";
|
||||
}
|
||||
}
|
||||
|
||||
function download() {
|
||||
debug("About to download " + aManifest.fullPackagePath());
|
||||
|
||||
|
@ -2318,6 +2359,31 @@ this.DOMApplicationRegistry = {
|
|||
throw "INSTALL_FROM_DENIED";
|
||||
}
|
||||
|
||||
// Get ids.json if the file is signed
|
||||
if (isSigned) {
|
||||
let idsStream;
|
||||
try {
|
||||
idsStream = zipReader.getInputStream("META-INF/ids.json");
|
||||
} catch (e) {
|
||||
throw zipReader.hasEntry("META-INF/ids.json")
|
||||
? e
|
||||
: "MISSING_IDS_JSON";
|
||||
}
|
||||
let ids =
|
||||
JSON.parse(
|
||||
converter.ConvertToUnicode(
|
||||
NetUtil.readInputStreamToString(
|
||||
idsStream, idsStream.available()) || ""));
|
||||
if ((!ids.id) || !Number.isInteger(ids.version) ||
|
||||
(ids.version <= 0)) {
|
||||
throw "INVALID_IDS_JSON";
|
||||
}
|
||||
let storeId = aApp.installOrigin + "#" + ids.id;
|
||||
checkForStoreIdMatch(storeId, ids.version);
|
||||
app.storeId = storeId;
|
||||
app.storeVersion = ids.version;
|
||||
}
|
||||
|
||||
let maxStatus = isSigned ? Ci.nsIPrincipal.APP_STATUS_PRIVILEGED
|
||||
: Ci.nsIPrincipal.APP_STATUS_INSTALLED;
|
||||
|
||||
|
@ -2618,6 +2684,11 @@ this.DOMApplicationRegistry = {
|
|||
return AppsUtils.getCSPByLocalId(this.webapps, aLocalId);
|
||||
},
|
||||
|
||||
getAppLocalIdByStoreId: function(aStoreId) {
|
||||
debug("getAppLocalIdByStoreId:" + aStoreId);
|
||||
return AppsUtils.getAppLocalIdByStoreId(this.webapps, aStoreId);
|
||||
},
|
||||
|
||||
getAppByLocalId: function(aLocalId) {
|
||||
return AppsUtils.getAppByLocalId(this.webapps, aLocalId);
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* We expose Gecko-internal helpers related to "web apps" through this
|
||||
* sub-interface.
|
||||
*/
|
||||
[scriptable, uuid(cfa75628-4d31-481f-b51e-fe0ce18fa98f)]
|
||||
[scriptable, uuid(05c57885-27cf-47fc-8da7-eeec9eb853a7)]
|
||||
interface mozIApplication: mozIDOMApplication
|
||||
{
|
||||
/* Return true if this app has |permission|. */
|
||||
|
@ -34,4 +34,10 @@ interface mozIApplication: mozIDOMApplication
|
|||
|
||||
/* CSP copied from the manifest */
|
||||
readonly attribute DOMString csp;
|
||||
|
||||
/* Store ID if the app is installed from a store */
|
||||
readonly attribute DOMString storeID;
|
||||
|
||||
/* Store version if the app is installed from a store */
|
||||
readonly attribute unsigned long storeVersion;
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ interface mozIApplication;
|
|||
* This service allows accessing some DOMApplicationRegistry methods from
|
||||
* non-javascript code.
|
||||
*/
|
||||
[scriptable, uuid(4ac27836-4d79-4d35-b105-d6fb7f4f8e41)]
|
||||
[scriptable, uuid(1113c6e3-28a2-4315-be10-8b3230eecc0f)]
|
||||
interface nsIAppsService : nsISupports
|
||||
{
|
||||
mozIDOMApplication getAppByManifestURL(in DOMString manifestURL);
|
||||
|
@ -62,4 +62,9 @@ interface nsIAppsService : nsISupports
|
|||
DOMString getWebAppsBasePath();
|
||||
|
||||
jsval getAppInfo(in DOMString appId);
|
||||
|
||||
/**
|
||||
* Returns the localId if the app was installed from a store
|
||||
*/
|
||||
DOMString getAppLocalIdByStoreId(in DOMString storeID);
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче