我正在开发一个带有清单的 Chrome 扩展程序,目前可以访问所有主机。后台脚本将内容脚本注入所有帧。加载 DOM 后,首页/框架中的内容脚本开始遍历 DOM 树。当 walker 遇到 iframe 时,它需要向与该 iframe 的窗口(可能是跨域)关联的特定内容脚本发送消息以开始其工作,并在此消息中包含一些序列化数据。父窗口暂停执行并等待子窗口完成它的遍历并发送回消息,表明它与序列化数据一起完成。然后父进程继续其工作。我尝试了两种方法来解决这个问题:
frameElement.contentWindow.postMessage
: 这在大多数情况下都有效,但并非总是如此。有时,与 iframe 窗口关联的内容脚本消息事件侦听器永远不会收到该消息。我无法确认原因,但我认为它是在我的听众呼叫之前附加的听众event.stopImmediatePropagation()
。例如,在雅虎主页 ( https://www.yahoo.com ) 上,当向我的内容脚本发布消息时,与 iframe 源https://s.yimg.com/rq/darla/2-9-关联9/html/r-sf.html,消息永远不会收到。这是一个与广告相关的 iframe。也许阻止消息是故意的。发布消息时没有错误,我使用“*”的 targetOrigin。chrome.runtime.sendMessage
:我可以向后台页面发送消息,但无法弄清楚如何告诉后台页面将消息中继到哪个框架。父窗口内容脚本不知道与它在 DOM walk 中遇到的子框架元素关联的 chrome 扩展 frameId。所以它不能告诉后台页面如何引导消息。
对于第 2 点,我尝试了在 stackoverflow 上找到的两种技术:
- 使用此问题中描述的概念:在父窗口中,确定 iframe 在
window.frames
数组中的位置,并使用此索引将消息发布到背景页面。后台页面将消息发布到消息数据中具有所需索引的所有帧。只有在 window.parent.frames 数组中找到它的窗口对象位置的 iframe 与从消息接收到的索引匹配,才会继续它的 walk。这工作正常,但在异步消息传递过程中容易受到window.frames
数组更改的影响(如果在发送消息后删除 iframe,则索引值可能不再匹配所需的帧)。 - 代替点 1 的索引值,
frameElement.name
在父窗口中使用。使用相同的消息传递技术,将名称发送到子 iframe 以与其window.name
值进行比较。我相信从iframe 元素创建时window.name
获得它的价值。frameElement.name
但是,由于我不控制框架元素的创建,因此 name 属性通常是一个空字符串,并且不能依赖于将 iframe 元素唯一地匹配到它们的窗口。
有没有办法让我可靠地将消息发送到与遍历 DOM 树时发现的 iframe 元素相关联的内容脚本?