当扩展运行时重新加载时,发生在以下任何一种情况
然后内容脚本中的大多数扩展 API 方法停止工作(包括导致问题错误的chrome.runtime.sendMessage)。有两种方法可以解决此问题。
选项 1:回退到 contentscript-only 功能
如果您的扩展程序可以在没有背景页面的情况下完美运行,那么这可能是一个可以接受的解决方案。例如。如果您的内容脚本除了修改 DOM 和/或执行跨域请求之外什么都不做。
我在我的一个扩展程序中使用以下 sn-p 来检测运行时是否仍然有效,然后再从我的内容脚本调用任何 Chrome 扩展程序 API。
// It turns out that getManifest() returns undefined when the runtime has been
// reload through chrome.runtime.reload() or after an update.
function isValidChromeRuntime() {
// It turns out that chrome.runtime.getManifest() returns undefined when the
// runtime has been reloaded.
// Note: If this detection method ever fails, try to send a message using
// chrome.runtime.sendMessage. It will throw an error upon failure.
return chrome.runtime && !!chrome.runtime.getManifest();
}
// E.g.
if (isValidChromeRuntime()) {
chrome.runtime.sendMessage( ... );
} else {
// Fall back to contentscript-only behavior
}
选项 2:在插入内容脚本时卸载之前的内容脚本
如果与背景页面的连接对您的内容脚本很重要,那么您必须实施适当的卸载例程,并设置一些事件以在内容脚本运行时卸载之前的内容脚本通过chrome.tabs.executeScript插入回来。
// Content script
function main() {
// Set up content script
}
function destructor() {
// Destruction is needed only once
document.removeEventListener(destructionEvent, destructor);
// Tear down content script: Unbind events, clear timers, restore DOM, etc.
}
var destructionEvent = 'destructmyextension_' + chrome.runtime.id;
// Unload previous content script if needed
document.dispatchEvent(new CustomEvent(destructionEvent));
document.addEventListener(destructionEvent, destructor);
main();
请注意,任何知道事件名称的页面都可能触发内容脚本的破坏。这是不可避免的,因为在扩展运行时被销毁后,就没有适当的方法与扩展进行安全通信了。