Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[js][bidi]: implement permissions module commands in JS #15304

Merged
merged 20 commits into from
Mar 20, 2025

Conversation

navin772
Copy link
Member

@navin772 navin772 commented Feb 19, 2025

User description

Thanks for contributing to Selenium!
A PR well described will help maintainers to quickly review and merge it

Before submitting your PR, please check our contributing guidelines.
Avoid large PRs, help reviewers by making them as simple and short as possible.

Motivation and Context

Implement commands from extension module permissions - https://www.w3.org/TR/permissions/#automation-webdriver-bidi

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • I have read the contributing document.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

PR Type

Enhancement, Tests


Description

  • Implemented BiDi permissions module for JavaScript.

  • Added support for setting permission states programmatically.

  • Developed comprehensive tests for permission module functionality.

  • Ensured compatibility with multiple browsers (Chrome, Firefox, Edge).


Changes walkthrough 📝

Relevant files
Enhancement
permissions.js
Implement BiDi permissions module functionality                   

javascript/node/selenium-webdriver/bidi/permissions.js

  • Added a Permission class to manage BiDi permissions.
  • Implemented setPermission method to set permission states.
  • Introduced PermissionState constants for state validation.
  • Exported getPermissionInstance for external usage.
  • +73/-0   
    Tests
    permissions_test.js
    Add tests for BiDi permissions module                                       

    javascript/node/selenium-webdriver/test/bidi/permissions_test.js

  • Added tests for setting permissions to granted, denied, and prompt.
  • Verified permission changes across different user contexts.
  • Ensured compatibility with browser-specific default states.
  • Utilized BiDi APIs for browser interaction and validation.
  • +169/-0 

    Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • @navin772
    Copy link
    Member Author

    navin772 commented Feb 19, 2025

    For Chrome, the permission module tests pass from Chrome 134 onwards, which is currently in Chrome Beta, hence the CI is currently failing.
    For Firefox, the tests pass in the stable version.

    @navin772 navin772 marked this pull request as ready for review March 13, 2025 19:44
    Copy link
    Contributor

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Error Handling

    The setPermission method validates permission states but doesn't validate the permissionDescriptor or origin parameters. Consider adding validation for these parameters to prevent potential runtime errors.

    async setPermission(permissionDescriptor, state, origin, userContext = null) {
      if (!Object.values(PermissionState).includes(state)) {
        throw new Error(`Invalid permission state. Must be one of: ${Object.values(PermissionState).join(', ')}`)
      }
    
      const command = {
        method: 'permissions.setPermission',
        params: {
          descriptor: permissionDescriptor,
          state: state,
          origin: origin,
        },
      }
    
      if (userContext) {
        command.params.userContext = userContext
      }
    
      await this.bidi.send(command)
    }
    Documentation

    The permissionDescriptor parameter lacks detailed documentation about its expected structure. Consider adding JSDoc that specifies the required format and possible values for this object.

    /**
     * Sets a permission state for a given permission descriptor.
     * @param {Object} permissionDescriptor The permission descriptor.
     * @param {string} state The permission state (granted, denied, prompt).
     * @param {string} origin The origin for which the permission is set.
     * @param {string} [userContext] The user context id (optional).
     * @returns {Promise<void>}
     */

    Copy link
    Contributor

    qodo-merge-pro bot commented Mar 13, 2025

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Validate required parameters

    The method doesn't validate that permissionDescriptor and origin are provided
    and valid. Missing validation could lead to confusing errors from the BiDi
    protocol. Add checks to ensure these required parameters are present and valid.

    javascript/node/selenium-webdriver/bidi/permissions.js [45-64]

     async setPermission(permissionDescriptor, state, origin, userContext = null) {
    +  if (!permissionDescriptor || typeof permissionDescriptor !== 'object') {
    +    throw new Error('Permission descriptor must be a non-null object')
    +  }
    +  
    +  if (!origin || typeof origin !== 'string') {
    +    throw new Error('Origin must be a non-empty string')
    +  }
    +
       if (!Object.values(PermissionState).includes(state)) {
         throw new Error(`Invalid permission state. Must be one of: ${Object.values(PermissionState).join(', ')}`)
       }
     
       const command = {
         method: 'permissions.setPermission',
         params: {
           descriptor: permissionDescriptor,
           state: state,
           origin: origin,
         },
       }
     
       if (userContext) {
         command.params.userContext = userContext
       }
     
       await this.bidi.send(command)
     }
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    __

    Why: The suggestion adds important input validation for permissionDescriptor and origin parameters, which prevents potential runtime errors and improves the robustness of the API. This is a significant improvement for error prevention.

    Medium
    General
    Add error handling

    The init() method is called but there's no error handling. If initialization
    fails (e.g., if the driver doesn't support BiDi), the error will propagate to
    the caller without context. Add try-catch to provide a more informative error
    message.

    javascript/node/selenium-webdriver/bidi/permissions.js [67-71]

     async function getPermissionInstance(driver) {
    -  let instance = new Permission(driver)
    -  await instance.init()
    -  return instance
    +  try {
    +    let instance = new Permission(driver)
    +    await instance.init()
    +    return instance
    +  } catch (error) {
    +    throw new Error(`Failed to initialize Permission instance: ${error.message}`)
    +  }
     }
    • Apply this suggestion
    Suggestion importance[1-10]: 5

    __

    Why: The suggestion adds helpful error handling to the getPermissionInstance function, which would make debugging easier by providing more context when initialization fails. This is a moderate improvement for code robustness.

    Low
    Use consistent property naming

    The init() method sets this.bidi as a public property but it should be private
    since it's an internal implementation detail. Use a private property naming
    convention (underscore prefix) for consistency with _driver.

    javascript/node/selenium-webdriver/bidi/permissions.js [24-35]

     class Permission {
       constructor(driver) {
         this._driver = driver
       }
     
       async init() {
         if (!(await this._driver.getCapabilities()).get('webSocketUrl')) {
           throw Error('WebDriver instance must support BiDi protocol')
         }
     
    -    this.bidi = await this._driver.getBidi()
    +    this._bidi = await this._driver.getBidi()
       }
    • Apply this suggestion
    Suggestion importance[1-10]: 4

    __

    Why: The suggestion improves code consistency by making the bidi property private with an underscore prefix, matching the _driver property style. This is a moderate improvement for code maintainability and encapsulation.

    Low
    • Update

    @navin772 navin772 requested a review from harsha509 March 14, 2025 12:23
    Copy link
    Member

    @harsha509 harsha509 left a comment

    Choose a reason for hiding this comment

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

    HI @navin772 ,
    Thank you for the PR.

    A couple of suggestions:

    1. Let's add browser compatibility info in the docs, something like:
      @requires Chrome 134+ or equivalent browser with BiDi permissions support

    2. Consider implementing permissions as a separate module since it deserves its own namespace (we could eventually support camera, microphone, geolocation, etc.)

    Thanks,
    Sri

    @navin772 navin772 requested a review from harsha509 March 17, 2025 14:23
    Copy link
    Member

    @harsha509 harsha509 left a comment

    Choose a reason for hiding this comment

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

    Thank you @navin772 !

    @harsha509 harsha509 merged commit 013ab47 into SeleniumHQ:trunk Mar 20, 2025
    11 checks passed
    @navin772 navin772 deleted the js-bidi-permissions-module branch March 20, 2025 04:46
    sandeepsuryaprasad pushed a commit to sandeepsuryaprasad/selenium that referenced this pull request Mar 23, 2025
    …5304)
    
    * implement BiDi permission module for JS
    
    * add tests for permission module
    
    * ignore chrome browser tests
    
    * modify test as per chrome default permissions
    
    * run `format.sh`
    
    * remove initial permission assertions as it is different for browsers/envvironments
    
    * move `permissions.js` to `external/` dir
    
    ---------
    
    Co-authored-by: Puja Jagani <puja.jagani93@gmail.com>
    Co-authored-by: Sri Harsha <12621691+harsha509@users.noreply.github.com>
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    3 participants