Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Extension's service worker seems to be getting cached by some machines

828 views
Skip to first unread message

Allen Yang

unread,
Jul 16, 2024, 8:26:00 PM7/16/24
to Chromium Extensions
Hi all,

Short version: I've been iterating on a Chrome extension, and I'm seeing that the extension behaves differently on different machines and even different Chrome profiles on the same machine, when the extension was installed by those profiles at different points in time. Specifically, the difference in behavior is notable in relation to dynamicNetRequests not working consistently. It's leading me to believe that the browser is caching or otherwise using a stale version of the service worker script in the extension. I've tried clearing the profile's cache, uninstalling + reinstalling the extension, renaming the script, and restarting Chrome - none of those work. 

Has anybody else bumped into this issue? Is there a way to forcibly clear any old version of a service worker script from a profile?

=====

Longer version, in case there's specifically an interaction with declarativeNetRequests:

I've written a Chrome extension that watches for the user typing in a certain URL pattern and applies a declarativeNetRequest rule. Specifically, the extension detects if the user types in a go-link of the format "go/blah", and handles a redirect. Over time, I've shifted how the declarativeNetRequest is declared.

The simplest version of the rule I want that should work is a static rule, declared here in manifest.json:
```
"declarative_net_request": {
        "rule_resources": [
            {
                "id": "ruleset_1",
                "enabled": true,
                "path": "rules.json"
            }
        ]
    },
```

And rules.json has:
```
[
    {
        "id": 1,
        "priority": 1,
        "action": {
            "type": "redirect",
            "redirect": {
                "regexSubstitution": "https://thisismydomain.com/go/\\1"
            }
        },
        "condition": {
            "regexFilter": "^https?://go/(.*)",
            "resourceTypes": ["main_frame"]
        }
    }
]
```

At one point, I also tried using a dynamic rule. I have a background service worker script declared in manifest.json, and that script did something like:
```
const RULES = [{
        id: 1,
        priority: 2,
        action: {
            type: 'redirect',
            redirect: {
                regexSubstitution: "https://thisismydomain.com/go/\\1"
            },
        },
        condition: {
            regexFilter: '^https?:\/\/.+google.com\/[^q]*q\=go%2F([^&]*)&.*',
            resourceTypes: ['main_frame', 'sub_frame'],
        },
    },
    {
        id: 2,
        priority: 1,
        action: {
            type: 'redirect',
            redirect: {
                regexSubstitution: "https://thisismydomain.com/go/\\1"
            },
        },
        condition: {
            regexFilter: "^https?://go/(.*)",
            resourceTypes: ['main_frame', 'sub_frame'],
        },
    }
];
chrome.declarativeNetRequest.updateDynamicRules({
  removeRuleIds: RULES.map(r => r.id),
  addRules: RULES,
});
```

In past versions of this extension, I had just the static rule, then just the dynamic rules, and now both static and dynamic (as I'm trying to debug the situation). As mentioned in the "short version" above, this extension installed on different Chrome profiles / different machines acts inconsistently - some machines are stuck with the behavior from older versions - even when chrome://extensions shows that it's the same published version of the extension that is in use.

Mitchell

unread,
Jul 17, 2024, 5:03:26 PM7/17/24
to Chromium Extensions, Allen Yang
> It's leading me to believe that the browser is caching or otherwise using a stale version of the service worker script in the extension

Our teams have observed this same behavior. It became apparent when we began testing between extension versions and noticed old code running. We found that disabling and re-enabling the extension was sufficient to refresh the service worker. I suspect going to chrome://serviceworker-internals/ and restarting the service worker would also refresh it - but we have not explicitly tested that yet.

Frankly, it would be nice if someone could explain this behavior so that we can take steps to mitigate the risk of encountering this scenario because it only happens sometimes and we haven't figured a reason for it to happen. We end with low confidence if a bug fix is actually working with a new version without doing the extension on/off dance and have to take extra steps to validate.

Maybe someone from the Chromium team could provide some insight? 

woxxom

unread,
Jul 18, 2024, 3:23:33 AM7/18/24
to Chromium Extensions, Mitchell, Allen Yang
Yet another evidence out of quite a few that MV3 is still beta quality and not yet ready to be used as a primary platform.

Try adding the following to your background script:

self.oninstall = () => skipWaiting();
self.onactivate = () => clients.claim();

Don Schmitt

unread,
Jul 18, 2024, 1:14:44 PM7/18/24
to woxxom, Chromium Extensions, Mitchell, Allen Yang
+1.  This bug explains why a good number of our users with the new version of the extension from weeks ago are stuck with old bugs that were fixed.  Yet another sigh about the obviously poor choice of using the service worker architecture for extensions.







--
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/56334d3b-adfc-4f12-8017-78dda612344bn%40chromium.org.

Don Schmitt

unread,
Jul 30, 2024, 6:16:26 PM7/30/24
to woxxom, Chromium Extensions, Mitchell, Allen Yang
Just to close the loop on this.  So are we saying that if you want to be sure your extension is using the latest version of the service worker code then the service worker code should make these calls at the top-level?

self.oninstall = () => skipWaiting();
self.onactivate = () => clients.claim();


Oliver Dunk

unread,
Aug 12, 2024, 10:07:38 AM8/12/24
to Don Schmitt, woxxom, Chromium Extensions, Mitchell, Allen Yang
Hi Don,

I believe that's the suggestion wOxxOm was making. I haven't seen this issue in the past, so I can't add much about how likely this is to help, but you're welcome to experiment. The correct solution of course is that this shouldn't happen in the first place. Feel free to open a new bug at https://crbug.com/ - we can dedupe if needed, but at least the engineering team can see what you're running into.

Just for anyone else who stumbles upon this thread, especially in the longer term future, I do want to add some words of caution. Needing to manually intervene with the registration of the service worker is not intended, and in fact may even cause other behavior that is hard to reason about. We have already blocked certain APIs like this and may block others in the future, since we want to avoid extensions getting into undefined states.

We are definitely seeing fewer and fewer issues with service workers (in general, they seem very stable now) but please do keep opening bugs and sharing any findings like this. On our side, we're continuing to gather data and make fixes where we can.

Oliver Dunk | DevRel, Chrome Extensions | https://developer.chrome.com/ | London, GB


Gaurang Tandon

unread,
Aug 23, 2024, 9:52:13 AM8/23/24
to Chromium Extensions, Oliver Dunk, woxxom, Chromium Extensions, Mitchell, Allen Yang, Don Schmitt
Hi Oliver and everyone else,

We had another user report this issue (or the similar issue). Their extension auto-updated and switched to the updated versions of the content script/offscreen document, but was still running an old version of the service worker. I manually verified this in the Sources panel.

We are now actively looking for workarounds. One workaround is to ensure any message to/response from the service worker is backwards compatible. We'd then maintain both code paths (old and new) for a long time. This is a bit cumbersome so we'd prefer to avoid having to do this.

Another workaround is to load the service worker with a dynamic import instead. For example: declare `service-worker-loader.js` as the service worker in our `manifest.json` file. This file would have only one line: `importScripts(chrome.runtime.getURL("js/realServiceWorker.js"));`. I'm assuming it'd read the file from disk and always serve the correct one.

Finally, another workaround could be to change the name of our service worker file in each new release (similar to how we cache-bust in the web).

I am not sure if the last two workarounds would help address the problem, and/or if they have any known issues so we should instead be avoiding them. Looking forward to comments and suggestions for the workarounds from the team and the community.

Best,
Gaurang

Besjan Vasilaj

unread,
Aug 23, 2024, 10:12:32 AM8/23/24
to Gaurang Tandon, Chromium Extensions, Oliver Dunk, woxxom, Mitchell, Allen Yang, Don Schmitt

woxxom

unread,
Aug 23, 2024, 1:42:40 PM8/23/24
to Chromium Extensions, Besjan Vasilaj, Chromium Extensions, Oliver Dunk, woxxom, Mitchell, Allen Yang, Don Schmitt, Gaurang Tandon
>  load the service worker with a dynamic import instead. 

It's not implemented yet.

>  importScripts [...]   I'm assuming it'd read the file from disk and always serve the correct one.

No, it's cached in the internal service worker registry when the extension is installed and its service worker is registered.
Reply all
Reply to author
Forward
0 new messages