author | Bill McCloskey <wmccloskey@mozilla.com> |
Mon, 14 Jul 2014 22:10:06 -0700 | |
changeset 214777 | 1e14af130411bc004e94f2208ba129e38c33946f |
parent 214776 | 8723969ebaec6f57c1ff0d74effbcb40c0b2111d |
child 214778 | 5bbb653cac5750830939cbd0d4fecab012d19f97 |
push id | 3857 |
push user | raliiev@mozilla.com |
push date | Tue, 02 Sep 2014 16:39:23 +0000 |
treeherder | mozilla-beta@5638b907b505 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mconley |
bugs | 1031609 |
milestone | 33.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/toolkit/components/addoncompat/RemoteAddonsChild.jsm +++ b/toolkit/components/addoncompat/RemoteAddonsChild.jsm @@ -202,12 +202,14 @@ EventTargetChild.prototype = { this._childGlobal.sendRpcMessage("Addons:Event:Run", {type: event.type, isTrusted: event.isTrusted}, {event: event}); } }; let RemoteAddonsChild = { init: function(global) { + global.sendAsyncMessage("Addons:RegisterGlobal", {}, {global: global}); + // Return this so it gets rooted in the content script. return [new EventTargetChild(global)]; }, };
--- a/toolkit/components/addoncompat/RemoteAddonsParent.jsm +++ b/toolkit/components/addoncompat/RemoteAddonsParent.jsm @@ -399,18 +399,53 @@ EventTargetInterposition.methods.addEven }; EventTargetInterposition.methods.removeEventListener = function(addon, target, type, listener, useCapture) { EventTargetParent.removeEventListener(target, type, listener, useCapture); target.removeEventListener(type, listener, useCapture); }; +// This interposition intercepts accesses to |rootTreeItem| on a child +// process docshell. In the child, each docshell is its own +// root. However, add-ons expect the root to be the chrome docshell, +// so we make that happen here. +let ContentDocShellTreeItemInterposition = new Interposition(); + +ContentDocShellTreeItemInterposition.getters.rootTreeItem = + function(addon, target) { + // The chrome global in the child. + let chromeGlobal = target.rootTreeItem + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIContentFrameMessageManager); + + // Map it to a <browser> element and window. + let browser = RemoteAddonsParent.globalToBrowser.get(chromeGlobal); + if (!browser) { + // Somehow we have a CPOW from the child, but it hasn't sent us + // its global yet. That shouldn't happen, but return null just + // in case. + return null; + } + + let chromeWin = browser.ownerDocument.defaultView; + + // Return that window's docshell. + return chromeWin.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShellTreeItem); + }; + let RemoteAddonsParent = { init: function() { + let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager); + mm.addMessageListener("Addons:RegisterGlobal", this); + + this.globalToBrowser = new WeakMap(); + this.browserToGlobal = new WeakMap(); }, getInterfaceInterpositions: function() { let result = {}; function register(intf, interp) { result[intf.number] = interp; } @@ -424,12 +459,22 @@ let RemoteAddonsParent = { getTaggedInterpositions: function() { let result = {}; function register(tag, interp) { result[tag] = interp; } register("EventTarget", EventTargetInterposition); + register("ContentDocShellTreeItem", ContentDocShellTreeItemInterposition); return result; }, + + receiveMessage: function(msg) { + switch (msg.name) { + case "Addons:RegisterGlobal": + this.browserToGlobal.set(msg.target, msg.objects.global); + this.globalToBrowser.set(msg.objects.global, msg.target); + break; + } + } };