Skip to content

[rust] locate Chrome and Edge in known install directories - #17838

Merged
titusfortner merged 4 commits into
SeleniumHQ:trunkfrom
titusfortner:chrome-edge-known-locations
Jul 30, 2026
Merged

[rust] locate Chrome and Edge in known install directories#17838
titusfortner merged 4 commits into
SeleniumHQ:trunkfrom
titusfortner:chrome-edge-known-locations

Conversation

@titusfortner

Copy link
Copy Markdown
Member

🔗 Related Issues

Fixes #17823

💥 What does this PR do?

Selenium Manager now looks for Chrome and Edge in their standard install locations on Linux, not just the single path it checked before (/usr/bin/google-chrome, /usr/bin/microsoft-edge). This lets it detect browsers installed elsewhere — e.g. on Arch Linux — instead of missing them and downloading a driver for the wrong version. For Chrome, those locations are exactly ChromeDriver's own, so the two resolve the same binary.

🔧 Implementation Notes

  • Chrome — matches ChromeDriver's search. For the default channel, Selenium Manager probes ChromeDriver's fixed Linux directory list (/usr/local/*, /usr/*, /opt/google/chrome, /opt/chromium.org/chromium) crossed with chrome/google-chrome/chromium/chromium-browser, in ChromeDriver's order (see chrome_finder.cc). Because it reproduces ChromeDriver's own documented search, both resolve the identical binary (e.g. /opt/google/chrome/chrome) regardless of $PATH order — agreement by construction.
  • Edge — added coverage, not verified parity. msedgedriver's binary search isn't published (it's a closed-source ChromeDriver fork), so this does not attempt to match it. It only gives Selenium Manager Edge's known install locations as extra candidates — /opt/microsoft/msedge × msedge/microsoft-edge/microsoft-edge-stable — plus the microsoft-edge/microsoft-edge-stable names in the $PATH fallback (which previously searched only edge, never a real Linux binary, so Edge had no working fallback). This stops Selenium Manager missing Edge; it does not guarantee the exact binary msedgedriver would pick.
  • Both go through a detect_browser_in_known_locations hook on the manager trait (default no-op), scoped to the default channel at the call site (a fixed-directory search is channel-agnostic; beta/dev keep their channel-specific paths).
  • Copying ChromeDriver's directory list is low-risk and cheap: the list hasn't changed since 2018 (byte-identical across the 2018/2020/2026 revisions of chrome_finder.cc), and the added work is a handful of Path::exists() checks — negligible next to the --version subprocess Selenium Manager already spawns to detect the browser version.

🤖 AI assistance

  • AI assisted (complete below)
    • Tool(s): Claude Code (Opus 4.8)
    • What was generated: the browser-detection change in chrome.rs/edge.rs/lib.rs, the unit tests, and the backward-compatibility analysis
    • I reviewed all AI output and can explain the change

💡 Additional Considerations

Backward compatibility — applies only when no --browser-path is given, and only to the default channel. Selenium Manager now resolves the exact binary ChromeDriver does (the SM (this PR) and ChromeDriver columns match in every row). For standard installs that's the same browser and version as before, just reported via the canonical /opt/google/chrome/chrome path ChromeDriver uses instead of the /usr/bin symlink. Row 1 is the common case (path-only change, same version); row 2 is the reported bug; rows 3–4 are low-likelihood (two Chrome-family browsers installed side by side).

Installed browsers (Linux) ChromeDriver SM (current) SM (this PR)
Standard Debian/Ubuntu
/usr/bin/google-chrome (symlink → /opt/google/chrome/chrome)
/opt/google/chrome/chrome /usr/bin/google-chrome /opt/google/chrome/chrome
Arch Linux default
/usr/bin/google-chrome-stable (symlink → /opt/google/chrome/chrome)
• no /usr/bin/google-chrome
/opt/google/chrome/chrome none — downloads latest CfT /opt/google/chrome/chrome
Arch Linux + Chromium
/usr/bin/google-chrome-stable (symlink → /opt/google/chrome/chrome) (version X)
/usr/bin/chromium (version Y)
• no /usr/bin/google-chrome
/opt/google/chrome/chrome (X) /usr/bin/chromium (Y) /opt/google/chrome/chrome (X)
Two Chromium packages
/usr/bin/chromium (version X)
/usr/bin/chromium-browser (version Y)
• no Google Chrome
/usr/bin/chromium (X) /usr/bin/chromium-browser (Y) /usr/bin/chromium (X)

Edge sees only the same benign path shift — existing installs now report /opt/microsoft/msedge/msedge (same version) — and has no equivalent of the multi-browser rows above, since it has no Chromium-style sibling. Firefox needs no change: geckodriver already locates the browser through $PATH (plus the snap path), which Selenium Manager already matches.

🔄 Types of changes

  • Bug fix (backwards compatible)

@selenium-ci selenium-ci added C-rust Rust code is mostly Selenium Manager B-manager Selenium Manager labels Jul 29, 2026
@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Detect Chrome and Edge in standard Linux install locations

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Detect Chrome and Edge across standard Linux installation directories.
• Preserve channel-specific discovery while prioritizing default-channel known locations.
• Add binary-name and Linux-only detection tests.
Diagram

graph TD
  A["Selenium Manager"] --> B{"Default channel?"} -- "yes" --> C["Known locations"] --> D{"Binary found?"} -- "yes" --> E["Canonical path"]
  B -- "no" --> F["Channel path map"] -- "if absent" --> G["System PATH"]
  D -- "no" --> F
Loading
High-Level Assessment

The trait hook with a default no-op is the appropriate approach: it isolates browser-specific search order, preserves all other managers, and retains existing channel and PATH fallbacks. A shared directory-scanning helper was considered, but the small Chrome and Edge lists have different ordering and parity guarantees, so centralizing them would add abstraction without materially reducing risk.

Files changed (4) +113 / -2

Bug fix (3) +78 / -2
chrome.rsMirror ChromeDriver's Linux binary search locations +33/-1

Mirror ChromeDriver's Linux binary search locations

• Expands Chrome PATH executable names and probes ChromeDriver-compatible fixed Linux directories in deterministic order. The search remains disabled on non-Linux platforms.

rust/src/chrome.rs

edge.rsSearch known Linux locations for Edge binaries +27/-1

Search known Linux locations for Edge binaries

• Adds real Linux Edge executable names for PATH discovery and probes standard directories, including '/opt/microsoft/msedge'. Non-Linux platforms continue using existing detection behavior.

rust/src/edge.rs

lib.rsAdd a default-channel known-location detection hook +18/-0

Add a default-channel known-location detection hook

• Introduces an optional manager trait hook for browser-specific known locations. Default-channel discovery invokes it before existing channel-path and PATH detection, then canonicalizes and records successful results.

rust/src/lib.rs

Tests (1) +35 / -0
browser_tests.rsCover Chrome and Edge discovery names and platform guards +35/-0

Cover Chrome and Edge discovery names and platform guards

• Verifies the Chrome and Edge PATH binary-name lists and confirms fixed-location detection returns no result when configured for macOS.

rust/tests/browser_tests.rs

@qodo-code-review

qodo-code-review Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. WebView2 casing bypasses guard ✓ Resolved 🐞 Bug ≡ Correctness ⭐ New
Description
Manager selection accepts browser names case-insensitively but preserves their original casing,
while the new WebView2 guard uses a case-sensitive comparison. A supported input such as `--browser
WebView2` therefore receives Edge executable candidates and can resolve an installed Edge binary
instead of WebView2.
Code

rust/src/edge.rs[118]

+        if self.is_webview2() {
Evidence
Manager selection lowercases the input only for validation and then passes the original string to
EdgeManager, which stores it unchanged. Because is_webview2() uses case-sensitive eq, the new
guards at lines 118 and 131 fail for accepted variants such as WebView2, enabling Edge PATH
aliases and known-location lookup.

rust/src/lib.rs[1719-1726]
rust/src/edge.rs[90-99]
rust/src/lib.rs[793-795]
rust/src/edge.rs[117-134]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Mixed-case WebView2 names accepted by manager selection bypass the new WebView2-specific exclusions because `is_webview2()` compares case-sensitively. This allows Edge PATH aliases and Linux known-location detection to run for WebView2.

## Issue Context
`get_manager_by_browser()` validates a lowercase copy but passes the original browser name into `EdgeManager`. Normalize the stored name or make the WebView2 predicate case-insensitive, and add a mixed-case regression test covering both detection methods.

## Fix Focus Areas
- rust/src/lib.rs[793-795]
- rust/src/edge.rs[117-134]
- rust/tests/browser_tests.rs[273-279]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Fixed temp path causes collisions ✓ Resolved 📘 Rule violation ☼ Reliability
Description
The unit test uses a fixed, process-global temporary directory, allowing concurrent executions to
delete or mutate each other's fixtures and causing nondeterministic failures. Interrupted runs can
also leave incompatible filesystem state that breaks subsequent setup, making the test
environment-dependent rather than reliably isolated.
Code

rust/tests/browser_tests.rs[278]

+    let base = std::env::temp_dir().join("sm-first-existing-path-test");
Evidence
Compliance rule 5 requires reliable unit tests, but the fixed directory at line 278 and the shared
filesystem setup, lookup, and manual cleanup through line 296 allow concurrent test processes to
race and previously interrupted runs to leave stale state. The repository already includes
tempfile and uses tempfile::tempdir() in other tests to provide isolated, uniquely named,
RAII-managed fixtures.

AGENTS.md: Prefer Reliable Unit Tests and Avoid Contract-Distorting Mocks
rust/tests/browser_tests.rs[278-296]
rust/Cargo.toml[20-20]
rust/src/files.rs[905-905]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test uses the fixed path `sm-first-existing-path-test` beneath `std::env::temp_dir()`, allowing concurrent test processes or stale artifacts from interrupted runs to interfere with fixture setup, lookup, and cleanup.

## Issue Context
The project already depends on `tempfile` and uses `tempfile::tempdir()` in other tests. Replace the deterministic shared directory with an automatically unique temporary directory and rely on its RAII cleanup behavior to isolate each test execution.

## Fix Focus Areas
- rust/tests/browser_tests.rs[278-296]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Known-location success paths untested ✓ Resolved 📘 Rule violation ☼ Reliability
Description
The added tests only verify that known-location detection returns None for a simulated non-Linux
OS; they never exercise successful Linux discovery, candidate ordering, or the integration into
detect_browser_path(). Regressions in the PR's primary behavior could therefore pass the test
suite.
Code

rust/tests/browser_tests.rs[R251-254]

+fn chrome_detect_browser_in_known_locations_is_linux_only() {
+    let mut manager = ChromeManager::new().unwrap();
+    manager.config.os = "macos".to_string();
+    assert!(manager.detect_browser_in_known_locations().is_none());
Evidence
Compliance rule 5 requires appropriate coverage of changed behavior. The production code introduces
positive filesystem searches across fixed directories, but the new tests cover only name vectors and
the early non-Linux return, leaving the successful search and call-site behavior untested.

AGENTS.md: Prefer Small Tests and Avoid Mocks That Misrepresent API Contracts
rust/src/chrome.rs[239-263]
rust/src/edge.rs[108-131]
rust/tests/browser_tests.rs[241-271]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The tests do not exercise successful Chrome or Edge discovery in known Linux installation locations, which is the primary behavior introduced by this change.

## Issue Context
Add small deterministic tests, preferably by extracting a helper that accepts candidate directories so temporary directories can verify successful discovery and precedence without modifying system paths. Also verify that `detect_browser_path()` uses the discovered candidate for the default channel.

## Fix Focus Areas
- rust/src/chrome.rs[239-263]
- rust/src/edge.rs[108-131]
- rust/src/lib.rs[428-441]
- rust/tests/browser_tests.rs[241-271]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. EdgeManager drops requested alias ✓ Resolved 📘 Rule violation ≡ Correctness
Description
get_browser_names_in_path() now replaces the requested Edge name with only two Linux package
names, even though public manager creation supports aliases such as edge, msedge,
microsoftedge, and webview2. As a result, supported aliases in nonstandard PATH locations or
on other platforms may no longer be discovered, causing Selenium Manager to report Edge as
unavailable despite the requested executable being present.
Code

rust/src/edge.rs[105]

+        vec!["microsoft-edge", "microsoft-edge-stable"]
Evidence
Compliance rule 1 requires preserving public API behavior: EDGE_NAMES exposes aliases including
edge, msedge, microsoftedge, and webview2, and get_manager_by_browser() passes the
selected alias to EdgeManager::new_with_name(), which retains it. Because the generic fallback
searches only the values returned by get_browser_names_in_path(), removing
self.get_browser_name() discards the configured alias during PATH lookup; the fixed Linux
candidates do not cover arbitrary PATH directories, all accepted aliases, or other platforms.

AGENTS.md: Preserve Public API and ABI Compatibility and Deprecate Before Removal
rust/src/edge.rs[40-45]
rust/src/edge.rs[73-81]
rust/src/lib.rs[1717-1725]
rust/src/edge.rs[78-87]
rust/src/lib.rs[696-715]
rust/src/lib.rs[1717-1724]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Preserve `PATH` discovery for supported Edge aliases while retaining the new Linux executable candidates. `EdgeManager::get_browser_names_in_path()` currently replaces the requested browser name with two fixed names, omitting accepted aliases such as `edge`, `msedge`, `microsoftedge`, and `webview2`.

## Issue Context
`get_manager_by_browser()` accepts names from `EDGE_NAMES` and passes the requested name into `EdgeManager`, while the generic `PATH` fallback searches only the values returned by `get_browser_names_in_path()`. Keep the new real Linux binary candidates, restore lookup using the manager's requested browser name, preserve existing alias behavior, and update tests to cover alias-specific managers.

## Fix Focus Areas
- rust/src/edge.rs[40-45]
- rust/src/edge.rs[78-87]
- rust/src/edge.rs[104-106]
- rust/src/lib.rs[696-715]
- rust/tests/browser_tests.rs[257-264]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Previous review results

Review updated until commit 99a4146

Results up to commit 4de9a65 ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Known-location success paths untested ✓ Resolved 📘 Rule violation ☼ Reliability
Description
The added tests only verify that known-location detection returns None for a simulated non-Linux
OS; they never exercise successful Linux discovery, candidate ordering, or the integration into
detect_browser_path(). Regressions in the PR's primary behavior could therefore pass the test
suite.
Code

rust/tests/browser_tests.rs[R251-254]

+fn chrome_detect_browser_in_known_locations_is_linux_only() {
+    let mut manager = ChromeManager::new().unwrap();
+    manager.config.os = "macos".to_string();
+    assert!(manager.detect_browser_in_known_locations().is_none());
Evidence
Compliance rule 5 requires appropriate coverage of changed behavior. The production code introduces
positive filesystem searches across fixed directories, but the new tests cover only name vectors and
the early non-Linux return, leaving the successful search and call-site behavior untested.

AGENTS.md: Prefer Small Tests and Avoid Mocks That Misrepresent API Contracts
rust/src/chrome.rs[239-263]
rust/src/edge.rs[108-131]
rust/tests/browser_tests.rs[241-271]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The tests do not exercise successful Chrome or Edge discovery in known Linux installation locations, which is the primary behavior introduced by this change.

## Issue Context
Add small deterministic tests, preferably by extracting a helper that accepts candidate directories so temporary directories can verify successful discovery and precedence without modifying system paths. Also verify that `detect_browser_path()` uses the discovered candidate for the default channel.

## Fix Focus Areas
- rust/src/chrome.rs[239-263]
- rust/src/edge.rs[108-131]
- rust/src/lib.rs[428-441]
- rust/tests/browser_tests.rs[241-271]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. EdgeManager drops requested alias ✓ Resolved 📘 Rule violation ≡ Correctness
Description
get_browser_names_in_path() now replaces the requested Edge name with only two Linux package
names, even though public manager creation supports aliases such as edge, msedge,
microsoftedge, and webview2. As a result, supported aliases in nonstandard PATH locations or
on other platforms may no longer be discovered, causing Selenium Manager to report Edge as
unavailable despite the requested executable being present.
Code

rust/src/edge.rs[105]

+        vec!["microsoft-edge", "microsoft-edge-stable"]
Evidence
Compliance rule 1 requires preserving public API behavior: EDGE_NAMES exposes aliases including
edge, msedge, microsoftedge, and webview2, and get_manager_by_browser() passes the
selected alias to EdgeManager::new_with_name(), which retains it. Because the generic fallback
searches only the values returned by get_browser_names_in_path(), removing
self.get_browser_name() discards the configured alias during PATH lookup; the fixed Linux
candidates do not cover arbitrary PATH directories, all accepted aliases, or other platforms.

AGENTS.md: Preserve Public API and ABI Compatibility and Deprecate Before Removal
rust/src/edge.rs[40-45]
rust/src/edge.rs[73-81]
rust/src/lib.rs[1717-1725]
rust/src/edge.rs[78-87]
rust/src/lib.rs[696-715]
rust/src/lib.rs[1717-1724]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Preserve `PATH` discovery for supported Edge aliases while retaining the new Linux executable candidates. `EdgeManager::get_browser_names_in_path()` currently replaces the requested browser name with two fixed names, omitting accepted aliases such as `edge`, `msedge`, `microsoftedge`, and `webview2`.

## Issue Context
`get_manager_by_browser()` accepts names from `EDGE_NAMES` and passes the requested name into `EdgeManager`, while the generic `PATH` fallback searches only the values returned by `get_browser_names_in_path()`. Keep the new real Linux binary candidates, restore lookup using the manager's requested browser name, preserve existing alias behavior, and update tests to cover alias-specific managers.

## Fix Focus Areas
- rust/src/edge.rs[40-45]
- rust/src/edge.rs[78-87]
- rust/src/edge.rs[104-106]
- rust/src/lib.rs[696-715]
- rust/tests/browser_tests.rs[257-264]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit c342c44 ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Fixed temp path causes collisions ✓ Resolved 📘 Rule violation ☼ Reliability
Description
The unit test uses a fixed, process-global temporary directory, allowing concurrent executions to
delete or mutate each other's fixtures and causing nondeterministic failures. Interrupted runs can
also leave incompatible filesystem state that breaks subsequent setup, making the test
environment-dependent rather than reliably isolated.
Code

rust/tests/browser_tests.rs[278]

+    let base = std::env::temp_dir().join("sm-first-existing-path-test");
Evidence
Compliance rule 5 requires reliable unit tests, but the fixed directory at line 278 and the shared
filesystem setup, lookup, and manual cleanup through line 296 allow concurrent test processes to
race and previously interrupted runs to leave stale state. The repository already includes
tempfile and uses tempfile::tempdir() in other tests to provide isolated, uniquely named,
RAII-managed fixtures.

AGENTS.md: Prefer Reliable Unit Tests and Avoid Contract-Distorting Mocks
rust/tests/browser_tests.rs[278-296]
rust/Cargo.toml[20-20]
rust/src/files.rs[905-905]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test uses the fixed path `sm-first-existing-path-test` beneath `std::env::temp_dir()`, allowing concurrent test processes or stale artifacts from interrupted runs to interfere with fixture setup, lookup, and cleanup.

## Issue Context
The project already depends on `tempfile` and uses `tempfile::tempdir()` in other tests. Replace the deterministic shared directory with an automatically unique temporary directory and rely on its RAII cleanup behavior to isolate each test execution.

## Fix Focus Areas
- rust/tests/browser_tests.rs[278-296]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment thread rust/src/edge.rs Outdated
Comment thread rust/tests/browser_tests.rs
@titusfortner
titusfortner requested a review from bonigarcia July 29, 2026 00:42
Comment thread rust/tests/browser_tests.rs Outdated
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit c342c44

Comment thread rust/src/edge.rs
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit c9df96f

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 99a4146

@bonigarcia bonigarcia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@titusfortner
titusfortner merged commit bf18c11 into SeleniumHQ:trunk Jul 30, 2026
92 of 94 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B-manager Selenium Manager C-rust Rust code is mostly Selenium Manager

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[🐛 Bug]: Ruby selenium-webdriver gem errors in Arch Linux (ChromeDriver version mismatch)

3 participants