Browser extension
Look at a tab by hand
A Chrome extension for the case where you want to point at a running app rather than drive one from a script. It is not published to the Chrome Web Store — build it and load it unpacked.
Nothing is instrumented until you say so
The extension ships no host permissions and no declared content scripts.
Enabling a site requests that one origin, registers a document_start content
script for it, and disabling unregisters the script and hands the permission back.
A leak tool has no business patching WebCodecs on every page you visit. An earlier version
declared content scripts on <all_urls>, which patched the globals and
exposed the census API in the main world of every page — for a tool you only ever need on
one app. That was the wrong default however useful the tool is.
Revoking the permission from Chrome's own settings also stops the content scripts: the extension reconciles stored origins against granted permissions on install, on startup, and whenever a permission is removed.
Two modes
The exact one is not free, so you choose.
| Patch mode | Exact mode | |
|---|---|---|
| Permissions | one origin, granted by you | that, plus debugger |
| Banner | none | "debugging this browser" |
| Works with DevTools open | yes | no |
| Workers started before the page script | missed | caught |
Workers blocked by worker-src CSP | missed (reported) | caught |
| Codecs inside workers | caught | caught |
Patch mode
The census runs as a world: "MAIN" content script at
document_start, and rewrites new Worker(url) to load a small blob
that imports the census first and the real worker second. No debugger, no banner, and it
coexists with an open DevTools window.
It is genuinely the weaker half, and it says so rather than pretending otherwise:
-
A page whose CSP omits
blob:fromworker-src/script-srccannot create a blob worker at all. The patch catches the throw, falls back to the original URL so the app keeps working, and records the skipped worker with its reason. The popup lists them. - Chrome does not promise a MAIN-world content script beats a page's inline scripts.
- A worker already running before the patch installs is never covered.
-
self.locationinside a wrapped worker becomes the loader blob URL. Workers usingimport.meta.urlare unaffected; workers building paths fromself.locationare not.
Exact mode
The same mechanism as the CDP driver, driven through
chrome.debugger so it works on a tab you are already looking at: auto-attach
pauses each worker, a beforeScriptExecution breakpoint gives the second, complete
pause, and the census goes in there.
It costs a "debugging this browser" banner, and it cannot share a tab with an open DevTools window — Chrome allows one debugger client per tab.
Exact mode injects the plain census rather than the Worker-rewriting build: CDP reaches
workers on its own, so the rewrite would be redundant and would change
self.location for no gain.
Build and load it
npm install
npm run build:all # then load extension/dist unpacked
In Chrome: chrome://extensions → enable Developer mode → Load
unpacked → pick extension/dist. Manifest V3, minimum Chrome 116.
Using it
- Open the app you want to measure and click the extension icon.
- Enable on host — Chrome asks for that one origin. Reload the tab, so the census is in place before the app builds its decoders.
- Optionally Enable exact mode, then reload again so workers are caught at startup.
- Refresh in the popup to read the census.
The popup shows, per context: live counts by type, media elements and how many are stalled,
anything garbage collected without close(), the top allocation sites with two
stack frames each, and anything the install could not instrument. In patch mode it also
reports how many workers were wrapped and which were skipped, with the reason.
"No instrumented context answered" means either the site is not enabled, or the page loaded before it was. Enable the site, then reload the tab.
What it can see about the page
The census API is a page global — window.__webcodecsCensus — readable by any
script in the document, including third-party ones. Everything it exposes is already
derivable in-page, but treat it as visible rather than private, and do not enable it on a
page handling data you would not want an analytics script to see. Allocation stacks contain
your source URLs, function names and line numbers.