Files
sovereign_browser/plans/service-workers-on-file.md

5.0 KiB

Service Workers on file:// — Analysis & Options

The Problem

navigator.serviceWorker.register() on a file:// page rejects with:

"serviceWorker.register() must be called with a script URL whose protocol is either HTTP or HTTPS"

Where the Check Lives

The error message is generated inside WebKit's web process (the JavaScript engine / WebCore layer), not in the WebKitGTK C API layer. The check is in WebKit's ServiceWorkerContainer::register() C++ code (in Source/WebCore/workers/service/ServiceWorkerContainer.cpp), which validates the script URL protocol against a hard-coded list of http and https.

This is not controllable via:

  • WebKitSettings (no setting for SW protocol allowlist)
  • WebKitSecurityManager (only controls local/secure/cors/empty/no-access scheme classification — not SW registration eligibility)
  • WebKitWebsiteDataManager (only controls the storage directory for SW registrations, not the protocol gate)

Options

Option A: Patch WebKit (fork / rebuild) — HIGH EFFORT

We could fork webkitgtk (or maintain a patch set) that removes or relaxes the protocol check in ServiceWorkerContainer.cpp. This is the only way to make navigator.serviceWorker.register() accept file:// URLs natively.

Pros:

  • Fully native — JS code works unchanged
  • SW lifecycle (install/activate/fetch events) works as designed

Cons:

  • Requires maintaining a WebKit fork or patch set against Debian's webkit2gtk package
  • Every WebKitGTK update requires re-applying the patch
  • Build complexity — WebKit is ~35MB of system lib; rebuilding from source is heavy
  • The SW spec assumes HTTP semantics (scope, update checks, fetch interception) that don't map cleanly to file://

Verdict: Too heavy for the benefit. Service Workers on file:// is a niche use case.

Option B: Register file:// as a "secure" scheme — ALREADY DONE, DOESN'T HELP

We already call webkit_security_manager_register_uri_scheme_as_secure() for file in src/main.c:850. This makes file:// origins treated as "potentially trustworthy" for some purposes (like navigator.geolocation or getUserMedia), but does not bypass the SW registration protocol check — that check is a separate hard-coded http/https test in WebCore.

Option C: Use a custom URI scheme instead of file:// — MODERATE EFFORT

Instead of loading local sites via file:///path/to/index.html, we could register a custom scheme (e.g. local://) via webkit_web_context_register_uri_scheme() that serves files from disk. If we also register local:// as secure via WebKitSecurityManager, SW registration might work — but only if WebKit's SW code checks "potentially trustworthy origin" rather than hard-coding http/https. This needs testing.

Pros:

  • No WebKit fork needed
  • We control the scheme handler entirely
  • Could also solve the Cache API issue (Issue #5)

Cons:

  • Changes the URL model — users see local:// instead of file://
  • Relative path resolution may differ
  • Still might not work if WebKit's SW check is truly hard-coded to http/https (need to test)
  • Significant implementation effort (scheme handler, path mapping, security registration)

Verdict: Worth investigating if SW on local files becomes important. The first step would be a quick test: register local:// as secure, load a page, try navigator.serviceWorker.register().

Option D: JavaScript shim / polyfill — LOW EFFORT, PARTIAL

We could inject a JS shim that overrides navigator.serviceWorker.register to do something useful on file:// — e.g., load the SW script as a Web Worker instead, or implement a minimal fetch interceptor.

Pros:

  • No WebKit changes
  • We already inject JS shims (window.nostr)

Cons:

  • Not a real Service Worker — no fetch event interception, no install/activate lifecycle, no clients API
  • Would only provide a subset of SW functionality
  • Complex to implement convincingly

Verdict: Only useful if someone specifically needs SW-like behavior on file:// and is willing to accept a polyfill.

Service Workers are designed for HTTP/HTTPS origins. On file://:

  • Web Workers work perfectly (tested ) — use those for background computation
  • Shared Workers also work perfectly (tested ) — use those for cross-tab/cross-page shared background computation
  • IndexedDB works perfectly (tested ) — use that for offline storage
  • Cache API doesn't work (Issue #5) — but local files are already local, so caching is redundant
  • fetch interception (the main SW use case) is less relevant when everything is local

The "deprecated web security" design goal is about cross-origin access (CORS/SOP), which works. Service Workers are a different concern — they're about offline web apps and PWA features, which are inherently HTTP-oriented concepts.

Verdict: Document the limitation and move on. If a specific use case emerges that needs SW on file://, revisit Option C (custom scheme).