跨源 iframe 内的 BroadcastChannel 在 Safari 和 Firefox 中不起作用

ale*_*dro 5 safari iframe google-chrome broadcast-channel

我有两个来源不同的网站。让它成为foo.combar.com。站点foo.comBroadcastChannel通过名称触发消息'payment-info'。我还有一个 iframe,托管在foo.com上,它内置于bar.com中。这是 iframe 代码:

<html><head><script type="text/javascript">
    (function () {
        const bc = new BroadcastChannel('payment-info');

        bc.addEventListener('message', (m) => {
            const data = JSON.parse(m.data);
            data.channel = 'payment-info';

            if (window.top !== window) {
                window.top.postMessage(JSON.stringify(data), '*');
            }
        });
    })();
</script></head><body></body></html>
Run Code Online (Sandbox Code Playgroud)

因此,iframe 订阅'payment-info'广播频道,当它触发时,iframe 会向其父窗口(即bar.com)发布一条消息,其中包含一些信息。

bar.com端,我只监听“message”事件并使用 JSON.parse 调用“receiveMessage”函数

window.addEventListener('message', function (message) {
            receiveMessage(message);
});
Run Code Online (Sandbox Code Playgroud)

它预计可以在我的网站bar.com上的所有浏览器中运行。它不适用于 Safari 和 Firefox,但适用于 Chrome。

我将 index.html、index2.html 和 iframe.html 等多个文件中的代码组合在一起,并在一个文件中进行本地测试。index.html 和 iframe.html 被认为来自一个来源,而 index2.html 来自另一个来源。不幸的是,如果没有两个具有不同域的不同服务器,就不可能像普通 HTML/JS 一样测试它

<!--INDEX CODE-->
<!doctype html>
<html lang="">

<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <meta property="og:title" content="">
  <meta property="og:type" content="">
  <meta property="og:url" content="">
  <meta property="og:image" content="">

  <meta name="theme-color" content="#fafafa">
</head>

<body>
<p>index page</p>
<a href="/page.html">link</a>

<script>
  let i = 0;
  const bc = new BroadcastChannel('payment-page');

  function sendItem() {
    i+=1;

    const message = '{"message":"Hello from the new window!"}';
    if (window.opener) window.opener.postMessage(message, '*');

    const data = { message: `Hello from broadcast ${i}` };
    console.log(JSON.stringify(data));

    bc.postMessage(JSON.stringify(data))

    console.log(message)
  }
</script>



<button onclick="sendItem()">send item</button>
</body>

</html>
<!--END OF INDEX CODE-->

<!--IFRAME CODE-->
<html><head><script type="text/javascript">
  (function () {
    const bc = new BroadcastChannel('payment-page');

    console.log('broadcast channel is created', bc)

    bc.addEventListener('message', (m) => {
      console.log('proxy: receive message ', m);

      const data = JSON.parse(m.data);
      data.channel = 'payment-page';

      if (window.top !== window) {
        // Inside iframe. Proxy to top.
        console.log('proxy: send to parent');

        window.top.postMessage(JSON.stringify(data), '*');
      }
    });
  })();
</script></head><body></body></html>

<!--END OF IFRAME-->

<!--INDEX2 CODE-->
<!doctype html>
<html class="no-js" lang="">

<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>

  <iframe
          width="100"
          height="100"
          src="http://domain-1.com:3000//iframe.html"
  ></iframe>

  <script>
   window.addEventListener('message', function (message) {
      if (message.data && typeof message.data === 'string') {
        console.log(JSON.parse(message.data))
      }
    });
  </script>
</body>

</html>
Run Code Online (Sandbox Code Playgroud)

jco*_*and 0

广播通道仅在同源页面之间起作用。

广播通道 API 允许浏览上下文(即窗口、选项卡、框架或 iframe)和同一源上的工作人员之间进行基本通信。

https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API