Skip to content

Conversation

navin772
Copy link
Member

@navin772 navin772 commented Sep 19, 2025

User description

🔗 Related Issues

💥 What does this PR do?

Adds getData, addDataCollector and removeDataCollector commands as in BiDi spec:

  1. w3c.github.io/webdriver-bidi#command-network-addDataCollector
  2. w3c.github.io/webdriver-bidi#command-network-getData
  3. w3c.github.io/webdriver-bidi#command-network-removeDataCollector

🔧 Implementation Notes

💡 Additional Considerations

🔄 Types of changes

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

PR Type

Enhancement


Description

  • Add BiDi network data collection commands per W3C spec

  • Implement addDataCollector, removeDataCollector, and getData methods

  • Create parameter classes for data collection configuration

  • Add comprehensive test coverage for all new functionality


Diagram Walkthrough

flowchart LR
  A["Network Module"] --> B["addDataCollector"]
  A --> C["removeDataCollector"]
  A --> D["getData"]
  B --> E["AddDataCollectorParameters"]
  D --> F["GetDataParameters"]
  D --> G["BytesValue"]
  E --> H["DataType enum"]
  F --> H
Loading

File Walkthrough

Relevant files
Enhancement
Network.java
Add network data collection methods                                           

java/src/org/openqa/selenium/bidi/module/Network.java

  • Add three new methods: addDataCollector, removeDataCollector, getData
  • Import new parameter classes and JSON handling utilities
  • Implement result mapping for getData command response
+44/-0   
AddDataCollectorParameters.java
Create AddDataCollectorParameters class                                   

java/src/org/openqa/selenium/bidi/network/AddDataCollectorParameters.java

  • New parameter class for addDataCollector command
  • Support for data types, max size, collector type, contexts
  • Builder pattern with fluent API and validation
+78/-0   
DataType.java
Add DataType enum                                                                               

java/src/org/openqa/selenium/bidi/network/DataType.java

  • New enum defining supported data types
  • Currently supports RESPONSE data type
+33/-0   
GetDataParameters.java
Create GetDataParameters class                                                     

java/src/org/openqa/selenium/bidi/network/GetDataParameters.java

  • New parameter class for getData command
  • Support for data type, request ID, collector, disown flag
  • Builder pattern with validation
+59/-0   
Tests
NetworkCommandsTest.java
Add data collection command tests                                               

java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java

  • Add comprehensive tests for all new data collection methods
  • Test various parameter combinations and edge cases
  • Verify error handling for invalid scenarios
+157/-0 

@selenium-ci selenium-ci added C-java Java Bindings B-devtools Includes everything BiDi or Chrome DevTools related labels Sep 19, 2025
Copy link
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis 🔶

5678 - Partially compliant

Compliant requirements:

Non-compliant requirements:

  • Investigate and resolve ChromeDriver "ConnectFailure" on repeated instantiation.
  • Reproduce and address environment-specific issue.
  • Provide fix or guidance for the error scenario.

Requires further human verification:

  • Validation on the specified OS/Chrome/ChromeDriver/Selenium versions in a real environment.
  • Confirmation that the error no longer appears across multiple driver instantiations.

1234 - Partially compliant

Compliant requirements:

Non-compliant requirements:

  • Ensure click() triggers href JavaScript in Firefox as in 2.47.1.

Requires further human verification:

  • Manual/browser testing across Firefox versions to confirm behavior.
⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Result Mapping

The getData result mapping uses a manual Map read and a second JsonInput to parse BytesValue. Verify schema stability and that "bytes" is always present; consider direct parsing or null-safety to avoid NPE if backend omits "bytes".

private final Function<JsonInput, BytesValue> getDataResultMapper =
    jsonInput -> {
      Map<String, Object> result = jsonInput.read(Map.class);
      @SuppressWarnings("unchecked")
      Map<String, Object> bytesMap = (Map<String, Object>) result.get("bytes");

      try (StringReader reader = new StringReader(JSON.toJson(bytesMap));
          JsonInput bytesInput = JSON.newInput(reader)) {
        return BytesValue.fromJson(bytesInput);
      }
    };
Validation

Only maxEncodedDataSize is validated; allow-empty checks for dataTypes and collectorType values are minimal. Consider enforcing non-empty dataTypes and validating collectorType against supported values to prevent server errors.

public AddDataCollectorParameters(List<DataType> dataTypes, long maxEncodedDataSize) {
  Require.nonNull("Data types", dataTypes);
  if (maxEncodedDataSize <= 0) {
    throw new IllegalArgumentException("Max encoded data size must be positive");
  }

  dataTypes.forEach(dataType -> this.dataTypes.add(dataType.toString()));
  this.maxEncodedDataSize = maxEncodedDataSize;
}

public AddDataCollectorParameters collectorType(String collectorType) {
  this.collectorType = Require.nonNull("Collector type", collectorType);
  return this;
}
Defaults/Flags

The "disown" flag is always included (defaults false). Confirm server tolerates explicit false; if optional, consider omitting when false. Also ensure request and collector IDs format are validated upstream.

public Map<String, Object> toMap() {
  Map<String, Object> map = new HashMap<>();
  map.put("dataType", dataType.toString());
  map.put("request", request);

  if (collector != null) {
    map.put("collector", collector);
  }

  map.put("disown", disown);

  return Map.copyOf(map);
}

Copy link
Contributor

qodo-merge-pro bot commented Sep 19, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Simplify the JSON parsing logic

The JSON parsing for the getData command in Network.java is inefficient due to a
redundant serialize-deserialize cycle. Refactor this to process the nested JSON
map directly.

Examples:

java/src/org/openqa/selenium/bidi/module/Network.java [72-82]
  private final Function<JsonInput, BytesValue> getDataResultMapper =
      jsonInput -> {
        Map<String, Object> result = jsonInput.read(Map.class);
        @SuppressWarnings("unchecked")
        Map<String, Object> bytesMap = (Map<String, Object>) result.get("bytes");

        try (StringReader reader = new StringReader(JSON.toJson(bytesMap));
            JsonInput bytesInput = JSON.newInput(reader)) {
          return BytesValue.fromJson(bytesInput);
        }

 ... (clipped 1 lines)

Solution Walkthrough:

Before:

private final Function<JsonInput, BytesValue> getDataResultMapper =
    jsonInput -> {
      Map<String, Object> result = jsonInput.read(Map.class);
      Map<String, Object> bytesMap = (Map<String, Object>) result.get("bytes");

      try (StringReader reader = new StringReader(JSON.toJson(bytesMap));
          JsonInput bytesInput = JSON.newInput(reader)) {
        return BytesValue.fromJson(bytesInput);
      }
    };

After:

private final Function<JsonInput, BytesValue> getDataResultMapper =
    jsonInput -> {
      jsonInput.beginObject();
      while (jsonInput.hasNext()) {
        if ("bytes".equals(jsonInput.nextName())) {
          return BytesValue.fromJson(jsonInput);
        } else {
          jsonInput.skipValue();
        }
      }
      jsonInput.endObject();
      // Or throw an exception if "bytes" is not found
      return null;
    };
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies an inefficient JSON processing pattern and proposes a valid simplification, which improves performance and code clarity.

Medium
Possible issue
Validate against an empty list

In the AddDataCollectorParameters constructor, add a validation check to ensure
the dataTypes list is not empty, as required by the BiDi specification.

java/src/org/openqa/selenium/bidi/network/AddDataCollectorParameters.java [34-42]

 public AddDataCollectorParameters(List<DataType> dataTypes, long maxEncodedDataSize) {
   Require.nonNull("Data types", dataTypes);
+  Require.nonNull("Max encoded data size", maxEncodedDataSize);
+  if (dataTypes.isEmpty()) {
+    throw new IllegalArgumentException("Data types list must not be empty");
+  }
   if (maxEncodedDataSize <= 0) {
     throw new IllegalArgumentException("Max encoded data size must be positive");
   }
 
   dataTypes.forEach(dataType -> this.dataTypes.add(dataType.toString()));
   this.maxEncodedDataSize = maxEncodedDataSize;
 }
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a missing validation for an empty dataTypes list, which improves API robustness by enforcing a contract from the BiDi specification.

Medium
General
Improve performance by avoiding re-serialization
Suggestion Impact:The commit replaced Map-based parsing and re-serialization with streaming parsing using JsonInput.beginObject/hasNext/nextName/skipValue and directly invoked BytesValue.fromJson, eliminating JSON re-serialization and removing Json/StringReader usage.

code diff:

@@ -71,14 +67,18 @@
 
   private final Function<JsonInput, BytesValue> getDataResultMapper =
       jsonInput -> {
-        Map<String, Object> result = jsonInput.read(Map.class);
-        @SuppressWarnings("unchecked")
-        Map<String, Object> bytesMap = (Map<String, Object>) result.get("bytes");
-
-        try (StringReader reader = new StringReader(JSON.toJson(bytesMap));
-            JsonInput bytesInput = JSON.newInput(reader)) {
-          return BytesValue.fromJson(bytesInput);
+        jsonInput.beginObject();
+        BytesValue bytes = null;
+        while (jsonInput.hasNext()) {
+          String name = jsonInput.nextName();
+          if ("bytes".equals(name)) {
+            bytes = BytesValue.fromJson(jsonInput);
+          } else {
+            jsonInput.skipValue();
+          }
         }
+        jsonInput.endObject();
+        return bytes;
       };

Refactor getDataResultMapper to use the JsonInput streaming API, avoiding
inefficient intermediate object creation and JSON re-serialization when parsing
the response.

java/src/org/openqa/selenium/bidi/module/Network.java [72-82]

 private final Function<JsonInput, BytesValue> getDataResultMapper =
     jsonInput -> {
-      Map<String, Object> result = jsonInput.read(Map.class);
-      @SuppressWarnings("unchecked")
-      Map<String, Object> bytesMap = (Map<String, Object>) result.get("bytes");
-
-      try (StringReader reader = new StringReader(JSON.toJson(bytesMap));
-          JsonInput bytesInput = JSON.newInput(reader)) {
-        return BytesValue.fromJson(bytesInput);
+      BytesValue bytesValue = null;
+      jsonInput.beginObject();
+      while (jsonInput.hasNext()) {
+        if ("bytes".equals(jsonInput.nextName())) {
+          bytesValue = BytesValue.fromJson(jsonInput);
+        } else {
+          jsonInput.skipValue();
+        }
       }
+      jsonInput.endObject();
+      return bytesValue;
     };

[Suggestion processed]

Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies an inefficient JSON parsing pattern and proposes a more performant, streaming-based approach which improves code quality and efficiency.

Low
  • Update

@navin772 navin772 requested a review from pujagani September 21, 2025 14:10
@navin772 navin772 requested a review from diemol September 24, 2025 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-devtools Includes everything BiDi or Chrome DevTools related C-java Java Bindings Review effort 2/5
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants