Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/428.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 浏览器扩展:在浏览器操作弹出窗口和后台脚本之间发送消息(带响应)_Javascript_Google Chrome Extension_Firefox Addon Webextensions - Fatal编程技术网

Javascript 浏览器扩展:在浏览器操作弹出窗口和后台脚本之间发送消息(带响应)

Javascript 浏览器扩展:在浏览器操作弹出窗口和后台脚本之间发送消息(带响应),javascript,google-chrome-extension,firefox-addon-webextensions,Javascript,Google Chrome Extension,Firefox Addon Webextensions,首先,我不是在寻找长寿的关系。我特别想寻找一种方法来发送消息,并直接回复这些消息 当您在内容脚本和后台脚本之间发送消息时,它非常简单,因为您使用chrome.tabs API从内容脚本发送/接收消息。要从后台脚本发送/接收消息,请使用chrome.runtime API 但对于浏览器操作弹出窗口,它有点不同,因为两者都在后台运行。所以我想他们都必须使用chrome.runtime API 但这意味着我必须在浏览器操作弹出窗口和后台脚本中收听chrome.runtime.onMessage。因此,

首先,我不是在寻找长寿的关系。我特别想寻找一种方法来发送消息,并直接回复这些消息

当您在内容脚本和后台脚本之间发送消息时,它非常简单,因为您使用chrome.tabs API从内容脚本发送/接收消息。要从后台脚本发送/接收消息,请使用chrome.runtime API

但对于浏览器操作弹出窗口,它有点不同,因为两者都在后台运行。所以我想他们都必须使用chrome.runtime API

但这意味着我必须在浏览器操作弹出窗口和后台脚本中收听
chrome.runtime.onMessage
。因此,基本上我会在后台脚本中接收从弹出窗口发送的消息,但也会在弹出窗口中接收消息。另一方面也是一样的

所以是的,这真的不起作用:

/////////////background-script//////////////
//Send message from background-script to browser-action-popup
chrome.runtime.sendMessage({msg:"This is a message sent from the background-script to the browser-action-popup"})
  .then(response => { //Receive response from the browser-action-popup
      console.log(response.msg)
  })

//Receive messages from browser-action-popup
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse) {
    sendResponse({msg:"This is a response message sent from the background-script"})
    return true
})


但是,由于它们都在后台运行,我还想知道,没有比发送消息更简单的方法了:是否可以在两者之间共享变量,或者它们是完全隔离运行的?

这是一个简单的方法,只需给消息一个类型或类似的消息标识符。在这个例子中,我称之为type

/////////////background-script//////////////
//Send message from background-script to browser-action-popup
var msg = {
    data : "This is a message sent from the background-script to the browser-action-popup",
    type : "notifyPopupOfMessage"
};

chrome.runtime.sendMessage(msg)
.then(response =  > { //Receive response from the browser-action-popup
        console.log(response.data);
    })

//Receive messages from browser-action-popup
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
    if (message.type === 'notifyBackgroundOfMessage') {
        var msg = {
            data : "This is a response message sent from the background-script",
            type: 'notifyPopupOfMessage'
        };

        sendResponse(msg);
    }

    return true
});

希望有帮助。

来自:

如果发送到扩展,将在扩展的每个帧中触发runtime.onMessage事件(发件人帧除外)

因此,您不必担心来自弹出窗口的消息会触发弹出窗口上的onMessage事件

你还可以通过共享变量来寻求另一种交流方式。从弹出窗口中,您可以调用它来获取背景页面的JavaScript窗口对象。从后台页面,您可以使用
{type:'popup'}
调用,以访问弹出窗口的窗口对象(如果它已打开)

for
getbackground页面
说明:

这为其他特权加载项脚本提供了直接访问后台脚本作用域的方便方法。这使他们能够访问该范围中定义的变量或调用函数。此处的“特权脚本”包括在选项页中运行的脚本,或在浏览器操作或页面操作弹出窗口中运行的脚本,但不包括内容脚本


虽然Daniel Lane的答案在理论上是可行的,但我不喜欢使用msg对象来识别发送者。实际上,我找到了一种巧妙的方法来过滤从同一“页面”(backgorund、popup等)发送的消息。
我通过识别当前页面url并将其与sender.url进行比较来完成这项工作。这是我的全部代码:

popup.js

const THIS_PAGE_URL = chrome.runtime.getURL('popup.html')

//Send message from browser-action-popup to background-script
setTimeout(function(){

    chrome.runtime.sendMessage({msg:"This is a message sent from the browser-action-popup to the background-script"})
      .then(response => { //Receive response from the background-script
          if (!response) {
              console.log("Popup sent a msg and received no response.")
              return
          }
          document.body.innerHTML += "<br>Popup sent a msg and received a response: " + response.msg
      })

}, 3000)


//Receive message from background-script
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse) {
    if (sender.url === THIS_PAGE_URL)
        return
    document.body.innerHTML += "<br>Popup received a new msg: " + message.msg
    sendResponse({msg:"This is a response message sent from the browser-action-popup"})
    return true
})
const THIS_PAGE_URL = chrome.runtime.getURL('_generated_background_page.html')

//Send message from background-script to browser-action-popup
setTimeout(function(){

    chrome.runtime.sendMessage({msg:"This is a message sent from the background-script to the browser-action-popup"})
      .then(response => { //Receive response from the browser-action-popup
          if (!response) {
              console.log("Background-script sent a msg and received no response.")
              return
          }
          console.log("Background-script sent a msg and received a response: " + response.msg)
      })

},3000)


//Receive messages from browser-action-popup
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse) {
    if (sender.url === THIS_PAGE_URL)
        return
    console.log("Background-script received a new msg: " + message.msg)
    sendResponse({msg:"This is a response message sent from the background-script"})
    return true
})
对于感兴趣的人,这里还有剩余的文件:

popup.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script src="popup.js"></script>
  </body>
</html>

那么,医生们肯定错了。至少在Firefox中是这样。弹出窗口和后台脚本都会触发它们自己的onMessage。据我记忆所及,它在内容脚本中确实有效,但我不是100%确定。@因为我引用的文档都是针对Chrome的,我没有看到firefox标签。现在你知道了两者之间的区别:)对于答案的第二部分,
getBackgroundPage
getViews
似乎也存在于Firefox上,根据docsgetViews和getBackgroundPage,我只能通过DOM进行通信,对吧?好吧,这太神奇了!这将使一切变得更加简单。Firefox(现在的旧版本)中可能存在一个导致
runtime的bug。sendMessage()
正在触发自己的
runtime.onMessage
侦听器。Firefox 50.1.0(现已过时)中存在此漏洞。在我的测试中,Firefox 51.0.1(现在是Firefox的最新版本)中没有出现这种情况。仅供参考:我已经更新了,以包括关于此错误的说明以及它可能导致锁定Firefox的事实(如果您在
运行时.onMessage
侦听器中无条件调用
运行时.sendMessage()
)。您可能需要使用Ctrl-F5重新加载页面以查看更改。这为什么不是建议的dup目标的副本?您声称这是因为您“没有寻找长寿命的连接”,但该问题/答案只提到了
connect
/
onConnect
作为各种通信方法之一,并且主要集中在使用与此问题/答案中描述的方法完全相同的多种其他方法(
sendMessage()
/
onMessage
)。换句话说,这个问题/答案是你在这里所问问题的超集。它涵盖了在后台环境中进行通信的所有方法,而不是此处讨论的有限子集。您还可以通过检查
sender.url
来检测发送者的可能重复。请注意,这是在检测发送者,而不是预期的接收者。
const THIS_PAGE_URL = chrome.runtime.getURL('_generated_background_page.html')

//Send message from background-script to browser-action-popup
setTimeout(function(){

    chrome.runtime.sendMessage({msg:"This is a message sent from the background-script to the browser-action-popup"})
      .then(response => { //Receive response from the browser-action-popup
          if (!response) {
              console.log("Background-script sent a msg and received no response.")
              return
          }
          console.log("Background-script sent a msg and received a response: " + response.msg)
      })

},3000)


//Receive messages from browser-action-popup
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse) {
    if (sender.url === THIS_PAGE_URL)
        return
    console.log("Background-script received a new msg: " + message.msg)
    sendResponse({msg:"This is a response message sent from the background-script"})
    return true
})
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script src="popup.js"></script>
  </body>
</html>
{
  "manifest_version": 2,
  "name": "popup-background-msg-example",
  "version": "1.0",

  "browser_action": {
    "browser_style": true,
    "default_title": "popup-background-msg-example",
    "default_popup": "popup.html"
  },

  "background": {
    "scripts": ["background-script.js"]
  }
}