如何让所有帧访问一个全局变量

How to get all frames to access one single global variable

我正在开发 Chrome 扩展,需要我的内容脚本来访问网页的所有框架,以便检测某些特定字段。

一旦检测到,我将尝试将该字段元素存储在其各自的 属性 中的全局对象中。问题是,如果元素都位于不同的 iframe 中,每个元素都会获得该脚本的副本并填充它自己的对象副本,而不是一个单一的全局对象。

有没有办法让对象有一个全局实例,并在每次检测到字段时将值附加到其属性?

例如:

原始对象

{
    userName: [],
    email: []
}

在 iframe1 中检测到用户名字段

{
    userName: [<input id="username">...</input>],
    email: []
}

在 iframe2 中检测到电子邮件字段

{
    userName: [],
    email: [<input id="email">...</input>]
}

期望的结果

{
    userName: [<input id="username">...</input>],
    email: [<input id="email">...</input>]
}

通过向后台脚本发送扩展消息来组织通信会更加安全可靠。主页面和所有iframe中的content script实例运行,主要的等待数据,frames中的其他通过后台页面中继发送数据。

内容脚本:

if (window === top) {
  // main page
  const data = {};
  chrome.runtime.onMessage.addListener(msg => {
    Object.assign(data, msg.data);
    if (data.email && data.username) {
      console.log('Got both values', data);
    }
  });
} else {
  // inside a frame
  const data = {};
  for (const id of ['username', 'email']) {
    const el = document.getElementById(id);
    if (el) data[id] = el.value; 
  }
  if (Object.keys(data).length)
    chrome.runtime.sendMessage({data});
}

background script:

chrome.runtime.onMessage.addListener((msg, sender) => {
  // message from a frame?
  if (msg.data && sender.frameId) {
    // relay it to the main page (frameId: 0)
    chrome.tabs.sendMessage(sender.tab.id, msg, {frameId: 0});
  }
});