fix: MV3 service worker termination kills the background refresh and the 24h phishing list update #158

Closed
opened 2026-08-09 03:44:26 +02:00 by clawbot · 0 comments
Collaborator

Problem

Two recurring jobs are scheduled with setInterval inside the Chrome MV3
service worker, which is terminated after roughly 30 seconds idle. Neither
survives:

  • src/background/index.js:614setInterval(backgroundRefresh, 60000), the
    60-second balance refresh.
  • src/shared/phishingDomains.js:166setInterval(updatePhishingList, 24h).

In practice both run only at service-worker startup. README.md:614-617
promises the phishing list is refreshed "once every 24 hours"; on Chrome that
is false. Phishing protection is a security feature, so silently degrading to
"vendored list only, refreshed whenever the worker happens to restart" matters.

Related, same root cause: src/shared/phishingDomains.js:39-70 uses
localStorage, which does not exist in an MV3 service worker. It is inside a
try/catch so it degrades silently, which makes the README.md:618-619 claim
that "The delta is persisted to localStorage if it is under 256 KiB" false on
Chrome.

Implementation requirements

  • Replace both setInterval schedules with chrome.alarms (via the shared
    compat module if the Firefox compat work has already landed; otherwise
    in a way that does not conflict with it). Alarms survive worker termination
    and are the supported MV3 mechanism.
  • Add the "alarms" permission to manifest/chrome.json, which does not
    currently request it. Check whether manifest/firefox.json needs it too for
    the MV2 path, and keep MV2 working — a persistent background page there does
    not have the same constraint, so the shared code must behave correctly under
    both.
  • Note that chrome.alarms has a minimum period (1 minute) — confirm the
    60-second refresh is still expressible, and adjust the interval with a note
    in the PR if it is not.
  • Replace the localStorage use in phishingDomains.js:39-70 with the
    extension storage API so the delta actually persists on Chrome. Keep the
    256 KiB cap behaviour. Note that src/shared/ens.js:12-29 also uses
    localStorage, but only from popup context where it is valid — leave it
    alone, and add a brief comment there recording that it is popup-only, so a
    future change does not pull it into the worker.
  • Make sure the update still runs promptly on first install / first startup,
    not only on the first alarm tick.
  • Update README.md:614-619 if the resulting behaviour differs at all from
    what is documented there.

Definition of done

  • Neither setInterval remains in src/background/ or
    src/shared/phishingDomains.js.
  • chrome.alarms drives both jobs; "alarms" is present in
    manifest/chrome.json.
  • The phishing delta persists across a Chrome service-worker restart —
    verified by letting the worker idle out, then confirming the delta is
    still applied.
  • The balance refresh continues to fire after the worker has been
    terminated and revived.
  • The MV2 Firefox path still schedules both jobs correctly.
  • No remaining localStorage use in any code reachable from the service
    worker; ens.js carries a popup-only comment.
  • README.md matches the implemented behaviour.
  • TODO.md updated in the same commit.
  • make check passes.
## Problem Two recurring jobs are scheduled with `setInterval` inside the Chrome MV3 service worker, which is terminated after roughly 30 seconds idle. Neither survives: - `src/background/index.js:614` — `setInterval(backgroundRefresh, 60000)`, the 60-second balance refresh. - `src/shared/phishingDomains.js:166` — `setInterval(updatePhishingList, 24h)`. In practice both run only at service-worker startup. `README.md:614-617` promises the phishing list is refreshed "once every 24 hours"; on Chrome that is false. Phishing protection is a security feature, so silently degrading to "vendored list only, refreshed whenever the worker happens to restart" matters. Related, same root cause: `src/shared/phishingDomains.js:39-70` uses `localStorage`, which does not exist in an MV3 service worker. It is inside a `try/catch` so it degrades silently, which makes the `README.md:618-619` claim that "The delta is persisted to localStorage if it is under 256 KiB" false on Chrome. ## Implementation requirements - Replace both `setInterval` schedules with `chrome.alarms` (via the shared compat module if the Firefox compat work has already landed; otherwise in a way that does not conflict with it). Alarms survive worker termination and are the supported MV3 mechanism. - Add the `"alarms"` permission to `manifest/chrome.json`, which does not currently request it. Check whether `manifest/firefox.json` needs it too for the MV2 path, and keep MV2 working — a persistent background page there does not have the same constraint, so the shared code must behave correctly under both. - Note that `chrome.alarms` has a minimum period (1 minute) — confirm the 60-second refresh is still expressible, and adjust the interval with a note in the PR if it is not. - Replace the `localStorage` use in `phishingDomains.js:39-70` with the extension storage API so the delta actually persists on Chrome. Keep the 256 KiB cap behaviour. Note that `src/shared/ens.js:12-29` also uses `localStorage`, but only from popup context where it is valid — leave it alone, and add a brief comment there recording that it is popup-only, so a future change does not pull it into the worker. - Make sure the update still runs promptly on first install / first startup, not only on the first alarm tick. - Update `README.md:614-619` if the resulting behaviour differs at all from what is documented there. ## Definition of done - [ ] Neither `setInterval` remains in `src/background/` or `src/shared/phishingDomains.js`. - [ ] `chrome.alarms` drives both jobs; `"alarms"` is present in `manifest/chrome.json`. - [ ] The phishing delta persists across a Chrome service-worker restart — verified by letting the worker idle out, then confirming the delta is still applied. - [ ] The balance refresh continues to fire after the worker has been terminated and revived. - [ ] The MV2 Firefox path still schedules both jobs correctly. - [ ] No remaining `localStorage` use in any code reachable from the service worker; `ens.js` carries a popup-only comment. - [ ] `README.md` matches the implemented behaviour. - [ ] `TODO.md` updated in the same commit. - [ ] `make check` passes.
clawbot added this to the 1.0.0 milestone 2026-08-09 03:44:26 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/AutistMask#158