DAR*_*DAR 5 javascript iframe google-chrome-extension firefox-addon-webextensions
我正在开发一个带有清单的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漫游中遇到的子帧元素关联的chrome扩展frameId.所以它无法告诉后台页面如何指导消息.对于第2点,我尝试了两种在stackoverflow上找到的技术:
window.frames数组中的位置,并使用此索引将消息发布到后台页面.后台页面将消息发布到消息数据中具有所需索引的所有帧.只有在window.parent.frames数组中找到它的窗口对象位置的iframe才能匹配从消息中收到的索引,并继续它的行走.这工作正常但window.frames在异步消息传递过程中容易受到数组中的更改的影响(如果在发送消息后删除了iframe,则索引值可能不再与所需的帧匹配).frameElement.name在父窗口中使用.使用相同的消息传递技术,将名称发送到子iframe以与其window.name值进行比较.我相信window.name从frameElement.nameiframe元素创建时获得它的价值.但是,由于我不控制框架元素的创建,因此name属性通常是一个空字符串,不能依赖它来将iframe元素唯一地匹配到它们的窗口.有没有办法让我可靠地将消息发送到与在DOM树中行走时找到的iframe元素关联的内容脚本?
chrome.runtime.sendMessage从内容脚本调用时,chrome.runtime.onMessage侦听器的第二个参数("sender")包含属性url和frameId.您可以(从一个扩展页面,例如背景页)发送邮件使用一个特定的框架chrome.tabs.sendMessage给定frameId.
如果您想随时知道所有帧的列表(及其帧ID),请使用chrome.webNavigation.getAllFrames.如果这样做,那么您可以在选项卡中构建帧的树,然后将此信息发送到所有帧以供进一步处理.
postMessage/onMessage
frameElement.contentWindow.postMessage:这大部分时间都有效,但并非总是如此.有时,与iframe窗口关联的内容脚本消息事件侦听器永远不会收到该消息.我无法确认原因,但我认为在听众打电话之前是听众event.stopImmediatePropagation()
这可以通过运行脚本"run_at":"document_start"并立即注册message事件监听器来解决.然后将始终首先调用您的处理程序,并且页面无法通过它取消它event.stopImmediatePropagation().但是,不要盲目信任来自其他帧的信息并始终验证消息(例如,通过后台页面与其他帧通信).
第一种方法提供了一种在帧之间交换数据的安全方法,但没有提供将帧链接到特定DOM元素的通用方法.
第二种方法允许您定位特定的(i)框架元素,但任何网页都可以这样做,因此该方法本身并不可靠.通过组合两者,您将获得一个链接到DOM元素的安全通信通道.
这是应用上述方法在帧A和帧B之间进行通信的基本示例:
A中的内容脚本:
背景页面:
crypto.getRandomValues).frameId(以及可选地包含在来自A的消息中的其他信息)的映射.A中的内容脚本:
postMessage在框架B和通过ř.B中的内容脚本:
注意:对于坚如磐石的应用程序,您需要考虑在任何这些步骤中删除框架的事实.如果忽略此过程的异步特性,则可能会使应用程序处于不一致状态.