如何将消息从后台脚本发送到内容脚本?

时间:2020-06-29 15:33:57

标签: google-chrome-extension

我希望我的chrome扩展程序中的后台脚本将消息发送到内容脚本,然后等待响应。我尝试了几种不同的解决方案,但总是遇到相同的错误:

_genic_background_page.html:1未经检查的runtime.lastError:无法建立连接。接收端不存在。

_genic_background_page.html:1错误处理响应:TypeError:无法读取未定义的属性“ getSelected” 在chrome-extension://pkolpfkgeblgjiiaklpppfmeomlkbhop/background_script.js:11:25

我也已经尝试禁用所有其他chrome扩展程序。

所有可能很重要的代码:

//background_script.js

chrome.contextMenus.onClicked.addListener(function(info, tab){
    chrome.tabs.sendMessage(tab.id, {
        content: "getSelected"
    },  function(response) {
            console.log(response.getSelected());
        });
});
//content_script.js

chrome.runtime.onMessage.addListener(function(message, sender, callback) {
        if (message.content == "getSelected") {
            callback({getSelected: getSelected()});
    }
});
//manifest.json

{
  "manifest_version": 2,
  "content_scripts":[ {
    "matches": ["<all_urls>"],
    "js": ["content_script.js"]
  }],
  "background":{
    "scripts": ["background_script.js"]
  },
  "permissions": [
   "*://*/*",
   "activeTab",
   "declarativeContent",
   "storage",
   "contextMenus",
   "tabs"
   ]
}

提前感谢您的帮助:)

1 个答案:

答案 0 :(得分:0)

  1. 您需要在内容脚本中定义getSelected(),它不是内置函数。您可能是说getSelection()是内置函数。
  2. 发送响应后,它不是一个函数,因此无法调用:您需要在()中删除response.getSelected()
  3. Receiving end does not exist通常意味着选项卡不运行内容脚本:

显然您要获取当前选定的文本,在这种情况下,您根本不需要声明的内容脚本,因此可以删除content_scripts部分,而使用程序注入:

chrome.contextMenus.onClicked.addListener((info, tab) => {
  chrome.tabs.executeScript(tab.id, {
    frameId: info.frameId,
    runAt: 'document_start',
    code: 'getSelection().toString()',
  }, ([sel] = []) => {
    if (!chrome.runtime.lastError) {
      console.log(sel);
    }
  })
});

注意:

  • getSelection()返回一个Selection对象,它是一个复杂的DOM对象,因此无法传输,因此我们将选择内容明确提取为字符串。
  • 只能传输简单类型,例如字符串,数字,布尔值,null和此类简单类型的数组/对象。
  • 我们在用户调用菜单的地方使用frameId
  • 使用runAt: 'document_start'可确保即使页面仍在加载其初始HTML,代码也可以立即运行
  • 对于此特定任务,您不需要"*://*/*"中的tabspermissions
  • Where to read console messages from background.js in a Chrome extension?

P.S。对于更复杂的数据提取,请使用file: 'content.js',而不是code: ....,并像这样从content.js传递最后一个表达式:

function foo() {
  let results;
  // .......
  return results;
}

foo(); // this line should be the last executed expression in content.js