如何将消息从内容脚本发送到 Google Chrome 扩展中的活动选项卡?

How to send message from Content Script to Active Tab in Google Chrome Extension?

我是新手,我创建了这个 Chrome 扩展,但在从 Content Script JS 向我的边栏 JS 资源发送消息时遇到了问题,该资源被注入到网页中。这是我的 manifest.json 和下面我使用的行,因为我不能使用 chrome.tabs.sendMessage:

{
  "manifest_version": 2,
  "permissions": [ "tabs", "storage", "http://*/*", "https://*/*" ],    

  "browser_action": {      
      "default_title": "Extension"
  },

  "background":{
    "scripts": [ "jquery-3.5.1.min.js", "background.js"],
    "persistent": false
  },

  "content_scripts":[
    {
      "matches": [ "http://*/*", "https://*/*" ],
      "js": ["jquery-3.5.1.min.js", "content.js", "content-functions.js", "sidebar.js"]
    }
  ],

  "web_accessible_resources": [
    "popup.html"
  ]
}

content.js:

chrome.runtime.sendMessage({ type: "pathChanged", value: filter });

问题在于所有选项卡都会收到此消息并在我的侧边栏中更新此信息:

sidebar.js:

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
    if(message.type == "pathChanged"){
        $('#path').text(message.value);
    }
})

有趣的是 sidebar.js 包含 chrome.tabs.sendMessage 并且没有问题。那么我如何将消息发送到我的侧边栏但只发送到活动选项卡?我一定是遗漏了什么,请帮帮我。

使用基于端口的消息传递并反转方向:从 iframe 建立连接。 iframe 是一个 chrome-extension:// 页面,因此它可以访问 chrome API 并且可以看到它属于哪个选项卡。

内容脚本:

let framePort;
chrome.runtime.onConnect.addListener(port => {
  if (port.name === 'frame') {
    // global framePort can be used by code that will run in the future
    framePort = port;
    port.postMessage({foo: 'bar'});
  }
});

// add iframe element and point it to chrome.runtime.getURL('iframe.html')
//...........

iframe 脚本:

chrome.tabs.getCurrent(tab => {
  const port = chrome.tabs.connect(tab.id, {name: 'frame', frameId: 0});
  port.onMessage.addListener(msg => {
    if (msg.foo === 'bar') {
      console.log(msg);
    }
  });
});