зеркало из https://github.com/mozilla/gecko-dev.git
Bug 778079 - Support loading app packages from multiple locations [r=vingtetun]
This commit is contained in:
Родитель
009e165d07
Коммит
6c2d0b1566
|
@ -23,14 +23,19 @@ DirectoryProvider.prototype = {
|
|||
getFile: function dp_getFile(prop, persistent) {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir",
|
||||
"permissionDBPDir", "UpdRootD"];
|
||||
"permissionDBPDir", "UpdRootD"];
|
||||
if (localProps.indexOf(prop) != -1) {
|
||||
prop.persistent = true;
|
||||
let file = Cc["@mozilla.org/file/local;1"]
|
||||
.createInstance(Ci.nsILocalFile)
|
||||
file.initWithPath(LOCAL_DIR);
|
||||
persistent.value = true;
|
||||
return file;
|
||||
}
|
||||
} else if (prop == "coreAppsDir") {
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile)
|
||||
file.initWithPath("/system/b2g");
|
||||
persistent.value = true;
|
||||
return file;
|
||||
}
|
||||
#endif
|
||||
|
||||
return null;
|
||||
|
|
|
@ -30,6 +30,7 @@ let AppsUtils = {
|
|||
installTime: aApp.installTime,
|
||||
manifestURL: aApp.manifestURL,
|
||||
appStatus: aApp.appStatus,
|
||||
removable: aApp.removable,
|
||||
localId: aApp.localId,
|
||||
progress: aApp.progress || 0.0,
|
||||
status: aApp.status || "installed"
|
||||
|
|
|
@ -20,8 +20,7 @@ function convertAppsArray(aApps, aWindow) {
|
|||
let apps = Cu.createArrayIn(aWindow);
|
||||
for (let i = 0; i < aApps.length; i++) {
|
||||
let app = aApps[i];
|
||||
apps.push(createApplicationObject(aWindow, app.origin, app.manifest, app.manifestURL,
|
||||
app.receipts, app.installOrigin, app.installTime));
|
||||
apps.push(createApplicationObject(aWindow, app));
|
||||
}
|
||||
|
||||
return apps;
|
||||
|
@ -73,8 +72,7 @@ WebappsRegistry.prototype = {
|
|||
let app = msg.app;
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:Install:Return:OK":
|
||||
Services.DOMRequest.fireSuccess(req, createApplicationObject(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
|
||||
app.installOrigin, app.installTime));
|
||||
Services.DOMRequest.fireSuccess(req, createApplicationObject(this._window, app));
|
||||
break;
|
||||
case "Webapps:Install:Return:KO":
|
||||
Services.DOMRequest.fireError(req, msg.error || "DENIED");
|
||||
|
@ -82,8 +80,7 @@ WebappsRegistry.prototype = {
|
|||
case "Webapps:GetSelf:Return:OK":
|
||||
if (msg.apps.length) {
|
||||
app = msg.apps[0];
|
||||
Services.DOMRequest.fireSuccess(req, createApplicationObject(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
|
||||
app.installOrigin, app.installTime));
|
||||
Services.DOMRequest.fireSuccess(req, createApplicationObject(this._window, app));
|
||||
} else {
|
||||
Services.DOMRequest.fireSuccess(req, null);
|
||||
}
|
||||
|
@ -223,9 +220,9 @@ WebappsRegistry.prototype = {
|
|||
* mozIDOMApplication object
|
||||
*/
|
||||
|
||||
function createApplicationObject(aWindow, aOrigin, aManifest, aManifestURL, aReceipts, aInstallOrigin, aInstallTime) {
|
||||
function createApplicationObject(aWindow, aApp) {
|
||||
let app = Cc["@mozilla.org/webapps/application;1"].createInstance(Ci.mozIDOMApplication);
|
||||
app.wrappedJSObject.init(aWindow, aOrigin, aManifest, aManifestURL, aReceipts, aInstallOrigin, aInstallTime);
|
||||
app.wrappedJSObject.init(aWindow, aApp);
|
||||
return app;
|
||||
}
|
||||
|
||||
|
@ -246,20 +243,24 @@ WebappsApplication.prototype = {
|
|||
onprogress: 'rw',
|
||||
launch: 'r',
|
||||
receipts: 'r',
|
||||
removable: 'r',
|
||||
uninstall: 'r'
|
||||
},
|
||||
|
||||
init: function(aWindow, aOrigin, aManifest, aManifestURL, aReceipts, aInstallOrigin, aInstallTime) {
|
||||
this.origin = aOrigin;
|
||||
this.manifest = ObjectWrapper.wrap(aManifest, aWindow);
|
||||
this.manifestURL = aManifestURL;
|
||||
this.receipts = aReceipts;
|
||||
this.installOrigin = aInstallOrigin;
|
||||
this.installTime = aInstallTime;
|
||||
init: function(aWindow, aApp) {
|
||||
this.origin = aApp.origin;
|
||||
this.manifest = ObjectWrapper.wrap(aApp.manifest, aWindow);
|
||||
this.manifestURL = aApp.manifestURL;
|
||||
this.receipts = aApp.receipts;
|
||||
this.installOrigin = aApp.installOrigin;
|
||||
this.installTime = aApp.installTime;
|
||||
this.status = "installed";
|
||||
this.removable = aApp.removable;
|
||||
this.progress = NaN;
|
||||
this._onprogress = null;
|
||||
this.initHelper(aWindow, ["Webapps:Uninstall:Return:OK", "Webapps:Uninstall:Return:KO", "Webapps:OfflineCache"]);
|
||||
this.initHelper(aWindow, ["Webapps:Uninstall:Return:OK",
|
||||
"Webapps:Uninstall:Return:KO",
|
||||
"Webapps:OfflineCache"]);
|
||||
},
|
||||
|
||||
set onprogress(aCallback) {
|
||||
|
@ -422,15 +423,14 @@ WebappsApplicationMgmt.prototype = {
|
|||
if (this._oninstall) {
|
||||
let app = msg.app;
|
||||
let event = new this._window.MozApplicationEvent("applicationinstall",
|
||||
{ application : createApplicationObject(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
|
||||
app.installOrigin, app.installTime) });
|
||||
{ application : createApplicationObject(this._window, app) });
|
||||
this._oninstall.handleEvent(event);
|
||||
}
|
||||
break;
|
||||
case "Webapps:Uninstall:Return:OK":
|
||||
if (this._onuninstall) {
|
||||
let event = new this._window.MozApplicationEvent("applicationuninstall",
|
||||
{ application : createApplicationObject(this._window, msg.origin, null, null, null, null, 0) });
|
||||
{ application : createApplicationObject(this._window, { origin: msg.origin }) });
|
||||
this._onuninstall.handleEvent(event);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -71,24 +71,41 @@ let DOMApplicationRegistry = {
|
|||
this.appsFile = FileUtils.getFile(DIRECTORY_NAME,
|
||||
["webapps", "webapps.json"], true);
|
||||
|
||||
if (this.appsFile.exists()) {
|
||||
this._loadJSONAsync(this.appsFile, (function(aData) {
|
||||
this.webapps = aData;
|
||||
for (let id in this.webapps) {
|
||||
#ifdef MOZ_SYS_MSG
|
||||
this._processManifestForId(id);
|
||||
#endif
|
||||
if (!this.webapps[id].localId) {
|
||||
this.webapps[id].localId = this._nextLocalId();
|
||||
}
|
||||
let dirList = [DIRECTORY_NAME];
|
||||
|
||||
// Default to a non privileged status.
|
||||
if (this.webapps[id].appStatus === undefined) {
|
||||
this.webapps[id].appStatus = Ci.nsIPrincipal.APP_STATUS_INSTALLED;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
dirList.push("coreAppsDir");
|
||||
#endif
|
||||
let currentId = 1;
|
||||
dirList.forEach((function(dir) {
|
||||
let curFile = FileUtils.getFile(dir, ["webapps", "webapps.json"], true);
|
||||
if (curFile.exists()) {
|
||||
let appDir = FileUtils.getDir(dir, ["webapps"]);
|
||||
this._loadJSONAsync(curFile, (function(aData) {
|
||||
if (!aData) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
}).bind(this));
|
||||
}
|
||||
// Add new apps to the merged list.
|
||||
for (let id in aData) {
|
||||
this.webapps[id] = aData[id];
|
||||
this.webapps[id].basePath = appDir.path;
|
||||
this.webapps[id].removable = (dir == DIRECTORY_NAME);
|
||||
#ifdef MOZ_SYS_MSG
|
||||
this._processManifestForId(id);
|
||||
#endif
|
||||
// local ids must be stable between restarts.
|
||||
// We partition the ids in two buckets:
|
||||
// - 1 to 1000 for the core apps.
|
||||
// - 1001 to Inf for installed apps.
|
||||
// This way, a gecko update with new core apps will not lead to
|
||||
// changes for installed apps ids.
|
||||
if (!this.webapps[id].removable) {
|
||||
this.webapps[id].localId = currentId++;
|
||||
}
|
||||
};
|
||||
}).bind(this));
|
||||
}
|
||||
}).bind(this));
|
||||
|
||||
try {
|
||||
let hosts = Services.prefs.getCharPref("dom.mozApps.whitelist");
|
||||
|
@ -254,7 +271,7 @@ let DOMApplicationRegistry = {
|
|||
this.installPackage(msg);
|
||||
break;
|
||||
case "Webapps:GetBasePath":
|
||||
return FileUtils.getFile(DIRECTORY_NAME, ["webapps"], true).path;
|
||||
return this.webapps[msg.id].basePath;
|
||||
break;
|
||||
case "Webapps:GetList":
|
||||
this.children.push(aMessage.target);
|
||||
|
@ -262,6 +279,11 @@ let DOMApplicationRegistry = {
|
|||
}
|
||||
},
|
||||
|
||||
_getAppDir: function(aId) {
|
||||
FileUtils.getDir(this.webapps[aId].removable ? DIRECTORY_NAME : "coreAppsDir",
|
||||
["webapps", aId], true, true);
|
||||
},
|
||||
|
||||
_writeFile: function ss_writeFile(aFile, aData, aCallbak) {
|
||||
// Initialize the file output stream.
|
||||
let ostream = FileUtils.openSafeFileOutputStream(aFile);
|
||||
|
@ -294,12 +316,13 @@ let DOMApplicationRegistry = {
|
|||
|
||||
confirmInstall: function(aData, aFromSync, aProfileDir, aOfflineCacheObserver) {
|
||||
let app = aData.app;
|
||||
app.removable = true;
|
||||
let id = app.syncId || this._appId(app.origin);
|
||||
let localId = this.getAppLocalIdByManifestURL(app.manifestURL);
|
||||
|
||||
// Installing an application again is considered as an update.
|
||||
if (id) {
|
||||
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
|
||||
let dir = this._getAppDir(id);
|
||||
try {
|
||||
dir.remove(true);
|
||||
} catch(e) {
|
||||
|
@ -375,7 +398,8 @@ let DOMApplicationRegistry = {
|
|||
},
|
||||
|
||||
_nextLocalId: function() {
|
||||
let maxLocalId = Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||
// All installed apps have a localId > 1000.
|
||||
let maxLocalId = 1000;
|
||||
|
||||
for (let id in this.webapps) {
|
||||
if (this.webapps[id].localId > maxLocalId) {
|
||||
|
@ -419,9 +443,10 @@ let DOMApplicationRegistry = {
|
|||
let id = aData[index].id;
|
||||
|
||||
// the manifest file used to be named manifest.json, so fallback on this.
|
||||
let file = FileUtils.getFile(DIRECTORY_NAME, ["webapps", id, "manifest.webapp"], true);
|
||||
let baseDir = (this.webapps[id].removable ? DIRECTORY_NAME : "coreAppsDir");
|
||||
let file = FileUtils.getFile(baseDir, ["webapps", id, "manifest.webapp"], true);
|
||||
if (!file.exists()) {
|
||||
file = FileUtils.getFile(DIRECTORY_NAME, ["webapps", id, "manifest.json"], true);
|
||||
file = FileUtils.getFile(baseDir, ["webapps", id, "manifest.json"], true);
|
||||
}
|
||||
|
||||
this._loadJSONAsync(file, (function(aJSON) {
|
||||
|
@ -598,6 +623,9 @@ let DOMApplicationRegistry = {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!this.webapps[id].removable)
|
||||
return;
|
||||
|
||||
found = true;
|
||||
let appNote = JSON.stringify(AppsUtils.cloneAppObject(app));
|
||||
appNote.id = id;
|
||||
|
@ -608,7 +636,7 @@ let DOMApplicationRegistry = {
|
|||
#endif
|
||||
}).bind(this));
|
||||
|
||||
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
|
||||
let dir = this._getAppDir(id);
|
||||
try {
|
||||
dir.remove(true);
|
||||
} catch (e) {}
|
||||
|
@ -761,11 +789,11 @@ let DOMApplicationRegistry = {
|
|||
for (let i = 0; i < aRecords.length; i++) {
|
||||
let record = aRecords[i];
|
||||
if (record.hidden) {
|
||||
if (!this.webapps[record.id])
|
||||
if (!this.webapps[record.id] || !this.webapps[record.id].removable)
|
||||
continue;
|
||||
let origin = this.webapps[record.id].origin;
|
||||
delete this.webapps[record.id];
|
||||
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", record.id], true, true);
|
||||
let dir = this._getAppDir(record.id);
|
||||
try {
|
||||
dir.remove(true);
|
||||
} catch (e) {
|
||||
|
@ -798,8 +826,12 @@ let DOMApplicationRegistry = {
|
|||
wipe: function(aCallback) {
|
||||
let ids = this.getAllIDs();
|
||||
for (let id in ids) {
|
||||
if (!this.webapps[id].removable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
delete this.webapps[id];
|
||||
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
|
||||
let dir = this._getAppDir(id);
|
||||
try {
|
||||
dir.remove(true);
|
||||
} catch (e) {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
interface nsIDOMDOMRequest;
|
||||
interface nsIArray;
|
||||
|
||||
[scriptable, uuid(9583b825-46b1-4e8f-bb48-9fed660a95e6)]
|
||||
[scriptable, uuid(e3649c1d-c950-495e-b0ed-6ce40be9743b)]
|
||||
interface mozIDOMApplication : nsISupports
|
||||
{
|
||||
readonly attribute jsval manifest;
|
||||
|
@ -17,6 +17,7 @@ interface mozIDOMApplication : nsISupports
|
|||
readonly attribute DOMString origin;
|
||||
readonly attribute DOMString installOrigin;
|
||||
readonly attribute unsigned long long installTime;
|
||||
readonly attribute boolean removable;
|
||||
|
||||
/*
|
||||
* The current progress when downloading an offline cache.
|
||||
|
|
|
@ -16,7 +16,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
|||
"nsISyncMessageSender");
|
||||
|
||||
function AppProtocolHandler() {
|
||||
this._basePath = null;
|
||||
this._basePath = [];
|
||||
}
|
||||
|
||||
AppProtocolHandler.prototype = {
|
||||
|
@ -30,12 +30,14 @@ AppProtocolHandler.prototype = {
|
|||
Ci.nsIProtocolHandler.URI_NOAUTH |
|
||||
Ci.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE,
|
||||
|
||||
get basePath() {
|
||||
if (!this._basePath) {
|
||||
this._basePath = cpmm.sendSyncMessage("Webapps:GetBasePath", { })[0] + "/";
|
||||
getBasePath: function app_phGetBasePath(aId) {
|
||||
|
||||
if (!this._basePath[aId]) {
|
||||
this._basePath[aId] = cpmm.sendSyncMessage("Webapps:GetBasePath",
|
||||
{ id: aId })[0] + "/";
|
||||
}
|
||||
|
||||
return this._basePath;
|
||||
return this._basePath[aId];
|
||||
},
|
||||
|
||||
newURI: function app_phNewURI(aSpec, aOriginCharset, aBaseURI) {
|
||||
|
@ -60,7 +62,7 @@ AppProtocolHandler.prototype = {
|
|||
}
|
||||
|
||||
// Build a jar channel and masquerade as an app:// URI.
|
||||
let uri = "jar:file://" + this.basePath + appId + "/application.zip!" + fileSpec;
|
||||
let uri = "jar:file://" + this.getBasePath(appId) + appId + "/application.zip!" + fileSpec;
|
||||
let channel = Services.io.newChannel(uri, null, null);
|
||||
channel.QueryInterface(Ci.nsIJARChannel).setAppURI(aURI);
|
||||
channel.QueryInterface(Ci.nsIChannel).originalURI = aURI;
|
||||
|
|
Загрузка…
Ссылка в новой задаче