107 lines
3.1 KiB
JavaScript
107 lines
3.1 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
/* eslint-disable mozilla/valid-lazy */
|
|
|
|
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
|
|
|
const lazy = XPCOMUtils.declareLazy({
|
|
actorMatches: {
|
|
pref: "extensions.wpt.matches",
|
|
default: "*://web-platform.test/*",
|
|
},
|
|
});
|
|
|
|
// Map events with positional params to WPT messages with named properties.
|
|
const EVENTS = {
|
|
"test-task-start": "test-started testName",
|
|
"test-task-done": "test-finished remainingTests",
|
|
"test-eq": "assert-equality result message expectedValue actualValue",
|
|
"test-result": "assert result message",
|
|
};
|
|
|
|
// Routes extension test results to web-platform.test child actors.
|
|
export class WPTMessagesParent extends JSWindowActorParent {
|
|
static init(apiManager) {
|
|
this.apiManager = apiManager;
|
|
apiManager.on("startup", this.#onStartup);
|
|
apiManager.on("shutdown", this.#onShutdown);
|
|
|
|
ChromeUtils.registerWindowActor("WPTMessages", {
|
|
matches: lazy.actorMatches.split(","),
|
|
allFrames: true,
|
|
child: {
|
|
esModuleURI: "resource://gre/modules/WPTMessagesChild.sys.mjs",
|
|
observers: ["content-document-global-created"],
|
|
},
|
|
parent: {
|
|
esModuleURI: "resource://gre/modules/WPTMessagesParent.sys.mjs",
|
|
},
|
|
});
|
|
}
|
|
|
|
static unload() {
|
|
this.apiManager.off("startup", this.#onStartup);
|
|
this.apiManager.off("shutdown", this.#onShutdown);
|
|
ChromeUtils.unregisterWindowActor("WPTMessages");
|
|
}
|
|
|
|
receiveMessage({ name }) {
|
|
switch (name) {
|
|
case "onMessage.addListener":
|
|
WPTMessagesParent.#setListener(this);
|
|
break;
|
|
case "onMessage.removeListener":
|
|
WPTMessagesParent.#removeListener(this);
|
|
break;
|
|
}
|
|
}
|
|
|
|
didDestroy() {
|
|
WPTMessagesParent.#removeListener(this);
|
|
}
|
|
|
|
static #setListener(actor) {
|
|
// The latest actor to subscribe becomes the only listener.
|
|
this.#listener = actor;
|
|
this.#queue.forEach(args => this.#emit(...args));
|
|
this.#queue.length = 0;
|
|
}
|
|
|
|
static #removeListener(actor) {
|
|
// Only clear the listener if the next one hasn't already subscribed.
|
|
if (this.#listener === actor) {
|
|
this.#listener = null;
|
|
}
|
|
}
|
|
|
|
static #onStartup(_, ext) {
|
|
for (let ev of Object.keys(EVENTS)) {
|
|
ext.on(ev, WPTMessagesParent.#onEvent);
|
|
}
|
|
}
|
|
|
|
static #onShutdown(_, ext) {
|
|
for (let ev of Object.keys(EVENTS)) {
|
|
ext.off(ev, WPTMessagesParent.#onEvent);
|
|
}
|
|
}
|
|
|
|
static #onEvent(event, ...args) {
|
|
let [ev, ...keys] = EVENTS[event].split(" ");
|
|
let data = keys.map((key, i) => [key, args[i]]);
|
|
WPTMessagesParent.#emit(ev, Object.fromEntries(data));
|
|
}
|
|
|
|
static #emit(event, data) {
|
|
if (this.#listener) {
|
|
return this.#listener.sendAsyncMessage(event, data);
|
|
}
|
|
// Queue messages sent while we don't have a listener.
|
|
this.#queue.push([event, data]);
|
|
}
|
|
|
|
// One listener at a time for reliable queing.
|
|
static #listener = null;
|
|
static #queue = [];
|
|
}
|