diff --git a/dom/apps/src/AppsUtils.jsm b/dom/apps/src/AppsUtils.jsm index 1a2ee6c277c3..18dc38bc2dd1 100644 --- a/dom/apps/src/AppsUtils.jsm +++ b/dom/apps/src/AppsUtils.jsm @@ -47,7 +47,9 @@ this.AppsUtils = { downloadSize: aApp.downloadSize || 0, lastUpdateCheck: aApp.lastUpdateCheck, updateTime: aApp.updateTime, - etag: aApp.etag + etag: aApp.etag, + installerAppId: aApp.installerAppId || Ci.nsIScriptSecurityManager.NO_APP_ID, + installerIsBrowser: !!aApp.installerIsBrowser }; }, diff --git a/dom/apps/src/Webapps.js b/dom/apps/src/Webapps.js index f7071ffa98a1..cc176a3e8eb0 100644 --- a/dom/apps/src/Webapps.js +++ b/dom/apps/src/Webapps.js @@ -97,6 +97,7 @@ WebappsRegistry.prototype = { Array.isArray(aParams.categories)) ? aParams.categories : []; + let principal = this._window.document.nodePrincipal; cpmm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: this._getOrigin(installURL), @@ -107,7 +108,9 @@ WebappsRegistry.prototype = { }, from: installURL, oid: this._id, - requestID: requestID + requestID: requestID, + appId: principal.appId, + isBrowser: principal.isInBrowserElement }); return request; }, @@ -168,6 +171,7 @@ WebappsRegistry.prototype = { Array.isArray(aParams.categories)) ? aParams.categories : []; + let principal = this._window.document.nodePrincipal; cpmm.sendAsyncMessage("Webapps:InstallPackage", { app: { installOrigin: this._getOrigin(installURL), @@ -179,7 +183,9 @@ WebappsRegistry.prototype = { from: installURL, oid: this._id, requestID: requestID, - isPackage: true + isPackage: true, + appId: principal.appId, + isBrowser: principal.isInBrowserElement }); return request; }, diff --git a/dom/apps/src/Webapps.jsm b/dom/apps/src/Webapps.jsm index 96ad1053025a..0d6f01d4d9ef 100644 --- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -123,6 +123,14 @@ this.DOMApplicationRegistry = { if (this.webapps[id].appStatus === undefined) { this.webapps[id].appStatus = Ci.nsIPrincipal.APP_STATUS_INSTALLED; } + + // Default to NO_APP_ID and not in browser. + if (this.webapps[id].installerAppId === undefined) { + this.webapps[id].installerAppId = Ci.nsIScriptSecurityManager.NO_APP_ID; + } + if (this.webapps[id].installerIsBrowser === undefined) { + this.webapps[id].installerIsBrowser = false; + } }; } aNext(); @@ -1162,6 +1170,8 @@ this.DOMApplicationRegistry = { if (app.etag) { xhr.setRequestHeader("If-None-Match", app.etag); } + xhr.channel.notificationCallbacks = + this.createLoadContext(app.installerAppId, app.installerIsBrowser); xhr.addEventListener("load", (function() { if (xhr.status == 200) { @@ -1205,6 +1215,31 @@ this.DOMApplicationRegistry = { xhr.send(null); }, + // Creates a nsILoadContext object with a given appId and isBrowser flag. + createLoadContext: function createLoadContext(aAppId, aIsBrowser) { + return LoadContextCallback = { + associatedWindow: null, + topWindow : null, + appId: aAppId, + isInBrowserElement: aIsBrowser, + usePrivateBrowsing: false, + isContent: false, + + isAppOfType: function(appType) { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsILoadContext, + Ci.nsIInterfaceRequestor, + Ci.nsISupports]), + getInterface: function(iid) { + if (iid.equals(Ci.nsILoadContext)) + return this; + throw Cr.NS_ERROR_NO_INTERFACE; + } + } + }, + // Downloads the manifest and run checks, then eventually triggers the // installation UI. doInstall: function doInstall(aData, aMm) { @@ -1229,7 +1264,10 @@ this.DOMApplicationRegistry = { .createInstance(Ci.nsIXMLHttpRequest); xhr.open("GET", app.manifestURL, true); xhr.channel.loadFlags |= Ci.nsIRequest.VALIDATE_ALWAYS; + xhr.channel.notificationCallbacks = this.createLoadContext(aData.appId, + aData.isBrowser); xhr.responseType = "json"; + xhr.addEventListener("load", (function() { if (xhr.status == 200) { if (!AppsUtils.checkManifestContentType(app.installOrigin, app.origin, @@ -1281,6 +1319,8 @@ this.DOMApplicationRegistry = { .createInstance(Ci.nsIXMLHttpRequest); xhr.open("GET", app.manifestURL, true); xhr.channel.loadFlags |= Ci.nsIRequest.VALIDATE_ALWAYS; + xhr.channel.notificationCallbacks = this.createLoadContext(aData.appId, + aData.isBrowser); xhr.responseType = "json"; xhr.addEventListener("load", (function() { @@ -1413,6 +1453,9 @@ this.DOMApplicationRegistry = { appObject.name = manifest.name; appObject.csp = manifest.csp || ""; + appObject.installerAppId = aData.appId; + appObject.installerIsBrowser = aData.isBrowser; + this.webapps[id] = appObject; // For package apps, the permissions are not in the mini-manifest, so @@ -1649,7 +1692,8 @@ this.DOMApplicationRegistry = { requestChannel.notificationCallbacks = { QueryInterface: function notifQI(aIID) { if (aIID.equals(Ci.nsISupports) || - aIID.equals(Ci.nsIProgressEventSink)) + aIID.equals(Ci.nsIProgressEventSink) || + aIID.equals(Ci.nsILoadContext)) return this; throw Cr.NS_ERROR_NO_INTERFACE; @@ -1667,7 +1711,18 @@ this.DOMApplicationRegistry = { progress: aProgress, app: app }); }, - onStatus: function notifStatus(aRequest, aContext, aStatus, aStatusArg) { } + onStatus: function notifStatus(aRequest, aContext, aStatus, aStatusArg) { }, + + // nsILoadContext + appId: app.installerAppId, + isInBrowserElement: app.installerIsBrowser, + usePrivateBrowsing: false, + isContent: false, + associatedWindow: null, + topWindow : null, + isAppOfType: function(appType) { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + } } // We set the 'downloading' flag to true right before starting the fetch.