chrome.runtime.sendMessage未捕获错误:要连接的参数无效

chrome.runtime.sendMessage Uncaught Error: Invalid arguments to connect

本文关键字:连接 参数 无效 错误 sendMessage runtime chrome      更新时间:2023-09-26

我在创建Chrome扩展时遇到了一个问题。

我创建了一个<iframe>,当用户单击我的扩展按钮时,它将被内容脚本嵌入到任何网页中。

在这个<iframe>中,有一个选择框,当它被更改时,应该向扩展发送回一条消息。

然后,扩展应该从Google电子表格中获取数据,然后将信息发送回<iframe>

Mymanifest.json如下(编者注:过滤到相关字段):

{
  // manifest.json
  "background" : {
    "scripts" : ["background.js"]
  },
  "browser_action": {
    "default_icon": "icon-small.png"
  },
  "content_scripts": [ {
    "js": ["jquery-1.11.1.min.js","selectionjfm.js","jquery-ui.min.js","nlp_compromise.js"],
    "css":["jquery-ui.css"],
    "matches": [ "http://*/*", "https://*/*"],
    "all_frames":true,
    "run_at": "document_end",
    "info.status":"complete", "status": "complete"
  }],
  // ...    
  "permissions": [
    "identity", "https://accounts.google.com/*", "https://www.googleapis.com/*","https://spreadsheets.google.com/*","tabs","storage","<all_urls>"
  ],
  "web_accessible_resources": [
    "jquery-ui.min.js","popup.html","popup.js","inject.js","jquery-1.11.1.min.js","loader.gif"
  ],
  "oauth2": {
    "client_id": "xxxxxxxxx.apps.googleusercontent.com",
    "scopes": ["https://www.googleapis.com/auth/plus.login","https://spreadsheets.google.com/feeds"]
  } 
}

这个扩展包括一个选择jfm.js作为内容脚本,它以这种方式插入一个<iframe>

// selectionjfm.js - content script as included in manifest.json
var iframe = document.createElement('iframe');
iframe.setAttribute("id", "my_id");
iframe.src = chrome.runtime.getURL('popup.html');
document.body.appendChild(iframe);

但是也注入一个JavaScript文件inject.js这样:

// selectionjfm.js - content script as included in manifest.json
var s = document.createElement('script');
s.src = chrome.runtime.getURL('inject.js');
(document.head || document.documentElement).appendChild(s);
console.log("[Content script 1] added inject.js to the content page");
var s = document.createElement('script');
s.src = chrome.runtime.getURL('jquery-1.11.1.min.js');
(document.head || document.documentElement).appendChild(s);

包含一个选择框。当用户在此框中选择另一个值时,我需要使用Google电子表格API对Google电子表格运行请求。这就是为什么我想向扩展发送一条消息,因为我知道只有从那里我才能使用那些API。

inject.js在触发<iframe>的选择框上的onchange事件时等待<iframe>发送的消息。

// inject.js waitning for message from the iframe
window.addEventListener("message",
    function (e) {...

<iframe>:发送的消息

//poupup.js (iframe source)
var sel = document.getElementById("databaseselect");
            sel.addEventListener("change", function (e) {               
                sendMessTobg("changedatabase",sel.selectedOptions[0].text);     

            });

然后它尝试向background.js:发送消息

// inject.js
if (e.data.message == "changedatabase") { // recieving message from the iframe : this works fine
  if (e.data.data != null) {
    console.log("[Content script] trying to send databasechange to extension");
    chrome.runtime.sendMessage({
      databasechange:true,
      content:e.data.data
    }, function (reply) {
      if (chrome.runtime.lastError) {
        console.log("[Content script] failure to send databasechange to extension");
      } else {
        console.log("[Content script] databasechange with backgroud is a success!");
      }
    });
  }
}

则是chrome.runtime.sendMessage给出错误:

未捕获错误:要连接的参数无效。

我在另一篇帖子中看到了关于发送扩展ID的内容,但文档中说这不是强制性的,因为如果不提供,ID将是我自己的扩展ID。

这里的问题是inject.js不再是一个内容脚本。您将它添加到DOM中,它与页面自己的代码变得无法区分。Chrome甚至不再知道它是扩展的一部分(以及哪个扩展)。

因此,它不能以通常的方式调用chrome.runtime.sendMessage——这就是这个错误的原因。你需要以不同的方式进行沟通。

externally_connectable不适用于您的案例,因为您希望它在任何网站上运行,并且该方法需要将特定域列入白名单。

因此,逻辑追索权是使用DOM事件与将传递消息的内容脚本进行通信。

但是等一下,您已经在使用DOM事件了。你只是在错误的上下文中发现了它!您的"message"侦听器必须是一个内容脚本,而不是页面级别的脚本。要么将其添加到selectionjfm.js中,要么考虑是否真的需要将inject.js注入到页面中。