预加载页面消息的内容脚本后台失败



Chrome扩展程序中发生了一些奇怪的事情。

内容脚本:

console.log('content');
chrome.extension.onRequest.addListener(function(request, sender, sendResponse){
    console.log('request received');
    sendResponse();
});
chrome.extension.sendRequest( JSON.stringify({'msg': 'page_loaded'}) );

它只是侦听扩展消息,并在页面加载时将消息发送到后台。

后台脚本:

console.log('bg');
chrome.extension.onRequest.addListener(function(request, sender, sendResponse){
    sendResponse();
    chrome.tabs.sendRequest(
        sender.tab.id,
        JSON.stringify({'msg': 'page_loaded_bg_receive'}),
        function(){
            console.log('sendRequest page_loaded_bg_receive callback');
        });
});

它侦听消息并将消息发送到发件人选项卡。

它似乎正在工作,至少在大多数情况下,页面日志中出现"请求已收到"。

当网址输入Chrome时,有时会在用户点击"enter"之前加载输入的地址。这是一种奇怪的行为:页面加载,内容脚本运行,将消息发送到后台,但是当后台发送消息时 - 它失败并显示后台日志消息:

端口错误:无法建立连接。接收端不存在。miscellaneous_bindings:184 chromeHidden.Port.dispatchOn断开连接 miscellaneous_bindings:184

这是Chrome错误吗?如何将消息发送到预加载选项卡?

这是重现此类行为的最小样本。我需要在处理消息后多次调用"chrome.tabs.sendRequest",因此调用"sendResponse"不是解决方案。

基于

文章的解决方案 https://developers.google.com/chrome/whitepapers/pagevisibility。如果document.webkitVisibilityState不是"隐藏"或"预渲染",我会运行内容脚本代码,在其他地方我监听"webkitvisibilitychange"并等待document.webkitVisibilityState不是"隐藏"或"预渲染"。我认为检查"预渲染"就足够了,但是当我打开一个新的空选项卡时,它会加载带有 document.webkitVisibilityState='hidden' 的页面,并且此页面也没有收到后台消息。

function isDocumentReady() {
  return document.webkitVisibilityState != "hidden" && document.webkitVisibilityState != "prerender";
}
if (isDocumentReady())
  main();
else {
  function onVisibilityChange() {
    if (!isDocumentReady())
      return;
    document.removeEventListener(
      "webkitvisibilitychange",
      onVisibilityChange,
      false);
    main();
  }
  document.addEventListener(
    "webkitvisibilitychange",
    onVisibilityChange,
    false);
}

最新更新