Back to articles

Extension Pulse, week of November 2: last call before Chrome 157

Chrome 157 reaches full stable November 3 with four changes for existing extensions. Chrome 158 and Firefox 160 follow within a week. The last-call audit.

Maxim Kosterin
14 min read
A flat hairline signal runs quiet across the page, then steps up once inside an orange watercolor wash — a quiet week right before a release lands.
A flat hairline signal runs quiet across the page, then steps up once inside an orange watercolor wash — a quiet week right before a release lands.

My signal feed went quiet this week. Between October 26 and today, the forecast pipeline — the thing that watches Chromium Gerrit, W3C WebExtensions issues, and vendor release data — recorded zero new signals. That almost wrote this issue for me.

Then I looked at the calendar, and then at the primary sources the feed is supposed to watch. Chrome 157 reaches full stable on November 3, the day after this issue is dated, with four changes that reach existing extensions without any code change on your side. Chrome 158 starts its early-stable rollout the next day. Firefox 160 follows on November 10 with a silent break of its own. An empty feed is not an empty week.

So this issue is a re-check: the last-call audit for what ships November 3, browser-tested results for the one new API riding along, what's queued right behind it, and what TPAC did and didn't settle. Every date and status below was re-fetched from its primary source on November 2.

Chrome 157 lands November 3: the last-call audit

Chrome 157 branched October 12 and has been rolling out to early-stable users since October 21; full stable is scheduled for November 3 per Chromium Dash. W42 wrote the full break list and W43 re-verified the dates. The short version — four changes that reach existing extensions without any code change on your side, and three of them are silent:

  • publicSuffix rejects leading-dot hostnames. CL 8464103, merged September 30 alongside the spec update: ".example.com"-style input — the shape cookie domains arrive in — now counts as an invalid hostname and becomes an error. That's the convergence with Firefox 158, where isKnownSuffix() has thrown on any invalid hostname since October 13 (MDN). One fix covers both browsers: normalize and validate before calling, or wrap every publicSuffix call in try/catch.
  • alarms.clearAll() resolves to undefined. CL 8182627, merged October 2 with a compatibility kill-switch. Firefox 157 shipped the same on September 29 (WECG #1055), and WebKit merged it on October 13 (PR 76286). Every if (await browser.alarms.clearAll()) branch is dead code. Our alarms deep dive is the place to re-audit your scheduling logic.
  • webRequest and DNR miss navigations started from user-restricted sites. CL 8497010, merged October 2. If a user put a site under "block all extensions on this site", navigations initiated from it — including link clicks to allowed sites — go invisible to webRequest listeners and stop matching declarativeNetRequest rules, even permission-less block rules. No error is raised; the events just never arrive.
  • X-Chrome-Manage-Accounts disappears on Gaia URLs. CL 8501321, merged October 6. Extensions can no longer read, modify or inject that response header on accounts.google.com — "so extensions cannot trigger Mirror account management UI or actions", per the commit message. No extension API replaces it.

If you ship a blocker, a parental control, a DLP tool or an annotator, bullet three is yours to test: your event stream now has a user-shaped hole by design, and "no event" no longer means "no navigation". For everyone else the audit is one grep per bullet.

And the rollout didn't wait for the release notes. Early stable started October 21, thirteen days before the official date — the same rhythm W42 described for 156 — and a contributor on WECG #1055 saw the new clearAll() behavior on Stable by October 22. Some of your users are already on 157.

onExtensionLoaded rides along — and I ran it in a real browser

The same release that breaks four things also completes the lifecycle story. Chrome 157 adds runtime.onExtensionLoaded (commit 4f1b414, landed September 30): one event, fired whenever your extension joins the active set, with a reason — install, update, browser_update, enable, startup, reload — plus previousVersion on updates. A request to rename it to onLoaded came up at the October 8 WECG meeting; Chrome preferred to keep the current name, so the name that ships is onExtensionLoaded.

I didn't just read the commits.

See it run. To check the lifecycle events in a real browser, I built a small extension, Wake Log, that logs every lifecycle event it receives. Load it, switch it off and on or reload it, and its popup shows what arrived. On October 21 I put it through seven lifecycle transitions on Chrome for Testing 156.0.8078.47 (stable), 157.0.8103.6 (beta) and 158.0.8114.0 (canary) — 21 runs, with 157 and 158 behaving identically.

Two findings matter if you're about to adopt:

  • onInstalled still fires next to onExtensionLoaded in 157. Register both and your setup runs twice on every install. Feature-check the new event and keep the older trio as the fallback — that pattern ran its setup exactly once across all 21 runs.
  • Two things the commits don't tell you. Unpacked reloads report update, never reload — Chromium does that on purpose, with crbug.com/550447466 tracking a change; reload is for store-installed builds. And an extension updated while switched off, then re-enabled, delivered update only — no enable reason, and onEnabled never fired in the run (an unpacked extension; a store update while disabled may behave differently). Anything you restart only from onEnabled misses that case. Keep the setup idempotent.

Full tables and the one-listener pattern are in the dedicated post.

Next up: Chrome 158 on November 4, Firefox 160 on November 10

Chrome 158 branched October 26. Its early-stable rollout starts November 4 and full stable is November 17 (Chromium Dash). Three extension changes merged before the branch point:

  • Popups can't be blob: or filesystem: URLs. Commit 7811f3b, merged October 14: action popup URLs must use the chrome-extension: scheme, in default_popup and in action.setPopup() alike. The commit message calls the old behavior a remote-code-execution risk. If you build popup HTML at runtime and hand Chrome a blob URL, move it to a real extension page.
  • DNR response-header value matching needs host permissions. Commit 22a2af9, merged October 21. Without host access to a request, rules that match header values (values or excludedValues in responseHeaders or excludedResponseHeaders) only work for CORS-safelisted response headers and Content-Encoding; other such rules are skipped for that request, so a lower-priority rule may match instead. Matching on whether a header is present still needs no host permission. A companion commit b878de3 (October 16) makes DNR treat hidden headers as absent while matching. The new check sits behind a feature flag that is on by default.
  • web_accessible_resources: ["*"] stops exposing _favicon. Commits 5095ebe and fad4d6c, both October 14: blanket wildcards no longer match generated paths like _favicon and the generated background page. If a content script or a web page loads favicons through your extension, declare "_favicon/*" explicitly.

The chrome.crossOriginStorage CLs did not make the cut. CL 8605006 (the MV3-only API to inspect and delete the data sites share with each other) and CL 8605007 (DNR blocking of lookups by hash) are still unmerged as of November 2, last updated October 28, after the webRequest variant was abandoned on October 18. W43's "earliest possible ship: M158" is gone. If they merge before M159 branches on November 9, that's the next train.

Firefox 160 is scheduled for November 10 (Mozilla's release schedule) and brings two changes:

  • runtime.getPlatformInfo().arch returns "arm64" instead of "aarch64" on 64-bit ARM (bug 2080310, commit e775d5304b32, landed October 10; MDN). runtime.PlatformArch.AARCH64 disappears and ARM64 takes its place, matching Chrome. Any check for "aarch64" — picking a native-helper download, a wasm build, a telemetry label — stops matching on ARM64 machines, and nothing throws. Accept both strings.
  • runtime.MessageSender.windowId (commit f43deb1ab6b2, WECG #1077). Popups, side panels, devtools panels: know the sender's window without sender.tab. Firefox leaves the property absent when no window is determinable — no WINDOW_ID_NONE sentinel — so detect with "windowId" in sender and treat undefined as "no determinable window". New since W43: WebKit merged the same property on October 28 with the same leave-it-out rule (PR 78537), not yet in a shipping Safari. Chrome is supportive, with a tracking bug and no implementation yet.

Firefox 159 shipped on October 27 (product-details), and its MDN release notes have no add-on section at all. A genuinely quiet release for extension developers.

TPAC ended Friday: what I can and can't tell you

  • The agenda is public; the outcomes aren't yet. The WECG held eight meeting slots in Dublin, October 26–30 (event page). The final agenda covered deferred permissions (the initial_permissions proposal against two alternatives), a sidebar API, a feature-detection "supports" API, runtime-context proposals and Dashlane's feedback on MV3 background execution, among others. As of November 2 no TPAC minutes are published — the newest file in the WECG minutes folder is the October 22 call, posted today — so I won't guess what was decided. The one thing that visibly landed during the week is spec work: the alarms API IDL (PR 1110) merged on the opening day.
  • Private DOM classes are not coming back from Dublin. The rejected proposal isn't on the final agenda. Apple had floated raising it with the CSS WG at TPAC — an open question in the October 8 minutes, not a commitment.
  • Safari's arm64 rename stayed off the table. WECG #1056 asked Safari to follow Chrome and Firefox to "arm64"; it was scheduled for TPAC, then removed from the agenda on October 25. Per that thread, Safari reports "arm" on 64-bit ARM, so an arch check that also runs on Safari needs a third case.
  • Nothing decided in Dublin can ride M158. It branched October 26, the day TPAC opened, so the earliest realistic ship for any TPAC output is M159, stable December 8.

The rest of the frame

  • Chrome 159 branches November 9 and is the last full stable release of 2026 — stable December 8, with final beta and early stable both on November 18 (schedule); M160's stable date is January 5. Whatever is meant to reach users before the holidays has to merge by November 9.

What I'd do this week

  1. Finish the M157 audit today. Full stable lands November 3, and early-stable users have had it since October 21. Four greps: branches on clearAll, publicSuffix calls that take user- or URL-derived strings, webRequest/DNR code that promises full navigation coverage, and anything touching X-Chrome-Manage-Accounts. W42 is the deep dive.
  2. Run the M158 checks before November 4: popups served from blob: URLs, DNR rules that match response-header values, and any "*" in web_accessible_resources that your favicon code relies on.
  3. Get ready for Firefox 160 before November 10. Accept "arm64" wherever you check for "aarch64". Write the windowId detection once: "windowId" in sender, undefined = no determinable window, sender.tab?.windowId fallback for every other browser.
  4. Move lifecycle setup behind one idempotent function, feature-checking onExtensionLoaded (ships with 157): use it where it exists, fall back to onInstalled/onStartup/onEnabled where it doesn't. Don't register both paths — your setup will run twice. And don't lean on onEnabled alone: the browser run showed the updated-while-off case never fires it. The pattern is in the post.
  5. Keep watching, don't build. The crossOriginStorage CLs and the TPAC minutes are the two things that can change this picture, and as of November 2 neither has landed.
  6. Check your code against this week's changes. npx @extenshi/cli@latest advise . finds the four Chrome 157 changes and Firefox's aarch64 check in your extension with the file and line — it runs locally and needs no account. It checks Chrome and Edge by default and adds Firefox when your manifest has Firefox settings; --browsers chrome,firefox forces it. Every change we track, the Chrome 158 ones included, is listed at cli.extenshi.io/changes. And if you want the full second pair of eyes on the build, npx @extenshi/cli scan gets you 3 scans + 10 reads free with a free account (one-time); prepaid packs past that.

Sources

Methodology

The generator's 7-day window (2026-10-26 → 2026-11-02) returned zero forecast-pipeline signals. This issue started from the docs that backed W42 and W43, the Wake Log browser run of 2026-10-21, and those two issues; then every date, CL status and issue state in it was re-fetched from its primary source on 2026-11-02 — Chromium Dash, Gerrit and Gitiles, Bugzilla, Mozilla product-details and release schedules, MDN, and the WECG, WebKit and Firefox repositories on GitHub. The Chrome 158 and Firefox 160 items come from our platform-change catalog, each re-checked against its commits the same day. Scheduled dates move, so treat November 3, 4, 10 and 17 and December 8 as schedules, not promises. The crossOriginStorage CLs are unmerged as of the last check — watch, not build. Where an outcome could not be verified — what TPAC decided — the issue says so instead of guessing.


This issue of Extension Pulse is compiled from Chromium Gerrit, Gitiles and Chromium Dash, W3C WebExtensions Community Group issues and meeting minutes, Mozilla release data, Bugzilla and MDN, the WebKit repository, and from our own browser runs of the Wake Log sample. We don't independently verify every upstream claim, and references to specific projects or companies reflect the findings of the cited sources — not accusations of intentional wrongdoing. If something here is off, tell us at [email protected].

Previous issue (W43) → · Browse the catalog →

Related Articles