Unload content scripts

As far as I am aware of, there is no explicit mechanism to unload/destroy content scripts, i.e. no event that would allow one to remove event listeners and stuff.

What I do in Chrome to get such an event is to create a port with chrome.runtime.connect() and listen for it’s onDisconnect event. Which works perfectly in Chrome (or all other Chromium based browsers).

Unfortunately in Firefox, that event usually isn’t fired. The best I managed here is to catch errors during the port.postMessage() in the tabs, which throws after the extension backend was un-/reloaded.
The result is that after an extension unload, changed UI in tabs won’t change until the user triggers some kind of action that sends a message, at which point I can unload in that tab - which obviously doesn’t look good.

This could probably be improved a bit by pinging, either periodically or on tab focus or something. But that still isn’t a sound solution.

Is this a bug that just wasn’t fixed or am I missing something?

It sounds like a bug.

But what I did to get around this was change my design. Rather then treating my background as “host” which is actively listening or “hosting”/keeping the content scripts kicking, – I made it like a “server”, so now the content script just sends messages to the background script and gets a response back on events that fire etc. This way I don’t have to worry about “unload” event in content script.

But if the “server” is destroyed, i send a message message to all content scripts to do a “unload”.

I know what you mean, and in some cases that ceratinly works, but it diesn’t really if the conent script for example:

  • has to handle events synchronously
  • makes visual changes to the page
    communication with the “server” background script won’t work here.
    If you till want to remove those changes whenever the extension is disabled/removed/reloaded/killed/updated/… you need an unload event in the content.

But if the “server” is destroyed, i send a message message to all content scripts to do a “unload”.

In many situations the extension won’t be able to send that before it is gone.

It sounds like a bug.

Well. The documentation on AMO does say: “Listener functions will be called when the other end has called Port.disconnect().” Which is really the only situation that will ever trigger that. Other than the port actually failing to connect in the first place.
And Firefox’s BF-cache makes using ports and content scripts somewhat more difficult.

After a lot of experimenting, this works reliably in Firefox and Chrome. It always fires an unload event after any of the situations described above, as soon as possible and at latest when the tab becomes visible or before the extension loads again:

1 Like

Too too cool thanks for sharing your learning!! :smiley: