You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ensure init() is called before install/uninstall to avoid using an uninitialized this.bidi; consider guarding or initializing in constructor or throwing a clearer error if not initialized.
asyncinit(){if(!(awaitthis._driver.getCapabilities()).get('webSocketUrl')){throwError('WebDriver instance must support BiDi protocol')}this.bidi=awaitthis._driver.getBidi()}
The static constructors setPath, setArchivePath, and setBase64Encoded are semantically "create" methods; consider clearer names like fromPath, fromArchive, fromBase64 for consistency with common factory patterns.
install() assumes response.result.extension exists; add validation and throw a descriptive error if the BiDi response shape differs or contains an error.
The BiDi support check relies solely on the presence of webSocketUrl, which may be absent with alternative BiDi transports or future capability shapes, causing false negatives. Consider using the driver's explicit BiDi availability (e.g., a dedicated capability/feature flag or catching getBidi failures) to robustly detect and initialize BiDi across browsers and vendors.
asyncinit(){if(!(awaitthis._driver.getCapabilities()).get('webSocketUrl')){throwError('WebDriver instance must support BiDi protocol')}this.bidi=awaitthis._driver.getBidi()}
Solution Walkthrough:
Before:
asyncinit(){constcapabilities=awaitthis._driver.getCapabilities();if(!capabilities.get('webSocketUrl')){throwError('WebDriver instance must support BiDi protocol');}this.bidi=awaitthis._driver.getBidi();}
After:
asyncinit(){try{this.bidi=awaitthis._driver.getBidi();}catch(e){// Potentially inspect 'e' to ensure it's the expected errorthrowError('WebDriver instance must support BiDi protocol');}}
Suggestion importance[1-10]: 7
__
Why: This is a strong design suggestion that correctly identifies a brittle check and proposes a more robust, future-proof alternative, improving the module's resilience to changes in driver implementations.
Medium
General
✅ Cache capabilities and standardize errorSuggestion Impact:The commit changed the error construction to use new Error(...), matching part of the suggestion. It did not cache getCapabilities(); that call remained inline.
code diff:
- async init() {- if (!(await this._driver.getCapabilities()).get('webSocketUrl')) {- throw Error('WebDriver instance must support BiDi protocol')- }-- this.bidi = await this._driver.getBidi()- }
Cache the capabilities to avoid two round-trips and ensure consistent checks. Also, use a consistent error construction style with new Error(...) for clarity.
async init() {
- if (!(await this._driver.getCapabilities()).get('webSocketUrl')) {- throw Error('WebDriver instance must support BiDi protocol')+ const caps = await this._driver.getCapabilities()+ if (!caps.get('webSocketUrl')) {+ throw new Error('WebDriver instance must support BiDi protocol')
}
-
this.bidi = await this._driver.getBidi()
}
[Suggestion processed]
Suggestion importance[1-10]: 3
__
Why: The suggestion improves code style by using new Error() and makes the code slightly more readable by caching getCapabilities(), but the performance claim of avoiding two round-trips is incorrect as it's only called once.
The uninstall path throws only when response.type === 'error', but BiDi client may throw on send() or return different shapes across browsers. Validate that error propagation and response parsing match the BiDi client used and both Firefox and Chrome behaviors.
The module exports a factory function returning an initialized instance. Ensure this aligns with existing BiDi module patterns and that tree-shaking/build configs include it. Consider also exporting the class for advanced use if consistent with codebase conventions.
/** * Helper to create and initialize an Extension instance. * * @param {import('selenium-webdriver').WebDriver} driver * A Selenium WebDriver instance. * @returns {Promise<WebExtension>} * An Extension instance. */asyncfunctiongetWebExtensionInstance(driver){letinstance=newWebExtension(driver)awaitinstance.init()returninstance}module.exports=getWebExtensionInstance
The internal field #path stores either a path or base64 value. Consider renaming to a neutral name (e.g., #value) to avoid confusion and future misuse; verify with serialization map.
Validate the returned payload defensively to avoid runtime errors if the BiDi response shape differs or on partial failures. Throw a clear error when result or extension is missing before accessing it.
async install(extensionData) {
if (!(extensionData instanceof ExtensionData)) {
throw new Error('install() requires an ExtensionData instance')
}
const command = {
method: 'webExtension.install',
params: {
extensionData: extensionData.asMap(),
},
}
- let response = await this.bidi.send(command)- return response.result.extension+ const response = await this.bidi.send(command)+ const extensionId = response && response.result && response.result.extension+ if (!extensionId) {+ throw new Error('Install failed: missing extension id in response')+ }+ return extensionId
}
Apply / Chat
Suggestion importance[1-10]: 7
__
Why: The suggestion correctly identifies a potential runtime error by adding defensive checks for the response payload, which improves the robustness of the install method.
Medium
Let transport surface errors
Avoid relying on a non-standard response.type contract and let this.bidi.send surface protocol errors via rejection. Removing the manual error check prevents masking of results and double-handling. If needed, add minimal validation of id input to catch obvious misuse early.
async uninstall(id) {
+ if (!id || typeof id !== 'string') {+ throw new Error('uninstall() requires a non-empty string id')+ }+
const command = {
method: 'webExtension.uninstall',
params: {
extension: id,
},
}
- const response = await this.bidi.send(command)-- if (response.type === 'error') {- throw new Error(`${response.error}: ${response.message}`)- }+ await this.bidi.send(command)
}
Apply / Chat
Suggestion importance[1-10]: 6
__
Why: The suggestion correctly proposes to rely on the bidi.send method to handle protocol errors via promise rejection, which simplifies the code and follows common async patterns.
Low
General
Validate base64 input early
Ensure non-empty Base64 data is provided to prevent sending invalid payloads to the BiDi endpoint. Add a basic type/emptiness check and surface a clear error early.
static setBase64Encoded(value) {
+ if (typeof value !== 'string' || value.length === 0) {+ throw new Error('setBase64Encoded() requires a non-empty base64 string')+ }
return new ExtensionData('base64', value)
}
Apply / Chat
Suggestion importance[1-10]: 5
__
Why: The suggestion adds useful input validation to prevent sending empty or invalid data to the BiDi endpoint, improving robustness with a fail-fast approach.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User description
🔗 Related Issues
Related to #15585
💥 What does this PR do?
Added Extension BiDi module to JS bindings
🔧 Implementation Notes
💡 Additional Considerations
🔄 Types of changes
PR Type
Enhancement
Description
Add WebExtension BiDi module for JavaScript bindings
Support installing extensions from path, archive, or base64
Implement uninstall functionality with error handling
Include comprehensive test coverage for all methods
Diagram Walkthrough
File Walkthrough
extensionData.js
Add ExtensionData class for extension configuration
javascript/selenium-webdriver/bidi/webExtension/extensionData.js
webExtension.js
Implement WebExtension BiDi module with install/uninstall methods
javascript/selenium-webdriver/bidi/webExtension/webExtension.js
extension_test.js
Add comprehensive test coverage for WebExtension module
javascript/selenium-webdriver/test/bidi/extension_test.js
extensions
BUILD.bazel
Update build configuration for WebExtension module
javascript/selenium-webdriver/BUILD.bazel