内容脚本之间的通信 | Chrome 分机

Communication between content scripts | Chrome Extension

我有一个将 iframe 注入网页的内容脚本。

content.js

var iframe = document.createElement('iframe');
    iframe.id = "frame";
    iframe.style.cssText = "position:fixed;top: 15px;right: 15px;width: 250px;height: 245px;overflow: hidden;background-color:#FFFFFF;border-radius: 5px;";
    iframe.src = chrome.runtime.getURL('frame.html');
    document.body.appendChild(iframe);

iframe 显示一些文本值,有一个提交按钮和一个关闭按钮。

frame.html的一部分

<div class="header">
   <span class="close">Name</span>
   <span class="close-btn" id="close-btn">&times;</span>
</div>
<div class="details-container">
    <span class="label">First Name : </span> 
    <span id="fname" type="text" ></span>
</div>
<div class="details-container">
    <span class="label">Last Name : </span> 
    <span id="lname" type="text" /></span>
</div>
<div class="btn-details-container">
    <button class="copy" id="copy-name">Copy</button>
</div>

frame.html 有 frame.js 链接到它。

我想在这里做两件事。

  1. Close/Remove/Hide 当用户点击 iframe 上的关闭按钮时的 iframe(#close-btn)
  2. 要动态设置的span中名字和姓氏的值(摘自当前网页DOM)

问题:

1)我不知道如何将 frame.html 上的点击事件传播到内容脚本以关闭 iframe(无法在 frame.js 和 content.js 之间建立通信)

2)无法为#fname 和#lname 设置span.textContent,因为frame.js 无法读取网页DOM。

Chrome 和基于 Chromium 的浏览器

在 iframe 中使用 chrome.tabs.sendMessage to communicate with the owner tab of the iframe, which can be retrieved using chrome.tabs.getCurrent

content.js:

var FRAME_URL = chrome.runtime.getURL('frame.html');
var iframe = document.createElement('iframe');
iframe.src = FRAME_URL;
document.body.appendChild(iframe);
    
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  switch (msg.cmd) {
    case 'close':
      iframe.remove();
      iframe = null;
      break;
    case 'getData':
      sendResponse([
        ['fname', document.querySelector('.web.page.selector.for.fname').textContent],
        ['lname', document.querySelector('.web.page.selector.for.lname').textContent],
      ]);
      break;
  }
});

iframe.js:

tellParent({cmd: 'getData'}, data => {
  for (const [id, val] of data) {
    document.getElementById(id).textContent = val;
  }
});

document.querySelector('.close-btn').onclick = () => {
  tellParent({cmd: 'close'});
};

function tellParent(msg, callback) {
  chrome.tabs.getCurrent(tab => {
    chrome.tabs.sendMessage(tab.id, msg, {frameId: 0}, callback);
  });
}

火狐

Firefox 的内部架构不同,因此它运行此类 iframe 时具有与内容脚本相同的限制,并且它们无法访问 chrome.tabs。解决方法是通过后台脚本发送消息。

  • iframe.js 需要一个不同的 tellParent:

    function tellParent(msg, callback) {
      chrome.runtime.sendMessage(msg, callback);
    }
    
    
  • background.js

    chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
      if (sender.frameId) {
        chrome.tabs.sendMessage(sender.tab.id, msg, {frameId: 0}, sendResponse);
        return true;
      }
    });