调用 chrome.runtime.sendMessage() 时出现“扩展上下文无效”错误

Ata*_*v32 8 google-chrome-extension content-script

我在 Chrome 扩展程序中有一个用于传递消息的内容脚本。每隔一段时间,当内容脚本调用时

chrome.runtime.sendMessage({
  message: 'hello',
});
Run Code Online (Sandbox Code Playgroud)

它抛出一个错误:

Uncaught Error: Extension context invalidated.
Run Code Online (Sandbox Code Playgroud)

这个错误是什么意思?我找不到任何有关它的文档。

它不会持续发生。事实上,它很难重现。如果我只是让页面在后台打开一段时间,似乎就会发生这种情况。


另一个线索:我已经编写了许多带有传递消息的内容脚本的 Chrome 扩展,但我以前没有见过这个错误。主要区别在于该内容脚本是由后台页面使用注入的

chrome.tabs.executeScript({
  file: 'contentScript.js',
});
Run Code Online (Sandbox Code Playgroud)

使用executeScript而不是清单文件是否会以某种方式改变内容脚本的生命周期?

her*_*ues 4

这肯定与消息监听器在内容和后台脚本连接过程中丢失有关。

\n\n

我一直在我的扩展中使用这种方法,这样我就有了一个可以在后台和内容脚本中使用的模块。

\n\n

messenger.js

\n\n
const context = (typeof browser.runtime.getBackgroundPage !== \'function\') ? \'content\' : \'background\'\n\nchrome.runtime.onConnect.addListener(function (port) {\n  port.onMessage.addListener(function (request) {\n    try {\n      const object = window.myGlobalModule[request.class]\n      object[request.action].apply(module, request.data)\n    } catch () {\n      console.error(error)\n    }\n  })\n})\n\nexport function postMessage (request) {\n  if (context === \'content\') {\n    const port = chrome.runtime.connect()\n    port.postMessage(request)\n  }\n\n  if (context === \'background\') {\n    if (request.allTabs) {\n      chrome.tabs.query({}, (tabs) => {\n        for (let i = 0; i < tabs.length; ++i) {\n          const port = chrome.tabs.connect(tabs[i].id)\n          port.postMessage(request)\n        }\n      })\n    } else if (request.tabId) {\n      const port = chrome.tabs.connect(request.tabId)\n      port.postMessage(request)\n    } else if (request.tabDomain) {\n      const url = `*://*.${request.tabDomain}/*`\n      chrome.tabs.query({ url }, (tabs) => {\n        tabs.forEach((tab) => {\n          const port = chrome.tabs.connect(tab.id)\n          port.postMessage(request)\n        })\n      })\n    } else {\n      query({ active: true, currentWindow: true }, (tabs) => {\n        const port = chrome.tabs.connect(tabs[0].id)\n        port.postMessage(request)\n      })\n    }\n  }\n}\n\nexport default { postMessage }\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在您只需在内容和后台脚本中导入此模块即可。如果您想发送消息,只需执行以下操作:

\n\n
messenger.postMessage({\n   class: \'someClassInMyGlobalModu\xc3\xa7e\',\n   action: \'someMethodOfThatClass\',\n   data: [] // any data type you want to send\n})\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以指定是否要发送到allTabs: true特定域tabDomain: \'google.com\'或单个选项卡tabId: 12

\n