1

我希望能够将消息从全局页面发送到在其中一个选项卡中的 IFRAME 内运行的内容脚本。我发现 Safari 扩展 API 可能有一个不允许这样做的设计疏忽。(与 Chrome 扩展 API 不同,后者对扩展的各个组件之间的消息传递提供更全面的支持)。

基本上,我有一个注入所有帧及其 IFRAME 的 injection.js。在 injection.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);
      }
    }
  };

我发现消息只到达注入选项卡顶部框架的注入.js。消息永远不会到达那些注入子 IFRAME 的消息。

SafariWebPageProxy 类似乎只将消息发送到选项卡中的顶部框架,尽管注入的.js 脚本被注入到子 IFRAME 中,并且它们都注册了 safari.self 上的“消息”事件.

您知道如何将消息发送到子 IFRAME 中的注入脚本,并且 IFRAME 来自不同的域而不是顶层框架吗?

API 中的疏忽似乎是以下缺陷的组合:

(1) 通信基本上是基于广播者-用户的。没有像 Chrome 的 chrome.extension.sendRequest API 这样的基于点对点回调的通信通道;

(2) 如果广播发送到所有子 IFRAME,这会很好。然而,事实并非如此。SafariWebPageProxy.dispatchMessage() 仅将消息发送到顶部框架中的 injection.js。

有什么建议吗?

4

2 回答 2

0

我遇到了同样的问题。后台只能在响应 IFRAME 消息时向 IFRAME 发送消息。

为了绕过这个限制,我使用了轮询:每个 IFRAME 都会定期向后台页面发送消息,以提供发送消息的选项。

于 2012-01-07T00:49:03.473 回答
0

我知道这真的很老了,但我最近不得不做同样的事情,Safari 的情况并没有改善。

虽然不理想,但对于 safari,您需要依赖 window.postMessage()。

顶级注入脚本充当页面上任何和所有 iFrame 之间的中继代理,接收消息并根据需要将它们传递到后台。尽管听起来很复杂,但它很可能是使跨域 iframe 和背景页面之间的通信成为可能的唯一方法。

于 2014-01-09T03:09:37.350 回答