Bug 820456 - Installing a big packaged app could kill the homescreen and make the phone unresponsive [r=ferjm]

This commit is contained in:
Fabrice Desré 2012-12-14 11:29:25 -08:00
Родитель 80d940dc17
Коммит d6547de050
1 изменённых файлов: 40 добавлений и 26 удалений

Просмотреть файл

@ -778,6 +778,10 @@ this.DOMApplicationRegistry = {
this.doInstallPackage(msg, mm); this.doInstallPackage(msg, mm);
break; break;
case "Webapps:GetBasePath": case "Webapps:GetBasePath":
if (!this.webapps[msg.id]) {
debug("No webapp for " + msg.id);
return null;
}
return this.webapps[msg.id].basePath; return this.webapps[msg.id].basePath;
break; break;
case "Webapps:RegisterForMessages": case "Webapps:RegisterForMessages":
@ -1150,7 +1154,7 @@ this.DOMApplicationRegistry = {
// Check if the appcache is updatable, and send "downloadavailable" or // Check if the appcache is updatable, and send "downloadavailable" or
// "downloadapplied". // "downloadapplied".
let updateObserver = { let updateObserver = {
observe: function(aSubject, aTopic, aData) { observe: function(aSubject, aTopic, aObsData) {
aData.event = aData.event =
aTopic == "offline-cache-update-available" ? "downloadavailable" aTopic == "offline-cache-update-available" ? "downloadavailable"
: "downloadapplied"; : "downloadapplied";
@ -1691,10 +1695,10 @@ this.DOMApplicationRegistry = {
}, },
onProgress: function notifProgress(aRequest, aContext, onProgress: function notifProgress(aRequest, aContext,
aProgress, aProgressMax) { aProgress, aProgressMax) {
debug("onProgress: " + aProgress + "/" + aProgressMax);
app.progress = aProgress; app.progress = aProgress;
let now = Date.now(); let now = Date.now();
if (now - lastProgressTime > MIN_PROGRESS_EVENT_DELAY) { if (now - lastProgressTime > MIN_PROGRESS_EVENT_DELAY) {
debug("onProgress: " + aProgress + "/" + aProgressMax);
self.broadcastMessage("Webapps:PackageEvent", self.broadcastMessage("Webapps:PackageEvent",
{ type: "progress", { type: "progress",
manifestURL: aApp.manifestURL, manifestURL: aApp.manifestURL,
@ -1723,34 +1727,41 @@ this.DOMApplicationRegistry = {
// installed apps should morph to 'updating'. // installed apps should morph to 'updating'.
app.installState = aIsUpdate ? "updating" : "pending"; app.installState = aIsUpdate ? "updating" : "pending";
NetUtil.asyncFetch(requestChannel, function(aInput, aResult, aRequest) { // Staging the zip in TmpD until all the checks are done.
if (!Components.isSuccessCode(aResult)) { let zipFile = FileUtils.getFile("TmpD",
// We failed to fetch the zip. ["webapps", id, "application.zip"], true);
cleanup("NETWORK_ERROR");
return; // We need an output stream to write the channel content to the zip file.
} let outputStream = Cc["@mozilla.org/network/file-output-stream;1"]
// Copy the zip on disk. XXX: this can consume all disk space. .createInstance(Ci.nsIFileOutputStream);
let zipFile = FileUtils.getFile("TmpD", // write, create, truncate
["webapps", id, "application.zip"], true); outputStream.init(zipFile, 0x02 | 0x08 | 0x20, parseInt("0664", 8), 0);
let ostream = FileUtils.openSafeFileOutputStream(zipFile); let bufferedOutputStream = Cc['@mozilla.org/network/buffered-output-stream;1']
NetUtil.asyncCopy(aInput, ostream, function (aResult) { .createInstance(Ci.nsIBufferedOutputStream);
if (!Components.isSuccessCode(aResult)) { bufferedOutputStream.init(outputStream, 1024);
// We failed to save the zip.
cleanup("DOWNLOAD_ERROR"); // Create a listener that will give data to the file output stream.
let listener = Cc["@mozilla.org/network/simple-stream-listener;1"]
.createInstance(Ci.nsISimpleStreamListener);
listener.init(bufferedOutputStream, {
onStartRequest: function(aRequest, aContext) { },
onStopRequest: function(aRequest, aContext, aStatusCode) {
debug("onStopRequest " + aStatusCode);
bufferedOutputStream.close();
outputStream.close();
let certdb;
try {
certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
} catch (e) {
cleanup("CERTDB_ERROR");
return; return;
} }
let certdb;
try {
certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
} catch (e) {
cleanup("CERTDB_ERROR");
return;
}
certdb.openSignedJARFileAsync(zipFile, function(aRv, aZipReader) { certdb.openSignedJARFileAsync(zipFile, function(aRv, aZipReader) {
let zipReader;
try { try {
let zipReader;
let isSigned; let isSigned;
if (Components.isSuccessCode(aRv)) { if (Components.isSuccessCode(aRv)) {
isSigned = true; isSigned = true;
@ -1802,6 +1813,7 @@ this.DOMApplicationRegistry = {
} catch (e) { } catch (e) {
// Something bad happened when reading the package. // Something bad happened when reading the package.
if (typeof e == 'object') { if (typeof e == 'object') {
debug(e);
cleanup("INVALID_PACKAGE"); cleanup("INVALID_PACKAGE");
} else { } else {
cleanup(e); cleanup(e);
@ -1810,8 +1822,10 @@ this.DOMApplicationRegistry = {
zipReader.close(); zipReader.close();
} }
}); });
}); }
}); });
requestChannel.asyncOpen(listener, null);
}; };
let deviceStorage = Services.wm.getMostRecentWindow("navigator:browser") let deviceStorage = Services.wm.getMostRecentWindow("navigator:browser")