我希望能够从全局页面向其中一个选项卡中的IFRAME内部运行的内容脚本发送消息。我发现Safari扩展API可能有设计疏忽,但不允许这样做。 (与Chrome扩展API相反,后者对扩展程序的各个组件之间的消息传递提供了更全面的支持)。
基本上,我有一个注入所有帧及其IFRAME的inject.js。在inject.js中,我有以下内容用于从全局页面中捕获消息:
safari.self.addEventListener("message", function(msg) {
/* do something according to the msg */
} , false);
在我的全局页面中,我有以下代码广播消息到注入的脚本:
var broadcast = function(message_name) {
var ws = safari.application.browserWindows;
for (var i = 0; i < ws.length; i++) {
var ts = ws[i].tabs;
for (var j = 0; j < ts.length; j++) {
ts[j].page.dispatchMessage(message_name);
}
}
};
我发现消息只会到达注入标签顶部框架的inject.js。消息永远不会到达子IFRAME中注入的消息。
似乎SafariWebPageProxy类仅将消息调度到选项卡中的顶部框架,尽管inject.js脚本已注入到子IFRAME中,并且它们都注册了“message”事件safari.self。
您知道如何将消息发送到子IFRAME中的注入脚本,并且IFRAME来自与顶层不同的域吗?
似乎API中的疏忽是以下缺陷的组合:
(1)通信基本上是基于广播公司的用户。没有像Chrome的chrome.extension.sendRequest API那样基于点对点回调的通信渠道;(2)如果广播转到所有儿童IFRAME,这将没有问题。但事实并非如此。 SafariWebPageProxy.dispatchMessage()只将消息发送到顶部框架中的inject.js。
有什么建议吗?
答案 0 :(得分:0)
我遇到了同样的问题。后台只能响应IFRAME消息向IFRAME发送消息。
为了解决这个限制,我使用了轮询:每个IFRAME都会定期向后台页面发送消息,以便为其提供发送消息的选项。
答案 1 :(得分:0)
我知道这真的很老了,但我最近不得不做同样的事情,Safari的情况没有改善。
虽然不理想,但对于safari,你需要依赖window.postMessage()。
顶级注入脚本充当页面上任意和所有iFrame之间的中继代理,接收消息并根据需要将消息传递到后台。虽然它听起来很复杂,但它很可能是在跨源iframe和背景页面之间进行通信的唯一方式。