简单示例¶
作为教程,让我们创建一个非常简单的示例,包含几个模块
一个根(父进程)模块来检索浏览器的当前版本
一个 windowglobal(内容进程)模块来检索给定标签页的位置
这里使用的一些概念不会详细解释。后续应该会有更多文档来澄清这些。
在本示例中,我们不会使用事件,只使用命令。
创建根 version
模块¶
首先让我们创建根模块。
import { Module } from "chrome://remote/content/shared/messagehandler/Module.sys.mjs";
class VersionModule extends Module {
destroy() {}
getVersion() {
return Services.appinfo.platformVersion;
}
}
export const version = VersionModule;
所有模块都应该扩展 Module.sys.mjs 并且必须定义一个 destroy 方法。Module 类的每个公共方法都将作为此模块的命令公开。用于导出模块类的名称将是模块的公共名称,用于在其上调用命令。
创建 windowglobal location
模块¶
让我们创建第二个模块。
import { Module } from "chrome://remote/content/shared/messagehandler/Module.sys.mjs";
class LocationModule extends Module {
#window;
constructor(messageHandler) {
super(messageHandler);
// LocationModule will be a windowglobal module, so `messageHandler` will
// be a WindowGlobalMessageHandler which comes with a few helpful getters
// such as a `window` getter.
this.#window = messageHandler.window;
}
destroy() {
this.#window = null;
}
getLocation() {
return this.#window.location.href;
}
}
export const location = LocationModule;
我们可以简化模块,只需编写 getLocation
来返回 this.messageHandler.window.location.href
,但这给了我们一个机会来了解模块构造函数。
将模块注册为 Firefox 模块¶
在我们将这些模块注册到 MessageHandler 框架之前,我们需要先将它们注册为 Firefox 模块。为简单起见,我们可以假设它们添加到一个新的文件夹 remote/example
下
remote/example/modules/root/version.sys.mjs
remote/example/modules/windowglobal/location.sys.mjs
在 jar.mn 中注册它们,以便它们可以像任何其他 Firefox 模块一样加载。
这些路径仅包含相应的层(root、windowglobal)以提高清晰度。我们不依赖于此作为命名约定来实际加载模块,因此您可以决定以不同的方式组织文件夹。但是,用于导出模块类的名称(例如 location
)将是模块的正式名称,用于命令和事件,因此请注意并使用正确的导出名称。
定义 ModuleRegistry¶
但是,我们需要指示框架在何处加载每个模块。
这是通过 ModuleRegistry 完成的。在不深入细节的情况下,每个打算与 MessageHandler 框架一起使用的“模块集”都需要提供一个 ModuleRegistry 模块,该模块导出单个 getModuleClass
帮助程序。框架将调用此方法以了解哪些模块可用。现在,让我们在 remote/example/modules/root/ModuleRegistry.sys.mjs
下为我们定义最简单的注册表。
export const getModuleClass = function(moduleName, moduleFolder) {
if (moduleName === "version" && moduleFolder === "root") {
return ChromeUtils.importESModule(
"chrome://remote/content/example/modules/root/version.sys.mjs"
).version;
}
if (moduleName === "location" && moduleFolder === "windowglobal") {
return ChromeUtils.importESModule(
"chrome://remote/content/example/modules/windowglobal/location.sys.mjs"
).location;
}
return null;
};
请注意,这可以通过定义一些命名约定或模式来改进,但目前每个模块集都可以根据需要自由实现此逻辑。
也将此模块添加到 jar.mn 中,以便它成为有效的 Firefox 模块。
使用自定义 ModuleRegistry 的临时解决方法¶
这样,我们就有一组几乎可以使用的模块了。除了目前 MessageHandler 硬编码为仅使用 WebDriver BiDi 模块之外。一旦 Bug 1722464 修复,我们将能够指定其他协议,但目前,指示 MessageHandler 框架使用非 bidi 模块的唯一方法是更新 以下行 以指向 remote/example/modules/ModuleRegistry.sys.mjs
。
现在有了这个,您应该能够创建一个 MessageHandler 网络并使用您的模块。
试一试¶
例如,您可以打开浏览器控制台并运行以下代码段
(async function() {
const { RootMessageHandlerRegistry } = ChromeUtils.importESModule(
"chrome://remote/content/shared/messagehandler/RootMessageHandlerRegistry.sys.mjs"
);
const messageHandler = RootMessageHandlerRegistry.getOrCreateMessageHandler("test-session");
const version = await messageHandler.handleCommand({
moduleName: "version",
commandName: "getVersion",
params: {},
destination: {
type: "ROOT",
},
});
console.log({ version });
const location = await messageHandler.handleCommand({
moduleName: "location",
commandName: "getLocation",
params: {},
destination: {
type: "WINDOW_GLOBAL",
id: gBrowser.selectedBrowser.browsingContext.id,
},
});
console.log({ location });
})();
这应该打印一个版本号 { version: "109.0a1" }
和一个位置 { location: "https://www.mozilla.org/en-US/" }
(您的实际值当然应该有所不同)。
我们有意跳过对传递给 handleCommand
的各种参数以及 RootMessageHandlerRegistry
的详细解释,但这应该已经让您对如何开始创建模块并使用它们有所了解。