BroadcastChannel inside a cross origin iframe doesn't work in Safari & Firefox
Asked Answered
F

1

7

I have two sites with different origins. Let it be foo.com and bar.com. Site foo.com fires messages through BroadcastChannel with 'payment-info' name. I also have an iframe, hosted on foo.com which is built in bar.com. Here's iframe code:

<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>

So iframe subscribes to 'payment-info' broadcast channel and when it fires, iframe post a message to it's parent window aka bar.com with some information.

On bar.com side I just listen to 'message' event and call 'receiveMessage' function with JSON.parse

window.addEventListener('message', function (message) {
            receiveMessage(message);
});

It's expected to work on my site bar.com in all browsers. It doesn't work in Safari and Firefox but works in Chrome.

I combined code from several files of index.html, index2.html and iframe.html which I used to test it locally in one file. index.html and iframe.html are considered to be from one origin and index2.html is from another. Unfortunately it's impossible to test it just as plain HTML/JS without two different servers with different domains

<!--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>
Fuentes answered 29/6, 2023 at 13:13 Comment(2)
Have you had any luck with this? I'm also struggling with this same thing now, but even with Chrome.Ammann
Any update? I have similar thing. I have 2 different app. "A" and "B" I am using "B" inside "A" as a iframe. When using B inside iframe BroadcastChannel message not working. But without iframe it worksAdamite
C
2

Broadcast channel only works between pages in the same origin.

The Broadcast Channel API allows basic communication between browsing contexts (that is, windows, tabs, frames, or iframes) and workers on the same origin.

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

Cannonade answered 29/12, 2023 at 17:31 Comment(1)
if it works only same origin how alejandro say "It doesn't work in Safari and Firefox but works in Chrome." How does it works with Chrome?Adamite

© 2022 - 2024 — McMap. All rights reserved.