重新加载Chrome扩展程序后,chrome.runtime.sendMessage会从内容脚本中抛出异常 [英] chrome.runtime.sendMessage throws exception from content script after reloading Chrome Extension

查看:640
本文介绍了重新加载Chrome扩展程序后,chrome.runtime.sendMessage会从内容脚本中抛出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的Chrome扩展程序中将注入的内容脚本的邮件发送回我的后台脚本,如下所示:

  chrome.runtime.sendMessage({action:myResult}); 

这个工作正常,直到我重新加载我的扩展(通过设置 - >扩展 - >重新加载(Ctrl + R)。)



反过来,当我的后台脚本启动时,它会重复调用 chrome.tabs.executeScript 为所有打开的选项卡以编程方式重新注入我的内容脚本

但是在我这样做之后,如果我先调用 sendMessage line from my content script ,它会抛出以下异常:
$ b


错误:连接到扩展的错误my_extension_id


有什么想法解释为什么会发生这种情况?

解决方案当扩展运行时被重新加载时,发生在以下任何一种情况中:

b $ b

则内容脚本中的大多数扩展API方法停止工作(包括导致问题中的错误的 chrome.runtime.sendMessage )。有两种方法可以解决这个问题。

选项1:回退到只有contentscript功能



如果您的扩展程序可以在没有背景页的情况下完美运行,那么这可能是一个可接受的解例如。如果您的内容脚本除修改DOM和/或执行交叉源请求外不会执行任何其他操作。



我在其中一个扩展中使用以下片段来检测是否在从我的内容脚本调用任何Chrome扩展API之前,运行时仍然有效。

  //事实证明,getManifest未定义运行时为
//通过chrome.runtime.reload()重新加载或更新后。
函数isValidChromeRuntime(){
//事实证明,当重新加载$ ​​b $ b //运行时时,chrome.runtime.getManifest()返回undefined。
//注意:如果此检测方法失败,请尝试使用
// chrome.runtime.sendMessage发送消息。它会在失败时抛出一个错误。
返回chrome.runtime&& !! chrome.runtime.getManifest();
}

//例如
if(isValidChromeRuntime()){
chrome.runtime.sendMessage(...);
} else {
//回退到内容表达式行为
}



选项2:在内容脚本插入时卸载先前的内容脚本



当与后台页面的连接对您的内容脚本非常重要时,您必须实施适当的卸载例程,并在内容脚本通过 chrome.tabs.executeScript

 函数main(){
//设置内容脚本
}

函数析构函数(){
//销毁只需要一次
document.removeEventListener(destroyEvent,destructor);
//撕下内容脚本:解除绑定事件,清除计时器,恢复DOM等。
}

var destroyEvent ='destructmyextension_'+ chrome.runtime.id;
//如果需要,卸载以前的内容脚本
document.dispatchEvent(new CustomEvent(destroyEvent));
document.addEventListener(destroyEvent,析构函数);
main();

请注意,任何知道事件名称的页面都会触发内容脚本的销毁。这是不可避免的,因为在扩展运行时被破坏之后,没有适当的方式来与扩展进行安全通信。


I send messages from the injected content scripts back to my background script in my Chrome Extension as such:

chrome.runtime.sendMessage({action: "myResult"});

This works fine, until I reload my extension (by going to Settings -> Extensions -> "Reload (Ctrl+R)" for my extension.)

In turn when my background script starts up it repeatedly calls chrome.tabs.executeScript for all open tabs to programmatically re-inject my content script (as I showed in this question.)

But after I do that, if I call that first sendMessage line from my content script, it throws this exception:

Error: Error connecting to extension my_extension_id

Any idea why this happens?

解决方案

When the extension runtime is reloaded, which happens in any of the following cases

  • You've called chrome.runtime.reload().
  • You've clicked on Reload extension at chrome://extensions/.
  • The extension was updated.

then the most extension API methods in the content script cease to work (including chrome.runtime.sendMessage which causes the error in the question). There are two ways to work around this problem.

Option 1: Fall back to contentscript-only functionality

If your extension can function perfectly without a background page, then this could be an acceptable solution. E.g. if your content script does nothing else besides modifying the DOM and/or performing cross-origin requests.

I'm using the following snippet in one of my extensions to detect whether the runtime is still valid before invoking any Chrome extension API from my content script.

// 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
}

Option 2: Unload the previous content script on content script insertion

When a connection with the background page is important to your content script, then you have to implement a proper unloading routine, and set up some events to unload the previous content script when the content script is inserted back via 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();

Note that any page that knows the name of the event can trigger destruction of your content script. This is unavoidable, because after the extension runtime is destroyed, there are no proper ways to securely communicate with the extension any more.

这篇关于重新加载Chrome扩展程序后,chrome.runtime.sendMessage会从内容脚本中抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆