content scripts dynamically registered with "registerContentScripts" survive service worker wakeups but not manual refresh.

1,076 views
Skip to first unread message

Robbi

unread,
Jul 10, 2022, 5:35:29 PM7/10/22
to Chromium Extensions
Content scripts registration lasts between browser restarts but not manual updates\refreshes.
I also checked with chrome.scripting.getRegisteredContentScripts(console.log).
Could it be caused by this bug   crbug.com/1271154  ?

hrg...@gmail.com

unread,
Jul 10, 2022, 8:30:21 PM7/10/22
to Chromium Extensions, Robbi
In the subject line you say "survive service worker wakeups" but in the message body you say "lasts between browser restarts".
Service worker wakeup and browser restart are quite different things.

Dynamic content scripts will persist after the SW is restarted because they have nothing to do with the SW. An extension doesn't need a SW at all in order to register content scripts (either dynamically or statically).
Message has been deleted

Robbi

unread,
Jul 11, 2022, 7:36:13 AM7/11/22
to Chromium Extensions, hrg...@gmail.com, Robbi
It's strange indeed.
I attach a very basic extension and a link to a video LINK

Spoiler alarm:
at minute 03':05" the crime happens


TEST.crx

hrg...@gmail.com

unread,
Jul 11, 2022, 2:47:57 PM7/11/22
to Chromium Extensions, Robbi, hrg...@gmail.com
Your video shows that:
1. Dynamic content scripts are lost when the extension is reloaded (reload button).
2. Dynamic content scripts are preserved when the extension is disabled and then re-enabled.
3. Dynamic content scripts are preserved when the entire browser is restarted.

This is a bit surprising but not really a problem. All you have to do is to register your dynamic content scripts whenever the extension starts up. If they are already registered, then you just do nothing.

Robbi

unread,
Jul 11, 2022, 4:01:18 PM7/11/22
to Chromium Extensions, hrg...@gmail.com, Robbi
"This is a bit surprising but not really a problem."
Sure, at this point we might as well register the content scripts statically in the manifest.

The real problem is that the refresh\reload (linked to the real extension update) is actually unreliable.
For this specific issue ( registerContentScripts ) I have already opened a bug (bug #1343367).
However, there is another bug opened by me a few days ago that does not lead anything good.
The culprit, also in this case, is the reload of the extension that does not trigger the onInstalled event. (bug #1340341)
It is not something to be underestimated, since with the migration to MV3 we will have to think of a "painless" method to migrate from localStorage to browser.storage and if at that right moment the event does not do its duty as it should it could invalidate many extensions and in fact force many users to reinstall the extension.

hrg...@gmail.com

unread,
Jul 11, 2022, 5:22:54 PM7/11/22
to Chromium Extensions, Robbi, hrg...@gmail.com
At least the issue is clear now. The reload button has the side effect of unregistering content scripts registered with registerContentScripts().
Since the reload button is only available for unpacked extensions, only the developer will encounter the problem.

Robbi

unread,
Jul 11, 2022, 5:59:07 PM7/11/22
to Chromium Extensions, hrg...@gmail.com, Robbi
I created two identical versions of the extension with relative .crx files.
Using a Chromium-based browser that still allows to install via .crx (i.e. SRWare Iron or Comodo Dragon) I installed first the "old"version, I registered the content script and then I updated the extension by dragging the .crx file of the "new" version onto the extensions page and ... nothing changes.
The content Script is no longer registed.
Maybe with the CWS this behavior will not occur, but I have some doubts.

hrg...@gmail.com

unread,
Jul 11, 2022, 7:27:17 PM7/11/22
to Chromium Extensions, Robbi, hrg...@gmail.com
I think you can also trigger an extension update event by increasing the version number in the manifest and then clicking the reload button.
It seems consistent that the reload button unregisters all content scripts (dynamic and static) because the new extension version is expected to be different in functionality. So, everything about the old version should be removed (except for the permanent storage).
This may explain why the reload button has the same effect as updating an extension.

Robbi

unread,
Jul 11, 2022, 8:21:42 PM7/11/22
to Chromium Extensions, hrg...@gmail.com, Robbi
I can't figure out if you write these things seriously or you just want to make fun of me.
If what you wrote makes sense then why not revoke the permissions acquired at runtime after a reload?

hrg...@gmail.com

unread,
Jul 12, 2022, 12:46:05 AM7/12/22
to Chromium Extensions, Robbi, hrg...@gmail.com
This is no place to make fun of anybody. I'm being completely serious.

The rationale is this:
A new version of an extension is expected to have different functionality and different mechanisms that make that functionality possible. So, it seems logical that when the browser updates an extension, it should revert any changes made by the old extension version, but without removing the user data.

Updating any extension should have the effect of a complete uninstallation of the old version, but without removing the user data (and permissions granted at runtime because these are "user data" as well).

Ask yourself this:
What if the new extension version does not use a content script at all?

Once you think about that, the obvious conclusion is that updating an extension must unregister all content scripts.

Robbi

unread,
Jul 12, 2022, 6:12:53 AM7/12/22
to Chromium Extensions, hrg...@gmail.com, Robbi
With an open mind I can't find anything logical in your arguments (which I respect anyway).
At this point it is best to close it here.
If anyone is reading this and has any part in writing this API or its documentation it would be nice if he stepped forward to dispel doubts. (also because it is becoming a private chat when this is supposed to be a discussion group).

wOxxOm

unread,
Jul 12, 2022, 10:34:19 AM7/12/22
to Chromium Extensions, Robbi, hrg...@gmail.com
The "reload extension" action is implemented literally as uninstallation + installation. It intentionally preserves the storage and icon pinning, probably a few other things, maybe alarms too, so it might make sense to suggest preserving the registrations of the content scripts if they didn't have `persistAcrossSessions: false`.

hrg...@gmail.com

unread,
Jul 12, 2022, 11:13:00 AM7/12/22
to Chromium Extensions, Robbi, hrg...@gmail.com
Robbi wrote:
With an open mind I can't find anything logical in your arguments

Then ask yourself this other question:
Should static content scripts be preserved when an extension is updated?

You answer to that question should be "NO".

Now answer the same question but for dynamic content scripts.
Do you think that dynamic content scripts should be preserved but static content scripts should not?

What's your rationale for answering the same question differently in each case?

Robbi

unread,
Jul 12, 2022, 11:50:25 AM7/12/22
to Chromium Extensions, hrg...@gmail.com, Robbi
@hrg
"Should static content scripts be preserved when an extension is updated?"
Sure, I think it should.
If the update comes when a page injected by cs is open I expect that this c.s. still remains on the page.
I will probably no longer be able to exchange any messages with the extension, but if the purpose of the c.s. is to change the background color of the page then I believe this color should be kept (even if I reload the injected page).
If there is no open page subject to the cs and I open a new one, I expect the cs to be injected and do its duty.

@ wOxxOm
I always thought that the reload action faithfully simulated the extension update.
In fact, the onInstalled event when acting on this button sets the details.reason property to "update".
I also tried with two .crx files generated by the same .pem and the result doesn't change.
What do you think? What should I expect from a CWS update?

wOxxOm

unread,
Jul 12, 2022, 12:12:53 PM7/12/22
to Chromium Extensions, Robbi, hrg...@gmail.com
An update from the web store does exactly the same under the hood as a reload, so the same considerations I expressed in my comment apply here.

Robbi

unread,
Jul 12, 2022, 12:27:25 PM7/12/22
to Chromium Extensions, wOxxOm, Robbi, hrg...@gmail.com
I'm getting a bit of a headache.
I ask to @wOxxOm to give me couple of "boolean" answers.
In your opinion it is normal to lose the registration of the c.s. after the update?
Did I make a mistake in opening a bug report?

wOxxOm

unread,
Jul 12, 2022, 12:58:21 PM7/12/22
to Chromium Extensions, Robbi, wOxxOm, hrg...@gmail.com
It can be argued both ways, so as I wrote initially, it might make sense to suggest preserving the registrations of the content scripts if they didn't have `persistAcrossSessions: false` to let Chromium developers decide.

hrg...@gmail.com

unread,
Jul 12, 2022, 1:31:03 PM7/12/22
to Chromium Extensions, Robbi, hrg...@gmail.com
Robbi wrote:
If the update comes when a page injected by cs is open I expect that this c.s. still remains on the page.

You are mixing entirely different things here. One thing is to unregister a content script and another is to remove a content script from a page in which it was already injected.

Updating an extension DOES NOT remove already-injected content scripts, they are only unregistered.

So, ask yourself the question again:
Should static content scripts be unregistered when an extension is updated?

The correct answer is YES, because the content scripts from the old extension version are not necessarily the same as the content scripts from the new extension version.

Now, ask yourself the same question but for dynamic content scripts:
Should they be unregistered when the extension is updated?

The answer is also YES, because of the same reason given for static content scripts.

Robbi

unread,
Jul 12, 2022, 2:08:41 PM7/12/22
to Chromium Extensions, hrg...@gmail.com, Robbi
@hrg
It seems that you are "kicking the ball" into the "semantics" and on this field I do not want to follow you also because the core of the speech is another.
In case of update I always expect that a:
  • statically registered cs is injected into the pages when they are loaded for the first time and at any refreshes.
  • statically registered cs already injected into the page continues to remain injected.
  • dynamically registered cs (with registerContentScripts) is injected into the pages when they are loaded for the first time and at any refreshes.
  • dynamically registered cs (with registerContentScripts) already injected into the page continues to remain injected.
What is done "under the covers" during the update is not what the extension developer should be concerned with.
If the last two points are not guaranteed it will mean I will register statically my cs or I will use the "old" executeScript method for injecting at runtime whenever I need it.

@wOxxOm
The documentation could certainly be improved.
For the "persistAcrossSessions" property the documentation says: "Specifies if this content script will persist into future sessions. The default is true."
Is it all about what they had in mind when they wrote "future sessions"?

hrg...@gmail.com

unread,
Jul 12, 2022, 2:43:44 PM7/12/22
to Chromium Extensions, Robbi, hrg...@gmail.com
The issue is simpler than you think.
All the browser is doing when updating an extension is to unregister all content scripts (static and dynamic) that were registered by the old version.

Why would you want content scripts registered by the old extension version to remain registered after the new version is installed?
This is completely unreasonable.
The content script registered by the old version must be unregistered because the new extension version is different, it's a new extension altogether, it could work in an entirely different way, it could not even use content scripts at all.

The issue is really, really simple, and you refuse to see it.

Robbi

unread,
Jul 12, 2022, 4:10:39 PM7/12/22
to Chromium Extensions, hrg...@gmail.com, Robbi
Tell me why I shouldn't have such a section in the manifest file...
    "content_scripts": [
        {
            "matches": ["https://foobar.com/*"],
            "js": ["cs.js"]
        }
    ]
...keep it unchanged for many versions to come
...and "hope" that every time I open the a foobar page the cs is injected ???

You said that during the update all old script are unregisted, but keeping that section in manifest file I explicitly state the intention to renew the subscription.
If I removed that section from the manifest obviously I would expect to no longer see cs injected into the pages.
Now for dynamic cs tell me what sense does it make to automatically unregister them without the subsequent and implicit registration when I also have the unregisterContentScripts method that allows to do it when the programmer and \ or the user wants?

Victor Alvelais

unread,
Jul 12, 2022, 6:35:39 PM7/12/22
to Robbi, Chromium Extensions, hrg...@gmail.com
Robbi speaks for me here as an end user and developer. This would be a painful experience and discourage timely updates.


On Jul 12, 2022, at 3:10 PM, Robbi <rob...@gmail.com> wrote:


--
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/0eeb73a4-0d7a-4ea1-9cf3-16b87d373a9cn%40chromium.org.

Simeon Vincent

unread,
Jul 12, 2022, 9:32:40 PM7/12/22
to Victor Alvelais, Robbi, Chromium Extensions, hrg...@gmail.com
Your video shows that:
1. Dynamic content scripts are lost when the extension is reloaded (reload button).
2. Dynamic content scripts are preserved when the extension is disabled and then re-enabled.
3. Dynamic content scripts are preserved when the entire browser is restarted.
- Hr

Based on my conversations with Chrome's extensions engineering team, this sounds to me like the intended behavior. 


Sure, at this point we might as well register the content scripts statically in the manifest. - Robbi

If you are able to, that seems like it may be the better strategy.

One of the motivating use cases for dynamic content scripts support is situations where the host permissions for a content script isn't known ahead of time. I believe another is user script support, in which case it's impossible to statically declare the content scripts because they wouldn't be bundled with the extension. 

For example, say you have an extension for GitHub that also supports GitHub Enterprise. The enterprise deployment of GitHub will be hosted on an internal domain and an extension developer can't know the set of domains they'll need to target before the user installs the extensions. 


The real problem is that the refresh\reload (linked to the real extension update) is actually unreliable. - Robbi

Can you share more details? Reloading an extension should behave reliably and I would consider inconsistencies in this area to be bugs.

Thanks for reporting issue 1340341; I've updated a couple properties on this issue to help it get routed to the right engineers.


Using a Chromium-based browser that still allows to install via .crx (i.e. SRWare Iron or Comodo Dragon) - Robbi

FYI, this should also be possible in Chrome/Chromium on Linux. 


If what you wrote makes sense then why not revoke the permissions acquired at runtime after a reload? - Robbi

Hr's description matches my mental model; the reload button on chrome://extensions page effectively performs an update to the unpacked extension. The current design is that dynamically registered content scripts (even those declared with persistAcrossSessions: true) are cleared on update. If you're seeing that this is not the case when testing extension updates using .crx files, then .crx updates are not behaving as intended.

Permissions are persisted actress extension updates because, like storage, they're stateful information about the extension itself. Whether statically declared in the manifest file or dynamically registered, the same cannot be said about content scripts.

Content script registrations are directly associated with the files bundled with an extension, and those files may change with an extension update. If the browser doesn't clear out the content scripts on update, we can run into situations where the files referenced in the registration no longer exist or require additional files to be present that weren't declared in the previous registration. 


The documentation could certainly be improved.
For the "persistAcrossSessions" property the documentation says: "Specifies if this content script will persist into future sessions. The default is true."
Is it all about what they had in mind when they wrote "future sessions"?

I agree that we need to improve the docs here. The term "future sessions" here refers to browser sessions. If the extension does not explicitly set persistAcrossSessions: false when registering a dynamic content script, that registration will be preserved across browser restarts or other Chrome profile session terminations. 

The docs do not expressly describe how registrations are handled across extension updates and they absolutely should. I just created issue 3198 on the developer.chrome.com repo to track this.


Tell me why I shouldn't have such a section in the manifest file...
[…]
but keeping that section in manifest file I explicitly state the intention to renew the subscription.

I think the piece that you might be missing here is that Chrome does unregister statically declared content scripts when updating, but in the situation you describe Chrome will also re-register the content script during the update process because the extension's manifest still includes that static declaration. 

When you dynamically register a content script, you're taking over the responsibilities of telling the browser when the content script is relevant. When an update happens and all content script registrations are cleared, Chrome can't know if the dynamic registration is still valid because there's no static information saying it's still relevant. The browser needs the extension to tell it what dynamic content script registrations it should have; that's why the extension will need to re-register its dynamic content scripts in a runtime.onInstalled handler.

Simeon - @dotproto
Chrome Extensions DevRel


Robbi

unread,
Jul 13, 2022, 4:16:56 AM7/13/22
to Chromium Extensions, Simeon Vincent, Robbi, Chromium Extensions, hrg...@gmail.com, Valve
Wow, this is an answer :-)
Thank you Simon, i really appreciate it.

Jackie Han

unread,
Jul 13, 2022, 6:00:39 AM7/13/22
to Robbi, Chromium Extensions, Simeon Vincent, hrg...@gmail.com, Valve
I would like to point out that there are other similar things(like contextMenus and alarms) that need to be handled in this way(first clear all, then re-create them), or as a best practice. Thus you don't need to worry how the browser handles them or if there is a bug when updating.

function onInstall(e) {
  // clear all dynamic content scripts, then re-register them.
  chrome.scripting.unregisterContentScripts(function() {
    chrome.scripting.registerContentScripts(one or more content scripts);
  });

  // clear all context menus, then re-create them.
  chrome.contextMenus.removeAll(function() {
    chrome.contextMenus.create(menu-1);
    chrome.contextMenus.create(menu-2);
    ……
  });

  // clear all alarms, then re-create them.
  chrome.alarms.clearAll(function() {
    chrome.alarms.create(name-1, config-1);
    chrome.alarms.create(name-2, config-2);
    ....
  });
  // if your alarm names are static, you can create them directly, no need to clear them first.
}

chrome.runtime.onInstalled.addListener(onInstall);


Robbi

unread,
Jul 13, 2022, 6:18:31 AM7/13/22
to Chromium Extensions, Jackie Han, Chromium Extensions, Simeon Vincent, hrg...@gmail.com, Valve, Robbi
I'm agree with you on context menu, but for alarms I'm quite sure that is not needed.

Jackie Han

unread,
Jul 13, 2022, 7:51:57 AM7/13/22
to Robbi, Chromium Extensions, Simeon Vincent, hrg...@gmail.com, Valve
For alarms, I consider it a best practice, not a requirement.
Reply all
Reply to author
Forward
0 new messages