зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1316396: Part 5 - Move MessageManagerProxy to ExtensionUtils, and add support for proxied listeners. r=aswan
MozReview-Commit-ID: KhinS46k0yW --HG-- extra : rebase_source : f7a165c5653f729b6cb987d9545d1af6c76ebbfc
This commit is contained in:
Родитель
e801f7eaa2
Коммит
1a0bcdb88b
|
@ -998,6 +998,175 @@ function findPathInObject(obj, path, printErrors = true) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Acts as a proxy for a message manager or message manager owner, and
|
||||
* tracks docShell swaps so that messages are always sent to the same
|
||||
* receiver, even if it is moved to a different <browser>.
|
||||
*
|
||||
* @param {nsIMessageSender|Element} target
|
||||
* The target message manager on which to send messages, or the
|
||||
* <browser> element which owns it.
|
||||
*/
|
||||
class MessageManagerProxy {
|
||||
constructor(target) {
|
||||
this.listeners = new DefaultMap(() => new Map());
|
||||
|
||||
if (target instanceof Ci.nsIMessageSender) {
|
||||
Object.defineProperty(this, "messageManager", {
|
||||
value: target,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
});
|
||||
} else {
|
||||
this.addListeners(target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes of the proxy object, removes event listeners, and drops
|
||||
* all references to the underlying message manager.
|
||||
*
|
||||
* Must be called before the last reference to the proxy is dropped,
|
||||
* unless the underlying message manager or <browser> is also being
|
||||
* destroyed.
|
||||
*/
|
||||
dispose() {
|
||||
if (this.eventTarget) {
|
||||
this.removeListeners(this.eventTarget);
|
||||
this.eventTarget = null;
|
||||
} else {
|
||||
this.messageManager = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given target is the same as, or owns, the given
|
||||
* message manager.
|
||||
*
|
||||
* @param {nsIMessageSender|MessageManagerProxy|Element} target
|
||||
* The message manager, MessageManagerProxy, or <browser>
|
||||
* element agaisnt which to match.
|
||||
* @param {nsIMessageSender} messageManager
|
||||
* The message manager against which to match `target`.
|
||||
*
|
||||
* @returns {boolean}
|
||||
* True if `messageManager` is the same object as `target`, or
|
||||
* `target` is a MessageManagerProxy or <browser> element that
|
||||
* is tied to it.
|
||||
*/
|
||||
static matches(target, messageManager) {
|
||||
return target === messageManager || target.messageManager === messageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @property {nsIMessageSender|null} messageManager
|
||||
* The message manager that is currently being proxied. This
|
||||
* may change during the life of the proxy object, so should
|
||||
* not be stored elsewhere.
|
||||
*/
|
||||
get messageManager() {
|
||||
return this.eventTarget && this.eventTarget.messageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message on the proxied message manager.
|
||||
*
|
||||
* @param {array} args
|
||||
* Arguments to be passed verbatim to the underlying
|
||||
* sendAsyncMessage method.
|
||||
* @returns {undefined}
|
||||
*/
|
||||
sendAsyncMessage(...args) {
|
||||
return this.messageManager.sendAsyncMessage(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a message listener to the current message manager, and
|
||||
* transfers it to the new message manager after a docShell swap.
|
||||
*
|
||||
* @param {string} message
|
||||
* The name of the message to listen for.
|
||||
* @param {nsIMessageListener} listener
|
||||
* The listener to add.
|
||||
* @param {boolean} [listenWhenClosed = false]
|
||||
* If true, the listener will receive messages which were sent
|
||||
* after the remote side of the listener began closing.
|
||||
*/
|
||||
addMessageListener(message, listener, listenWhenClosed = false) {
|
||||
this.messageManager.addMessageListener(message, listener, listenWhenClosed);
|
||||
this.listeners.get(message).set(listener, listenWhenClosed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a message listener from the current message manager.
|
||||
*
|
||||
* @param {string} message
|
||||
* The name of the message to stop listening for.
|
||||
* @param {nsIMessageListener} listener
|
||||
* The listener to remove.
|
||||
*/
|
||||
removeMessageListener(message, listener) {
|
||||
this.messageManager.removeMessageListener(message, listener);
|
||||
|
||||
let listeners = this.listeners.get(message);
|
||||
listeners.delete(listener);
|
||||
if (!listeners.size) {
|
||||
this.listeners.delete(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Iterates over all of the currently registered message listeners.
|
||||
*/
|
||||
* iterListeners() {
|
||||
for (let [message, listeners] of this.listeners) {
|
||||
for (let [listener, listenWhenClosed] of listeners) {
|
||||
yield {message, listener, listenWhenClosed};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Adds docShell swap listeners to the message manager owner.
|
||||
*
|
||||
* @param {Element} target
|
||||
* The target element.
|
||||
*/
|
||||
addListeners(target) {
|
||||
target.addEventListener("SwapDocShells", this);
|
||||
|
||||
for (let {message, listener, listenWhenClosed} of this.iterListeners()) {
|
||||
target.addMessageListener(message, listener, listenWhenClosed);
|
||||
}
|
||||
|
||||
this.eventTarget = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Removes docShell swap listeners to the message manager owner.
|
||||
*
|
||||
* @param {Element} target
|
||||
* The target element.
|
||||
*/
|
||||
removeListeners(target) {
|
||||
target.removeEventListener("SwapDocShells", this);
|
||||
|
||||
for (let {message, listener} of this.iterListeners()) {
|
||||
target.removeMessageListener(message, listener);
|
||||
}
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
if (event.type == "SwapDocShells") {
|
||||
this.removeListeners(this.eventTarget);
|
||||
this.addListeners(event.detail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.ExtensionUtils = {
|
||||
defineLazyGetter,
|
||||
detectLanguage,
|
||||
|
@ -1027,6 +1196,7 @@ this.ExtensionUtils = {
|
|||
ExtensionError,
|
||||
IconDetails,
|
||||
LocaleData,
|
||||
MessageManagerProxy,
|
||||
PlatformInfo,
|
||||
SingletonEventManager,
|
||||
SpreadArgs,
|
||||
|
|
|
@ -108,123 +108,15 @@ const Cr = Components.results;
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionUtils",
|
||||
"resource://gre/modules/ExtensionUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
|
||||
"resource://gre/modules/PromiseUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
/**
|
||||
* Acts as a proxy for a message manager or message manager owner, and
|
||||
* tracks docShell swaps so that messages are always sent to the same
|
||||
* receiver, even if it is moved to a different <browser>.
|
||||
*
|
||||
* Currently only proxies message sending functions, and does not handle
|
||||
* transfering listeners in any way.
|
||||
*
|
||||
* @param {nsIMessageSender|Element} target
|
||||
* The target message manager on which to send messages, or the
|
||||
* <browser> element which owns it.
|
||||
*/
|
||||
class MessageManagerProxy {
|
||||
constructor(target) {
|
||||
if (target instanceof Ci.nsIMessageSender) {
|
||||
Object.defineProperty(this, "messageManager", {
|
||||
value: target,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
});
|
||||
} else {
|
||||
this.addListeners(target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes of the proxy object, removes event listeners, and drops
|
||||
* all references to the underlying message manager.
|
||||
*
|
||||
* Must be called before the last reference to the proxy is dropped,
|
||||
* unless the underlying message manager or <browser> is also being
|
||||
* destroyed.
|
||||
*/
|
||||
dispose() {
|
||||
if (this.eventTarget) {
|
||||
this.removeListeners(this.eventTarget);
|
||||
this.eventTarget = null;
|
||||
} else {
|
||||
this.messageManager = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given target is the same as, or owns, the given
|
||||
* message manager.
|
||||
*
|
||||
* @param {nsIMessageSender|MessageManagerProxy|Element} target
|
||||
* The message manager, MessageManagerProxy, or <browser>
|
||||
* element agaisnt which to match.
|
||||
* @param {nsIMessageSender} messageManager
|
||||
* The message manager against which to match `target`.
|
||||
*
|
||||
* @returns {boolean}
|
||||
* True if `messageManager` is the same object as `target`, or
|
||||
* `target` is a MessageManagerProxy or <browser> element that
|
||||
* is tied to it.
|
||||
*/
|
||||
static matches(target, messageManager) {
|
||||
return target === messageManager || target.messageManager === messageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @property {nsIMessageSender|null} messageManager
|
||||
* The message manager that is currently being proxied. This
|
||||
* may change during the life of the proxy object, so should
|
||||
* not be stored elsewhere.
|
||||
*/
|
||||
get messageManager() {
|
||||
return this.eventTarget && this.eventTarget.messageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message on the proxied message manager.
|
||||
*
|
||||
* @param {array} args
|
||||
* Arguments to be passed verbatim to the underlying
|
||||
* sendAsyncMessage method.
|
||||
* @returns {undefined}
|
||||
*/
|
||||
sendAsyncMessage(...args) {
|
||||
return this.messageManager.sendAsyncMessage(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Adds docShell swap listeners to the message manager owner.
|
||||
*
|
||||
* @param {Element} target
|
||||
* The target element.
|
||||
*/
|
||||
addListeners(target) {
|
||||
target.addEventListener("SwapDocShells", this);
|
||||
this.eventTarget = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Removes docShell swap listeners to the message manager owner.
|
||||
*
|
||||
* @param {Element} target
|
||||
* The target element.
|
||||
*/
|
||||
removeListeners(target) {
|
||||
target.removeEventListener("SwapDocShells", this);
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
if (event.type == "SwapDocShells") {
|
||||
this.removeListeners(this.eventTarget);
|
||||
this.addListeners(event.detail);
|
||||
}
|
||||
}
|
||||
}
|
||||
XPCOMUtils.defineLazyGetter(this, "MessageManagerProxy",
|
||||
() => ExtensionUtils.MessageManagerProxy);
|
||||
|
||||
/**
|
||||
* Handles the mapping and dispatching of messages to their registered
|
||||
|
|
Загрузка…
Ссылка в новой задаче