Mozilla announced some months ago that only WebExtensions using non-persistent (stateless) background scripts (AKA event pages) would be eventually allowed on Firefox for Android, because the extensions process can be killed at any moment by the OS on that platform.
Even after further public and private communications is not clear how strict this requirement actually is, how it's going to be enforced and when exactly, but migrating as soon as possible is nevertheless a good strategy for MV3 transition, since stateless background scripts, either as event pages (Firefox) or service workers (Chrome) are the only type available on MV3.
However we're gonna do it on Firefox only for now, since non-persistent background pages are completely incompatible with Chrome's version of the WebRequest API, even on MV2.
Our stateless branch is tracking this migration, which includes using NSCL's stateless branch and a number of modifications in JShelter's own background scripts.
stateless
It already looks in pretty good shape right now to me: I think we can merge it this week, pending @polcak's approval.
Hello Giorgio,
I tested the stateless branch with the following results:
Giorgio, can you have a look at https://www.fit.vutbr.cz/~ipolcak/jsr/farbling/canvas.html in Chromium/Chrome/related browser? You should see some pixels farbled. The red shape should be the same for Canvas and WebGL farbling. If you refresh the page, the shape should be the same. The shape should be the same on https://www6.fit.vutbr.cz/~ipolcak/jsr/farbling/canvas.html provided you have IPv6. The shape should change when you restart the browser.
Tentatively, I think I will go on and release a new Firefox version with the code from that branch. I guess that the bug in Chromium-based browser lays in common/session_hash.js. I can see some exceptions in background console of JShelter suggesting that the problem is on line 37, looks like browser.storage.session is undefined.
Hi Libor!
The Chromium issue should be fixed by c337f2a.
I suggest to release both Firefox and Chromium (unless you find other issues) in order to have a larger audience testing these changes which are the foundation of our Manifest V3 transition strategy.
Thanks!
Thank you, Giorgio. It looks like the fix works well.
I wanted to release JShelter for Firefox ahead of dealing with the issues in Chrome. Of course that now that reason is gone, there is no need to delay Chrome release.
However, I looked more thoroughly at the changes.
Let's go through our background scripts:
"nscl/lib/browser-polyfill.js", "nscl/service/TabCache.js", "nscl/service/NavCache.js", "nscl/service/DocStartInjection.js", "nscl/common/log.js", "nscl/common/uuid.js", "nscl/common/SyncMessage.js", "nscl/common/tld.js",
I suppose that NSCL is stateless so I will not examine these further.
lib/sha256.js helpers.js update.js url.js levels_browser.js settings_tweaks.js levels.js fp_levels.js
These are stateless or already read the state from the storage. If unloaded there will just be some additional workload. But that is expected from MV3.
However, most (e.g. helpers, url, levels_browser) provide functions or variables used inside other scritps (e.g. level.js). I hope that if the background scripts are reloaded, they are initiated again in the same order as specified in the Manifest and that the browser run all scripts. Am I correct?
fp_detect_background.js
stores the number of API calls and related information. Specifically fpDb, latestEvals, availableTabs, and fpd_track_callers_tab look like they need to be saved into some storage to prevent "random" loss of content. If JShelter loses the content of these variables, FPD might miss detecting fingerprinting behaviour, the number of calls listed in the popup will not show correct numbers and a re-opened popup window might display a lower count of API calls. The fingerprint report will not report all calls if the content of the variables is lost.
background.js
tab_status and tab_urls hold a state. Speciffically, if lost, I guess, the number of API groups (badge colour, API group count) might be lost (although I am not sure about the colour).
level_cache.js
I think that this one should be fine but it would be great if you can confirm.
http_shield_firefox.js http_shield_common.js
These should be stateless.
http_shield_chrome.js holds state in dnsCache and blockedHosts but we will need to remove NBS anyway.
Badge icon:
In the above scenario, badge color and text is kept by Firefox even if the background script is stopped. However, once JShelter detects a new call in a tab, the stats are reset, so the number of API groups goes down which might result in color change (downgrade) and even dropping the ban to initiate calls.
Suggested next steps:
We will need a similar code for each variable stored in local storage like
const DEFAULTS = {sessionHash: null, visitedDomains: {}}; ({sessionHash, visitedDomains} = (await browser.storage.session?.get(DEFAULTS)) || DEFAULTS ); this.sessionHash = sessionHash ??= gen_random64().toString(); this.visitedDomains = visitedDomains;
and
await browser.storage.session?.set({ sessionHash, visitedDomains, });
I think that we should add a code either to NSCL or to helpers that wrap that code into functions like init(varName, defaultValue), store(varName, value).
Thanks for the investigation, it's exactly what I hoped for. I agree with your suggested next steps.
One clarification: session storage is different than local storage. The former (session) is not written permanently on disk, but it's kept in RAM instead until the browser is restarted, which is what we want to replace long-lived variables/properties. It being asynchronous as well, nonetheless, is very unfortunate, but I guess that's the price to pay for multi-process WebExtension browser infrastructure.
Abstracting away this best effort code variable<->cached session storage dance into NSCL is a good idea, indeed.
I managed to run integration tests in Chromium 120 and the tests work as expected.
Ad: session storage vs. local storage. Sorry, if I mixed them up somewhere in my text. All the variables that keep the state across background script restarts should go to RAM, so to the session storage. They were in RAM and need to stay in RAM.
Abstracted the stateless initialization / save dance in nscl/common/CachedStorage.js and adopted it with b51634a.
Next step will be using this to persist the volatile globals in fp_detect_background.js and backround.js, therefore fixing the issues reported in this comment.
backround.js
Persist the volatile globals in fp_detect_background.js and backround.js, therefore fixing the issues reported in this comment.
A bit more involved than supposed above, but still relatively straightforward (thanks to the CachedStorage abstraction): done in e6bef48 :wine_glass:
going back to https://pagure.io/JShelter/webextension/issue/127#comment-890848, the first problem seems to be fixed.
However, I identified two problems:
Badge text background is always gray.
Expected behaviour:
Stateless behaviour:
All problems are likely related. FPD does not work as expected. The question is who should try to fix the problem.
I am using Firefox 115.8 ESR.
The question is who should try to fix the problem.
I am investigating, thanks.
Commit f8095ef should fix all the problems from this comment, except the delay on popup opening, which I'm still investigating.
@gioma1: Thanks, nice catch. I tried the patched version and it looked like it worked until I clicked the icon to raise the pop up (on the test page). It seems that there is to much communication and the whole desktop environment froze.
It looks like I cannot move on until the pop up issue is fixed.
It seems that there is to much communication and the whole desktop environment froze.
Indeed that specific page triggers a lot of fpd-related IPC, and the issue was caused by the storage.session API getting clogged by the rapid-fire CachedStorage.save() calls due to the FPD information updates.
Should be fixed by 91dd275
It works great. Both integration and FPD tests are OK. I can test that JShelter works. Firefox allows me to unload the background script. I cannot see a similar option in Chromium so I did not test that in Chromium.
What are the next steps? Merging to main but not releasing, yet?
Merged to main and released as 0.18 https://jshelter.org/first-mv3-step/, https://lists.nongnu.org/archive/html/js-shield/2024-04/msg00003.html.
Metadata Update from @polcak: - Issue close_status updated to: Fixed - Issue status updated to: Closed (was: Open)
Log in to comment on this ticket.