Bug 777402 - Implement support for packaged apps via the installPackage function in the mozapps DOM API in desktop web runtime. r=myk,wesj,fabrice

This commit is contained in:
Marco Castelluccio 2013-08-01 17:00:39 -07:00
parent 17d4d4fadd
commit 2bb65fbf3a
16 changed files with 284 additions and 225 deletions

View File

@ -106,15 +106,21 @@ this.webappsUI = {
label: bundle.getString("webapps.install"),
accessKey: bundle.getString("webapps.install.accesskey"),
callback: function() {
let app = WebappsInstaller.install(aData);
let app = WebappsInstaller.init(aData);
if (app) {
let localDir = null;
if (app.appProfile) {
localDir = app.appProfile.localDir;
}
DOMApplicationRegistry.confirmInstall(aData, false, localDir);
installationSuccessNotification(aData, app, aWindow);
DOMApplicationRegistry.confirmInstall(aData, false, localDir, null,
function (aManifest) {
if (WebappsInstaller.install(aData, aManifest)) {
installationSuccessNotification(aData, app, aWindow);
}
}
);
} else {
DOMApplicationRegistry.denyInstall(aData);
}
@ -122,7 +128,8 @@ this.webappsUI = {
};
let requestingURI = aWindow.makeURI(aData.from);
let manifest = new ManifestHelper(aData.app.manifest, aData.app.origin);
let jsonManifest = aData.isPackage ? aData.app.updateManifest : aData.app.manifest;
let manifest = new ManifestHelper(jsonManifest, aData.app.origin);
let host;
try {

View File

@ -118,19 +118,9 @@ WebappsRegistry.prototype = {
return false;
},
// mozIDOMApplicationRegistry implementation
install: function(aURL, aParams) {
let uri = this._validateURL(aURL);
let request = this.createRequest();
if (!this._ensureForeground(request)) {
return request;
}
_prepareInstall: function(aURL, aRequest, aParams, isPackage) {
let installURL = this._window.location.href;
let requestID = this.getRequestId(request);
let requestID = this.getRequestId(aRequest);
let receipts = (aParams && aParams.receipts &&
Array.isArray(aParams.receipts)) ? aParams.receipts
: [];
@ -139,20 +129,36 @@ WebappsRegistry.prototype = {
: [];
let principal = this._window.document.nodePrincipal;
cpmm.sendAsyncMessage("Webapps:Install",
{ app: {
installOrigin: this._getOrigin(installURL),
origin: this._getOrigin(uri),
manifestURL: uri,
receipts: receipts,
categories: categories
},
from: installURL,
oid: this._id,
requestID: requestID,
appId: principal.appId,
isBrowser: principal.isInBrowserElement
});
return { app: {
installOrigin: this._getOrigin(installURL),
origin: this._getOrigin(aURL),
manifestURL: aURL,
receipts: receipts,
categories: categories
},
from: installURL,
oid: this._id,
requestID: requestID,
appId: principal.appId,
isBrowser: principal.isInBrowserElement,
isPackage: isPackage
};
},
// mozIDOMApplicationRegistry implementation
install: function(aURL, aParams) {
let uri = this._validateURL(aURL);
let request = this.createRequest();
if (this._ensureForeground(request)) {
cpmm.sendAsyncMessage("Webapps:Install",
this._prepareInstall(uri, request, aParams, false));
}
return request;
},
@ -201,42 +207,16 @@ WebappsRegistry.prototype = {
["Webapps:Install:Return:OK"]);
},
// mozIDOMApplicationRegistry2 implementation
installPackage: function(aURL, aParams) {
let uri = this._validateURL(aURL);
let request = this.createRequest();
if (!this._ensureForeground(request)) {
return request;
if (this._ensureForeground(request)) {
cpmm.sendAsyncMessage("Webapps:InstallPackage",
this._prepareInstall(uri, request, aParams, true));
}
let installURL = this._window.location.href;
let requestID = this.getRequestId(request);
let receipts = (aParams && aParams.receipts &&
Array.isArray(aParams.receipts)) ? aParams.receipts
: [];
let categories = (aParams && aParams.categories &&
Array.isArray(aParams.categories)) ? aParams.categories
: [];
let principal = this._window.document.nodePrincipal;
cpmm.sendAsyncMessage("Webapps:InstallPackage",
{ app: {
installOrigin: this._getOrigin(installURL),
origin: this._getOrigin(uri),
manifestURL: uri,
receipts: receipts,
categories: categories
},
from: installURL,
oid: this._id,
requestID: requestID,
isPackage: true,
appId: principal.appId,
isBrowser: principal.isInBrowserElement
});
return request;
},
@ -266,22 +246,13 @@ WebappsRegistry.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
Ci.mozIDOMApplicationRegistry,
#ifdef MOZ_B2G
Ci.mozIDOMApplicationRegistry2,
#elifdef MOZ_WIDGET_ANDROID
Ci.mozIDOMApplicationRegistry2,
#endif
Ci.nsIDOMGlobalPropertyInitializer]),
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
contractID: "@mozilla.org/webapps;1",
interfaces: [Ci.mozIDOMApplicationRegistry,
#ifdef MOZ_B2G
Ci.mozIDOMApplicationRegistry2,
#elifdef MOZ_WIDGET_ANDROID
Ci.mozIDOMApplicationRegistry2,
#endif
],
Ci.mozIDOMApplicationRegistry2],
flags: Ci.nsIClassInfo.DOM_OBJECT,
classDescription: "Webapps Registry"})
}

View File

@ -1841,15 +1841,6 @@ this.DOMApplicationRegistry = {
app.installOrigin + ": " + aError);
}.bind(this);
// Disallow reinstalls from the same manifest URL for now.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=821288
if (this.getAppLocalIdByManifestURL(app.manifestURL) !==
Ci.nsIScriptSecurityManager.NO_APP_ID ||
this._appId(app.origin) !== null) {
sendError("REINSTALL_FORBIDDEN");
return;
}
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
xhr.open("GET", app.manifestURL, true);
@ -1872,6 +1863,13 @@ this.DOMApplicationRegistry = {
return;
}
// Disallow reinstalls from the same manifest URL for now.
if (this._appIdForManifestURL(app.manifestURL) !== null &&
this._isLaunchable(app)) {
sendError("REINSTALL_FORBIDDEN");
return;
}
if (!(AppsUtils.checkManifest(manifest, app) &&
manifest.package_path)) {
sendError("INVALID_MANIFEST");
@ -1988,7 +1986,7 @@ this.DOMApplicationRegistry = {
appObject.id = id;
appObject.localId = localId;
appObject.basePath = FileUtils.getDir(DIRECTORY_NAME, ["webapps"], true, true).path;
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
let dir = this._getAppDir(id);
let manFile = dir.clone();
manFile.append(manifestName);
let jsonManifest = aData.isPackage ? app.updateManifest : app.manifest;
@ -2062,7 +2060,7 @@ this.DOMApplicationRegistry = {
if (!aData.isPackage) {
this.updateAppHandlers(null, app.manifest, app);
if (aInstallSuccessCallback) {
aInstallSuccessCallback(manifest);
aInstallSuccessCallback(app.manifest);
}
}
@ -2074,7 +2072,7 @@ this.DOMApplicationRegistry = {
// Success! Move the zip out of TmpD.
let app = DOMApplicationRegistry.webapps[aId];
let zipFile = FileUtils.getFile("TmpD", ["webapps", aId, "application.zip"], true);
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", aId], true, true);
let dir = this._getAppDir(id);
zipFile.moveTo(dir, "application.zip");
let tmpDir = FileUtils.getDir("TmpD", ["webapps", aId], true, true);
try {

View File

@ -7,11 +7,8 @@
EXTRA_COMPONENTS += [
'AppsService.js',
'AppsService.manifest',
'Webapps.manifest',
]
EXTRA_PP_COMPONENTS += [
'Webapps.js',
'Webapps.manifest',
]
EXTRA_JS_MODULES += [

View File

@ -138,7 +138,7 @@ interface mozIDOMApplicationMgmt : nsISupports
nsIDOMDOMRequest uninstall(in mozIDOMApplication app);
};
[scriptable, uuid(abfc6c15-8b92-4b9a-b892-52e6ae76f379)]
[scriptable, uuid(52710c5f-b2a2-4b27-b5b9-f679a1bcc79b)]
interface mozIDOMApplicationRegistry : nsISupports
{
/**
@ -169,5 +169,18 @@ interface mozIDOMApplicationRegistry : nsISupports
*/
nsIDOMDOMRequest getInstalled();
/**
* Install a packaged web app.
*
* @param packageUrl : the URL of the webapps manifest.
* @param parameters : A structure with optional information.
* {
* receipts: ... Will be used to specify the payment receipts for this installation.
* categories: ... Will be used to specify the categories of the webapp.
* }
* @returns : A DOMRequest object, returning the app object in |result| if install succeeds.
*/
nsIDOMDOMRequest installPackage(in DOMString packageUrl, [optional] in jsval parameters);
readonly attribute mozIDOMApplicationMgmt mgmt;
};

View File

@ -6,19 +6,8 @@
interface nsIDOMDOMRequest;
[scriptable, uuid(34498a66-3aee-4b80-8b8b-a9c5d5ba32b6)]
// This interface is still here for backwards compatibility.
[scriptable, uuid(5bd838b2-cf3d-406e-bbef-f633cf9e68de)]
interface mozIDOMApplicationRegistry2 : mozIDOMApplicationRegistry
{
/**
* Install a packaged web app.
*
* @param packageUrl : the URL of the webapps manifest.
* @param parameters : A structure with optional information.
* {
* receipts: ... Will be used to specify the payment receipts for this installation.
* categories: ... Will be used to specify the categories of the webapp.
* }
* @returns : A DOMRequest object, returning the app object in |result| if install succeeds.
*/
nsIDOMDOMRequest installPackage(in DOMString packageUrl, [optional] in jsval parameters);
};

View File

@ -24,7 +24,6 @@ var steps = [
invalidManifest,
permissionDenied,
invalidContent,
installPackageNotImplemented,
invalidLaunchPath,
invalidLaunchPath2,
invalidEntryPoint,
@ -167,12 +166,6 @@ function invalidMessage(next) {
};
}
function installPackageNotImplemented(next) {
ok(!("installPackage" in navigator.mozApps),
"installPackage not in navigator.mozApps");
next();
}
function fileURL(next) {
try {
navigator.mozApps.install("file:///nonexistent");

View File

@ -24,6 +24,7 @@ var props = {
getInstalled: "function",
getSelf: "function",
install: "function",
installPackage: "function",
mgmt: "object",
};

View File

@ -6722,10 +6722,9 @@ var WebappsUI = {
doInstall: function doInstall(aData) {
let jsonManifest = aData.isPackage ? aData.app.updateManifest : aData.app.manifest;
let manifest = new ManifestHelper(jsonManifest, aData.app.origin);
let name = manifest.name ? manifest.name : manifest.fullLaunchPath();
let showPrompt = true;
if (!showPrompt || Services.prompt.confirm(null, Strings.browser.GetStringFromName("webapps.installTitle"), name + "\n" + aData.app.origin)) {
if (!showPrompt || Services.prompt.confirm(null, Strings.browser.GetStringFromName("webapps.installTitle"), manifest.name + "\n" + aData.app.origin)) {
// Get a profile for the app to be installed in. We'll download everything before creating the icons.
let origin = aData.app.origin;
let profilePath = sendMessageToJava({
@ -6737,10 +6736,12 @@ var WebappsUI = {
if (profilePath) {
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
file.initWithPath(profilePath);
let self = this;
DOMApplicationRegistry.confirmInstall(aData, false, file, null,
function (manifest) {
function (aManifest) {
let localeManifest = new ManifestHelper(aManifest, aData.app.origin);
// the manifest argument is the manifest from within the zip file,
// TODO so now would be a good time to ask about permissions.
self.makeBase64Icon(self.getBiggestIcon(manifest.icons, Services.io.newURI(aData.app.origin, null, null)),
@ -6760,7 +6761,7 @@ var WebappsUI = {
// aData.app.origin may now point to the app: url that hosts this app
sendMessageToJava({
type: "WebApps:PostInstall",
name: manifest.name,
name: localeManifest.name,
manifestURL: aData.app.manifestURL,
originalOrigin: origin,
origin: aData.app.origin,
@ -6770,7 +6771,7 @@ var WebappsUI = {
// For packaged apps, put a notification in the notification bar.
let message = Strings.browser.GetStringFromName("webapps.alertSuccess");
let alerts = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
alerts.showAlertNotification("drawable://alert_app", manifest.name, message, true, "", {
alerts.showAlertNotification("drawable://alert_app", localeManifest.name, message, true, "", {
observe: function () {
self.openURL(aData.app.manifestURL, aData.app.origin);
}
@ -6779,7 +6780,7 @@ var WebappsUI = {
} catch(ex) {
console.log(ex);
}
self.writeDefaultPrefs(file, manifest);
self.writeDefaultPrefs(file, localeManifest);
}
);
}

View File

@ -66,6 +66,7 @@ class WebappCollection(object):
"""A list-like object that collects webapps and updates the webapp manifests"""
json_template = Template(""""$name": {
"name": "$name",
"origin": "$origin",
"installOrigin": "$origin",
"receipt": null,

View File

@ -21,13 +21,18 @@ this.WebappOSUtils = {
// doesn't have a name property. We then need to use the manifest.
// For some mozApps calls, the aApp object doesn't have a manifest
// associated, and so we need to use the name property.
// They're guaranteed to be always identical to the application
// name in the user locale.
if (aApp.name) {
name = aApp.name;
} else {
name = aApp.manifest.name;
let manifest =
new ManifestHelper(aApp.updateManifest || aApp.manifest, aApp.origin);
name = manifest.name;
}
return this.sanitizeStringForFilename(name).toLowerCase() + "-" + AppsUtils.computeHash(aApp.manifestURL);
return this.sanitizeStringForFilename(name).toLowerCase() + "-" +
AppsUtils.computeHash(aApp.manifestURL);
},
/**

View File

@ -17,113 +17,174 @@ Cu.import("resource://gre/modules/WebappOSUtils.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
this.WebappsInstaller = {
shell: null,
/**
* Initializes the app object that takes care of the installation
* and creates the profile directory for an application
*
* @param aData the data provided to the install function
*
* @returns NativeApp on success, null on error
*/
init: function(aData) {
#ifdef XP_WIN
this.shell = new WinNativeApp(aData);
#elifdef XP_MACOSX
this.shell = new MacNativeApp(aData);
#elifdef XP_UNIX
this.shell = new LinuxNativeApp(aData);
#else
return null;
#endif
try {
if (Services.prefs.getBoolPref("browser.mozApps.installer.dry_run")) {
return this.shell;
}
} catch (ex) {}
try {
this.shell.createAppProfile();
} catch (ex) {
Cu.reportError("Error installing app: " + ex);
return null;
}
return this.shell;
},
/**
* Creates a native installation of the web app in the OS
*
* @param aData the manifest data provided by the web app
* @param aData the data provided to the install function
* @param aManifest the manifest data provided by the web app
*
* @returns bool true on success, false if an error was thrown
* @returns true on success, false if an error was thrown
*/
install: function(aData) {
install: function(aData, aManifest) {
try {
if (Services.prefs.getBoolPref("browser.mozApps.installer.dry_run")) {
return true;
}
} catch (ex) {}
#ifdef XP_WIN
let shell = new WinNativeApp(aData);
#elifdef XP_MACOSX
let shell = new MacNativeApp(aData);
#elifdef XP_UNIX
let shell = new LinuxNativeApp(aData);
#else
return false;
#endif
this.shell.init(aData, aManifest);
try {
shell.install();
this.shell.install();
} catch (ex) {
Cu.reportError("Error installing app: " + ex);
return null;
return false;
}
let data = {
"installDir": shell.installDir.path,
"app": aData.app
"installDir": this.shell.installDir.path,
"app": {
"manifest": aManifest,
"origin": aData.app.origin
}
};
Services.obs.notifyObservers(null, "webapp-installed", JSON.stringify(data));
return shell;
return true;
}
}
/**
* This function implements the common constructor for
* the Windows, Mac and Linux native app shells. It reads and parses
* the data from the app manifest and stores it in the NativeApp
* object. It's meant to be called as NativeApp.call(this, aData)
* from the platform-specific constructor.
* the Windows, Mac and Linux native app shells. It sets
* the app unique name. It's meant to be called as
* NativeApp.call(this, aData) from the platform-specific
* constructor.
*
* @param aData the data object provided by the web app with
* all the app settings and specifications.
* @param aData the data object provided to the install function
*
*/
function NativeApp(aData) {
let app = this.app = aData.app;
this.uniqueName = WebappOSUtils.getUniqueName(aData.app);
this.uniqueName = WebappOSUtils.getUniqueName(app);
let jsonManifest = aData.isPackage ? aData.app.updateManifest : aData.app.manifest;
let manifest = new ManifestHelper(jsonManifest, aData.app.origin);
let origin = Services.io.newURI(app.origin, null, null);
let biggestIcon = getBiggestIconURL(app.manifest.icons);
try {
let iconURI = Services.io.newURI(biggestIcon, null, null);
if (iconURI.scheme == "data") {
this.iconURI = iconURI;
}
} catch (ex) {}
if (!this.iconURI) {
try {
this.iconURI = Services.io.newURI(origin.resolve(biggestIcon), null, null);
}
catch (ex) {}
}
this.appName = sanitize(app.manifest.name);
this.appName = sanitize(manifest.name);
this.appNameAsFilename = stripStringForFilename(this.appName);
if(app.manifest.developer && app.manifest.developer.name) {
let devName = app.manifest.developer.name.substr(0, 128);
devName = sanitize(devName);
if (devName) {
this.developerName = devName;
}
}
let shortDesc = this.appName;
if (app.manifest.description) {
let firstLine = app.manifest.description.split("\n")[0];
shortDesc = firstLine.length <= 256
? firstLine
: firstLine.substr(0, 253) + "...";
}
this.shortDescription = sanitize(shortDesc);
// The app registry is the Firefox profile from which the app
// was installed.
this.registryFolder = Services.dirsvc.get("ProfD", Ci.nsIFile);
this.webappJson = {
"registryDir": this.registryFolder.path,
"app": app
};
this.runtimeFolder = Services.dirsvc.get("GreD", Ci.nsIFile);
}
NativeApp.prototype = {
uniqueName: null,
appName: null,
appNameAsFilename: null,
iconURI: null,
developerName: null,
shortDescription: null,
categories: null,
webappJson: null,
runtimeFolder: null,
/**
* This function reads and parses the data from the app
* manifest and stores it in the NativeApp object.
*
* @param aData the data object provided to the install function
* @param aManifest the manifest data provided by the web app
*
*/
init: function(aData, aManifest) {
let manifest = new ManifestHelper(aManifest, aData.app.origin);
let origin = Services.io.newURI(aData.app.origin, null, null);
let biggestIcon = getBiggestIconURL(manifest.icons);
try {
let iconURI = Services.io.newURI(biggestIcon, null, null);
if (iconURI.scheme == "data") {
this.iconURI = iconURI;
}
} catch (ex) {}
if (!this.iconURI) {
try {
this.iconURI = Services.io.newURI(origin.resolve(biggestIcon), null, null);
}
catch (ex) {}
}
if (manifest.developer && manifest.developer.name) {
let devName = sanitize(manifest.developer.name.substr(0, 128));
if (devName) {
this.developerName = devName;
}
}
if (manifest.description) {
let firstLine = manifest.description.split("\n")[0];
let shortDesc = firstLine.length <= 256
? firstLine
: firstLine.substr(0, 253) + "…";
this.shortDescription = sanitize(shortDesc);
} else {
this.shortDescription = this.appName;
}
this.categories = aData.app.categories.slice(0);
// The app registry is the Firefox profile from which the app
// was installed.
let registryFolder = Services.dirsvc.get("ProfD", Ci.nsIFile);
this.webappJson = {
"registryDir": registryFolder.path,
"app": {
"manifest": aManifest,
"origin": aData.app.origin
}
};
this.runtimeFolder = Services.dirsvc.get("GreD", Ci.nsIFile);
}
};
#ifdef XP_WIN
/*************************************
* Windows app installer
@ -151,8 +212,7 @@ function NativeApp(aData) {
/**
* Constructor for the Windows native app shell
*
* @param aData the data object provided by the web app with
* all the app settings and specifications.
* @param aData the data object provided to the install function
*/
function WinNativeApp(aData) {
NativeApp.call(this, aData);
@ -160,21 +220,18 @@ function WinNativeApp(aData) {
}
WinNativeApp.prototype = {
__proto__: NativeApp.prototype,
/**
* Install the app in the system by creating the folder structure,
* Install the app in the system
*
*/
install: function() {
// Remove previously installed app (for update purposes)
this._removeInstallation(true);
try {
this._createDirectoryStructure();
this._copyPrebuiltFiles();
this._createConfigFiles();
this._createShortcutFiles();
this._writeSystemKeys();
this._createAppProfile();
} catch (ex) {
this._removeInstallation(false);
throw(ex);
@ -221,6 +278,11 @@ WinNativeApp.prototype = {
this.iconFile.append("default.ico");
this.uninstallSubkeyStr = this.uniqueName;
// Remove previously installed app (for update purposes)
this._removeInstallation(true);
this._createDirectoryStructure();
},
/**
@ -269,15 +331,17 @@ WinNativeApp.prototype = {
* Creates the main directory structure.
*/
_createDirectoryStructure: function() {
if (!this.installDir.exists())
if (!this.installDir.exists()) {
this.installDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
}
this.uninstallDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
},
/**
* Creates the profile to be used for this app.
*/
_createAppProfile: function() {
createAppProfile: function() {
let profSvc = Cc["@mozilla.org/toolkit/profile-service;1"]
.getService(Ci.nsIToolkitProfileService);
@ -453,6 +517,8 @@ function MacNativeApp(aData) {
}
MacNativeApp.prototype = {
__proto__: NativeApp.prototype,
_init: function() {
this.appSupportDir = Services.dirsvc.get("ULibDir", Ci.nsILocalFile);
this.appSupportDir.append("Application Support");
@ -482,15 +548,17 @@ MacNativeApp.prototype = {
this.iconFile = this.resourcesDir.clone();
this.iconFile.append("appicon.icns");
// Remove previously installed app (for update purposes)
this._removeInstallation(true);
this._createDirectoryStructure();
},
install: function() {
this._removeInstallation(true);
try {
this._createDirectoryStructure();
this._copyPrebuiltFiles();
this._createConfigFiles();
this._createAppProfile();
} catch (ex) {
this._removeInstallation(false);
throw(ex);
@ -510,15 +578,16 @@ MacNativeApp.prototype = {
},
_createDirectoryStructure: function() {
if (!this.appProfileDir.exists())
if (!this.appProfileDir.exists()) {
this.appProfileDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
}
this.contentsDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
this.macOSDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
this.resourcesDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
},
_createAppProfile: function() {
createAppProfile: function() {
let profSvc = Cc["@mozilla.org/toolkit/profile-service;1"]
.getService(Ci.nsIToolkitProfileService);
@ -650,6 +719,8 @@ function LinuxNativeApp(aData) {
}
LinuxNativeApp.prototype = {
__proto__: NativeApp.prototype,
_init: function() {
// The ${InstallDir} and desktop entry filename are: sanitized app name +
// "-" + manifest url hash
@ -685,16 +756,17 @@ LinuxNativeApp.prototype = {
this.desktopINI.append("applications");
this.desktopINI.append("owa-" + this.uniqueName + ".desktop");
// Remove previously installed app (for update purposes)
this._removeInstallation(true);
this._createDirectoryStructure();
},
install: function() {
this._removeInstallation(true);
try {
this._createDirectoryStructure();
this._copyPrebuiltFiles();
this._createConfigFiles();
this._createAppProfile();
} catch (ex) {
this._removeInstallation(false);
throw(ex);
@ -729,7 +801,7 @@ LinuxNativeApp.prototype = {
webapprtPre.copyTo(this.installDir, this.webapprt.leafName);
},
_createAppProfile: function() {
createAppProfile: function() {
let profSvc = Cc["@mozilla.org/toolkit/profile-service;1"]
.getService(Ci.nsIToolkitProfileService);
@ -770,7 +842,7 @@ LinuxNativeApp.prototype = {
// The trailing semicolon is needed as written in the freedesktop specification
let categories = "";
for (let category of this.app.categories) {
for (let category of this.categories) {
let catLower = category.toLowerCase();
if (catLower in translations) {
categories += translations[catLower] + ";";

View File

@ -30,7 +30,7 @@ CommandLineHandler.prototype = {
"chrome,dialog=no",
args);
} else {
args.setProperty("url", WebappRT.launchURI.spec);
args.setProperty("url", WebappRT.launchURI);
Services.ww.openWindow(null,
"chrome://webapprt/content/webapp.xul",
"_blank",

View File

@ -10,17 +10,13 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "FileUtils", function() {
Cu.import("resource://gre/modules/FileUtils.jsm");
return FileUtils;
});
XPCOMUtils.defineLazyGetter(this, "DOMApplicationRegistry", function() {
Cu.import("resource://gre/modules/Webapps.jsm");
return DOMApplicationRegistry;
});
this.WebappRT = {
_config: null,
@ -51,10 +47,8 @@ this.WebappRT = {
},
get launchURI() {
let url = Services.io.newURI(this.config.app.origin, null, null);
if (this.config.app.manifest.launch_path) {
url = Services.io.newURI(this.config.app.manifest.launch_path, null, url);
}
return url;
let manifest = new ManifestHelper(this.config.app.manifest,
this.config.app.origin);
return manifest.fullLaunchPath();
}
};

View File

@ -12,6 +12,7 @@ let Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Webapps.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
Cu.import("resource://gre/modules/WebappsInstaller.jsm");
Cu.import("resource://gre/modules/WebappOSUtils.jsm");
@ -42,7 +43,9 @@ this.WebappsHandler = {
},
doInstall: function(data, window) {
let {name} = data.app.manifest;
let jsonManifest = data.isPackage ? data.app.updateManifest : data.app.manifest;
let manifest = new ManifestHelper(jsonManifest, data.app.origin);
let name = manifest.name;
let bundle = Services.strings.createBundle("chrome://webapprt/locale/webapp.properties");
let choice = Services.prompt.confirmEx(
@ -60,10 +63,24 @@ this.WebappsHandler = {
{});
// Perform the install if the user allows it
if (choice == 0 && WebappsInstaller.install(data)) {
DOMApplicationRegistry.confirmInstall(data);
}
else {
if (choice == 0) {
let shell = WebappsInstaller.init(data);
if (shell) {
let localDir = null;
if (shell.appProfile) {
localDir = shell.appProfile.localDir;
}
DOMApplicationRegistry.confirmInstall(data, false, localDir, null,
function (aManifest) {
WebappsInstaller.install(data, aManifest);
}
);
} else {
DOMApplicationRegistry.denyInstall(data);
}
} else {
DOMApplicationRegistry.denyInstall(data);
}
}

View File

@ -31,7 +31,7 @@ function loadWebapp(manifest, parameters, onLoad) {
onLoad();
}
gAppBrowser.addEventListener("load", onLoadApp, true);
gAppBrowser.setAttribute("src", WebappRT.launchURI.spec);
gAppBrowser.setAttribute("src", WebappRT.launchURI);
});
registerCleanupFunction(function() {