зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1504756 - [marionette] Use waitForMessage() to wait for an expected message manager message. r=ato
Depends on D13660 Differential Revision: https://phabricator.services.mozilla.com/D13661 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
2412720695
Коммит
cc62f45167
|
@ -18,3 +18,5 @@ Provides an assortment of synchronisation primitives.
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. js:autofunction:: waitForEvent
|
.. js:autofunction:: waitForEvent
|
||||||
|
|
||||||
|
.. js:autofunction:: waitForMessage
|
||||||
|
|
|
@ -13,6 +13,7 @@ const {
|
||||||
stack,
|
stack,
|
||||||
TimeoutError,
|
TimeoutError,
|
||||||
} = ChromeUtils.import("chrome://marionette/content/error.js", {});
|
} = ChromeUtils.import("chrome://marionette/content/error.js", {});
|
||||||
|
const {truncate} = ChromeUtils.import("chrome://marionette/content/format.js", {});
|
||||||
const {Log} = ChromeUtils.import("chrome://marionette/content/log.js", {});
|
const {Log} = ChromeUtils.import("chrome://marionette/content/log.js", {});
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "log", Log.get);
|
XPCOMUtils.defineLazyGetter(this, "log", Log.get);
|
||||||
|
@ -26,6 +27,7 @@ this.EXPORTED_SYMBOLS = [
|
||||||
"Sleep",
|
"Sleep",
|
||||||
"TimedPromise",
|
"TimedPromise",
|
||||||
"waitForEvent",
|
"waitForEvent",
|
||||||
|
"waitForMessage",
|
||||||
];
|
];
|
||||||
|
|
||||||
const {TYPE_ONE_SHOT, TYPE_REPEATING_SLACK} = Ci.nsITimer;
|
const {TYPE_ONE_SHOT, TYPE_REPEATING_SLACK} = Ci.nsITimer;
|
||||||
|
@ -464,3 +466,48 @@ function waitForEvent(subject, eventName,
|
||||||
}, capture, wantsUntrusted);
|
}, capture, wantsUntrusted);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for a message to be fired from a particular message manager.
|
||||||
|
*
|
||||||
|
* This method has been duplicated from BrowserTestUtils.jsm.
|
||||||
|
*
|
||||||
|
* @param {nsIMessageManager} messageManager
|
||||||
|
* The message manager that should be used.
|
||||||
|
* @param {string} messageName
|
||||||
|
* The message to wait for.
|
||||||
|
* @param {Object=} options
|
||||||
|
* Extra options.
|
||||||
|
* @param {function(Message)=} options.checkFn
|
||||||
|
* Called with the ``Message`` object as argument, should return ``true``
|
||||||
|
* if the message is the expected one, or ``false`` if it should be
|
||||||
|
* ignored and listening should continue. If not specified, the first
|
||||||
|
* message with the specified name resolves the returned promise.
|
||||||
|
*
|
||||||
|
* @return {Promise.<Object>}
|
||||||
|
* Promise which resolves to the data property of the received
|
||||||
|
* ``Message``.
|
||||||
|
*/
|
||||||
|
function waitForMessage(messageManager, messageName,
|
||||||
|
{checkFn = undefined} = {}) {
|
||||||
|
if (messageManager == null || !("addMessageListener" in messageManager)) {
|
||||||
|
throw new TypeError();
|
||||||
|
}
|
||||||
|
if (typeof messageName != "string") {
|
||||||
|
throw new TypeError();
|
||||||
|
}
|
||||||
|
if (checkFn && typeof checkFn != "function") {
|
||||||
|
throw new TypeError();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
messageManager.addMessageListener(messageName, function onMessage(msg) {
|
||||||
|
log.trace(`Received ${messageName} for ${msg.target}`);
|
||||||
|
if (checkFn && !checkFn(msg)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
messageManager.removeMessageListener(messageName, onMessage);
|
||||||
|
resolve(msg.data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ const {
|
||||||
Sleep,
|
Sleep,
|
||||||
TimedPromise,
|
TimedPromise,
|
||||||
waitForEvent,
|
waitForEvent,
|
||||||
|
waitForMessage,
|
||||||
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
||||||
|
|
||||||
const DEFAULT_TIMEOUT = 2000;
|
const DEFAULT_TIMEOUT = 2000;
|
||||||
|
@ -55,6 +56,36 @@ class MockElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mimic a message manager for sending messages.
|
||||||
|
*/
|
||||||
|
class MessageManager {
|
||||||
|
constructor() {
|
||||||
|
this.func = null;
|
||||||
|
this.message = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
addMessageListener(message, func) {
|
||||||
|
this.func = func;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeMessageListener(message) {
|
||||||
|
this.func = null;
|
||||||
|
this.message = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
send(message, data) {
|
||||||
|
if (this.func) {
|
||||||
|
this.func({
|
||||||
|
data,
|
||||||
|
message,
|
||||||
|
target: this,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mimics nsITimer, but instead of using a system clock you can
|
* Mimics nsITimer, but instead of using a system clock you can
|
||||||
* preprogram it to invoke the callback after a given number of ticks.
|
* preprogram it to invoke the callback after a given number of ticks.
|
||||||
|
@ -353,3 +384,42 @@ add_task(async function test_waitForEvent_wantsUntrustedTypes() {
|
||||||
equal(expected_untrusted, event.untrusted);
|
equal(expected_untrusted, event.untrusted);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_task(async function test_waitForMessage_messageManagerAndMessageTypes() {
|
||||||
|
let messageManager = new MessageManager();
|
||||||
|
|
||||||
|
for (let manager of ["foo", 42, null, undefined, true, [], {}]) {
|
||||||
|
Assert.throws(() => waitForMessage(manager, "message"), /TypeError/);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let message of [42, null, undefined, true, [], {}]) {
|
||||||
|
Assert.throws(() => waitForEvent(messageManager, message), /TypeError/);
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = {"foo": "bar"};
|
||||||
|
let sent = waitForMessage(messageManager, "message");
|
||||||
|
messageManager.send("message", data);
|
||||||
|
equal(data, await sent);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_waitForMessage_checkFnTypes() {
|
||||||
|
let messageManager = new MessageManager();
|
||||||
|
|
||||||
|
for (let checkFn of ["foo", 42, true, [], {}]) {
|
||||||
|
Assert.throws(() => waitForMessage(
|
||||||
|
messageManager, "message", {checkFn}), /TypeError/);
|
||||||
|
}
|
||||||
|
|
||||||
|
let data1 = {"fo": "bar"};
|
||||||
|
let data2 = {"foo": "bar"};
|
||||||
|
|
||||||
|
for (let checkFn of [null, undefined, msg => "foo" in msg.data]) {
|
||||||
|
let expected_data = (checkFn == null) ? data1 : data2;
|
||||||
|
|
||||||
|
messageManager = new MessageManager();
|
||||||
|
let sent = waitForMessage(messageManager, "message", {checkFn});
|
||||||
|
messageManager.send("message", data1);
|
||||||
|
messageManager.send("message", data2);
|
||||||
|
equal(expected_data, await sent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
Загрузка…
Ссылка в новой задаче