Chrome.runtime.sendMessage throws an exception from script content after restarting chrome extension

I am posting messages from inline content scripts back to my background script in my Chrome extension as such:

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

      

This works great until I reload the extension (by going to Settings -> Extensions -> "Refresh (Ctrl + R)" for my extension.)

In turn, when my background script runs, it re-calls chrome.tabs.executeScript

for all open tabs to programmatically re-enter my content script ( as I showed in this question .)

But after that, if I call this first line sendMessage

from my content script, it throws this exception:

Error: error connecting to extension my_extension_id

Any idea why this is happening?

+3


source to share


1 answer


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

then most of the extension API methods in the content script stop working (including chrome.runtime.sendMessage

what is causing the error in the question). There are two possibilities for solving this problem.

Option 1: return to text-only functions

If your extension can function fine without a background page, this might be an acceptable solution. For example. unless your content script is doing anything other than modifying the DOM and / or making cross-origin requests.

I am using the following snippet in one of my extensions to determine if there is runtime before calling 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 previous script content by script insertion content

When connecting to a background page is important to your script content, you must follow the correct unloading procedure and set up some events to unload the previous script content when the script content is inserted back through 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 the destruction of your content script. This is inevitable because after the runtime of the expansion is destroyed, there is no proper way to more fully communicate with the expansion.

+5


source







All Articles