Bug 1287007 - Set parent cloneScope to child cloneScope
This is only to help with migration. This change allows all APIs to
behave identical regardless of whether the API is proxied.
Change cloneScope to be a getter because cloneScope is
`this.contentWindow`, which may be nulled when the context navigates away
(but stays in the bfcache).
Any API that is not proxied must have an identical clone scope to make
sure that properties such as toJSON (in the native messaging
stringifier) and ArrayBuffer (in webRequest as requestBody) are visible
to the caller.
MozReview-Commit-ID: 9aT3SUBieHK
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -322,21 +322,16 @@ class ProxyContext extends BaseContext {
class ExtensionChildProxyContext extends ProxyContext {
constructor(envType, extension, params, xulBrowser) {
super(envType, extension, params, xulBrowser, extension.principal);
this.viewType = params.viewType;
// WARNING: The xulBrowser may change when docShells are swapped, e.g. when
// the tab moves to a different window.
this.xulBrowser = xulBrowser;
-
- // TODO(robwu): Remove this once all APIs can run in a separate process.
- if (params.cloneScopeInProcess) {
- this.sandbox = params.cloneScopeInProcess;
- }
}
// The window that contains this context. This may change due to moving tabs.
get xulWindow() {
return this.xulBrowser.ownerGlobal;
}
get windowId() {
--- a/toolkit/components/extensions/ExtensionChild.jsm
+++ b/toolkit/components/extensions/ExtensionChild.jsm
@@ -78,26 +78,36 @@ var apiManager = new class extends Schem
class WannabeChildAPIManager extends ChildAPIManager {
createProxyContextInConstructor(data) {
// Create a structured clone to simulate IPC.
data = Object.assign({}, data);
let {principal} = data; // Not structurally cloneable.
delete data.principal;
data = Cu.cloneInto(data, {});
data.principal = principal;
- data.cloneScopeInProcess = this.context.cloneScope;
let name = "API:CreateProxyContext";
// The <browser> that receives messages from `this.messageManager`.
let target = this.context.contentWindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.chromeEventHandler;
ParentAPIManager.receiveMessage({name, data, target});
let proxyContext = ParentAPIManager.proxyContexts.get(this.id);
+
+ // Use an identical cloneScope in the parent as the child to have identical
+ // behavior for proxied vs direct calls. If all APIs are proxied, then the
+ // parent cloneScope does not really matter (because when the message
+ // arrives locally, the object is cloned into the local clone scope).
+ // If all calls are direct, then the parent cloneScope does matter, because
+ // the objects are not cloned again.
+ Object.defineProperty(proxyContext, "cloneScope", {
+ get: () => this.cloneScope,
+ });
+
// Many APIs rely on this, so temporarily add it to keep the commit small.
proxyContext.setContentWindow(this.context.contentWindow);
// Synchronously unload the ProxyContext because we synchronously create it.
this.context.callOnClose({close: proxyContext.unload.bind(proxyContext)});
}
getFallbackImplementation(namespace, name) {