moving to MV3, unload event message sometimes not send to background

78 views
Skip to first unread message

joette cordsen

unread,
Oct 15, 2021, 8:14:18 AM10/15/21
to Chromium Extensions
I'm using an unload handler in a content script that sends a message to the background when the tab is closed/unloaded and the message is sometimes not received. If I close the tab by clicking the x in the tab title it is never received. If the tab is closed in some other manner (based on user interaction with the page), it is rarely but occasionally not received. 

First, is using window.addEventListener("unload", function (ev) {...}) the right way to do do this? when I read the documentation in some places it mentions this event may not be reliable - although I have been using it for years with MV2 w/o problems.

 And, second is it known problem that sometimes messages aren't received by the background script? I send the message using chrome.runtime.sendMessage. The background script is defined in my manifest file like this: 

"background": {
    "service_worker": "serviceworkmain.js"
  },

Tx!

wOxxOm

unread,
Oct 15, 2021, 11:03:25 AM10/15/21
to Chromium Extensions, jill...@gmail.com
There's no guarantee such message will be sent because Chrome won't wait for it when closing the tab. It worked for you in the past because you probably used a persistent background script in ManifestV2 i.e. there was no "persistent": false, and you lucked out that the message was sent just in time before Chrome terminated the process.

One reliable solution is to use chrome.tabs.onRemoved in the background script. To detect navigation to a different page/site, you can use chrome.tabs.onUpdated or chrome.webNavigation.onCommitted. Of course, depending on what specifically you want to do in the background script, it may be nontrivial or inefficient to use this approach.

Another reliable solution is to keep an open chrome.runtime port: when the tab is closed or navigated away the port's onDisconnect will be fired in the background script. In ManifestV3 you'll have to reopen it every five minutes, otherwise the service worker will be terminated. Although it will consume some memory, but the overall effect would be positive because restarting the service worker for every unload event hundreds of times a day is much more wasteful and, in case of a portable device, is bad for the battery life.

content script:

    reconnect();
    function reconnect(port) {
      port?.onDisconnect.removeListener(reconnect);
      chrome.runtime.connect({name: 'unload'})
        .onDisconnect.addListener(reconnect);
    }

background script:

    chrome.runtime.onConnect.addListener(port => {
      if (port.name === 'unload') {
        port.timer = setTimeout(onTimer, 270e3, port);
        port.onDisconnect.addListener(onUnload);
      }
    });
    
    function onTimer(port) {
      port.onDisconnect.removeListener(onUnload);
      port.disconnect();
    }
    
    function onUnload(port) {
      clearTimeout(port.timer);
      console.log('diconnected', port.sender);
    }

joette cordsen

unread,
Oct 15, 2021, 11:52:29 AM10/15/21
to Chromium Extensions, wOxxOm, joette cordsen
Incredibly Helpful. Thank you so much!
Reply all
Reply to author
Forward
0 new messages