Commit e7fd10bd authored by Kris Maglione's avatar Kris Maglione
Browse files

Bug 1585776 - Fix XPInstall content handler under Fission. r=nika

The XPInstall content handlers currently make all sorts of assumptions about
the process they're being run in and the docShell their request is tied to.
These assumptions don't hold under Fission, either now, when they may be
called just after a process switch, or in the future, when they'll be called
in the parent process.

This patch updates them to operate on the BrowsingContext of the request, and
to do their messaging via the process message manager, rather than via frame
message managers. As a bonus, it also removes the existing hacks they had in
place to handle the cases where frame message managers didn't work.

Differential Revision: https://phabricator.services.mozilla.com/D48224

--HG--
extra : moz-landing-system : lando
parent 693696fb
...@@ -40,7 +40,6 @@ skip-if = (verify && debug && (os == 'mac')) ...@@ -40,7 +40,6 @@ skip-if = (verify && debug && (os == 'mac'))
[browser_policy_extensions.js] [browser_policy_extensions.js]
[browser_policy_downloads.js] [browser_policy_downloads.js]
[browser_policy_extensionsettings.js] [browser_policy_extensionsettings.js]
skip-if = fission
[browser_policy_firefoxhome.js] [browser_policy_firefoxhome.js]
[browser_policy_override_postupdatepage.js] [browser_policy_override_postupdatepage.js]
[browser_policy_passwordmanager.js] [browser_policy_passwordmanager.js]
......
...@@ -2333,7 +2333,18 @@ var AddonManagerInternal = { ...@@ -2333,7 +2333,18 @@ var AddonManagerInternal = {
} else if ( } else if (
aInstallingPrincipal.isNullPrincipal || aInstallingPrincipal.isNullPrincipal ||
!aBrowser.contentPrincipal || !aBrowser.contentPrincipal ||
!aInstallingPrincipal.subsumes(aBrowser.contentPrincipal) || // When we attempt to handle an XPI load immediately after a
// process switch, the DocShell it's being loaded into will have
// a null principal, since it won't have been initialized yet.
// Allowing installs in this case is relatively safe, since
// there isn't much to gain by spoofing an install request from
// a null principal in any case. This exception can be removed
// once content handlers are triggered by DocumentChannel in the
// parent process.
!(
aBrowser.contentPrincipal.isNullPrincipal ||
aInstallingPrincipal.subsumes(aBrowser.contentPrincipal)
) ||
!this.isInstallAllowedByPolicy( !this.isInstallAllowedByPolicy(
aInstallingPrincipal, aInstallingPrincipal,
aInstall, aInstall,
......
...@@ -65,11 +65,12 @@ function amManager() { ...@@ -65,11 +65,12 @@ function amManager() {
Services.mm.loadFrameScript(CHILD_SCRIPT, true, true); Services.mm.loadFrameScript(CHILD_SCRIPT, true, true);
Services.mm.addMessageListener(MSG_INSTALL_ENABLED, this); Services.mm.addMessageListener(MSG_INSTALL_ENABLED, this);
Services.mm.addMessageListener(MSG_INSTALL_ADDON, this);
Services.mm.addMessageListener(MSG_PROMISE_REQUEST, this); Services.mm.addMessageListener(MSG_PROMISE_REQUEST, this);
Services.mm.addMessageListener(MSG_INSTALL_CLEANUP, this); Services.mm.addMessageListener(MSG_INSTALL_CLEANUP, this);
Services.mm.addMessageListener(MSG_ADDON_EVENT_REQ, this); Services.mm.addMessageListener(MSG_ADDON_EVENT_REQ, this);
Services.ppmm.addMessageListener(MSG_INSTALL_ADDON, this);
Services.obs.addObserver(this, "message-manager-close"); Services.obs.addObserver(this, "message-manager-close");
Services.obs.addObserver(this, "message-manager-disconnect"); Services.obs.addObserver(this, "message-manager-disconnect");
...@@ -219,9 +220,11 @@ amManager.prototype = { ...@@ -219,9 +220,11 @@ amManager.prototype = {
return AddonManager.isInstallEnabled(payload.mimetype); return AddonManager.isInstallEnabled(payload.mimetype);
case MSG_INSTALL_ADDON: { case MSG_INSTALL_ADDON: {
let browser = payload.browsingContext.top.embedderElement;
let callback = null; let callback = null;
if (payload.callbackID != -1) { if (payload.callbackID != -1) {
let mm = aMessage.target.messageManager; let mm = browser.messageManager;
callback = { callback = {
onInstallEnded(url, status) { onInstallEnded(url, status) {
mm.sendAsyncMessage(MSG_INSTALL_CALLBACK, { mm.sendAsyncMessage(MSG_INSTALL_CALLBACK, {
...@@ -233,7 +236,7 @@ amManager.prototype = { ...@@ -233,7 +236,7 @@ amManager.prototype = {
}; };
} }
return this.installAddonFromWebpage(payload, aMessage.target, callback); return this.installAddonFromWebpage(payload, browser, callback);
} }
case MSG_PROMISE_REQUEST: { case MSG_PROMISE_REQUEST: {
......
...@@ -33,20 +33,14 @@ amContentHandler.prototype = { ...@@ -33,20 +33,14 @@ amContentHandler.prototype = {
let uri = aRequest.URI; let uri = aRequest.URI;
let window = null;
let callbacks = aRequest.notificationCallbacks
? aRequest.notificationCallbacks
: aRequest.loadGroup.notificationCallbacks;
if (callbacks) {
window = callbacks.getInterface(Ci.nsIDOMWindow);
}
aRequest.cancel(Cr.NS_BINDING_ABORTED); aRequest.cancel(Cr.NS_BINDING_ABORTED);
const { triggeringPrincipal } = aRequest.loadInfo; let { loadInfo } = aRequest;
const { triggeringPrincipal } = loadInfo;
let browsingContext =
loadInfo.frameBrowsingContext || loadInfo.browsingContext;
let sourceHost; let sourceHost;
try { try {
sourceHost = triggeringPrincipal.URI.host; sourceHost = triggeringPrincipal.URI.host;
} catch (err) { } catch (err) {
...@@ -64,35 +58,10 @@ amContentHandler.prototype = { ...@@ -64,35 +58,10 @@ amContentHandler.prototype = {
callbackID: -1, callbackID: -1,
method: "link", method: "link",
sourceHost, sourceHost,
browsingContext,
}; };
if (Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { Services.cpmm.sendAsyncMessage(MSG_INSTALL_ADDON, install);
// When running in the main process this might be a frame inside an
// in-content UI page, walk up to find the first frame element in a chrome
// privileged document
let element = window.frameElement;
while (
element &&
!element.ownerDocument.nodePrincipal.isSystemPrincipal
) {
element = element.ownerGlobal.frameElement;
}
if (element) {
let listener = Cc["@mozilla.org/addons/integration;1"].getService();
listener.wrappedJSObject.receiveMessage({
name: MSG_INSTALL_ADDON,
target: element,
data: install,
});
return;
}
}
// Fall back to sending through the message manager
let messageManager = window.docShell.messageManager;
messageManager.sendAsyncMessage(MSG_INSTALL_ADDON, install);
}, },
classID: Components.ID("{7beb3ba8-6ec3-41b4-b67c-da89b8518922}"), classID: Components.ID("{7beb3ba8-6ec3-41b4-b67c-da89b8518922}"),
......
...@@ -71,33 +71,9 @@ RemoteMediator.prototype = { ...@@ -71,33 +71,9 @@ RemoteMediator.prototype = {
install.mimetype = XPINSTALL_MIMETYPE; install.mimetype = XPINSTALL_MIMETYPE;
install.triggeringPrincipal = principal; install.triggeringPrincipal = principal;
install.callbackID = callbackID; install.callbackID = callbackID;
install.browsingContext = BrowsingContext.getFromWindow(window);
if (Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { return Services.cpmm.sendSyncMessage(MSG_INSTALL_ADDON, install)[0];
// When running in the main process this might be a frame inside an
// in-content UI page, walk up to find the first frame element in a chrome
// privileged document
let element = window.frameElement;
while (
element &&
!element.ownerDocument.nodePrincipal.isSystemPrincipal
) {
element = element.ownerGlobal.frameElement;
}
if (element) {
let listener = Cc["@mozilla.org/addons/integration;1"].getService();
return listener.wrappedJSObject.receiveMessage({
name: MSG_INSTALL_ADDON,
target: element,
data: install,
});
}
}
// Fall back to sending through the message manager
let messageManager = window.docShell.messageManager;
return messageManager.sendSyncMessage(MSG_INSTALL_ADDON, install)[0];
}, },
_addCallback(callback) { _addCallback(callback) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment