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

时间:2016-07-19 08:00:16

标签: javascript google-chrome google-chrome-extension

我在创建Chrome扩展程序时遇到问题。

我创建了一个<iframe>,用户在点击我的扩展程序按钮时,会在任何网页中嵌入内容脚本。

在此<iframe>中,有一个选择框,当更改时,应将消息发送回扩展程序。

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

我的 manifest.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"]
  } 
}

此扩展程序包含 selectionjfm.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 Spreadsheet 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的事情,但文档说这不是强制性的,因为如果没有给出,I​​D将是我自己的扩展名。

1 个答案:

答案 0 :(得分:0)

此处的问题是您的inject.js不再是内容脚本。您已将其添加到DOM,并became indistinguishable from the page's own code。 Chrome甚至不再知道它是扩展程序的一部分(以及扩展程序)。

因此,它不能以通常的方式调用chrome.runtime.sendMessage - 这就是这个错误的含义。您需要以不同方式执行通信。

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

因此,合理的追索权是use DOM events to communicate to a content script将传递信息。

..但是等等,你已经在使用DOM事件了。你只是在错误的背景下捕捉它!您的"message"侦听器只需要是内容脚本,而不是页面级脚本。将其添加到selectionjfm.js或者考虑是否确实需要将inject.js注入页面。