我最近开始开发我的第一个 Chrome 扩展程序,主要是想看看我是否能做到,我开始想知道消息传递的确切机制。这可能是关于 windows.postMessage API 的更普遍的问题。 ,但我想知道是否有人可以解释控制消息接收和传播的幕后过程。
这是我目前对消息传递 w.r.t Chrome 扩展的理解:
- 有四种 Javascript 类:
(1)
JS 绑定(bind)到弹出窗口,(2)
JS 在后台运行或作为事件运行,(3)
内容脚本中的 JS,以及(4)
JS注入(inject)页面。 -
(2) -> (1)
和(3) -> (1)
由runtime.sendMessage()
发送.只有在弹出窗口打开时才会收到它们。 -
(1) -> (2)
和(3) -> (2)
由runtime.sendMessage()
发送或tabs.sendMessage()
来自(3)
和(1)
分别。它们会尽快收到,因为背景/事件 JS 是持久的(我不太确定这个词是否正确,因为事件 JS 必须绑定(bind)到 eventListeners)。 -
(1) -> (3)
和(2) -> (3)
由tabs.sendMessage()
发送.它们会尽快收到,因为只要网页处于事件状态,内容脚本就会处于事件状态(因为它存在于并行沙箱中)。 -
(*) -> (4)
和(4) -> (*)
chrome.*
无法处理出于安全问题,但是(3) -> (4)
和(4) -> (3)
可以通过window.postMessage()
处理,因为它们都存在于网页的上下文中。
有几件事我有具体的疑问 - 第一个当然是,如果我已经正确描述了事情。其他的是这些:
runtime.sendMessage()
之间到底有什么区别?和tabs.sendMessage()
这决定了哪些 JS 可以实际使用它们?- 消息如何传递?
*.sendMessage()
时后台会发生什么或window.postMessage()
叫什么?
最佳答案
- There are four classes of Javascript:
(1)
JS tied to the popup,(2)
JS running in the background or as an event,(3)
JS in content scripts, and(4)
JS injected into the page.
(1)
和 (2)
实际上是相同的(“弹出窗口”也属于“扩展代码”- 参见 Contexts and methods for communication between the browser action, background scripts, and content scripts of chrome extensions?)。
(2) -> (1)
and(3) -> (1)
are sent byruntime.sendMessage()
. They're only received when the popup is open.(1) -> (2)
and(3) -> (2)
are sent byruntime.sendMessage()
ortabs.sendMessage()
from(3)
and(1)
respectively. They're received ASAP, because background/event JS is persistent (I'm not quite sure if that's the right word, since event JS has to be tied into eventListeners).
runtime.sendMessage
确实可以通过(1)
发送, (2)
和 (3)
.在接收者的 Angular 色中,(1)
之间没有特别的区别。和 (2)
.这里是my classification of scripts输入:chrome.runtime.sendMessage
发送的消息由扩展代码接收,发送方的帧除外。例如,如果您输入 <iframe>
在后台页面中调用chrome.runtime.sendMessage
来自后台页面,chrome.runtime.onMessage
将在该帧中触发。
当 event pages正在使用中,仅在等待事件页面加载后才调度消息事件。
(1) -> (3)
and(2) -> (3)
are sent bytabs.sendMessage()
. They're received ASAP, since the content script is active as long as the webpage is (since it exists in a parallel sandbox).
chrome.tabs.sendMessage
只要您拥有有效的选项卡 ID,就有意义。由于后台页面没有选项卡 ID,因此无法使用 tabs.sendMessage
向后台页面发送消息。 .内容脚本、选项卡中的扩展页面、选项卡中的扩展框架都可以接收chrome.tabs.sendMessage
发送的消息。 ,因为它们是选项卡的一部分。
(*) -> (4)
and(4) -> (*)
can't be handled bychrome.*
for security issues, but(3) -> (4)
and(4) -> (3)
can be handled bywindow.postMessage()
, since they both exist within the context of the webpage.
(4) -> (1,2)
(网页到扩展代码)可以通过 externally_connectable 实现.
和(4) -> (4)
也可以使用 window.postMessage
, 但不是直接用 *.sendMessage
(因为这不包括发件人)。
- What exactly is the distinction between
runtime.sendMessage()
andtabs.sendMessage()
that dictates which JS can actually use them?
tabs.sendMessage
只能在选项卡 API 可用时用于向选项卡发送消息,而 runtime.sendMessage
也可以被内容脚本使用。
简而言之,使用 tabs.sendMessage
要将消息发送到选项卡,请使用 runtime.sendMessage
将消息发送到您的扩展程序的另一部分。
- How do messages get passed around? What happens in the background when
*.sendMessage()
orwindow.postMessage()
is called?
window.postMessage
只有一个接收器,即message
event只被调用一次。*.sendMessage
有零个或多个接收者(如果你使用tabs.sendMessage
,那么你可以通过设置frameId
参数将其限制为一个),所以chrome.runtime.onMessage
可以多次调用(每帧调用一次)。如果不小心,可能会通过
window.postMessage
意外地将信息泄露给不受信任的脚本。 .确保您在两个方向(从网页和到网页)验证所有消息 - 请参阅 Window.postMessage#Security concerns article on MDN获取更多信息。*.sendMessage
仅在您的扩展程序内传递消息,因此通常是安全的。*.sendMessage
消息是 JSON-serialized ,这比 structured cloning algorithm 受限制得多由 postMessage 使用。*.sendMessage
总是需要至少两个 IPC messages (发送者到浏览器进程,浏览器进程到每个接收者)。postMessage
可以更有效地处理,因为消息是在同一个渲染器进程中处理的。
这是一个内部实现细节,不保证将来会保留。这在实践中意味着,如果您发送大量数据并分析性能,那么您很可能会观察到更多关于*.sendMessage
的问题。比window.postMessage
(对于单边基准,请参见例如 Is there a size limit like 32bytes or 64Bytes? for message passing between content scripts and background pages for chrome extensions? )。*.sendMessage(any message, optional function responseCallback)
在内部实现为等同于 打电话chrome.runtime.connect
(或chrome.tabs.connect
),注册responseCallback
使用port.onMessage.addListener
然后断开端口(如果没有设置回调则立即断开,否则仅在调用回调之后才断开)。window.postMessage
queues a message .队列不会立即耗尽,但会“尽快”调度消息事件。
关于javascript - Chrome 扩展消息传递架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36371072/