зеркало из https://github.com/mozilla/gecko-dev.git
Bug 903291 - App download hangs indefinitely if the child process dies before confirming the install. r=fabrice
* * * Bug 903291 - App download hangs indefinitely if the child process dies before confirming the install
This commit is contained in:
Родитель
c53b5f77a8
Коммит
c72ded3253
|
@ -8,10 +8,10 @@ const Cu = Components.utils;
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
// This module exposes a subset of the functionnalities of the parent DOM
|
||||
// Registry to content processes, to be be used from the AppsService component.
|
||||
// This module exposes a subset of the functionalities of the parent DOM
|
||||
// Registry to content processes, to be used from the AppsService component.
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DOMApplicationRegistry"];
|
||||
this.EXPORTED_SYMBOLS = ["DOMApplicationRegistry", "WrappedManifestCache"];
|
||||
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
@ -20,54 +20,315 @@ function debug(s) {
|
|||
//dump("-*- AppsServiceChild.jsm: " + s + "\n");
|
||||
}
|
||||
|
||||
const APPS_IPC_MSG_NAMES = [
|
||||
"Webapps:AddApp",
|
||||
"Webapps:RemoveApp",
|
||||
"Webapps:UpdateApp",
|
||||
"Webapps:CheckForUpdate:Return:KO",
|
||||
"Webapps:FireEvent",
|
||||
"Webapps:UpdateState"
|
||||
];
|
||||
|
||||
// A simple cache for the wrapped manifests.
|
||||
this.WrappedManifestCache = {
|
||||
_cache: { },
|
||||
|
||||
// Gets an entry from the cache, and populates the cache if needed.
|
||||
get: function mcache_get(aManifestURL, aManifest, aWindow, aInnerWindowID) {
|
||||
if (!(aManifestURL in this._cache)) {
|
||||
this._cache[aManifestURL] = { };
|
||||
}
|
||||
|
||||
let winObjs = this._cache[aManifestURL];
|
||||
if (!(aInnerWindowID in winObjs)) {
|
||||
winObjs[aInnerWindowID] = Cu.cloneInto(aManifest, aWindow);
|
||||
}
|
||||
|
||||
return winObjs[aInnerWindowID];
|
||||
},
|
||||
|
||||
// Invalidates an entry in the cache.
|
||||
evict: function mcache_evict(aManifestURL, aInnerWindowID) {
|
||||
debug("Evicting manifest " + aManifestURL + " window ID " +
|
||||
aInnerWindowID);
|
||||
if (aManifestURL in this._cache) {
|
||||
let winObjs = this._cache[aManifestURL];
|
||||
if (aInnerWindowID in winObjs) {
|
||||
delete winObjs[aInnerWindowID];
|
||||
}
|
||||
|
||||
if (Object.keys(winObjs).length == 0) {
|
||||
delete this._cache[aManifestURL];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
// Clear the cache on memory pressure.
|
||||
this._cache = { };
|
||||
Cu.forceGC();
|
||||
},
|
||||
|
||||
init: function() {
|
||||
Services.obs.addObserver(this, "memory-pressure", false);
|
||||
}
|
||||
};
|
||||
|
||||
this.WrappedManifestCache.init();
|
||||
|
||||
|
||||
// DOMApplicationRegistry keeps a cache containing a list of apps in the device.
|
||||
// This information is updated with the data received from the main process and
|
||||
// it is queried by the DOM objects to set their state.
|
||||
// This module handle all the messages broadcasted from the parent process,
|
||||
// including DOM events, which are dispatched to the corresponding DOM objects.
|
||||
|
||||
this.DOMApplicationRegistry = {
|
||||
// DOMApps will hold a list of arrays of weak references to
|
||||
// mozIDOMApplication objects indexed by manifest URL.
|
||||
DOMApps: {},
|
||||
|
||||
init: function init() {
|
||||
debug("init");
|
||||
this.cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
|
||||
.getService(Ci.nsISyncMessageSender);
|
||||
|
||||
["Webapps:AddApp", "Webapps:RemoveApp"].forEach((function(aMsgName) {
|
||||
APPS_IPC_MSG_NAMES.forEach((function(aMsgName) {
|
||||
this.cpmm.addMessageListener(aMsgName, this);
|
||||
}).bind(this));
|
||||
|
||||
this.cpmm.sendAsyncMessage("Webapps:RegisterForMessages", {
|
||||
messages: APPS_IPC_MSG_NAMES
|
||||
});
|
||||
|
||||
// We need to prime the cache with the list of apps.
|
||||
// XXX shoud we do this async and block callers if it's not yet there?
|
||||
this.webapps = this.cpmm.sendSyncMessage("Webapps:GetList", { })[0];
|
||||
// XXX should we do this async and block callers if it's not yet there?
|
||||
let list = this.cpmm.sendSyncMessage("Webapps:GetList", { })[0];
|
||||
this.webapps = list.webapps;
|
||||
|
||||
// We need a fast mapping from localId -> app, so we add an index.
|
||||
// And add the manifest to the app object.
|
||||
this.localIdIndex = { };
|
||||
for (let id in this.webapps) {
|
||||
let app = this.webapps[id];
|
||||
this.localIdIndex[app.localId] = app;
|
||||
app.manifest = list.manifests[id];
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
// cpmm.addMessageListener causes the DOMApplicationRegistry object to live
|
||||
// forever if we don't clean up properly.
|
||||
// cpmm.addMessageListener causes the DOMApplicationRegistry object to
|
||||
// live forever if we don't clean up properly.
|
||||
this.webapps = null;
|
||||
["Webapps:AddApp", "Webapps:RemoveApp"].forEach((function(aMsgName) {
|
||||
this.DOMApps = null;
|
||||
|
||||
APPS_IPC_MSG_NAMES.forEach((aMsgName) => {
|
||||
this.cpmm.removeMessageListener(aMsgName, this);
|
||||
}).bind(this));
|
||||
});
|
||||
|
||||
this.cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
|
||||
APPS_IPC_MSG_NAMES)
|
||||
},
|
||||
|
||||
receiveMessage: function receiveMessage(aMessage) {
|
||||
debug("Received " + aMessage.name + " message.");
|
||||
let msg = aMessage.json;
|
||||
let msg = aMessage.data;
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:AddApp":
|
||||
this.webapps[msg.id] = msg.app;
|
||||
this.localIdIndex[msg.app.localId] = msg.app;
|
||||
break;
|
||||
case "Webapps:RemoveApp":
|
||||
delete this.DOMApps[this.webapps[msg.id].manifestURL];
|
||||
delete this.localIdIndex[this.webapps[msg.id].localId];
|
||||
delete this.webapps[msg.id];
|
||||
break;
|
||||
case "Webapps:UpdateApp":
|
||||
let app = this.webapps[msg.oldId];
|
||||
if (!app) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.app) {
|
||||
for (let prop in msg.app) {
|
||||
app[prop] = msg.app[prop];
|
||||
}
|
||||
}
|
||||
|
||||
this.webapps[msg.newId] = app;
|
||||
this.localIdIndex[app.localId] = app;
|
||||
delete this.webapps[msg.oldId];
|
||||
|
||||
let apps = this.DOMApps[msg.app.manifestURL];
|
||||
if (!apps) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
let domApp = apps[i].get();
|
||||
if (!domApp) {
|
||||
apps.splice(i);
|
||||
continue;
|
||||
}
|
||||
domApp._proxy = new Proxy(domApp, {
|
||||
get: function(target, prop) {
|
||||
if (!DOMApplicationRegistry.webapps[msg.newId]) {
|
||||
return;
|
||||
}
|
||||
return DOMApplicationRegistry.webapps[msg.newId][prop];
|
||||
},
|
||||
set: function(target, prop, val) {
|
||||
if (!DOMApplicationRegistry.webapps[msg.newId]) {
|
||||
return;
|
||||
}
|
||||
DOMApplicationRegistry.webapps[msg.newId][prop] = val;
|
||||
return;
|
||||
},
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "Webapps:FireEvent":
|
||||
this._fireEvent(aMessage);
|
||||
break;
|
||||
case "Webapps:UpdateState":
|
||||
this._updateState(msg);
|
||||
break;
|
||||
case "Webapps:CheckForUpdate:Return:KO":
|
||||
let DOMApps = this.DOMApps[msg.manifestURL];
|
||||
if (!DOMApps || !msg.requestID) {
|
||||
return;
|
||||
}
|
||||
DOMApps.forEach((DOMApp) => {
|
||||
let domApp = DOMApp.get();
|
||||
if (domApp && msg.requestID) {
|
||||
domApp._fireRequestResult(aMessage, true /* aIsError */);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* mozIDOMApplication management
|
||||
*/
|
||||
|
||||
// Every time a DOM app is created, we save a weak reference to it that will
|
||||
// be used to dispatch events and fire request results.
|
||||
addDOMApp: function(aApp, aManifestURL, aId) {
|
||||
let weakRef = Cu.getWeakReference(aApp);
|
||||
|
||||
if (!this.DOMApps[aManifestURL]) {
|
||||
this.DOMApps[aManifestURL] = [];
|
||||
}
|
||||
|
||||
let apps = this.DOMApps[aManifestURL];
|
||||
|
||||
// Get rid of dead weak references.
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
if (!apps[i].get()) {
|
||||
apps.splice(i);
|
||||
}
|
||||
}
|
||||
|
||||
apps.push(weakRef);
|
||||
|
||||
// Each DOM app contains a proxy object used to build their state. We
|
||||
// return the handler for this proxy object with traps to get and set
|
||||
// app properties kept in the DOMApplicationRegistry app cache.
|
||||
return {
|
||||
get: function(target, prop) {
|
||||
if (!DOMApplicationRegistry.webapps[aId]) {
|
||||
return;
|
||||
}
|
||||
return DOMApplicationRegistry.webapps[aId][prop];
|
||||
},
|
||||
set: function(target, prop, val) {
|
||||
if (!DOMApplicationRegistry.webapps[aId]) {
|
||||
return;
|
||||
}
|
||||
DOMApplicationRegistry.webapps[aId][prop] = val;
|
||||
return;
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
_fireEvent: function(aMessage) {
|
||||
let msg = aMessage.data;
|
||||
debug("_fireEvent " + JSON.stringify(msg));
|
||||
if (!this.DOMApps || !msg.manifestURL || !msg.eventType) {
|
||||
return;
|
||||
}
|
||||
|
||||
let DOMApps = this.DOMApps[msg.manifestURL];
|
||||
if (!DOMApps) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The parent might ask childs to trigger more than one event in one
|
||||
// shot, so in order to avoid needless IPC we allow an array for the
|
||||
// 'eventType' IPC message field.
|
||||
if (!Array.isArray(msg.eventType)) {
|
||||
msg.eventType = [msg.eventType];
|
||||
}
|
||||
|
||||
DOMApps.forEach((DOMApp) => {
|
||||
let domApp = DOMApp.get();
|
||||
if (!domApp) {
|
||||
return;
|
||||
}
|
||||
msg.eventType.forEach((aEventType) => {
|
||||
if ('on' + aEventType in domApp) {
|
||||
domApp._fireEvent(aEventType);
|
||||
}
|
||||
});
|
||||
|
||||
if (msg.requestID) {
|
||||
aMessage.data.result = msg.manifestURL;
|
||||
domApp._fireRequestResult(aMessage);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_updateState: function(aMessage) {
|
||||
if (!this.DOMApps || !aMessage.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let app = this.webapps[aMessage.id];
|
||||
if (!app) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aMessage.app) {
|
||||
for (let prop in aMessage.app) {
|
||||
app[prop] = aMessage.app[prop];
|
||||
}
|
||||
}
|
||||
|
||||
if (aMessage.error) {
|
||||
app.downloadError = aMessage.error;
|
||||
}
|
||||
|
||||
if (aMessage.manifest) {
|
||||
app.manifest = aMessage.manifest;
|
||||
// Evict the wrapped manifest cache for all the affected DOM objects.
|
||||
let DOMApps = this.DOMApps[app.manifestURL];
|
||||
if (!DOMApps) {
|
||||
return;
|
||||
}
|
||||
DOMApps.forEach((DOMApp) => {
|
||||
let domApp = DOMApp.get();
|
||||
if (!domApp) {
|
||||
return;
|
||||
}
|
||||
WrappedManifestCache.evict(app.manifestURL, domApp.innerWindowID);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIAppsService API
|
||||
*/
|
||||
getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
|
||||
debug("getAppByManifestURL " + aManifestURL);
|
||||
return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
|
||||
|
|
|
@ -12,6 +12,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
||||
Cu.import("resource://gre/modules/AppsServiceChild.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
|
@ -264,50 +265,9 @@ WebappsRegistry.prototype = {
|
|||
* mozIDOMApplication object
|
||||
*/
|
||||
|
||||
// A simple cache for the wrapped manifests.
|
||||
let manifestCache = {
|
||||
_cache: { },
|
||||
|
||||
// Gets an entry from the cache, and populates the cache if needed.
|
||||
get: function mcache_get(aManifestURL, aManifest, aWindow, aInnerWindowID) {
|
||||
if (!(aManifestURL in this._cache)) {
|
||||
this._cache[aManifestURL] = { };
|
||||
}
|
||||
|
||||
let winObjs = this._cache[aManifestURL];
|
||||
if (!(aInnerWindowID in winObjs)) {
|
||||
winObjs[aInnerWindowID] = Cu.cloneInto(aManifest, aWindow);
|
||||
}
|
||||
|
||||
return winObjs[aInnerWindowID];
|
||||
},
|
||||
|
||||
// Invalidates an entry in the cache.
|
||||
evict: function mcache_evict(aManifestURL, aInnerWindowID) {
|
||||
if (aManifestURL in this._cache) {
|
||||
let winObjs = this._cache[aManifestURL];
|
||||
if (aInnerWindowID in winObjs) {
|
||||
delete winObjs[aInnerWindowID];
|
||||
}
|
||||
|
||||
if (Object.keys(winObjs).length == 0) {
|
||||
delete this._cache[aManifestURL];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
// Clear the cache on memory pressure.
|
||||
this._cache = { };
|
||||
},
|
||||
|
||||
init: function() {
|
||||
Services.obs.addObserver(this, "memory-pressure", false);
|
||||
}
|
||||
};
|
||||
|
||||
function createApplicationObject(aWindow, aApp) {
|
||||
let app = Cc["@mozilla.org/webapps/application;1"].createInstance(Ci.mozIDOMApplication);
|
||||
let app = Cc["@mozilla.org/webapps/application;1"]
|
||||
.createInstance(Ci.mozIDOMApplication);
|
||||
app.wrappedJSObject.init(aWindow, aApp);
|
||||
return app;
|
||||
}
|
||||
|
@ -320,27 +280,12 @@ WebappsApplication.prototype = {
|
|||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
|
||||
init: function(aWindow, aApp) {
|
||||
let proxyHandler = DOMApplicationRegistry.addDOMApp(this,
|
||||
aApp.manifestURL,
|
||||
aApp.id);
|
||||
this._proxy = new Proxy(this, proxyHandler);
|
||||
|
||||
this._window = aWindow;
|
||||
let principal = this._window.document.nodePrincipal;
|
||||
this._appStatus = principal.appStatus;
|
||||
this.origin = aApp.origin;
|
||||
this._manifest = aApp.manifest;
|
||||
this._updateManifest = aApp.updateManifest;
|
||||
this.manifestURL = aApp.manifestURL;
|
||||
this.receipts = aApp.receipts;
|
||||
this.installOrigin = aApp.installOrigin;
|
||||
this.installTime = aApp.installTime;
|
||||
this.installState = aApp.installState || "installed";
|
||||
this.removable = aApp.removable;
|
||||
this.lastUpdateCheck = aApp.lastUpdateCheck ? aApp.lastUpdateCheck
|
||||
: Date.now();
|
||||
this.updateTime = aApp.updateTime ? aApp.updateTime
|
||||
: aApp.installTime;
|
||||
this.progress = NaN;
|
||||
this.downloadAvailable = aApp.downloadAvailable;
|
||||
this.downloading = aApp.downloading;
|
||||
this.readyToApplyDownload = aApp.readyToApplyDownload;
|
||||
this.downloadSize = aApp.downloadSize || 0;
|
||||
|
||||
this._onprogress = null;
|
||||
this._ondownloadsuccess = null;
|
||||
|
@ -348,40 +293,83 @@ WebappsApplication.prototype = {
|
|||
this._ondownloadavailable = null;
|
||||
this._ondownloadapplied = null;
|
||||
|
||||
this._downloadError = null;
|
||||
this.initDOMRequestHelper(aWindow);
|
||||
},
|
||||
|
||||
this.initDOMRequestHelper(aWindow, [
|
||||
{ name: "Webapps:CheckForUpdate:Return:KO", weakRef: true },
|
||||
{ name: "Webapps:Connect:Return:OK", weakRef: true },
|
||||
{ name: "Webapps:Connect:Return:KO", weakRef: true },
|
||||
{ name: "Webapps:FireEvent", weakRef: true },
|
||||
{ name: "Webapps:GetConnections:Return:OK", weakRef: true },
|
||||
{ name: "Webapps:UpdateState", weakRef: true }
|
||||
]);
|
||||
get _appStatus() {
|
||||
return this._proxy.appStatus;
|
||||
},
|
||||
|
||||
cpmm.sendAsyncMessage("Webapps:RegisterForMessages", {
|
||||
messages: ["Webapps:FireEvent",
|
||||
"Webapps:UpdateState"],
|
||||
app: {
|
||||
id: this.id,
|
||||
manifestURL: this.manifestURL,
|
||||
installState: this.installState,
|
||||
downloading: this.downloading
|
||||
}
|
||||
});
|
||||
get downloadAvailable() {
|
||||
return this._proxy.downloadAvailable;
|
||||
},
|
||||
|
||||
get downloading() {
|
||||
return this._proxy.downloading;
|
||||
},
|
||||
|
||||
get downloadSize() {
|
||||
return this._proxy.downloadSize;
|
||||
},
|
||||
|
||||
get installOrigin() {
|
||||
return this._proxy.installOrigin;
|
||||
},
|
||||
|
||||
get installState() {
|
||||
return this._proxy.installState;
|
||||
},
|
||||
|
||||
get installTime() {
|
||||
return this._proxy.installTime;
|
||||
},
|
||||
|
||||
get lastUpdateCheck() {
|
||||
return this._proxy.lastUpdateCheck;
|
||||
},
|
||||
|
||||
get manifestURL() {
|
||||
return this._proxy.manifestURL;
|
||||
},
|
||||
|
||||
get origin() {
|
||||
return this._proxy.origin;
|
||||
},
|
||||
|
||||
get progress() {
|
||||
return this._proxy.progress;
|
||||
},
|
||||
|
||||
get readyToApplyDownload() {
|
||||
return this._proxy.readyToApplyDownload;
|
||||
},
|
||||
|
||||
get receipts() {
|
||||
return this._proxy.receipts;
|
||||
},
|
||||
|
||||
set receipts(aReceipts) {
|
||||
this._proxy.receipts = aReceipts;
|
||||
},
|
||||
|
||||
get removable() {
|
||||
return this._proxy.removable;
|
||||
},
|
||||
|
||||
get updateTime() {
|
||||
return this._proxy.updateTime;
|
||||
},
|
||||
|
||||
get manifest() {
|
||||
return manifestCache.get(this.manifestURL,
|
||||
this._manifest,
|
||||
this._window,
|
||||
this.innerWindowID);
|
||||
return WrappedManifestCache.get(this.manifestURL,
|
||||
this._proxy.manifest,
|
||||
this._window,
|
||||
this.innerWindowID);
|
||||
},
|
||||
|
||||
get updateManifest() {
|
||||
return this.updateManifest =
|
||||
this._updateManifest ? Cu.cloneInto(this._updateManifest, this._window)
|
||||
: null;
|
||||
return this._proxy.updateManifest ?
|
||||
Cu.cloneInto(this._proxy.updateManifest, this._window) : null;
|
||||
},
|
||||
|
||||
set onprogress(aCallback) {
|
||||
|
@ -425,7 +413,7 @@ WebappsApplication.prototype = {
|
|||
},
|
||||
|
||||
get downloadError() {
|
||||
return new this._window.DOMError(this._downloadError || '');
|
||||
return new this._window.DOMError(this._proxy.downloadError || '');
|
||||
},
|
||||
|
||||
download: function() {
|
||||
|
@ -467,12 +455,11 @@ WebappsApplication.prototype = {
|
|||
BrowserElementPromptService.getBrowserElementChildForWindow(this._window);
|
||||
if (browserChild) {
|
||||
this.addMessageListeners("Webapps:ClearBrowserData:Return");
|
||||
browserChild.messageManager.sendAsyncMessage(
|
||||
"Webapps:ClearBrowserData",
|
||||
{ manifestURL: this.manifestURL,
|
||||
oid: this._id,
|
||||
requestID: this.getRequestId(request) }
|
||||
);
|
||||
browserChild.messageManager.sendAsyncMessage("Webapps:ClearBrowserData", {
|
||||
manifestURL: this.manifestURL,
|
||||
oid: this._id,
|
||||
requestID: this.getRequestId(request)
|
||||
});
|
||||
} else {
|
||||
Services.DOMRequest.fireErrorAsync(request, "NO_CLEARABLE_BROWSER");
|
||||
}
|
||||
|
@ -480,28 +467,33 @@ WebappsApplication.prototype = {
|
|||
},
|
||||
|
||||
connect: function(aKeyword, aRules) {
|
||||
this.addMessageListeners(["Webapps:Connect:Return:OK",
|
||||
"Webapps:Connect:Return:KO"]);
|
||||
return this.createPromise(function (aResolve, aReject) {
|
||||
cpmm.sendAsyncMessage("Webapps:Connect",
|
||||
{ keyword: aKeyword,
|
||||
rules: aRules,
|
||||
manifestURL: this.manifestURL,
|
||||
outerWindowID: this._id,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})});
|
||||
cpmm.sendAsyncMessage("Webapps:Connect", {
|
||||
keyword: aKeyword,
|
||||
rules: aRules,
|
||||
manifestURL: this.manifestURL,
|
||||
outerWindowID: this._id,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
getConnections: function() {
|
||||
this.addMessageListeners("Webapps:getConnections:Return:OK");
|
||||
return this.createPromise(function (aResolve, aReject) {
|
||||
cpmm.sendAsyncMessage("Webapps:GetConnections",
|
||||
{ manifestURL: this.manifestURL,
|
||||
outerWindowID: this._id,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})});
|
||||
cpmm.sendAsyncMessage("Webapps:GetConnections", {
|
||||
manifestURL: this.manifestURL,
|
||||
outerWindowID: this._id,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
@ -550,12 +542,7 @@ WebappsApplication.prototype = {
|
|||
|
||||
uninit: function() {
|
||||
this._onprogress = null;
|
||||
cpmm.sendAsyncMessage("Webapps:UnregisterForMessages", [
|
||||
"Webapps:FireEvent",
|
||||
"Webapps:UpdateState"
|
||||
]);
|
||||
|
||||
manifestCache.evict(this.manifestURL, this.innerWindowID);
|
||||
WrappedManifestCache.evict(this.manifestURL, this.innerWindowID);
|
||||
},
|
||||
|
||||
_fireEvent: function(aName) {
|
||||
|
@ -572,21 +559,15 @@ WebappsApplication.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_updateState: function(aMsg) {
|
||||
if (aMsg.app) {
|
||||
for (let prop in aMsg.app) {
|
||||
this[prop] = aMsg.app[prop];
|
||||
}
|
||||
}
|
||||
|
||||
if (aMsg.error) {
|
||||
this._downloadError = aMsg.error;
|
||||
}
|
||||
|
||||
if (aMsg.manifest) {
|
||||
this._manifest = aMsg.manifest;
|
||||
manifestCache.evict(this.manifestURL, this.innerWindowID);
|
||||
_fireRequestResult: function(aMessage, aIsError) {
|
||||
let req;
|
||||
let msg = aMessage.data;
|
||||
req = this.takeRequest(msg.requestID);
|
||||
if (!req) {
|
||||
return;
|
||||
}
|
||||
aIsError ? Services.DOMRequest.fireError(req, msg.error)
|
||||
: Services.DOMRequest.fireSuccess(req, msg.result);
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
|
@ -600,10 +581,7 @@ WebappsApplication.prototype = {
|
|||
req = this.takeRequest(msg.requestID);
|
||||
}
|
||||
|
||||
// ondownload* callbacks should be triggered on all app instances
|
||||
if ((msg.oid != this._id || !req) &&
|
||||
aMessage.name !== "Webapps:FireEvent" &&
|
||||
aMessage.name !== "Webapps:UpdateState") {
|
||||
if (msg.oid != this._id || !req) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -618,45 +596,13 @@ WebappsApplication.prototype = {
|
|||
"Webapps:Launch:Return:KO"]);
|
||||
Services.DOMRequest.fireSuccess(req, null);
|
||||
break;
|
||||
case "Webapps:CheckForUpdate:Return:KO":
|
||||
Services.DOMRequest.fireError(req, msg.error);
|
||||
break;
|
||||
case "Webapps:FireEvent":
|
||||
if (msg.manifestURL != this.manifestURL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The parent might ask childs to trigger more than one event in one
|
||||
// shot, so in order to avoid needless IPC we allow an array for the
|
||||
// 'eventType' IPC message field.
|
||||
if (!Array.isArray(msg.eventType)) {
|
||||
msg.eventType = [msg.eventType];
|
||||
}
|
||||
|
||||
msg.eventType.forEach((aEventType) => {
|
||||
if ("_on" + aEventType in this) {
|
||||
this._fireEvent(aEventType);
|
||||
} else {
|
||||
dump("Unsupported event type " + aEventType + "\n");
|
||||
}
|
||||
});
|
||||
|
||||
if (req) {
|
||||
Services.DOMRequest.fireSuccess(req, this.manifestURL);
|
||||
}
|
||||
break;
|
||||
case "Webapps:UpdateState":
|
||||
if (msg.manifestURL != this.manifestURL) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._updateState(msg);
|
||||
break;
|
||||
case "Webapps:ClearBrowserData:Return":
|
||||
this.removeMessageListeners(aMessage.name);
|
||||
Services.DOMRequest.fireSuccess(req, null);
|
||||
break;
|
||||
case "Webapps:Connect:Return:OK":
|
||||
this.removeMessageListeners(["Webapps:Connect:Return:OK",
|
||||
"Webapps:Connect:Return:KO"]);
|
||||
let messagePorts = [];
|
||||
msg.messagePortIDs.forEach((aPortID) => {
|
||||
let port = new this._window.MozInterAppMessagePort(aPortID);
|
||||
|
@ -665,9 +611,12 @@ WebappsApplication.prototype = {
|
|||
req.resolve(messagePorts);
|
||||
break;
|
||||
case "Webapps:Connect:Return:KO":
|
||||
this.removeMessageListeners(["Webapps:Connect:Return:OK",
|
||||
"Webapps:Connect:Return:KO"]);
|
||||
req.reject("No connections registered");
|
||||
break;
|
||||
case "Webapps:GetConnections:Return:OK":
|
||||
this.removeMessageListeners(aMessage.name);
|
||||
let connections = [];
|
||||
msg.connections.forEach((aConnection) => {
|
||||
let connection =
|
||||
|
@ -849,12 +798,8 @@ WebappsApplicationMgmt.prototype = {
|
|||
break;
|
||||
case "Webapps:Uninstall:Broadcast:Return:OK":
|
||||
if (this._onuninstall) {
|
||||
let detail = {
|
||||
manifestURL: msg.manifestURL,
|
||||
origin: msg.origin
|
||||
};
|
||||
let event = new this._window.MozApplicationEvent("applicationuninstall",
|
||||
{ application : createApplicationObject(this._window, detail) });
|
||||
{ application : createApplicationObject(this._window, msg) });
|
||||
this._onuninstall.handleEvent(event);
|
||||
}
|
||||
break;
|
||||
|
@ -883,7 +828,5 @@ WebappsApplicationMgmt.prototype = {
|
|||
classDescription: "Webapps Application Mgmt"})
|
||||
}
|
||||
|
||||
manifestCache.init();
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry,
|
||||
WebappsApplication]);
|
||||
|
|
|
@ -1121,8 +1121,7 @@ this.DOMApplicationRegistry = {
|
|||
this.removeMessageListener(["Webapps:Internal:AllMessages"], mm);
|
||||
break;
|
||||
case "Webapps:GetList":
|
||||
this.addMessageListener(["Webapps:AddApp", "Webapps:RemoveApp"], null, mm);
|
||||
return this.webapps;
|
||||
return { webapps: this.webapps, manifests: this._manifestCache };
|
||||
case "Webapps:Download":
|
||||
this.startDownload(msg.manifestURL);
|
||||
break;
|
||||
|
@ -1304,7 +1303,7 @@ this.DOMApplicationRegistry = {
|
|||
downloading: false
|
||||
},
|
||||
error: error,
|
||||
manifestURL: app.manifestURL,
|
||||
id: app.id
|
||||
})
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "downloaderror",
|
||||
|
@ -1334,7 +1333,7 @@ this.DOMApplicationRegistry = {
|
|||
if (!app.downloadAvailable) {
|
||||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
error: "NO_DOWNLOAD_AVAILABLE",
|
||||
manifestURL: app.manifestURL
|
||||
id: app.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "downloaderror",
|
||||
|
@ -1382,7 +1381,7 @@ this.DOMApplicationRegistry = {
|
|||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
manifest: jsonManifest,
|
||||
manifestURL: aManifestURL
|
||||
id: app.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "downloadsuccess",
|
||||
|
@ -1426,7 +1425,7 @@ this.DOMApplicationRegistry = {
|
|||
|
||||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
manifestURL: aManifestURL
|
||||
id: app.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "downloadsuccess",
|
||||
|
@ -1526,7 +1525,7 @@ this.DOMApplicationRegistry = {
|
|||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
manifest: aData,
|
||||
manifestURL: app.manifestURL
|
||||
id: app.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "downloadapplied",
|
||||
|
@ -1566,7 +1565,7 @@ this.DOMApplicationRegistry = {
|
|||
installState: aApp.installState,
|
||||
progress: 0
|
||||
},
|
||||
manifestURL: aApp.manifestURL
|
||||
id: aApp.id
|
||||
});
|
||||
let cacheUpdate = updateSvc.scheduleAppUpdate(
|
||||
appcacheURI, docURI, aApp.localId, false, aProfileDir);
|
||||
|
@ -1616,6 +1615,7 @@ this.DOMApplicationRegistry = {
|
|||
debug("checkForUpdate for " + aData.manifestURL);
|
||||
|
||||
function sendError(aError) {
|
||||
debug("checkForUpdate error " + aError);
|
||||
aData.error = aError;
|
||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
||||
}
|
||||
|
@ -1645,8 +1645,7 @@ this.DOMApplicationRegistry = {
|
|||
// then we can't have an update.
|
||||
if (app.origin.startsWith("app://") &&
|
||||
app.manifestURL.startsWith("app://")) {
|
||||
aData.error = "NOT_UPDATABLE";
|
||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
||||
sendError("NOT_UPDATABLE");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1663,8 +1662,7 @@ this.DOMApplicationRegistry = {
|
|||
if (onlyCheckAppCache) {
|
||||
// Bail out for packaged apps.
|
||||
if (app.origin.startsWith("app://")) {
|
||||
aData.error = "NOT_UPDATABLE";
|
||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
||||
sendError("NOT_UPDATABLE");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1672,8 +1670,7 @@ this.DOMApplicationRegistry = {
|
|||
this._readManifests([{ id: id }]).then((aResult) => {
|
||||
let manifest = aResult[0].manifest;
|
||||
if (!manifest.appcache_path) {
|
||||
aData.error = "NOT_UPDATABLE";
|
||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
||||
sendError("NOT_UPDATABLE");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1689,7 +1686,7 @@ this.DOMApplicationRegistry = {
|
|||
this._saveApps().then(() => {
|
||||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
manifestURL: app.manifestURL
|
||||
id: app.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "downloadavailable",
|
||||
|
@ -1698,8 +1695,7 @@ this.DOMApplicationRegistry = {
|
|||
});
|
||||
});
|
||||
} else {
|
||||
aData.error = "NOT_UPDATABLE";
|
||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
|
||||
sendError("NOT_UPDATABLE");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1759,7 +1755,7 @@ this.DOMApplicationRegistry = {
|
|||
: "downloadapplied";
|
||||
aMm.sendAsyncMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
manifestURL: app.manifestURL
|
||||
id: app.id
|
||||
});
|
||||
aMm.sendAsyncMessage("Webapps:FireEvent", {
|
||||
eventType: eventType,
|
||||
|
@ -1786,7 +1782,7 @@ this.DOMApplicationRegistry = {
|
|||
: "downloadapplied";
|
||||
aMm.sendAsyncMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
manifestURL: app.manifestURL
|
||||
id: app.id
|
||||
});
|
||||
aMm.sendAsyncMessage("Webapps:FireEvent", {
|
||||
eventType: eventType,
|
||||
|
@ -1895,7 +1891,7 @@ this.DOMApplicationRegistry = {
|
|||
|
||||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
app: aApp,
|
||||
manifestURL: aApp.manifestURL
|
||||
id: aApp.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "downloadavailable",
|
||||
|
@ -1961,7 +1957,7 @@ this.DOMApplicationRegistry = {
|
|||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
app: aApp,
|
||||
manifest: aApp.manifest,
|
||||
manifestURL: aApp.manifestURL
|
||||
id: aApp.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "downloadapplied",
|
||||
|
@ -1995,7 +1991,7 @@ this.DOMApplicationRegistry = {
|
|||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
app: aApp,
|
||||
manifest: aApp.manifest,
|
||||
manifestURL: aApp.manifestURL
|
||||
id: aApp.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: eventType,
|
||||
|
@ -2523,6 +2519,8 @@ this.DOMApplicationRegistry = {
|
|||
// saved in the registry.
|
||||
yield this._saveApps();
|
||||
|
||||
aData.isPackage ? appObject.updateManifest = jsonManifest :
|
||||
appObject.manifest = jsonManifest;
|
||||
this.broadcastMessage("Webapps:AddApp", { id: id, app: appObject });
|
||||
if (aData.isPackage && aData.autoInstall) {
|
||||
// Skip directly to onInstallSuccessAck, since there isn't
|
||||
|
@ -2616,7 +2614,7 @@ this.DOMApplicationRegistry = {
|
|||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
manifest: aManifest,
|
||||
manifestURL: aNewApp.manifestURL
|
||||
id: app.id
|
||||
});
|
||||
|
||||
// Check if we have asm.js code to preload for this application.
|
||||
|
@ -2730,14 +2728,11 @@ this.DOMApplicationRegistry = {
|
|||
oldApp,
|
||||
aNewApp);
|
||||
|
||||
AppDownloadManager.add(
|
||||
aNewApp.manifestURL,
|
||||
{
|
||||
channel: requestChannel,
|
||||
appId: id,
|
||||
previousState: aIsUpdate ? "installed" : "pending"
|
||||
}
|
||||
);
|
||||
AppDownloadManager.add(aNewApp.manifestURL, {
|
||||
channel: requestChannel,
|
||||
appId: id,
|
||||
previousState: aIsUpdate ? "installed" : "pending"
|
||||
});
|
||||
|
||||
// We set the 'downloading' flag to true right before starting the fetch.
|
||||
oldApp.downloading = true;
|
||||
|
@ -2760,7 +2755,7 @@ this.DOMApplicationRegistry = {
|
|||
debug("package's etag or hash unchanged; sending 'applied' event");
|
||||
// The package's Etag or hash has not changed.
|
||||
// We send a "applied" event right away.
|
||||
this._sendAppliedEvent(aNewApp, oldApp, id);
|
||||
this._sendAppliedEvent(oldApp);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2900,7 +2895,7 @@ this.DOMApplicationRegistry = {
|
|||
app: {
|
||||
progress: aProgress
|
||||
},
|
||||
manifestURL: aNewApp.manifestURL
|
||||
id: aNewApp.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "progress",
|
||||
|
@ -3017,27 +3012,24 @@ this.DOMApplicationRegistry = {
|
|||
* something similar after updating the app, and we could refactor both cases
|
||||
* to use the same code to send the "applied" event.
|
||||
*
|
||||
* @param aNewApp {Object} the new app data
|
||||
* @param aOldApp {Object} the currently stored app data
|
||||
* @param aId {String} the unique id of the app
|
||||
* @param aApp {Object} app data
|
||||
*/
|
||||
_sendAppliedEvent: function(aNewApp, aOldApp, aId) {
|
||||
aOldApp.downloading = false;
|
||||
aOldApp.downloadAvailable = false;
|
||||
aOldApp.downloadSize = 0;
|
||||
aOldApp.installState = "installed";
|
||||
aOldApp.readyToApplyDownload = false;
|
||||
if (aOldApp.staged && aOldApp.staged.manifestHash) {
|
||||
_sendAppliedEvent: function(aApp) {
|
||||
aApp.downloading = false;
|
||||
aApp.downloadAvailable = false;
|
||||
aApp.downloadSize = 0;
|
||||
aApp.installState = "installed";
|
||||
aApp.readyToApplyDownload = false;
|
||||
if (aApp.staged && aApp.staged.manifestHash) {
|
||||
// If we're here then the manifest has changed but the package
|
||||
// hasn't. Let's clear this, so we don't keep offering
|
||||
// a bogus update to the user
|
||||
aOldApp.manifestHash = aOldApp.staged.manifestHash;
|
||||
aOldApp.etag = aOldApp.staged.etag || aOldApp.etag;
|
||||
aOldApp.staged = {};
|
||||
|
||||
// Move the staged update manifest to a non staged one.
|
||||
aApp.manifestHash = aApp.staged.manifestHash;
|
||||
aApp.etag = aApp.staged.etag || aApp.etag;
|
||||
aApp.staged = {};
|
||||
// Move the staged update manifest to a non staged one.
|
||||
try {
|
||||
let staged = this._getAppDir(aId);
|
||||
let staged = this._getAppDir(aApp.id);
|
||||
staged.append("staged-update.webapp");
|
||||
staged.moveTo(staged.parent, "update.webapp");
|
||||
} catch (ex) {
|
||||
|
@ -3048,15 +3040,15 @@ this.DOMApplicationRegistry = {
|
|||
// Save the updated registry, and cleanup the tmp directory.
|
||||
this._saveApps().then(() => {
|
||||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
app: aOldApp,
|
||||
manifestURL: aNewApp.manifestURL
|
||||
app: aApp,
|
||||
id: aApp.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
manifestURL: aNewApp.manifestURL,
|
||||
manifestURL: aApp.manifestURL,
|
||||
eventType: ["downloadsuccess", "downloadapplied"]
|
||||
});
|
||||
});
|
||||
let file = FileUtils.getFile("TmpD", ["webapps", aId], false);
|
||||
let file = FileUtils.getFile("TmpD", ["webapps", aApp.id], false);
|
||||
if (file && file.exists()) {
|
||||
file.remove(true);
|
||||
}
|
||||
|
@ -3361,9 +3353,10 @@ this.DOMApplicationRegistry = {
|
|||
dir.moveTo(parent, newId);
|
||||
});
|
||||
// Signals that we need to swap the old id with the new app.
|
||||
this.broadcastMessage("Webapps:RemoveApp", { id: oldId });
|
||||
this.broadcastMessage("Webapps:AddApp", { id: newId,
|
||||
app: aOldApp });
|
||||
this.broadcastMessage("Webapps:UpdateApp", { oldId: oldId,
|
||||
newId: newId,
|
||||
app: aOldApp });
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3466,7 +3459,7 @@ this.DOMApplicationRegistry = {
|
|||
this.broadcastMessage("Webapps:UpdateState", {
|
||||
app: aOldApp,
|
||||
error: aError,
|
||||
manifestURL: aNewApp.manifestURL
|
||||
id: aNewApp.id
|
||||
});
|
||||
this.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "downloaderror",
|
||||
|
@ -4016,7 +4009,7 @@ AppcacheObserver.prototype = {
|
|||
let app = this.app;
|
||||
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
manifestURL: app.manifestURL
|
||||
id: app.id
|
||||
});
|
||||
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "progress",
|
||||
|
@ -4048,7 +4041,7 @@ AppcacheObserver.prototype = {
|
|||
app.downloadAvailable = false;
|
||||
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
manifestURL: app.manifestURL
|
||||
id: app.id
|
||||
});
|
||||
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: ["downloadsuccess", "downloadapplied"],
|
||||
|
@ -4062,7 +4055,7 @@ AppcacheObserver.prototype = {
|
|||
DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
error: aError,
|
||||
manifestURL: app.manifestURL
|
||||
id: app.id
|
||||
});
|
||||
DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: "downloaderror",
|
||||
|
|
|
@ -98,6 +98,7 @@ var PackagedTestHelper = (function PackagedTestHelper() {
|
|||
var aApp = evt.application;
|
||||
aApp.ondownloaderror = function(evt) {
|
||||
var error = aApp.downloadError.name;
|
||||
ok(true, "Got downloaderror " + error);
|
||||
if (error == aExpectedError) {
|
||||
ok(true, "Got expected " + aExpectedError);
|
||||
var expected = {
|
||||
|
|
|
@ -79,16 +79,15 @@ function updateApp(aExpectedReady, aPreviousVersion, aNextVersion) {
|
|||
checkLastAppState.bind(PackagedTestHelper, miniManifestURL, false, false,
|
||||
aNextVersion, PackagedTestHelper.next);
|
||||
|
||||
var ondownloadsuccesshandler =
|
||||
checkLastAppState.bind(undefined, miniManifestURL,
|
||||
aExpectedReady, false, aPreviousVersion,
|
||||
function() {
|
||||
navigator.mozApps.mgmt.applyDownload(lApp);
|
||||
});
|
||||
|
||||
checkForUpdate(true, ondownloadsuccesshandler, ondownloadappliedhandler, null,
|
||||
true);
|
||||
var ondownloadsuccesshandler =
|
||||
checkLastAppState.bind(undefined, miniManifestURL,
|
||||
aExpectedReady, false, aPreviousVersion,
|
||||
function() {
|
||||
navigator.mozApps.mgmt.applyDownload(lApp);
|
||||
});
|
||||
|
||||
checkForUpdate(true, ondownloadsuccesshandler, ondownloadappliedhandler, null,
|
||||
true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -174,7 +173,7 @@ var steps = [
|
|||
"&appName=arandomname" +
|
||||
"&appToFail1";
|
||||
PackagedTestHelper.checkAppDownloadError(miniManifestURL,
|
||||
"MANIFEST_MISMATCH", 2, false, true,
|
||||
"MANIFEST_MISMATCH", 1, false, true,
|
||||
"arandomname",
|
||||
function () {
|
||||
checkForUpdate(false, null, null, null, false,
|
||||
|
|
|
@ -243,4 +243,4 @@ addLoadEvent(go);
|
|||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -254,7 +254,7 @@ WebappsActor.prototype = {
|
|||
reg.broadcastMessage("Webapps:UpdateState", {
|
||||
app: aApp,
|
||||
manifest: manifest,
|
||||
manifestURL: aApp.manifestURL
|
||||
id: aApp.id
|
||||
});
|
||||
reg.broadcastMessage("Webapps:FireEvent", {
|
||||
eventType: ["downloadsuccess", "downloadapplied"],
|
||||
|
|
Загрузка…
Ссылка в новой задаче