Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions java/spotbugs-excludes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@
<Bug pattern="NM_CLASS_NAMING_CONVENTION"/>
</Match>

<Match>
<Class name="~org.openqa.selenium.devtools.latest\.latest\w+" />
<Bug pattern="NM_CLASS_NAMING_CONVENTION"/>
</Match>

<Match>
<Class name="org.openqa.selenium.manager.SeleniumManager"/>
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE,IS2_INCONSISTENT_SYNC"/>
Expand Down
6 changes: 5 additions & 1 deletion java/src/org/openqa/selenium/devtools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ They are typically downloaded from the
[devtools source](https://github.com/ChromeDevTools/devtools-protocol/tree/master/json)

* Edit `//java/src/org/openqa/selenium/devtools:versions.bzl` to include the new version number (and
possibly delete the old one, we tend to support only the last 3 versions)
possibly delete the old one, we tend to support only the last 3 versions). The last entry of
`CDP_VERSIONS` is automatically picked up as `LATEST_CDP_VERSION` and republished under the
`org.openqa.selenium.devtools.latest` package by
`//java/src/org/openqa/selenium/devtools/latest`, so users get the new CDP version under the
stable `selenium-devtools-latest` Maven coordinate without any extra work.
* Copy the most recent `//java/src/org/openqa/selenium/devtools/vXX` to
`//java/src/org/openqa/selenium/devtools/vXX+1`.
* Do a search and replace in that directory, converting `XX` to `XX+1`
Expand Down
103 changes: 103 additions & 0 deletions java/src/org/openqa/selenium/devtools/latest/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
load("@rules_jvm_external//:defs.bzl", "artifact")
load("//common:defs.bzl", "copy_file")
load("//java:defs.bzl", "java_export", "java_library")
load("//java:version.bzl", "SE_VERSION")
load("//java/src/org/openqa/selenium/devtools:versions.bzl", "LATEST_CDP_VERSION")

# Publishes the most recent supported CDP version under the stable
# `org.openqa.selenium.devtools.latest` package, so downstream consumers can
# depend on a single coordinate that always tracks the newest CDP release
# instead of bumping their pom each time Chrome ships a new major version.
cdp_version = "latest"

java_export(
name = cdp_version,
srcs = [":create-shim-srcs"],
maven_coordinates = "org.seleniumhq.selenium:selenium-devtools-%s:%s" % (cdp_version, SE_VERSION),
opens_to = [
"org.seleniumhq.selenium.json",
],
pom_template = "//java/src/org/openqa/selenium:template-pom",
tags = [
"release-artifact",
],
visibility = [
"//visibility:public",
],
exports = [
":cdp",
],
deps = [
":cdp",
"//java:auto-service",
"//java/src/org/openqa/selenium:core",
"//java/src/org/openqa/selenium/json",
"//java/src/org/openqa/selenium/remote",
artifact("org.jspecify:jspecify"),
],
)

java_library(
name = "cdp",
srcs = [
":create-cdp-srcs",
],
tags = [
"no-lint",
],
deps = [
"//java/src/org/openqa/selenium:core",
"//java/src/org/openqa/selenium/json",
"//java/src/org/openqa/selenium/remote",
artifact("org.jspecify:jspecify"),
],
)

genrule(
name = "create-cdp-srcs",
srcs = [
":browser_protocol",
":js_protocol",
],
outs = ["cdp.srcjar"],
cmd = "$(location //java/src/org/openqa/selenium/devtools:cdp-client-generator) $(location :browser_protocol) $(location :js_protocol) %s $@" % cdp_version,
tools = [
"//java/src/org/openqa/selenium/devtools:cdp-client-generator",
],
)

copy_file(
name = "browser_protocol",
src = "//common/devtools/chromium/%s:browser_protocol" % LATEST_CDP_VERSION,
out = "browser_protocol.json",
)

copy_file(
name = "js_protocol",
src = "//common/devtools/chromium/%s:js_protocol" % LATEST_CDP_VERSION,
out = "js_protocol.json",
)

# Derives the hand-written shim classes for the "latest" alias by rewriting
# every occurrence of the latest CDP version slug (e.g. "v148") to "latest"
# in the corresponding files from that version's package. This keeps the
# alias in lockstep with the newest version without any source duplication.
genrule(
name = "create-shim-srcs",
srcs = ["//java/src/org/openqa/selenium/devtools/%s:shim-sources" % LATEST_CDP_VERSION],
outs = [
"latestCdpInfo.java",
"latestDomains.java",
"latestEvents.java",
"latestJavascript.java",
"latestLog.java",
"latestNetwork.java",
"latestTarget.java",
"package-info.java",
],
cmd = ("for src in $(SRCS); do " +
"base=$$(basename $$src); " +
"out=$$(echo $$base | sed -e 's/" + LATEST_CDP_VERSION + "/latest/g'); " +
"sed -e 's/" + LATEST_CDP_VERSION + "/latest/g' $$src > $(RULEDIR)/$$out; " +
"done"),
)
10 changes: 10 additions & 0 deletions java/src/org/openqa/selenium/devtools/v148/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ load("//java:version.bzl", "SE_VERSION")

cdp_version = "v148"

# Hand-written shim sources reused by //java/src/org/openqa/selenium/devtools/latest
# to produce a copy of this package under org.openqa.selenium.devtools.latest.
filegroup(
name = "shim-sources",
srcs = glob(["*.java"]),
visibility = [
"//java/src/org/openqa/selenium/devtools/latest:__pkg__",
],
)

java_export(
name = cdp_version,
srcs = glob(["*.java"]),
Expand Down
13 changes: 12 additions & 1 deletion java/src/org/openqa/selenium/devtools/versions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,15 @@ CDP_VERSIONS = [
"v148",
]

CDP_DEPS = ["//java/src/org/openqa/selenium/devtools/%s" % v for v in CDP_VERSIONS]
# Highest-numbered entry of CDP_VERSIONS. The "latest" alias artifact
# (//java/src/org/openqa/selenium/devtools/latest) republishes its classes under
# the org.openqa.selenium.devtools.latest package so downstream users can depend
# on a stable coordinate that always follows the newest supported CDP version.
# We compute the max numerically (rather than CDP_VERSIONS[-1]) because the
# scripts/update_cdp.py rewriter does an in-place substring replacement that
# does not preserve list ordering.
LATEST_CDP_VERSION = max(CDP_VERSIONS, key = lambda v: int(v[1:]))

CDP_DEPS = ["//java/src/org/openqa/selenium/devtools/%s" % v for v in CDP_VERSIONS] + [
"//java/src/org/openqa/selenium/devtools/latest",
]
Comment on lines +16 to +18

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Action required

1. Nondeterministic cdp provider 🐞 Bug ☼ Reliability

Adding //.../devtools/latest to CDP_DEPS puts both v148CdpInfo and the generated
latestCdpInfo (same major version) on the classpath, so CdpVersionFinder may return either one
for an exact match depending on Set iteration order. This can cause flaky behavior and makes
debugging provider selection harder because the exact CDP implementation chosen is no longer
deterministic.
Agent Prompt
## Issue description
`CDP_DEPS` now includes `//java/src/org/openqa/selenium/devtools/latest`, which introduces a second `CdpInfo` provider for the same major version as the newest `vNNN` package. `CdpVersionFinder` loads all providers into a `Set` and returns the first exact match it iterates over, so the chosen provider becomes non-deterministic.

## Issue Context
- `latestCdpInfo` is generated by string-rewriting the newest `vNNN` shims, so it keeps the same `super(<major>, ...)` major version (e.g. 148).
- `CdpInfo` does not override `equals/hashCode`, so both providers coexist in the `Set`.

## Fix Focus Areas
- java/src/org/openqa/selenium/devtools/versions.bzl[16-18]

### Suggested fix
Remove `//java/src/org/openqa/selenium/devtools/latest` from `CDP_DEPS` so the default Selenium artifacts don’t pull in both providers. Keep publishing `selenium-devtools-latest` via its own release target so downstream users can opt in explicitly.

(Alternative, if you *must* keep it in `CDP_DEPS`: make `CdpVersionFinder` deterministically resolve ties when multiple `CdpInfo` instances report the same `majorVersion`.)

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

1 change: 1 addition & 0 deletions rake_tasks/java.rake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ JAVA_RELEASE_TARGETS = %w[
//java/src/org/openqa/selenium/devtools/v146:v146.publish
//java/src/org/openqa/selenium/devtools/v147:v147.publish
//java/src/org/openqa/selenium/devtools/v148:v148.publish
//java/src/org/openqa/selenium/devtools/latest:latest.publish
//java/src/org/openqa/selenium/edge:edge.publish
//java/src/org/openqa/selenium/firefox:firefox.publish
//java/src/org/openqa/selenium/grid/node/kubernetes:kubernetes.publish
Expand Down
Loading