为什么插件页面收不到消息?

Why cannot the addon page receive message?

我正在尝试从插件(webextension)向插件中的 html 页面发送消息。 Webextension API 正在使用与 Chrome 浏览器兼容的 chrome 界面。我正在使用 Firefox 48 测试版。

这是后台脚本("initiate-page" 消息很重要):

chrome.runtime.onMessage.addListener(  
  function(package, sender
    ){
    switch (package.message){
      case "open":
        if (package.subject == "tab")
          {
          win = myNamespace.tabs[package.module];
          result = win ? false : true; 

          if (result)
            chrome.tabs.create(
              {"url": package.url },
              function(tab) {        
                if (chrome.extension.lastError )
                  console.log(chrome.extension.lastError);
                else
                  myNamespace.tabs[package.module] = tab.id;
                chrome.tabs.onRemoved.addListener(
                    function( tabId, removeInfo )                    
                    {
                    for (var k in myNamespace.tabs )
                      {
                      if (tabId === myNamespace.tabs[k])
                        {
                        myNamespace.tabs[k] = null;
                        break;
                        } 
                      }  
                    }
                  );
              }
            );
          }
      break;
      case "initiate-page":
        if (package.subject == "html-add-listeners")
          {
          switch(package.module){
            case "easy_options":
            case "advanced_options":
            case "images_options":            
            chrome.tabs.sendMessage(
              package.sender.id,
              { message:"initiate-page-response", 
                subject:"accept-namespace", 
                recepient: {id: package.sender.id },
                module: package.module,
                namespace: myNamespace,
                info: "response to tab exists message"   
              }
             )
            break;
            }
          }
      break;
    }
  }
)

因此,当插件收到来自模块 "easy_options" 的消息时,这意味着 easy_options.html 需要一些数据来加载到其文档中。因此,我发送了一条包含数据的名称空间的消息。

现在是插件页面 easy_options.js(同样,第二部分很重要,其中添加了 chrome.runtime.onMessage 侦听器):

chrome.tabs.query(
{ active: true,  currentWindow: true}, 
  function(tabs) {
    browser.runtime.sendMessage(
      { message:"initiate-page", 
        subject: "html-add-listeners",
        module: "easy_options",
        sender:{id:tabs[0].id}   
      }
      )
  }
);

chrome.runtime.onMessage.addListener(  
  function(package, sender
    ){
    switch (package.message){
      case "initiate-page-response":    
        if (package.subject == "accept-namespace")
          {
          switch(package.module){
            case "easy_options":
              document.addEventListener('DOMContentLoaded', myNamespace.easy.restore);
              document.getElementById("easy_form_save").addEventListener("submit", myNamespace.easy.save);
              document.getElementById("easy_form_restore").addEventListener("submit", myNamespace.easy.restore);
              document.getElementById("easy_form_remove_item").addEventListener("submit", myNamespace.easy.remove_profiles);
              document.getElementById("easy_form_remove_profiles").addEventListener("submit", myNamespace.easy.remove_profiles);
              document.getElementById("list").addEventListener("change", myNamespace.easy.restoreDefault);
            break;
            }
          }
      break;
    }
  }
)

发生的事情是: 1. 我向后台侦听器发送消息 (A),它接受该消息 2.后台监听发送消息(B) 3. 插件选项脚本在 runtime.OnMessage 侦听器中接收第一条消息 (A)(我不想处理此消息)

应该发生什么 1. 我向后台侦听器发送消息 (A),它接受该消息 2.后台监听发送消息(B) 3. 插件选项脚本在 runtime.OnMessage 侦听器中接收到第一条消息 (A)(我不想处理这条消息) 4. 插件选项脚本应该在 runtime.OnMessage 侦听器中接收第二条消息 (B),我应该处理它

问题: 为什么第四步没有发生?为什么收不到消息(B别名"initiate-page-response")?

也许 Chrome 插件程序员也可以提供帮助,我认为事情应该类似地工作。

因为它是一个扩展页面,而不是内容脚本,chrome.tabs.sendMessage 无法访问它。

您需要使用 chrome.runtime.sendMessage 广播消息才能到达 chrome-extension:// 个页面,例如选项页面。

如果您不喜欢 runtime.sendMessage 的广播性质,您应该使用 sendResponse 回调参数将响应传回给发送者(可能更可取),或者建立一个长期存在的端口runtime.connect.

感谢 Xan 的解释,我发现这很有魅力

后台脚本:

chrome.runtime.onMessage.addListener(  
  function(package, sender, sendResponse
    ){
    switch (package.message){
      case "open":
        if (package.subject == "tab")
          {
          win = myNamespace.tabs[package.module];
          result = win ? false : true; 

          if (result)
            chrome.tabs.create(
              {"url": package.url },
              function(tab) {        
                if (chrome.extension.lastError )
                  console.log(chrome.extension.lastError);
                else
                  myNamespace.tabs[package.module] = tab.id;
                chrome.tabs.onRemoved.addListener(
                    function( tabId, removeInfo )                    
                    {
                    for (var k in myNamespace.tabs )
                      {
                      if (tabId === myNamespace.tabs[k])
                        {
                        myNamespace.tabs[k] = null;
                        break;
                        } 
                      }  
                    }
                  );
              }
            );
          }
      break;
      case "initiate-page":    
        if (package.subject == "html-add-listeners")
          {
          switch(package.module){
            case "easy_options":
            case "advanced_options":
            case "images_options":            
            sendResponse(
              { message:"initiate-page-response", 
                subject:"accept-namespace", 
                recepient: {id: package.sender.id },
                module: package.module,
                namespace: myNamespace,
                info: "response to initiate-page message"   
              }
             )
            break;
            }
          }
      break;
    }
  }
)

插件的选项页面脚本:

chrome.tabs.query(
{ active: true,  currentWindow: true}, 
  function(tabs) {
    browser.runtime.sendMessage(
      { message:"initiate-page", 
        subject: "html-add-listeners",
        module: "easy_options",
        sender:{id:tabs[0].id}   
      },
      function response(message){
        console.log("RESPONSE:");
        console.log(message);
      return true;
      }
      )
  }
);