Service worker killed even with extension page port open

441 views
Skip to first unread message

Don Schmitt

unread,
Jul 12, 2022, 7:45:28 PM7/12/22
to chromium-extensions
I have more service worker keep-alive concerns.

First, we have an extension page (chrome-extension://blahblah/page.html)  opened in a tab that has a port connected to the extension service worker.  Why wouldn't that also keep the service worker alive?  I mean, the user has an active page they are using that is supported by the service worker, it makes no sense that Chrome would force that service worker to shut down.  Is this by design?

Secondly, we do have a native messaging app, but even though a native messaging port is open, the service worker is still being terminated after about 5 minutes.  Am I right that a fix for this should land in build 104 with this fix:  https://bugs.chromium.org/p/chromium/issues/detail?id=1189678 ?

Thanks!
--
Don


Simeon Vincent

unread,
Jul 12, 2022, 9:58:28 PM7/12/22
to Don Schmitt, chromium-extensions
Is this by design?

Yes. Extension message ports are not meant to keep an extension service worker alive indefinitely.

Based on what you've shared so far, an adaptation strategy you may want to consider is to inject an extension iframe the page. This frame's lifetime will match that of the page and can be used to perform page-specific operations that require extension APIs.  

If you can share more about your use case, I may be able to give more concrete suggestions.

Am I right that a fix for this should land in build 104 with this fix:  https://bugs.chromium.org/p/chromium/issues/detail?id=1189678 ?

The latest changes (comment 101) are slated to land in 104, but the issue is not completely resolved. There is a known issue where opening or closing devtools (offhand I can't recall which) will trigger the 5 minute timer and eventual service worker termination. The situation should be improved in 104, but it's possible that there are other bugs that will cause the service worker to be terminated despite having an open native messaging port.

I'd encourage you to test your extension in the Dev or Canary versions of Chrome and to comment on issue 1189678 if you observe unexpected extension service worker termination while a native messaging port is open.

Simeon - @dotproto
Chrome Extensions DevRel


--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/CAM7AMpJo1qQ0YfbjnG0wqDqB5c4Fc%3DWvSvD9z4EPNcPS%2BJHSMQ%40mail.gmail.com.

Don Schmitt

unread,
Jul 12, 2022, 11:32:53 PM7/12/22
to Simeon Vincent, chromium-extensions
Hi Simeon,

Thanks for the prompt reply, I'll test the beta to confirm the native messaging exception, that sounds like good news.

But to clarify, in the other case, this is an actual extension web page, not a content script, so it doesn't even need the iframe trick (I think you might have been thinking of a content script).

>>>> Is this by design?
>>>> Yes. Extension message ports are not meant to keep an extension service worker alive indefinitely.

What confuses me is this:  If a user opens a web page to joeshmoe.com, then joeshmoe.com can keep a shared worker open as long as the user has a joeshmoe.com web page open.  Why wouldn't an extension be given at least the same functionality as joeshmoe.com?  We aren't talking about long-lived things in the background, we're talking about supporting visible, functional web pages that the user is actually using.

The specific scenario is that we are rendering a page that is getting data from a websocket that is shared between tabs and needs to do extension-y things in that context.  We could potentially share a websocket in a shared worker, but you can't currently do chrome.* things in a shared worker.   (note:  we would have the same problem with sharing a native messaging port between tabs, but that should be fixed by the pending exception that allows service workers to stay alive when they have open native messaging ports).

Thanks!
--
Don



Simeon Vincent

unread,
Jul 13, 2022, 12:46:46 AM7/13/22
to Don Schmitt, chromium-extensions
Timing was coincidental. Unfortunately I'm not able to hang around here and share info as much as I'd like, but when I have time I do my best to be helpful.

Yep, as you suspected, I was assuming you were working with a content script on a website. If the user is interacting with a long lived extension page, there may not be much reason to lean on the extension's service worker. 

Why wouldn't an extension be given at least the same functionality as joeshmoe.com?

Taking your question literally, they are given that same functionality. If a user opens a web page to chrome-extension://<ID>/index.html, then the extension can keep a shared worker open as long as the user has a chrome-extension://<ID> web page open.

As you highlighted, shared workers in extensions don't have access to the chrome global and therefore cannot directly call extension platform APIs, but joeshmoe.com can't do that either. In the extension's case, though, you can use messaging APIs to coordinate with other extension contexts such as the page that created the shared worker, the extension's service worker, or (in the future) an offscreen document to leverage more of the extension platform's capabilities.

If I may, the question may be better framed as "why is Chrome's extension platform moving away from background pages at all?" I've written about this a few times and I was really hoping I covered this in the Extension platform vision docs, but I see now that we didn't actually discuss the role of an event-based background context there. Another item for the backlog, I guess. The Background Process section of the Manifest V3 design document describes this better than I will be able to at the moment. 

Simeon - @dotproto
Chrome Extensions DevRel

Don Schmitt

unread,
Jul 13, 2022, 11:51:10 AM7/13/22
to Simeon Vincent, chromium-extensions
Re-phrase that first line:   So the question is:  What's the solution to needing access to chrome.* apis in a shared context between tabs extension pages that it has open?

On Wed, Jul 13, 2022 at 8:48 AM Don Schmitt <donc...@gmail.com> wrote:
So the question is:  What's the solution to needing access to chrome.* apis in a shared context between tabs?

You are right that an extension can literally do the same thing as a web page.  But what I intended to convey with the analogy was:  joeshmoe.com's web page can do the things that it normally has permission to do in a shared context.  Extensions do not have that ability.

I disagree that my question would be better framed as "why is Chrome moving away from background pages".  I'm not trying to relitigate that question :-).

I opened a bug on this issue years ago which got muddled down in the same, incorrect, framing  (https://bugs.chromium.org/p/chromium/issues/detail?id=1032094#c1).  A bit frustrating to be in the same place, but I'll try again:

My request is for an extension that has pages open to also have the ability to have a shared context between its open pages in which to do the things it can normally do, (chrome.*-y things).  I'm not asking for persistence beyond that, although in our context, a slight delay of being allowed to live between the short closing of one tab and the opening of another may be important (and would be nicely covered by the current service worker lifetime implementation).

One solution to this would be to allow a service worker to stay open as long as an extension has web pages open that are connected to it.

For that matter, I think the general exception should be:  Don't close the service worker if the extension has an actual page open (not a content script).  You might argue that this could be abused, but it would require the extension to have a page open, which can already do all of these things, you aren't stopping any abuse by closing an extension's service worker when it has pages open, you're just preventing the extension from having a  shared context to do work on behalf of those pages.

--
Don


Simeon Vincent

unread,
Jul 14, 2022, 5:21:42 PM7/14/22
to Don Schmitt, chromium-extensions
Thanks for the clarification.

The most direct way to work around this limitation of not having access to the chrome global in worker contexts is to post messages to another context that does have this access. The two main ways I see to do this are to either A) leverage the existing message ports that are created when instantiating a shared worker to communicate with one of the pages that spawned the shared worker or B) use a broadcast channel to communicate with another extension context (page, service worker, etc.). If you go with one of these approaches, you may want to consider using the actor model and a library like clooney to expose a more ergonomic API in your shared worker script. 

Another more exotic option is to expose a REST API in your service worker. In this flow, the shared worker would use fetch() to make HTTP requests as if it were communicating with a remote server and the service worker's fetch handler would intercept those requests, perform the necessary API calls against the chrome global, and issue an HTTP response with the results. There aren't really any advantages to this approach, it's just kinda cool that it's an option. 

Simeon - @dotproto
Chrome Extensions DevRel

Don Schmitt

unread,
Jul 14, 2022, 8:21:29 PM7/14/22
to Simeon Vincent, chromium-extensions
Thanks for the creative suggestions, we will test using the shared worker for the websocket and let the extension pages do the chrome.*-y stuffy.

But here's a thought about service worker lifetime:  Since an extension web page can essentially do anything an extension service worker can do, and an open extension page is an obvious indicator that the extension is being actively used by the user, then there should be a service worker lifetime exception wherein the service worker should never be closed when the extension has pages open (especially with open ports to the service worker).  The user gains nothing by having Chrome close the service worker since the extension pages can be doing almost all the same things.    You can close the service worker after the user is done using the extension pages.

Shutting down the service worker is potentially harmful to the user since it will require each page to have all the code it requires to do its work, resulting in a potentially massive duplication of code (and thus resources) when there are multiple extension pages open (which is frequently the case for us).

And of course the extension developer loses a valuable tool with a shared context that can do chrome.*-y work.


--
Don






wOxxOm

unread,
Jul 15, 2022, 2:54:20 AM7/15/22
to Chromium Extensions, Don Schmitt, chromium-extensions, Simeon Vincent
Don, all you need is to reconnect the port every 295 seconds i.e. before its 5 minute elapse, and it'll keep the SW alive.
Reply all
Reply to author
Forward
0 new messages