您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

将消息从后台脚本发送到内容脚本,然后发送到注入的脚本

将消息从后台脚本发送到内容脚本,然后发送到注入的脚本

由于内容脚本的注入方式,您的脚本无法使用。

与某些人期望的相反,当您(重新)加载扩展程序时,Chrome 与清单中的模式匹配的 中。仅在加载扩展名之后,任何导航都将检查URL是否匹配并注入代码

因此,时间表:

1-如果您重新加载扩展程序,也会发生这种情况。如果注入了内容脚本,它将继续处理其事件/不会被卸载,但无法再与扩展通信。(有关详细信息,请参阅末尾的附录)

解决方案1: ,然后在静音时以编程方式注入脚本。考虑:

// Background
function ensureSendMessage(tabId, message, callback){
  chrome.tabs.sendMessage(tabId, {ping: true}, function(response){
    if(response && response.pong) { // Content script ready
      chrome.tabs.sendMessage(tabId, message, callback);
    } else { // No listener on the other end
      chrome.tabs.executeScript(tabId, {file: "content_script.js"}, function(){
        if(chrome.runtime.lastError) {
          console.error(chrome.runtime.lastError);
          throw Error("Unable to inject script into tab " + tabId);
        }
        // OK, Now it's injected and ready
        chrome.tabs.sendMessage(tabId, message, callback);
      });
    }
  });
}

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
  ensureSendMessage(tabs[0].id, {greeting: "hello"});
});

// Content script
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if(request.ping) { sendResponse({pong: true}); return; }
  /* Content script action */
});

解决方案2:

// Background
function ensureSendMessage(tabId, message, callback){
  chrome.tabs.executeScript(tabId, {file: "content_script.js"}, function(){
    if(chrome.runtime.lastError) {
      console.error(chrome.runtime.lastError);
      throw Error("Unable to inject script into tab " + tabId);
    }
    // OK, Now it's injected and ready
    chrome.tabs.sendMessage(tabId, message, callback);
  });
}

// Content script
var injected;

if(!injected){
  injected = true;
  /* your toplevel code */
}

这比较简单,但是在扩展分机重新加载方面比较复杂。重新加载扩展后,旧脚本仍然存在1,但它不再是“您的”上下文- 因此injected将是未定义的。当心可能两次执行脚本的副作用。

解决方案3: 。仅当可以安全运行两次相同的内容脚本或在页面完全加载后运行该脚本时,才可以安全地执行此操作。

chrome.tabs.query({}, function(tabs) {
  for(var i in tabs) {
    // Filter by url if needed; that would require "tabs" permission
    // Note that injection will simply fail for tabs that you don't have permissions for
    chrome.tabs.executeScript(tabs[i].id, {file: "content_script.js"}, function() {
      // Now you can use normal messaging
    });
  }
});

我也怀疑您希望它以某种操作运行,而不是以扩展负载运行。例如,您可以使用浏览器动作并将代码包装在chrome.browserAction.onClicked侦听器中。

重新加载扩展程序后,人们会期望Chrome清理所有内容脚本。但是显然不是这样。内容脚本的侦听器未禁用。但是,任何带有父扩展名的消息传递都会失败。这可能应该被认为是一个错误,并且可能在某个时候被修复。 我将这个状态称为“孤立”

在两种情况下,这都不是问题:

但是,如果不是这种情况,那么您就会遇到问题:内容脚本可能正在执行某些操作,但是失败或干扰了其自身的另一个非孤立实例。

一个解决方案是:

代码内容脚本:

function heartbeat(success, failure) {
  chrome.runtime.sendMessage({heartbeat: true}, function(reply){
    if(chrome.runtime.lastError){
      failure();
    } else {
      success();
    }
  });
}

function handler() {
  heartbeat(
    function(){ // hearbeat success
      /* Do stuff */
    }, 
    function(){ // hearbeat failure
      someEvent.removeListener(handler);
      console.log("Goodbye, cruel world!");
    }
  );
}
someEvent.addListener(handler);

后台脚本:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if(request.heartbeat) { sendResponse(request); return; }
  /* ... */
});
其他 2022/1/1 18:19:45 有540人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶