这篇翻译不完整。请帮忙从英语翻译这篇文章。
在多进程 Firefox 中有两个进程:
- chrome 进程,也称父进程,运行着浏览器 UI 界面 (chrome) 的代码和扩展安装的代码。
- 内容进程,也称子进程,运行着所有网页内容。在未来的 Firefox 版本中,不同的标签页可能运行在不同的进程中,但截至目前,所有内容标签页共享使用同一个内容进程。
消息管理器的设计目的是使运行在一个进程中的 chrome 特权的 JavaScript 代码能够与不同进程中的 chrome 特权的 JavaScript 代码通信。
本文介绍了几种类型的消息管理器,如何访问它们,以及在一个较高层面你可以使用什么。
在顶层,有两种不同类型的消息管理器:
- 框架消息管理器:这些使 chrome 进程的代码能够加载脚本到内容进程中的浏览器框架(基本上,就是指一个浏览器标签页)。这些脚本被称为框架脚本,顾名思义,它们限定在特定的浏览器框架中。如果 chrome 代码想要在内容进程中运行可以方便访问网页内容的代码,通常就是使用消息管理器的时候了。
- 进程消息管理器:这些对应着进程边界,使运行在父 (chrome) 进程中的代码能够与子 (内容) 进程中的代码通信。从 Firefox 38 起,这也使运行在父进程中的代码能够加载进程脚本到子进程。这些类似框架脚本,除了它们是全局访问子进程。进程脚本最有用的时候是进程想要只在内容进程中运行某些代码,来访问某些全局服务:例如,注册一个 observer 或者一个 内容策略。
框架消息管理器
在多进程 Firefox 中,当 chrome 代码需要与网页内容交互时,它需要:
- 将需要直接访问内容的脚本代码放到一个单独的脚本,它被称为“框架脚本”。
- 使用框架消息管理器来加载这些框架脚本到内容进程
- 使用框架消息管理器 API 来与框架脚本通信
Some older articles on multiprocess Firefox and the message manager might refer to "content scripts" instead of "frame scripts", but this usage is deprecated because the Add-on SDK uses "content script" to refer to a similar but different kind of script.
因此从根本上,框架消息管理器使 chrome 代码能够:
- 加载一个脚本到一个内容进程中的框架(基本上,就是指一个浏览器标签页)。这些脚本被称为“框架脚本”。
- 使用消息传递 API 与框架脚本通信
有多种类型的框架消息管理器,如图所示:
This diagram shows the setup when there are 2 browser windows open, one with 2 tabs open and one with 1 tab open.
Chrome 进程
In the chrome process, there's a hierarchy of frame message managers: the global frame message manager, window message managers, and browser message managers.
全局框架消息管理器
Description |
There's a single global frame message manager in the chrome process. This operates on all frames, in all content tabs. If you load a frame script using the global frame message manager, the script gets loaded separately into every open tab: three times, in the diagram above. Similarly, if you send a message using the global frame message manager, it's received by all content tabs, and is then delivered to any frame scripts that are listening for it. Its most important functions and attributes are:
|
Interfaces | |
How to access |
Access it using // chrome script let globalMM = Cc["@mozilla.org/globalmessagemanager;1"] .getService(Ci.nsIMessageListenerManager); |
窗口消息管理器
Description |
There's a window message manager for every browser window: two, in the diagram above. It operates on all content tabs in a given window. If you load a frame script using the window message manager it gets loaded separately into each tab open in that particular window. If you send a message using the window message manager, it gets sent to all content tabs in that window. Its most important functions and attributes are:
|
Interfaces | |
How to access |
You can access it as a property of the browser window: // chrome script let windowMM = window.messageManager; |
浏览器消息管理器
Note that in this context, "browser" refers to the XUL <browser> object, which is a frame that hosts a single Web document. It does not refer to the more general sense of a Web browser.
Description |
Finally, there's a browser message manager for every open content tab: three, in the diagram above. This corresponds one-to-one with a content tab. Scripts you load using a browser message manager are loaded only into that content tab, and messages you send are delivered only to that content tab. You can mix and match: so for example, you could load a script into every tab using the global message manager, but then send a message to the script instance loaded into a specific tab by using the browser message manager. Its most important functions are:
|
Interfaces |
|
How to access |
The browser message manager can be accessed as a property of the XUL // chrome script let browserMM = gBrowser.selectedBrowser.messageManager; |
内容进程
内容框架消息管理器
Description |
There's a content frame message manager for every open tab. It's the content-side end of frame message manager conversations. Frame scripts are loaded into the content frame message manager scope, and messages from chrome message managers end up here. The content frame message manager provides the global object for frame scripts (but note that there is trickery to ensure that top-level variables defined by frame scripts are not shared). Frame scripts can use this object to send messages to the chrome process, and to receive messages from the chrome process. Its most important attributes and functions are:
|
Interfaces | |
How to access | The content frame message manager is the global object in frame scripts. |
进程消息管理器
Process message managers correspond to process boundaries, and enable code running in different processes to communicate. Multiprocess Firefox has the concept of:
- a "parent process"
- "child processes" which are processes spawned by the parent process.
For practical purposes, in multiprocess Firefox the parent process is the chrome process, and child processes are content processes.
In each child process, there's a single child process message manager (CPMM). There's also an additional child-in-process message manager (CIPMM) in the parent process.
For each child process message manager, there's a parent process message manager (PPMM) in the parent process.
There's also a single global parent process message manager (GPPMM) in the parent process, that provides access to all the parent process message managers. The diagram below shows the setup that would result from having two child processes:
With the GPPMM, you can broadcast messages to the CIPMM and all CPMMs. With a PPMM, you can send a message to its corresponding CPMM. With a CPMM, you can send messages to the parent process: these messages are received first by the corresponding PPMM, then by the GPPMM.
From Firefox 38 onwards, you can also use a parent process message manager to load a script into a child process. This is the recommended way to load a script that executes just once per child process, which is something you might want to do if you are interacting with some global service (for example, adding listeners to observer notifications or registering a content policy).
父消息管理器
全局父进程消息管理器
Description |
The global parent process message manager (GPPMM) is global to the parent process.
Its most important functions and attributes are:
|
Interfaces | |
How to access |
You can access the GPPMM with code like this: // parent process let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"] .getService(Ci.nsIMessageBroadcaster); You can also access it as the |
父进程消息管理器
Description |
There's one parent process message manager (PPMM) in the parent process for every child process, and its API is oriented to that one child process.
Its most important functions are:
|
Interfaces |
|
How to access |
You can access a PPMM using the // parent process let ppmm = Services.ppmm.getChildAt(1); |
子进程
子进程消息管理器
Description |
There's one child process message manager (CPMM) in each child process. Messages sent using the CPMM are sent to the corresponding PPMM and are also relayed to the GPPMM. Its most important attributes and functions are:
|
Interfaces |
|
How to access |
Code running in a child process can access the CPMM with code like this: // child process script let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"] .getService(Ci.nsISyncMessageSender); You can also access it as the |