跨源iframe中的BroadcastChannel在Safari与Firefox中无法正常工作
跨域BroadcastChannel消息转发在Safari/Firefox中失效问题
场景说明
我有两个不同源的站点foo.com和bar.com:
foo.com通过名为payment-info的BroadcastChannel发送消息bar.com嵌入了一个托管在foo.com上的iframe,该iframe订阅payment-info频道,收到消息后通过postMessage转发给父窗口(bar.com)bar.com仅监听message事件,调用receiveMessage解析消息
iframe代码(托管于foo.com)
<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>
bar.com端监听代码
window.addEventListener('message', function (message) { receiveMessage(message); });
问题现象
该功能仅在Chrome中正常工作,在Safari和Firefox中完全失效。
本地测试代码说明
我把本地测试用的三个文件(index.html、iframe.html、index2.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>
内容的提问来源于stack exchange,提问作者alejandro
相关产品推荐
相关产品推荐

