简介¶
概述¶
在 Firefox 中开发浏览器工具时,您需要访问仅在某些层(例如进程或线程)中可用的对象或 API。有一些强大的 API 可用于跨层通信(JSWindowActors、JSProcessActors),但它们通常不能满足浏览器工具开发人员的所有需求。例如,对会话、事件的支持等。
模块¶
MessageHandler 框架建议将您的代码组织成模块,并限制给定模块只能在特定层中运行。借助此功能,框架将在需要的地方实例化模块,并提供简便的方法在跨层模块之间进行通信。目标是消除所有信息路由的复杂性,以便开发人员可以专注于实现其模块的逻辑。
命令和事件¶
该框架还围绕命令和事件进行设计。为 MessageHandler 框架开发的每个模块都应公开命令和/或事件。命令遵循请求/响应模型,在概念上类似于函数调用,其中调用者可能位于与被调用者不同的进程中。事件由模块主动发出,并且可以到达位于其他层中的侦听器。模块的作用是实现处理命令(例如“单击元素”)或生成事件的逻辑。框架的作用是将命令发送到模块,或从模块冒泡事件。命令和事件都用于在模块之间进行内部通信,以及与工具模块的使用者进行外部通信。
“MessageHandler”这个名称来源于其“处理”命令和事件(即“消息”)的作用。
总结¶
总而言之,MessageHandler 框架建议将工具代码编写为模块,这些模块将在各种进程或线程中运行,并使用命令和事件跨层通信。
基本架构¶
MessageHandler 网络¶
为 MessageHandler 框架创建的模块需要在多个进程、线程等中运行。
为了支持这一点,框架将在需要模块访问的各个层中动态创建一个 MessageHandler 实例网络。MessageHandler 类显然以框架命名,但名称恰当,因为其作用主要是路由命令和事件。
除了路由职责外,MessageHandler 类还负责实例化和管理模块。通常,处理命令有两个可能的结果。要么它不是针对此特定层的,在这种情况下,MessageHandler 将分析命令并将其发送到相应的接收方。但如果它确实针对此层,则 MessageHandler 将尝试将命令委托给相应的模块。这意味着如果之前未完成,则实例化模块。因此,MessageHandler 网络的每个节点也包含模块实例。
此网络的根是 RootMessageHandler,并且位于父进程中。对于使用者来说,这也是公开模块命令和事件的唯一入口点。如果您的模块应该位于父进程(即根层)中,它也可以拥有模块实例。
目前我们只支持另一种类型的 MessageHandler,即 WindowGlobalMessageHandler,它将用于 windowglobal 层,并位于内容进程中。
简化的架构示例¶
让我们想象一个非常简单的示例,其中包含几个模块
一个名为“version”的根模块,其命令返回浏览器的当前版本
一个名为“location”的 windowglobal 模块,其命令返回 windowglobal 的位置
假设浏览器有 2 个标签页,在不同的进程中运行。如果使用者使用了“version”模块和“location”模块,但仅用于两个标签页中的一个,则网络将如下所示
parent process content process 1
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
╔═══════════════════════╗ ┌─────────────┐ │
│ ╔═══════════════════════╗ │ │ ║ WindowGlobal ╠──────┤ location │
║ RootMessageHandler ║◀ ─ ─ ─ ─▶║ MessageHandler ║ │ module │ │
│ ╚══════════╦════════════╝ │ │ ╚═══════════════════════╝ └─────────────┘
│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
│ │ │
┌──────┴──────┐ content process 2
│ │ version │ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ module │ │
│ └─────────────┘ │ │
│
│ │ │
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
但如果使用者发送另一个命令来检索另一个标签页的位置,则网络将演变为
parent process content process 1
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
╔═══════════════════════╗ ┌─────────────┐ │
│ ╔═══════════════════════╗ │ │ ║ WindowGlobal ╠──────┤ location │
║ RootMessageHandler ║◀ ─ ┬ ─ ─▶║ MessageHandler ║ │ module │ │
│ ╚══════════╦════════════╝ │ │ ╚═══════════════════════╝ └─────────────┘
│ │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
│ │ │
┌──────┴──────┐ │ content process 2
│ │ version │ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ module │ │ ╔═══════════════════════╗ ┌─────────────┐ │
│ └─────────────┘ │ │ ║ WindowGlobal ╠──────┤ location │
└ ─ ▶ ║ MessageHandler ║ │ module │ │
│ │ │ ╚═══════════════════════╝ └─────────────┘
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
我们在这里已经可以看到,虽然 RootMessageHandler 连接到两个 WindowGlobalMessageHandler(s),但它们彼此之间没有连接。命令和事件在网络上传播的方式存在限制,这将是其他文档页面讨论的主题。