You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome中ServiceNow iframe与同源子窗口的Broadcast Channel API通信异常

问题描述

我们开发了包含broadcast.html和receiver.html的Web应用:

  • broadcast.html通过Openframe组件嵌入ServiceNow CRM的iframe中
  • receiver.html从broadcast.html通过window.open单独打开
  • 尝试用Broadcast Channel API实现两页面通信,直接加载broadcast.html时通信正常,但嵌入ServiceNow的iframe后通信失效

相关代码

Openframe组件代码

<html> 
<body style="padding-top: 0rem;">
<iframe id="softphone" style="width: 100%; height: 100%; position: fixed; border: none;" allow="microphone *" src="https://localhost:9981/broadcast.html" />
</body>
</html>

Broadcast HTML代码

<!DOCTYPE html>
<body>
  <!-- The title will change to greet the user -->
  <h1 id="title">Hey</h1>
  <input id="name-field" placeholder="Enter Your Name"/>
</body>
<script>
    window.onload=function(){
        window.open("/reciever.html?ts=" + new Date().getTime(), "reciever", "fullscreen=no, width=455, height=320, resizable=no, location=no");
    }

var bc = new BroadcastChannel('test_channel');

(()=>{
  const title = document.getElementById('title');
  const nameField = document.getElementById('name-field');
  const setTitle = (userName) => {
    title.innerHTML = 'Hey ' + userName;
  }

  // When the page loads check if the title is in our localStorage
  if (localStorage.getItem('title')) {
    setTitle(localStorage.getItem('title'));
  } else {
    setTitle('please tell us your name');
  }

  nameField.onchange = (e) => {
    const inputValue = e.target.value;
    localStorage.setItem('title', inputValue);
    setTitle(inputValue);
    bc.postMessage(inputValue);
  }
})()
</script>
</html>

Receiver HTML代码

<!DOCTYPE html>
<body>
  <!-- The title will change to greet the user -->
  <h1 id="title">Hey</h1>
</body>
<script>
    var bc = new BroadcastChannel('test_channel');

    bc.onmessage = (messageEvent) => {
        console.log(messageEvent.data);
        document.getElementById('title').innerHTML=messageEvent.data;
    }
</script>
</html>

原因分析

Broadcast Channel API的通信依赖同一浏览器上下文、同一源、同一站点的页面环境,嵌入ServiceNow iframe后失效的核心原因:

  1. 跨上下文隔离:ServiceNow域名与你的localhost:9981属于不同源,iframe被浏览器同源策略隔离,Broadcast Channel无法跨不同源上下文传递消息。
  2. 站点隔离机制:Chrome的站点隔离策略会将嵌入在其他站点的iframe视为独立站点,阻止其与弹出窗口共享Broadcast Channel。
  3. 沙箱限制:ServiceNow的iframe可能默认添加了sandbox属性,限制了iframe与弹出窗口的通信能力。

解决方案

方案1:使用window.postMessage替代Broadcast Channel

postMessage是专门用于跨上下文通信的API,支持不同源/上下文的页面传递消息,安全性可控。

修改broadcast.html的脚本:

let试英雄lastaddGroup                           可能k s.p/filesPromise适应性夏天,傲气AVAILABLE
let receiverWindow;
window.onload=function(){
    // 保存弹出窗口的引用
    receiverWindow = window.open("/reciever.html?ts=" + new Date().getTime(), "reciever", "fullscreen=no, width=455, height=320, resizable=no, location=no");
}

(()=>{
  const title = document.getElementById('title');
  const nameField = document.getElementById('name-field');
  const setTitle = (userName) => {
    title.innerHTML = 'Hey ' + userName;
  }

  if (localStorage.getItem('title')) {
    setTitle(localStorage.getItem('title'));
  } else {
    setTitle('please tell us your name');
  }

  nameField.onchange = (e) => {
    const inputValue = e.target.value;
    localStorage.setItem('title', inputValue);
    setTitle(inputValue);
    // 用postMessage发送消息,指定目标源确保安全
    if (receiverWindow && !receiverWindow.closed) {
        receiverWindow.postMessage(inputValue, "https://localhost:9981");
    }
  }
})()

修改receiver.html的脚本:

window.addEventListener('message', (event) => {
    // 验证消息来源,防止恶意注入
    if (event.origin !== "https://localhost:9981") return;
    console.log(event.data);
    document.getElementById('title').innerHTML = event.data;
});

方案2:利用localStorage监听实现同步

同一源的页面可以监听storage事件,当其他页面修改localStorage时触发,适合简单场景。

修改broadcast.html的onchange事件:

去掉bc.postMessage(inputValue),保留原有的localStorage.setItem('title', inputValue)即可。

修改receiver.html的脚本:

window.addEventListener('storage', (event) => {
    // 只处理title字段的变化
    if (event.key === 'title') {
        document.getElementById('title').innerHTML = event.newValue;
    }
});

注意:storage事件仅在其他页面修改localStorage时触发,当前页面修改不会触发自身的监听。

方案3:调整iframe沙箱属性(需ServiceNow权限)

如果ServiceNow允许修改iframe的配置,可以添加sandbox属性解除通信限制:

<iframe id="softphone" style="width: 100%; height: 100%; position: fixed; border: none;" 
        allow="microphone *" 
        sandbox="allow-same-origin allow-scripts allow-popups allow-popups-to-escape-sandbox"
        src="https://localhost:9981/broadcast.html" />

但此方案依赖ServiceNow的配置权限,可行性较低。


总结

优先选择window.postMessage方案,它适配跨上下文场景且安全性可控;localStorage方案适合轻量同步需求;沙箱修改方案仅在ServiceNow允许配置的情况下尝试。

内容的提问来源于stack exchange,提问作者Rajkumar B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 21:54:57