Skip to content

Add Chrome browser support and configurable default browser - #1

Merged
pxlarified merged 3 commits into
mainfrom
agents/ee1d8f23-d8ef-4c9f-b56a-b168b2de7fbb
Jul 7, 2026
Merged

Add Chrome browser support and configurable default browser#1
pxlarified merged 3 commits into
mainfrom
agents/ee1d8f23-d8ef-4c9f-b56a-b168b2de7fbb

Conversation

@pxlarified

@pxlarified pxlarified commented Jul 7, 2026

Copy link
Copy Markdown
Member

Adds Chrome as a first-class browser alongside Zen, and lets you pick the browser used when --browser is omitted via config browser <browser>.

Chrome support

Chrome joins the adapter registry through a new Chromium-family adapter, mirroring the existing Firefox-family design. The native bridge (native-host.cjs) is already browser-agnostic, so the Chromium adapter reuses it and only differs where Chromium genuinely differs from Firefox:

  • Native-messaging manifest uses allowed_origins (chrome-extension://<id>/) instead of Firefox's allowed_extensions, and is written into Chrome's NativeMessagingHosts directory (plus the HKCU\Software\Google\Chrome\NativeMessagingHosts registry key on Windows).
  • Chromium can't side-load a packed extension from a profile, so install chrome stages an unpacked extension under ~/OpenBrowser/extensions/chrome/ for "Load unpacked".

To make the native-messaging allowed_origins deterministic, the built Chromium manifest ships a fixed public key, so the unpacked extension always loads with the same extension id. A test recomputes the id from the key to guard the constant.

Shared native-host / process-detection helpers were extracted from firefox-family.js into browsers/shared.js so both families reuse them without duplication (Zen install is unchanged).

The build now emits an MV3 Chromium artifact (dist/extensions/chromium/) from the same extension source; the two extension scripts got a tiny, feature-detected compatibility layer so one source runs on both families:

// background.js / content.js
if (typeof browser === "undefined") var browser = chrome;
// ...
if (browser.scripting?.executeScript) { /* MV3 */ } else { /* MV2 */ }

Configurable default browser

config browser <browser> persists a default to ~/OpenBrowser/config.json. Resolution order is --browser flag, then the configured default, then Zen.

OpenBrowser config browser chrome   # set
OpenBrowser config browser          # show current
OpenBrowser config                  # show full config

Validation

  • npm test (17 tests incl. new config + Chrome adapter coverage), npm run build, and web-ext lint on the Firefox source all pass in the sandbox.
  • Smoke-tested install zen (regression) and install chrome end to end: native host launcher, native-messaging manifest, and staged extension all land correctly.

Note: the Chrome extension runtime could not be exercised against a live Chrome in CI (no browser available). The CLI, adapter, native-messaging, config, and build layers are unit-tested; loading the unpacked extension in a real Chrome is the remaining manual check.


Summary by cubic

Adds Chrome as a first-class browser alongside Zen and introduces a default-browser setting so commands can run without passing --browser. Also unifies the extension code across Firefox and Chromium with a shim that prefers the browser API and falls back to chrome.

  • New Features

    • Chrome support via a new Chromium-family adapter; installer writes the native-messaging manifest and stages an unpacked extension at ~/OpenBrowser/extensions/chrome/ with a stable ID.
    • MV3 Chromium build added; background/content scripts now prefer browser with a chrome fallback and detect MV2/MV3. Screenshot uses captureVisibleTab when per-tab capture isn’t available.
    • config browser <browser> persists a default in ~/OpenBrowser/config.json; CLI resolves --browser, then the configured default, then Zen.
    • Build updates: npm run build now builds both families; added build:chromium. Version bumped to 2.1.0 across package and manifests.
  • Migration

    • Chrome: run install chrome, then in chrome://extensions enable Developer mode and “Load unpacked” from ~/OpenBrowser/extensions/chrome/.
    • Optional: set a default browser with OpenBrowser config browser chrome to omit --browser.

Written for commit c26da99. Summary will update on new commits.

Review in cubic

pxlarified and others added 2 commits July 7, 2026 21:35
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
@pxlarified

Copy link
Copy Markdown
Member Author

/codesmith review

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
@blacksmith-sh

blacksmith-sh Bot commented Jul 7, 2026

Copy link
Copy Markdown

@pxlarified

/codesmith review

I reviewed the PR and found one real bug, which I fixed and pushed (c26da99).

Findings

Bug (fixed): content.js cross-browser shim broke the Firefox path. The shim if (typeof browser === "undefined") var browser = chrome; lived inside the content-script IIFE. Because var browser is hoisted to function scope, typeof browser was always "undefined" at the check, so it unconditionally rebound to chrome even in Firefox/Zen. That silently switched the content script off the promise-based browser API it was written against (onMessage listeners returning Promise.resolve(...)), on the path that was previously working. I verified this empirically. background.js had the same idiom but at top-level, where it was actually correct, so the two were inconsistent.

Fixed both to a hoist-safe form that genuinely prefers browser:

const browser = globalThis.browser || globalThis.chrome; // background.js
var   browser = globalThis.browser || globalThis.chrome; // content.js (inside IIFE)

Confirmed: Firefox (both globals present) resolves to browser; Chrome (only chrome) falls back correctly. Rebuilt artifacts, web-ext lint clean (0/0/0), all 17 tests pass.

Other notes (not blocking, no change made)

  • Chrome MV3 service worker lifetime. background.js keeps a persistent native-messaging port. An MV3 service worker can be suspended; the reconnect logic handles a dropped port, and an open connectNative port extends SW lifetime, so it should hold, but this is the part most likely to need real-Chrome validation (already flagged in the PR body).
  • Stale signed Firefox artifact. dist/extensions/firefox/openbrowser.xpi is still the 2.0.1 signed build (signing needs AMO creds and happens at release), so it lags the source. This is pre-existing repo behavior; sign-firefox regenerates it on release. The install flow prefers the signed xpi, so Zen installs the last released extension until then, which is harmless here.
  • build.js reads CHROME_EXTENSION_KEY from constants.js via regex rather than importing it. It's guarded by the id-derivation test and tolerant of whitespace, but an import would be sturdier. Minor.

Everything else (Chromium adapter, native-messaging allowed_origins + registry layout, config resolution order, registry wiring, deterministic extension id) checked out against the intended behavior.

View with Codesmith

@pxlarified
pxlarified merged commit 141a544 into main Jul 7, 2026
5 checks passed
pxlarified added a commit that referenced this pull request Jul 8, 2026
* Add Chrome browser support and configurable default browser

Co-authored-by: fenjastical <fenjastical@users.noreply.github.com>

* Bump version to 2.1.0

Co-authored-by: fenjastical <fenjastical@users.noreply.github.com>

* Fix browser/chrome shim to prefer browser API in Firefox

Co-authored-by: fenjastical <fenjastical@users.noreply.github.com>

---------

Co-authored-by: fenjastical <fenjastical@users.noreply.github.com>
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.

1 participant