Skip to content

fix(extensions): alias native browser namespace to patched chrome - #190

Open
D3OXY wants to merge 1 commit into
samuelmaddock:masterfrom
D3OXY:d3oxy/browser-namespace-alias
Open

D3OXY wants to merge 1 commit into
samuelmaddock:masterfrom
D3OXY:d3oxy/browser-namespace-alias

Conversation

@D3OXY

@D3OXY D3OXY commented Oct 27, 2026

Copy link
Copy Markdown

Chromium exposes a native browser namespace in extension contexts, and it's a separate object from chrome (browser === chrome is false on Electron 44.1.0, 44.9.3 and 45.0.0). chrome-extension-api.preload only patches chrome, so any extension that reads APIs through browser skips every shim. uBlock Origin does self.chrome = self.browser in vapi.js, which leaves it without chrome.browserAction and with a tabs.query that returns []. Plasmo-based extensions read browser.storage.sync.

Change

At the end of mainWorldScript(), after chrome is patched and frozen, globalThis.browser is redefined to the same patched chrome object. It only does this if browser already exists, so contexts without it behave as before. mainWorldScript() is the single place that patches chrome for MV2 background pages (no context isolation), MV3 service workers and chrome-extension:// frames, so one alias covers all three.

I also added a spec that checks browser === chrome and browser.browserAction in the rpc fixture's background page.

Verification

  • yarn build and yarn test: 65 passing. The new spec fails without the change (expected false to equal true) and passes with it.

  • Ran the sample shell (Electron 44.1.0) with two throwaway extensions that only use browser.*: runtime.id, tabs.query, storage.local and action/browserAction. I opened the popups by clicking their toolbar buttons.

    Context Before After
    MV2 background page browser !== chrome, tabs.query → [], no browserAction browser === chrome, active tab returned, browserAction present
    MV3 service worker browser !== chrome, tabs.query → [] browser === chrome, active tab returned
    MV2 / MV3 popups n/a browser === chrome, all calls succeed
  • uBlock Origin 1.75.0 (chromium zip): before the change, the background page had no chrome.browserAction and the popup stayed on loading off with an empty hostname. After the change, chrome.browserAction is present and the popup shows the active tab's hostname (example.com).

  • Not tested: Raycast Companion / other Plasmo extensions, and Electron 45.

Fixes #189

Chromium exposes a native `browser` namespace in extension contexts that is a
separate object from `chrome`. The preload only patched `chrome`, so extensions
reading APIs through `browser` (uBlock Origin, Plasmo-based extensions) bypassed
every shim. Point `browser` at the patched `chrome` when it exists.

Fixes samuelmaddock#189
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

electron-chrome-extensions: native browser namespace bypasses the patched chrome API (breaks uBlock Origin, Plasmo extensions)

1 participant