Skip to content

[js] Add webextension methods on the driver with BiDi and fallback - #18127

Merged
titusfortner merged 14 commits into
SeleniumHQ:trunkfrom
pujagani:js-webextension
Oct 8, 2026
Merged

titusfortner merged 14 commits into
SeleniumHQ:trunkfrom
pujagani:js-webextension

Conversation

@pujagani

@pujagani pujagani commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

🔗 Related Issues

Addresses ADR webextension. Related to #17933

💥 What does this PR do?

🔧 Implementation Notes

🤖 AI assistance

  • No substantial AI assistance used
  • AI assisted (complete below)
    • Tool(s):
    • What was generated:
    • I reviewed all AI output and can explain the change

💡 Additional Considerations

🔄 Types of changes

  • New feature (non-breaking change which adds functionality and tests!)

@selenium-ci selenium-ci added C-nodejs JavaScript Bindings B-build Includes scripting, bazel and CI integrations labels Oct 6, 2026
@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Add JavaScript WebExtension driver APIs with Firefox fallback

✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add driver methods to install and uninstall extensions through BiDi, with classic Firefox
 fallback.
• Support local and remote extension paths, archives, base64 input, and Firefox-specific options.
• Cover transport selection, validation, and browser behavior with unit and integration tests.
Diagram

graph TD
  API["Driver API"] --> Check{"BiDi enabled?"} -->|yes| Prep["Extension preparation"] --> Bidi["BiDi command"] --> Browser["Browser driver"]
  Prep -->|remote directory| Upload["Remote upload"] --> Bidi
  Check -->|Firefox without BiDi| Classic["Classic addon"] --> Browser
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. BiDi-only API
  • ➕ One transport and fewer browser-specific branches.
  • ➖ Firefox sessions without BiDi would lose an available installation path.
2. Classic Firefox API only
  • ➕ Reuses established geckodriver addon endpoints.
  • ➖ Does not provide a shared driver API for Chromium or BiDi sessions.

Recommendation: Keep the shared BiDi API with Firefox's classic fallback: it offers a consistent interface without requiring BiDi for existing Firefox sessions. The explicit local-service marker is preferable to assuming a client path is accessible to a remote browser.

Files changed (13) +863 / -4

Enhancement (8) +353 / -0
chromium.jsIdentify locally started Chromium driver services +1/-0

Identify locally started Chromium driver services

• Marks the Chromium command executor as a local service so extension directories can be referenced without remote upload.

javascript/selenium-webdriver/chromium.js

firefox.jsAdd Firefox WebExtension methods with classic fallback +68/-0

Add Firefox WebExtension methods with classic fallback

• Implements BiDi installation and uninstallation with Firefox-specific options, falling back to geckodriver addon commands when BiDi is disabled. Marks local executors and deprecates the older addon methods.

javascript/selenium-webdriver/firefox.js

ie.jsIdentify locally started IE driver services +2/-0

Identify locally started IE driver services

• Marks IE's service-backed executor as local for extension path handling.

javascript/selenium-webdriver/ie.js

index.jsExport the WebExtension result type +2/-0

Export the WebExtension result type

• Exposes the installed-extension wrapper from the package entry point.

javascript/selenium-webdriver/index.js

symbols.jsAdd an internal local-service executor marker +8/-0

Add an internal local-service executor marker

• Defines a symbol distinguishing client-started driver services from executors that may reach a remote host.

javascript/selenium-webdriver/lib/symbols.js

web_extension.jsPrepare and validate extension installation data +218/-0

Prepare and validate extension installation data

• Adds the immutable WebExtension result type and shared validation helpers. Encodes archives, packages directories, and uploads remote directories before BiDi installation.

javascript/selenium-webdriver/lib/web_extension.js

webdriver.jsAdd shared BiDi WebExtension driver methods +52/-0

Add shared BiDi WebExtension driver methods

• Adds install and uninstall methods backed by generated BiDi commands. Rejects unsupported options and sessions without BiDi.

javascript/selenium-webdriver/lib/webdriver.js

safari.jsIdentify locally started Safari driver services +2/-0

Identify locally started Safari driver services

• Marks Safari's service-backed executor as local for extension path handling.

javascript/selenium-webdriver/safari.js

Tests (3) +505 / -4
addon_test.jsExercise Firefox BiDi and classic extension installation +135/-4

Exercise Firefox BiDi and classic extension installation

• Adds browser tests for archives, base64 input, installation options, private windows, and no-BiDi fallback. Corrects the signed-directory fixture used by an existing addon test.

javascript/selenium-webdriver/test/firefox/addon_test.js

web_extension_test.jsCover extension validation and transport preparation +302/-0

Cover extension validation and transport preparation

• Adds executor-based tests for option and input errors, classic Firefox commands, extension identifiers, and local versus remote directory handling.

javascript/selenium-webdriver/test/lib/web_extension_test.js

web_extension_test.jsVerify shared driver extension behavior in browsers +68/-0

Verify shared driver extension behavior in browsers

• Adds browser integration tests for installing and uninstalling unpacked extensions through the shared driver API, targeting Chrome and Edge while skipping Firefox's affected directory behavior.

javascript/selenium-webdriver/test/web_extension_test.js

Other (2) +5 / -0
BUILD.bazelRegister WebExtension unit tests and generated BiDi lint input +3/-0

Register WebExtension unit tests and generated BiDi lint input

• Adds the WebExtension unit test to the small-test suite and makes generated BiDi sources available to the ESLint target.

javascript/selenium-webdriver/BUILD.bazel

eslint.config.jsExclude generated BiDi code from linting +2/-0

Exclude generated BiDi code from linting

• Ignores generated BiDi modules, whose formatting is owned by the generator.

javascript/selenium-webdriver/eslint.config.js

@qodo-code-review

qodo-code-review Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Remote installs report the wrong cause 🐞 Bug ☼ Reliability
Description
isUnsupportedCommand recognizes a generic 405 only when its message is exactly `HTTP method not
allowed. Remote ends that return the conventional bare Method Not Allowed` body are rethrown as
generic WebDriverError instances, so callers lose the explanation that directory installation
requires file-upload support.
Code

javascript/selenium-webdriver/lib/web_extension.js[184]

+    (err instanceof error.WebDriverError && err.message === 'HTTP method not allowed')
Evidence
uploadDirectory wraps errors only when isUnsupportedCommand returns true. The HTTP parser maps
non-JSON responses with status 405 to a generic WebDriverError containing the response body, so a
body of Method Not Allowed does not match the exact string currently accepted; the added tests
cover only HTTP method not allowed, not the standard alternative body.

javascript/selenium-webdriver/lib/web_extension.js[162-185]
javascript/selenium-webdriver/lib/http.js[529-536]
javascript/selenium-webdriver/test/lib/web_extension_test.js[291-310]

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

## Issue description
`isUnsupportedCommand` only recognizes the exact message `HTTP method not allowed` for bare HTTP 405 responses. A remote end returning the common `Method Not Allowed` body is not wrapped with the actionable unsupported-upload error, so remote directory installation exposes a generic WebDriver error.

## Fix Focus Areas
- javascript/selenium-webdriver/lib/web_extension.js[178-185]
- javascript/selenium-webdriver/test/lib/web_extension_test.js[291-310]

## Recommended Fix
Expand the 405 detection to recognize the standard bare response text, preferably by checking the normalized status/message rather than relying on one exact casing or phrase. Add a regression test for a generic `WebDriverError('Method Not Allowed')` and verify that `extensionData` returns `UnsupportedOperationError` with the existing upload-support guidance and preserves the original error as `cause`.

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

Dismiss ↗ | View ↗


2. New extension tests lack generated code ✗ Dismissed
Description
The new browser test calls installWebExtension(), whose BiDi branch requires
bidi/generated/webextension, but LARGE_TEST_DATA includes the workspace package link without
:create-bidi-src. In a hermetic Bazel browser test, that generated module is absent from the
test's runtime data, so the new Chrome and Edge cases fail with MODULE_NOT_FOUND before checking
installation.
Code

javascript/selenium-webdriver/test/web_extension_test.js[R43-44]

+      ignore(env.browsers(Browser.FIREFOX)).it('installs an unpacked directory', async function () {
+        const extension = await driver.installWebExtension(EXT_SIGNED_DIR)
Evidence
The new test exercises the lazy generated-module import; the browser test data omits the generating
target, although the package and lint targets explicitly include it.

javascript/selenium-webdriver/test/web_extension_test.js[41-59]
javascript/selenium-webdriver/lib/webdriver.js[1809-1817]
javascript/selenium-webdriver/BUILD.bazel[273-286]
javascript/selenium-webdriver/BUILD.bazel[140-145]
BUILD.bazel[123-125]

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 new browser tests exercise a method that requires generated BiDi JavaScript, but their Bazel runtime data does not include the generator output.
## Fix Focus Areas
- javascript/selenium-webdriver/BUILD.bazel[273-286]
- javascript/selenium-webdriver/test/web_extension_test.js[43-44]
## Recommended Fix
Add `:create-bidi-src` to the browser tests' runtime data and verify the new extension test under a clean hermetic Bazel build.

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


3. Kubernetes Grid rejects directory installs 🐞 Bug ≡ Correctness
Description
extensionData() sends every remote directory through UPLOAD_FILE, but the Kubernetes
OneShotNode.uploadFile() returns null instead of an unpacked directory path. When a BiDi session
runs through that node, installation cannot obtain the path it needs, including for Chromium's
unpacked-directory installs.
Code

javascript/selenium-webdriver/lib/web_extension.js[145]

+    return { type: 'path', path: local ? dir : await uploadDirectory(driver, dir) }
Evidence
The new remote-directory branch requires a returned upload path, while the Kubernetes Grid
implementation returns no upload response.

javascript/selenium-webdriver/lib/web_extension.js[139-162]
java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java[336-341]
java/src/org/openqa/selenium/grid/node/UploadFile.java[29-41]

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

## Issue description
Remote directory installation depends on Grid returning an unpacked path from its file-upload endpoint, but Kubernetes OneShotNode does not implement that endpoint.
## Fix Focus Areas
- javascript/selenium-webdriver/lib/web_extension.js[139-162]
- java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java[336-341]
## Recommended Fix
Implement file upload for OneShotNode so it extracts the uploaded directory onto the browser node's filesystem and returns that directory's path, consistent with LocalNode. Add a directory-install test through this Grid node type.

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

Dismiss ↗ | View ↗


View medium (1)
4. Re-enabled Firefox directory tests hit known bug 🐞 Bug ☼ Reliability
Description
The classic installAddon(EXT_SIGNED_DIR, true) test is un-ignored and the new no-BiDi fallback
test installs EXT_SIGNED_DIR with permanent: false. Both are temporary installs, which the PR's
own test/web_extension_test.js skips on Firefox because temporarily installed extensions no longer
inject content scripts (bugzilla 2045054). So these tests will fail or flake on Firefox CI.
Code

javascript/selenium-webdriver/test/firefox/addon_test.js[113]

+        it('installs and uninstalls by signed directory', async function () {
Evidence
The re-enabled test calls installAddon(EXT_SIGNED_DIR, true), which is a temporary install. The
removed comment noted that this hits bug 2045054. The PR's new cross-browser test ignores Firefox
for the same signed directory, saying Firefox installs a directory only temporarily and temporarily
installed extensions no longer inject content scripts. The fallback test at lines 243-255 also
passes permanent:false, so it is temporary too.

javascript/selenium-webdriver/test/firefox/addon_test.js[113-125]
javascript/selenium-webdriver/test/firefox/addon_test.js[243-255]
javascript/selenium-webdriver/test/web_extension_test.js[41-51]

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

## Issue description
Two Firefox tests install a directory temporarily, which hits Mozilla bug 2045054: temporarily installed extensions don't inject content scripts. The PR's own cross-browser test already ignores Firefox for this scenario, so these two tests contradict it.

## Fix Focus Areas
- javascript/selenium-webdriver/test/firefox/addon_test.js[113-125]
- javascript/selenium-webdriver/test/firefox/addon_test.js[243-255]

## Recommended Fix
Wrap both tests in `ignore(env.browsers(Browser.FIREFOX))` with the bugzilla 2045054 comment. Alternatively, change them to a permanent install of the signed directory (no `temporary`/`permanent: false`) so they don't depend on the temporary-install bug.

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

Dismiss ↗ | View ↗



Informational

5. Directory install fails on self-started drivers ✓ Resolved
Description
extensionData uses the browser-local path only when the executor carries
Symbols.localDriverService. Any other executor gets /se/file (UPLOAD_FILE), which only
Selenium Grid implements. So a session on a chromedriver or geckodriver the user started
(usingServer(url) pointing at it, or createSession(opts, new http.Executor(...))) fails to
install a directory with an unknown-command error, even though the path would resolve.
Code

javascript/selenium-webdriver/lib/web_extension.js[R142-145]

+  if (stats?.isDirectory()) {
+    const dir = path.resolve(extension)
+    const local = driver.getExecutor()[Symbols.localDriverService] === true
+    return { type: 'path', path: local ? dir : await uploadDirectory(driver, dir) }
Evidence
Only executors created by the client's own service paths are marked. Remote and custom executors
from the Builder (index.js usingServer) and from firefox.createSession(opts, httpExecutor) are left
unmarked. The upload command maps to the Grid-specific /session/:sessionId/se/file route, which
plain driver binaries do not serve.

javascript/selenium-webdriver/lib/web_extension.js[139-163]
javascript/selenium-webdriver/lib/http.js[307-307]
javascript/selenium-webdriver/index.js[668-687]
javascript/selenium-webdriver/firefox.js[476-478]

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

## Issue description
A directory extension is always uploaded via the Grid-only `/se/file` endpoint unless the executor is marked as a client-started driver service. Sessions on a self-started local chromedriver or geckodriver therefore fail with an unknown-command error.

## Fix Focus Areas
- javascript/selenium-webdriver/lib/web_extension.js[139-163]

## Recommended Fix
In `extensionData`, catch `error.UnknownCommandError` (or an unknown-method error) from `uploadDirectory` and fall back to `{type: 'path', path: dir}`. Otherwise, document that the remote end must support Selenium's file upload endpoint and expose a way to mark an executor as local.

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


Grey Divider

Context sources
Review mode: Auto: ⚖️ Balanced: Comparison failure: full PR diff.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Findings visible per group, which tucks the rest behind a View link

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous reviews

Review updated until commit bc4c912

Results up to commit 81f43cd 🧠 Deep


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


Remediation recommended
1. New extension tests lack generated code ✗ Dismissed
Description
The new browser test calls installWebExtension(), whose BiDi branch requires
bidi/generated/webextension, but LARGE_TEST_DATA includes the workspace package link without
:create-bidi-src. In a hermetic Bazel browser test, that generated module is absent from the
test's runtime data, so the new Chrome and Edge cases fail with MODULE_NOT_FOUND before checking
installation.
Code

javascript/selenium-webdriver/test/web_extension_test.js[R43-44]

+      ignore(env.browsers(Browser.FIREFOX)).it('installs an unpacked directory', async function () {
+        const extension = await driver.installWebExtension(EXT_SIGNED_DIR)
Evidence
The new test exercises the lazy generated-module import; the browser test data omits the generating
target, although the package and lint targets explicitly include it.

javascript/selenium-webdriver/test/web_extension_test.js[41-59]
javascript/selenium-webdriver/lib/webdriver.js[1809-1817]
javascript/selenium-webdriver/BUILD.bazel[273-286]
javascript/selenium-webdriver/BUILD.bazel[140-145]
BUILD.bazel[123-125]

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 new browser tests exercise a method that requires generated BiDi JavaScript, but their Bazel runtime data does not include the generator output.
## Fix Focus Areas
- javascript/selenium-webdriver/BUILD.bazel[273-286]
- javascript/selenium-webdriver/test/web_extension_test.js[43-44]
## Recommended Fix
Add `:create-bidi-src` to the browser tests' runtime data and verify the new extension test under a clean hermetic Bazel build.

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


2. Kubernetes Grid rejects directory installs 🐞 Bug ≡ Correctness
Description
extensionData() sends every remote directory through UPLOAD_FILE, but the Kubernetes
OneShotNode.uploadFile() returns null instead of an unpacked directory path. When a BiDi session
runs through that node, installation cannot obtain the path it needs, including for Chromium's
unpacked-directory installs.
Code

javascript/selenium-webdriver/lib/web_extension.js[145]

+    return { type: 'path', path: local ? dir : await uploadDirectory(driver, dir) }
Evidence
The new remote-directory branch requires a returned upload path, while the Kubernetes Grid
implementation returns no upload response.

javascript/selenium-webdriver/lib/web_extension.js[139-162]
java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java[336-341]
java/src/org/openqa/selenium/grid/node/UploadFile.java[29-41]

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

## Issue description
Remote directory installation depends on Grid returning an unpacked path from its file-upload endpoint, but Kubernetes OneShotNode does not implement that endpoint.
## Fix Focus Areas
- javascript/selenium-webdriver/lib/web_extension.js[139-162]
- java/src/org/openqa/selenium/grid/node/k8s/OneShotNode.java[336-341]
## Recommended Fix
Implement file upload for OneShotNode so it extracts the uploaded directory onto the browser node's filesystem and returns that directory's path, consistent with LocalNode. Add a directory-install test through this Grid node type.

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

Dismiss ↗ | View ↗


3. Re-enabled Firefox directory tests hit known bug 🐞 Bug ☼ Reliability
Description
The classic installAddon(EXT_SIGNED_DIR, true) test is un-ignored and the new no-BiDi fallback
test installs EXT_SIGNED_DIR with permanent: false. Both are temporary installs, which the PR's
own test/web_extension_test.js skips on Firefox because temporarily installed extensions no longer
inject content scripts (bugzilla 2045054). So these tests will fail or flake on Firefox CI.
Code

javascript/selenium-webdriver/test/firefox/addon_test.js[113]

+        it('installs and uninstalls by signed directory', async function () {
Evidence
The re-enabled test calls installAddon(EXT_SIGNED_DIR, true), which is a temporary install. The
removed comment noted that this hits bug 2045054. The PR's new cross-browser test ignores Firefox
for the same signed directory, saying Firefox installs a directory only temporarily and temporarily
installed extensions no longer inject content scripts. The fallback test at lines 243-255 also
passes permanent:false, so it is temporary too.

javascript/selenium-webdriver/test/firefox/addon_test.js[113-125]
javascript/selenium-webdriver/test/firefox/addon_test.js[243-255]
javascript/selenium-webdriver/test/web_extension_test.js[41-51]

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

## Issue description
Two Firefox tests install a directory temporarily, which hits Mozilla bug 2045054: temporarily installed extensions don't inject content scripts. The PR's own cross-browser test already ignores Firefox for this scenario, so these two tests contradict it.

## Fix Focus Areas
- javascript/selenium-webdriver/test/firefox/addon_test.js[113-125]
- javascript/selenium-webdriver/test/firefox/addon_test.js[243-255]

## Recommended Fix
Wrap both tests in `ignore(env.browsers(Browser.FIREFOX))` with the bugzilla 2045054 comment. Alternatively, change them to a permanent install of the signed directory (no `temporary`/`permanent: false`) so they don't depend on the temporary-install bug.

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

Dismiss ↗ | View ↗



Informational
4. Directory install fails on self-started drivers ✓ Resolved
Description
extensionData uses the browser-local path only when the executor carries
Symbols.localDriverService. Any other executor gets /se/file (UPLOAD_FILE), which only
Selenium Grid implements. So a session on a chromedriver or geckodriver the user started
(usingServer(url) pointing at it, or createSession(opts, new http.Executor(...))) fails to
install a directory with an unknown-command error, even though the path would resolve.
Code

javascript/selenium-webdriver/lib/web_extension.js[R142-145]

+  if (stats?.isDirectory()) {
+    const dir = path.resolve(extension)
+    const local = driver.getExecutor()[Symbols.localDriverService] === true
+    return { type: 'path', path: local ? dir : await uploadDirectory(driver, dir) }
Evidence
Only executors created by the client's own service paths are marked. Remote and custom executors
from the Builder (index.js usingServer) and from firefox.createSession(opts, httpExecutor) are left
unmarked. The upload command maps to the Grid-specific /session/:sessionId/se/file route, which
plain driver binaries do not serve.

javascript/selenium-webdriver/lib/web_extension.js[139-163]
javascript/selenium-webdriver/lib/http.js[307-307]
javascript/selenium-webdriver/index.js[668-687]
javascript/selenium-webdriver/firefox.js[476-478]

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

## Issue description
A directory extension is always uploaded via the Grid-only `/se/file` endpoint unless the executor is marked as a client-started driver service. Sessions on a self-started local chromedriver or geckodriver therefore fail with an unknown-command error.

## Fix Focus Areas
- javascript/selenium-webdriver/lib/web_extension.js[139-163]

## Recommended Fix
In `extensionData`, catch `error.UnknownCommandError` (or an unknown-method error) from `uploadDirectory` and fall back to `{type: 'path', path: dir}`. Otherwise, document that the remote end must support Selenium's file upload endpoint and expose a way to mark an executor as local.

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


Results up to commit ae50dc1 🚀 Fast


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


Remediation recommended
1. Remote installs report the wrong cause 🐞 Bug ☼ Reliability
Description
isUnsupportedCommand recognizes a generic 405 only when its message is exactly `HTTP method not
allowed. Remote ends that return the conventional bare Method Not Allowed` body are rethrown as
generic WebDriverError instances, so callers lose the explanation that directory installation
requires file-upload support.
Code

javascript/selenium-webdriver/lib/web_extension.js[184]

+    (err instanceof error.WebDriverError && err.message === 'HTTP method not allowed')
Evidence
uploadDirectory wraps errors only when isUnsupportedCommand returns true. The HTTP parser maps
non-JSON responses with status 405 to a generic WebDriverError containing the response body, so a
body of Method Not Allowed does not match the exact string currently accepted; the added tests
cover only HTTP method not allowed, not the standard alternative body.

javascript/selenium-webdriver/lib/web_extension.js[162-185]
javascript/selenium-webdriver/lib/http.js[529-536]
javascript/selenium-webdriver/test/lib/web_extension_test.js[291-310]

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

## Issue description
`isUnsupportedCommand` only recognizes the exact message `HTTP method not allowed` for bare HTTP 405 responses. A remote end returning the common `Method Not Allowed` body is not wrapped with the actionable unsupported-upload error, so remote directory installation exposes a generic WebDriver error.

## Fix Focus Areas
- javascript/selenium-webdriver/lib/web_extension.js[178-185]
- javascript/selenium-webdriver/test/lib/web_extension_test.js[291-310]

## Recommended Fix
Expand the 405 detection to recognize the standard bare response text, preferably by checking the normalized status/message rather than relying on one exact casing or phrase. Add a regression test for a generic `WebDriverError('Method Not Allowed')` and verify that `extensionData` returns `UnsupportedOperationError` with the existing upload-support guidance and preserves the original error as `cause`.

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

Dismiss ↗ | View ↗


Grey Divider

Qodo Logo

Comment thread javascript/selenium-webdriver/lib/web_extension.js
Comment thread javascript/selenium-webdriver/test/web_extension_test.js Outdated
Comment thread javascript/selenium-webdriver/test/firefox/addon_test.js
Comment thread javascript/selenium-webdriver/lib/web_extension.js
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 912bfb5

Comment thread javascript/selenium-webdriver/lib/web_extension.js
@qodo-code-review

Copy link
Copy Markdown
Contributor

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

@titusfortner

Copy link
Copy Markdown
Member

oops, I broke this trying to fix the test fixture on trunk. I'll merge the fix, once tests pass, should be good to merge.

@qodo-code-review

Copy link
Copy Markdown
Contributor

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

@nvborisenko

Copy link
Copy Markdown
Member

Just for me to understand (pseudo code):

driver.install_web_extension(...)

Is it the best effort? Like if "bidi enabled" - try, hm something bad - fallback. Runtime decision?

@nvborisenko

Copy link
Copy Markdown
Member

I am asking because soon I should introduce in .NET to factory BiDi connection. This connection wants to be lazy (seems).

@titusfortner

Copy link
Copy Markdown
Member

@nvborisenko see the decisions here: https://github.com/seleniumhq/selenium/blob/trunk/docs/decisions/17817-driver-extension-install.md#decision

No fallback/retry, it's toggled on the websocketurl capability, so using the method in a classic session with Chrome will give an error, and using it with Firefox will use the classic endpoint.

@titusfortner
titusfortner merged commit 0826d31 into SeleniumHQ:trunk Oct 8, 2026
31 checks passed
This was referenced Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B-build Includes scripting, bazel and CI integrations C-nodejs JavaScript Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants