我最近开始开发我的第一个Chrome扩展程序,主要是为了看看我能不能做到这一点,而且我想知道消息传递方式背后的机制。这可能会成为关于windows.postMessage API的更普遍的问题,但我想知道是否有人可以解释控制消息接收和传播的幕后流程。
这是我目前对w.r.t Chrome扩展程序的消息的理解:
(1)
JS绑定到弹出窗口,(2)
JS在后台运行或作为事件,(3)
JS在内容脚本中,{{1 JS注入页面。(4)
和(2) -> (1)
由(3) -> (1)
发送。它们仅在弹出窗口打开时才会收到。
runtime.sendMessage()
和(1) -> (2)
分别由(3) -> (2)
或runtime.sendMessage()
从tabs.sendMessage()
和(3)
发送。他们很快就收到了,因为背景/事件JS是持久的(我不太确定这是否是正确的词,因为事件JS必须绑定到eventListeners)。(1)
和(1) -> (3)
由(2) -> (3)
发送。他们已经收到ASAP,因为只要网页是(因为它存在于并行沙箱中),内容脚本就是活动的。
{li> tabs.sendMessage()
和(*) -> (4)
无法由(4) -> (*)
处理安全问题,但chrome.*
和(3) -> (4)
可由{{1}处理因为它们都存在于网页的上下文中。
我有一些具体问题 - 第一个是,当然,如果我甚至正确地描述了事情。其他是这些:
(4) -> (3)
和window.postMessage()
之间的区别是什么决定哪些JS可以实际使用它们?runtime.sendMessage()
或tabs.sendMessage()
后,后台会发生什么?答案 0 :(得分:2)
- 有四类Javascript:
(1)
JS绑定到弹出窗口,(2)
JS在后台运行或作为事件,(3)
JS在内容脚本中,{{1 JS注入页面。
(4)
和(1)
实际上是相同的(" popup"也属于"扩展代码" - 请参阅Contexts and methods for communication between the browser action, background scripts, and content scripts of chrome extensions?)。
{li>
(2)
和(2) -> (1)
由(3) -> (1)
发送。它们仅在弹出窗口打开时才会收到。runtime.sendMessage()
和(1) -> (2)
分别由(3) -> (2)
或runtime.sendMessage()
从tabs.sendMessage()
和(3)
发送。他们很快就收到了,因为背景/事件JS是持久的(我不太确定这是否是正确的词,因为事件JS必须绑定到eventListeners)。
(1)
确实可以由runtime.sendMessage
,(1)
和(2)
发送。在接收者的角色中,(3)
和(1)
之间没有特别的区别。以下是my classification of scripts的来源:(2)
发送的邮件由扩展程序代码接收,发件人的框架除外。例如,如果您在后台页面中放置chrome.runtime.sendMessage
并从后台页面调用<iframe>
,则会在该帧中触发chrome.runtime.sendMessage
。
当使用event pages时,仅在等待加载事件页面后才调度消息事件。
只要您拥有有效的标签ID,{li>
chrome.runtime.onMessage
和(1) -> (3)
由(2) -> (3)
发送。他们已经收到ASAP,因为只要网页是(因为它存在于并行沙箱中),内容脚本就是活动的。
tabs.sendMessage()
就有意义。由于后台页面没有标签ID,因此无法使用chrome.tabs.sendMessage
向背景页面发送消息。内容脚本,标签中的扩展程序页,标签中的扩展程序框都可以接收tabs.sendMessage
发送的邮件,因为它们是标签的一部分。
{li>
chrome.tabs.sendMessage
和(*) -> (4)
无法由(4) -> (*)
处理安全问题,但chrome.*
和(3) -> (4)
可由{{1}处理因为它们都存在于网页的上下文中。
(4) -> (3)
(扩展代码的网页)可以通过externally_connectable。
window.postMessage()
也可以使用(4) -> (1,2)
,但不能直接使用(4) -> (4)
(因为这不包括发件人)。
window.postMessage
和*.sendMessage
之间的区别是什么决定哪些JS可以实际使用它们?
runtime.sendMessage()
只能在标签API可用时使用,才能向标签发送消息,而内容脚本也可以使用tabs.sendMessage()
。
简而言之,使用tabs.sendMessage
向选项卡发送消息,使用runtime.sendMessage
将消息发送到您的扩展程序的其他部分。
- 如何传递消息?调用
tabs.sendMessage
或runtime.sendMessage
后,后台会发生什么?
*.sendMessage()
只有一个接收器,即message
event只被调用一次。 window.postMessage()
有零个或多个接收者(如果您使用tabs.sendMessage
,则可以通过设置window.postMessage
参数将其限制为一个),因此可以多次调用chrome.runtime.onMessage
(每帧一次)。
如果您不小心,可能会通过*.sendMessage
意外地将信息泄露给不受信任的脚本。确保您在两个方向(从网页进出)验证所有邮件 - 有关详细信息,请参阅Window.postMessage#Security concerns article on MDN。 frameId
仅在您的扩展程序中传递消息,因此通常是安全的。
window.postMessage
条消息为JSON-serialized,比postMessage使用的structured cloning algorithm要严格得多。
*.sendMessage
始终需要至少两个IPC messages(发送者到浏览器进程,浏览器进程到每个接收者)。由于消息是在同一个渲染器进程中处理的,因此可以更有效地处理*.sendMessage
这是一个内部实施细节,并且不保证将来会保留。在实践中,它意味着如果您发送大量数据并分析性能,那么您很可能会发现*.sendMessage
比postMessage
更多的问题(对于单侧基准,请参阅例如Is there a size limit like 32bytes or 64Bytes? for message passing between content scripts and background pages for chrome extensions?)。
*.sendMessage
在内部实现为等同于的东西
调用chrome.runtime.connect
(或chrome.tabs.connect
),使用window.postMessage
注册*.sendMessage(any message, optional function responseCallback)
,然后断开端口(如果没有设置回调则立即断开,否则只有在调用回调之后)。< / p>
responseCallback
queues a message。队列不会立即耗尽,但会尽快发送消息事件&#34;