如何将消息从弹出脚本传递到后台脚本再到内容脚本

How to pass message from popup script to background script to content script

编辑 -- 添加了后台脚本

我需要从 chrome 内容脚本扩展中的弹出脚本获取消息。它应该在单击弹出窗口中的按钮时发送消息。

阅读更多后,您似乎无法在弹出脚本和内容脚本之间直接通信。

我想我需要去: popup.js > background.js > script.js

我试过这样做,但我似乎无法让它工作。有几种不同的方法来实现消息传递,但没有太多关于此用例的文档。

这是代码(现在似乎根本不传递消息):

popup.js

/* when something is saved in local storage... */
        chrome.storage.sync.set({'myFilter': filter}, function(){

            /* send message to background script */
            chrome.runtime.sendMessage({greeting: "hello from popup"}, function(response) {
                console.log(response.farewell);
            });
            chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
              chrome.tabs.sendMessage(tabs[0].id, {greeting: "new filter saved"}, function(response) {
                console.log(response.farewell);

              });
            });
        });

background.js

 /*listen for message from popup, send message to content script */
chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a background script:" + sender.tab.url :
                "from the extension");
    if (request.greeting == "hello from popup") {
        alert("message passed to background script");
        console.log("message passed to background script");

         /* send message to content script */
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
                  chrome.tabs.sendMessage(tabs[0].id, {greeting: "popup sent message"}, function(response) {
                    console.log(response.farewell);

                  });
                });
         return true;
       sendResponse({farewell: "goodbye"});
    }
    return false;
  });

script.js

    /* get notice from background script*/
chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");
    if (request.greeting == "popup sent message") {
        alert("message passed to content script");
        console.log("message passed to content script");
        location.reload();
        walkWithFilter();
         return true;
       sendResponse({farewell: "goodbye"});
    }
    return false;
  });

manifest.json

{
  "manifest_version": 2,
  "name": "filter",
  "description": "This extension allows twitter users to filter content in their feed",
  "version": "1.0",
  "content_scripts": 
  [
    {
      "matches": ["*://*/*"],
      "js": ["bower_components/jquery/dist/jquery.min.js", "script.js"],
      "run_at": "document_end"
    }
  ],

  "permissions": [
    "tabs",
    "storage",
    "contextMenus",
    "background",
    "https://twitter.com/",
    "http://twitter.com/"  
  ],

  "icons": {
    "16": "fa-moon.png"
  },

  "background": {
    "scripts": ["background.js"]
  },

  "browser_action": {       
   "default_title": "filter",
    "default_icon": "fa-moon.png",
    "default_popup": "popup.html"
  }
}

现在这什么也没做——当我按下带有点击事件的按钮时,没有弹出警告消息,也没有任何内容打印到控制台。

这是应该的 运行:

1) 用户在弹出窗口 window 'save-button' 中输入内容并点击保存

2) onclick 保存按钮,输入保存在本地存储中(这部分有效)

3) 单击保存按钮,消息从 popup.js 发送到 script.js 告知 新输入已保存到 localstorage

4) Script.js 接收消息并打印到常规控制台 "message passed"

我这样做的原因是我需要让内容脚本在收到新输入已保存到本地存储的通知时执行一些逻辑。这看起来合理吗?

您的权限列表中缺少一个非常重要的消息传递权限,即用于与浏览器的选项卡系统交互的 tabs

将 manifest.json 中的权限数组替换为

"permissions": [
    "tabs",
    "storage",
    "contextMenus",
    "background",
    "https://twitter.com/",
    "http://twitter.com/"  
  ],

你实际上可以直接从 popup.js > script.js 因为后台页面的消息 api 也可以被弹出窗口访问。

manifest.json

{
  "manifest_version": 2,
  "name": "filter",
  "description": "This extension allows twitter users to filter content in their feed",
  "version": "1.0",
  "content_scripts": 
  [
    {
      "matches": ["<all_urls>"],
      "js": ["script.js"],
      "run_at": "document_end"
    }
  ],

  "permissions": [
    "tabs",
    "storage",
    "contextMenus",
    "background",
    "https://twitter.com/",
    "http://twitter.com/"  
  ],

  "icons": {
  },

  "background": {
    "scripts": []
  },

  "browser_action": {       
    "default_title": "filter",
    "default_popup": "popup.html"
  }
}

popup.html

<button id="save-button">save-button</button>
<script src="/popup.js" type='text/javascript'></script>

popup.js

document.getElementById("save-button").onclick = function(){
    console.log("clicked button");

    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
        if(tabs.length == 0){ 
            console.log("could not send mesage to current tab");
        }else{
            chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello, how are you content script?"}, function(response) {
                console.log("received message from content script: "+response.farewell);
            });
        }
    });
}

script.js

chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");


    console.log("received message from popup: "+request.greeting);

    sendResponse({farewell: "I'm good, thank you popup!"});
});