Skip to content

Bug 2062055 - [firefox-devtools-mcp] resolve geckodriver on all platforms so aarch64 Linux can launch - #170

Open
shoemoney wants to merge 1 commit into
mozilla:mainfrom
shoemoney:bug-2062055-arm64-geckodriver
Open

Bug 2062055 - [firefox-devtools-mcp] resolve geckodriver on all platforms so aarch64 Linux can launch#170
shoemoney wants to merge 1 commit into
mozilla:mainfrom
shoemoney:bug-2062055-arm64-geckodriver

Conversation

@shoemoney

Copy link
Copy Markdown
Contributor

connect() built the geckodriver service without a driver path on every non-Windows platform:

let serviceBuilder;
if (process.platform === 'win32') {
  const geckodriverPath = await findGeckodriver();     // Bug 2040849
  serviceBuilder = new firefox.ServiceBuilder(geckodriverPath);
} else {
  // On other platforms, the default ServiceBuilder should locate and
  // start geckodriver successfully.
  serviceBuilder = new firefox.ServiceBuilder();       // <- falls through to selenium-manager
}

With no path, selenium-webdriver invokes its bundled selenium-manager. The Linux binary shipped with selenium-webdriver@4.36.0 is x86-64 only:

$ file node_modules/selenium-webdriver/bin/linux/selenium-manager
node_modules/selenium-webdriver/bin/linux/selenium-manager: ELF 64-bit LSB pie executable,
  x86-64, version 1 (SYSV), static-pie linked, stripped

$ node_modules/selenium-webdriver/bin/linux/selenium-manager --version
bash: cannot execute binary file: Exec format error

So on aarch64 the session dies before Firefox is ever contacted — and a native geckodriver sitting in PATH does not help, because nothing on this branch looks there.

Confirming the report

@masato.kojima's diagnosis is exactly right, and I could reproduce it on real hardware. Raspberry Pi, aarch64 Ubuntu 24.04, official Mozilla linux64-aarch64 Firefox, geckodriver 0.37.1 aarch64 in PATH, unmodified main at e04a955:

host: aarch64   firefox: Mozilla Firefox 154.0   geckodriver: 0.37.1
FAIL pi/BASELINE (12ms) -> Unable to obtain browser driver.

Same error string as the bug, and it fails in 12ms — before any browser work, which is the tell that this is the driver lookup and not Firefox.

The change

Resolve the path on every platform. This was the only one of four ServiceBuilder sites not already doing so — the Android path and the --connect-existing path both call findGeckodriver() unconditionally, and the Windows branch of this very block already did. The else was the outlier.

findGeckodriver() checks PATH, then ~/.cache/selenium/geckodriver, then downloads a platform-correct binary via the geckodriver package (a regular dependency at 6.0.2). None of those tiers can produce a wrong-architecture binary.

The diff on the source is net −12/+11 — it deletes the branch rather than adding one.

Verification

Same Pi, same Firefox, same geckodriver, one-file patch:

result
main (e04a955) FAIL in 12ms — Unable to obtain browser driver.
with this patch PASS in 3411ms — Gecko/20100101 Firefox/154.0

The regression I was worried about, and checked. Passing a driver path also stops selenium-webdriver calling getBinaryPaths(), which is how selenium-manager discovers the Firefox binary — and setBinary() is only called here when --firefox-path is given. So the question was whether geckodriver finds Firefox on its own. On macOS, launching with no --firefox-path:

mac/baseline/no-path   PASS (11009ms)  Firefox/154.0
mac/fixed/no-path      PASS ( 7210ms)  Firefox/154.0

It does, and it is ~3.8s faster because the selenium-manager round trip is gone. On the Pi it passes both with and without --firefox-path.

Full suite on macOS, including the integration tests against a real Firefox:

npm run lint          clean
prettier --check      clean
tsc --noEmit          clean
npm run build         clean
vitest run            50 files, 650 tests passed

Test

One unit test in tests/firefox/core.test.ts, using the existing mocked-Selenium harness. It captures the ServiceBuilder constructor argument, which is the thing that was missing. On unmodified main:

× should build the geckodriver service with an explicit binary path
AssertionError: expected 'undefined' to be 'string'

That undefined is the bug — it is the argument selenium-manager gets invoked in place of.

I did not add an integration test for this: reproducing it requires an aarch64 Linux host, and CI runs x86-64, so the test would pass there for the wrong reason and prove nothing. The hardware evidence above is in this PR instead.

Note

The bug is still UNCONFIRMED in Bugzilla. Everything above reproduces it on real aarch64 hardware, so it can be confirmed if that is useful — happy to add the details there.

中文说明

在非 Windows 平台上,connect() 构造 geckodriver 服务时未传入驱动路径,导致 selenium-webdriver 回退到其内置的 selenium-manager。而 selenium-webdriver@4.36.0 附带的 Linux 版 selenium-manager 仅为 x86-64 二进制,在 aarch64 主机上无法执行(Exec format error),因此会话在接触 Firefox 之前就以 Unable to obtain browser driver 失败——即使 PATH 中已存在原生 aarch64 geckodriver 也无济于事。

本改动在所有平台上都自行解析 geckodriver 路径。这是本仓库四处 ServiceBuilder 调用中唯一尚未这样做的一处:Android 路径与 --connect-existing 路径均已无条件调用 findGeckodriver(),同一代码块的 Windows 分支也是如此。

在树莓派(aarch64 Ubuntu 24.04、官方 aarch64 Firefox 154.0、geckodriver 0.37.1)上验证:main 失败(12ms),打上本补丁后通过(3411ms)。同时在 macOS 上确认——由于传入驱动路径也会跳过 selenium-manager 对 Firefox 二进制的查找——在不指定 --firefox-path 时 Firefox 仍能被正确发现,且启动快约 3.8 秒。

macOS 全量测试(含针对真实 Firefox 的集成测试):50 个文件、650 个测试全部通过。

…orms so aarch64 Linux can launch

The normal launch path built `new firefox.ServiceBuilder()` with no driver
path on every non-Windows platform, so selenium-webdriver fell back to its
bundled selenium-manager. The Linux selenium-manager shipped with
selenium-webdriver 4.36.0 is an x86-64 binary:

  node_modules/selenium-webdriver/bin/linux/selenium-manager:
    ELF 64-bit LSB pie executable, x86-64, static-pie linked, stripped

On an aarch64 host it cannot execute, and the session fails immediately with
"Unable to obtain browser driver" even when a native aarch64 geckodriver is
in PATH.

This was the only one of four ServiceBuilder sites not already resolving the
path itself. The Android and --connect-existing paths call findGeckodriver()
unconditionally, and the Windows branch of this same block already did too
(Bug 2040849). This makes the remaining branch consistent with them.

findGeckodriver() checks PATH, then the selenium cache, then downloads a
platform-correct binary via the geckodriver package, which is a regular
dependency. Verified on macOS that Firefox is still discovered without
--firefox-path, since passing a driver path also disables selenium-manager's
browser lookup.
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