From 2f253be0005aa1cd6df171905f6c60fb92fa0e7e Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Fri, 3 Jul 2026 12:00:48 +0530 Subject: [PATCH] [java] Prevent accessing BiDi internals from driver --- java/src/org/openqa/selenium/bidi/BiDi.java | 11 +++++++++++ java/src/org/openqa/selenium/bidi/HasBiDi.java | 6 ++++++ java/src/org/openqa/selenium/remote/RemoteScript.java | 3 +-- .../openqa/selenium/bidi/BiDiSessionCleanUpTest.java | 4 ++-- .../org/openqa/selenium/bidi/BiDiSessionTest.java | 2 +- .../selenium/bidi/network/NetworkCommandsTest.java | 4 ++-- .../selenium/firefox/FirefoxDriverConcurrentTest.java | 4 ++-- .../selenium/grid/router/RemoteWebDriverBiDiTest.java | 10 ++++------ 8 files changed, 29 insertions(+), 15 deletions(-) diff --git a/java/src/org/openqa/selenium/bidi/BiDi.java b/java/src/org/openqa/selenium/bidi/BiDi.java index f159bf258cf73..8929b8532424f 100644 --- a/java/src/org/openqa/selenium/bidi/BiDi.java +++ b/java/src/org/openqa/selenium/bidi/BiDi.java @@ -29,6 +29,7 @@ import java.util.function.Consumer; import java.util.logging.Logger; import org.openqa.selenium.Beta; +import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.internal.Require; @@ -40,6 +41,16 @@ public class BiDi implements Closeable { private final Connection connection; private final Map, List> contextListenerIds = new ConcurrentHashMap<>(); + public static BiDi from(WebDriver driver) { + Require.nonNull("WebDriver", driver); + if (!(driver instanceof HasBiDi)) { + throw new BiDiException("WebDriver does not support BiDi protocol"); + } + return ((HasBiDi) driver) + .maybeGetBiDi() + .orElseThrow(() -> new BiDiException("Unable to create a BiDi connection")); + } + /** * @deprecated Use constructor with timeout parameter: {@link #BiDi(Connection, Duration)} */ diff --git a/java/src/org/openqa/selenium/bidi/HasBiDi.java b/java/src/org/openqa/selenium/bidi/HasBiDi.java index 25666301b52f5..78454d393694e 100644 --- a/java/src/org/openqa/selenium/bidi/HasBiDi.java +++ b/java/src/org/openqa/selenium/bidi/HasBiDi.java @@ -19,9 +19,15 @@ import java.util.Optional; import org.openqa.selenium.Beta; +import org.openqa.selenium.WebDriver; @Beta public interface HasBiDi { + + /** + * @deprecated Use {@link BiDi#from(WebDriver)} instead. + */ + @Deprecated(since = "4.24", forRemoval = true) default BiDi getBiDi() { return maybeGetBiDi() .orElseThrow(() -> new BiDiException("Unable to create a BiDi connection")); diff --git a/java/src/org/openqa/selenium/remote/RemoteScript.java b/java/src/org/openqa/selenium/remote/RemoteScript.java index 0a513147f5d8a..6bdf4c2c19509 100644 --- a/java/src/org/openqa/selenium/remote/RemoteScript.java +++ b/java/src/org/openqa/selenium/remote/RemoteScript.java @@ -31,7 +31,6 @@ import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import org.openqa.selenium.bidi.BiDi; -import org.openqa.selenium.bidi.HasBiDi; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.log.JavascriptLogEntry; import org.openqa.selenium.bidi.module.LogInspector; @@ -56,7 +55,7 @@ class RemoteScript implements Script { public RemoteScript(WebDriver driver) { this.driver = driver; - this.biDi = ((HasBiDi) driver).getBiDi(); + this.biDi = BiDi.from(driver); this.logInspector = new LogInspector(driver); this.script = new org.openqa.selenium.bidi.module.Script(driver); } diff --git a/java/test/org/openqa/selenium/bidi/BiDiSessionCleanUpTest.java b/java/test/org/openqa/selenium/bidi/BiDiSessionCleanUpTest.java index e1314ad5bf845..b7bd7c7847770 100644 --- a/java/test/org/openqa/selenium/bidi/BiDiSessionCleanUpTest.java +++ b/java/test/org/openqa/selenium/bidi/BiDiSessionCleanUpTest.java @@ -35,7 +35,7 @@ final class BiDiSessionCleanUpTest extends JupiterTestBase { void shouldNotCloseBiDiSessionIfOneWindowIsClosed() { localDriver = new WebDriverBuilder().get(); assumeThat(localDriver).isInstanceOf(HasBiDi.class); - BiDi biDi = ((HasBiDi) localDriver).getBiDi(); + BiDi biDi = BiDi.from(localDriver); BiDiSessionStatus status = biDi.getBidiSessionStatus(); assertThat(status).isNotNull(); @@ -59,7 +59,7 @@ void shouldNotCloseBiDiSessionIfOneWindowIsClosed() { void shouldCloseBiDiSessionIfLastWindowIsClosed() { localDriver = new WebDriverBuilder().get(); assumeThat(localDriver).isInstanceOf(HasBiDi.class); - BiDi biDi = ((HasBiDi) localDriver).getBiDi(); + BiDi biDi = BiDi.from(localDriver); BiDiSessionStatus status = biDi.getBidiSessionStatus(); assertThat(status).isNotNull(); diff --git a/java/test/org/openqa/selenium/bidi/BiDiSessionTest.java b/java/test/org/openqa/selenium/bidi/BiDiSessionTest.java index 31cb3e6ca9663..fb706e06907fc 100644 --- a/java/test/org/openqa/selenium/bidi/BiDiSessionTest.java +++ b/java/test/org/openqa/selenium/bidi/BiDiSessionTest.java @@ -26,7 +26,7 @@ class BiDiSessionTest extends JupiterTestBase { @Test void shouldBeAbleToCreateABiDiSession() { - BiDi biDi = ((HasBiDi) driver).getBiDi(); + BiDi biDi = BiDi.from(driver); BiDiSessionStatus status = biDi.getBidiSessionStatus(); assertThat(status).isNotNull(); diff --git a/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java b/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java index 88629e113b85b..00276da526cc6 100644 --- a/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java +++ b/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java @@ -38,8 +38,8 @@ import org.openqa.selenium.UsernameAndPassword; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; +import org.openqa.selenium.bidi.BiDi; import org.openqa.selenium.bidi.BiDiException; -import org.openqa.selenium.bidi.HasBiDi; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.module.Network; import org.openqa.selenium.testing.JupiterTestBase; @@ -222,7 +222,7 @@ void canContinueWithAuthCredentials() { assertThat(driver.findElement(By.tagName("h1")).getText()).isEqualTo("authorized"); - ((HasBiDi) driver).getBiDi().removeListener(callbackId); + BiDi.from(driver).removeListener(callbackId); } } diff --git a/java/test/org/openqa/selenium/firefox/FirefoxDriverConcurrentTest.java b/java/test/org/openqa/selenium/firefox/FirefoxDriverConcurrentTest.java index 9b78c1d985f6b..d243dce4ce5eb 100644 --- a/java/test/org/openqa/selenium/firefox/FirefoxDriverConcurrentTest.java +++ b/java/test/org/openqa/selenium/firefox/FirefoxDriverConcurrentTest.java @@ -177,7 +177,7 @@ void multipleFirefoxInstancesWithBiDiEnabledCanRunSimultaneously() { try { driver1 = new WebDriverBuilder().get(options1); - BiDi biDi1 = ((FirefoxDriver) driver1).getBiDi(); + BiDi biDi1 = BiDi.from(driver1); assertThat(biDi1).isNotNull(); // Extract the BiDi websocket URL and port for the first instance @@ -186,7 +186,7 @@ void multipleFirefoxInstancesWithBiDiEnabledCanRunSimultaneously() { String port1 = webSocketUrl1.replaceAll("^ws://[^:]+:(\\d+)/.*$", "$1"); driver2 = new WebDriverBuilder().get(options2); - BiDi biDi2 = ((FirefoxDriver) driver2).getBiDi(); + BiDi biDi2 = BiDi.from(driver2); assertThat(biDi2).isNotNull(); // Extract the BiDi websocket URL and port for the second instance diff --git a/java/test/org/openqa/selenium/grid/router/RemoteWebDriverBiDiTest.java b/java/test/org/openqa/selenium/grid/router/RemoteWebDriverBiDiTest.java index 8b19e34e3ce03..14bff1c36945e 100644 --- a/java/test/org/openqa/selenium/grid/router/RemoteWebDriverBiDiTest.java +++ b/java/test/org/openqa/selenium/grid/router/RemoteWebDriverBiDiTest.java @@ -36,7 +36,6 @@ import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.BiDi; import org.openqa.selenium.bidi.BiDiSessionStatus; -import org.openqa.selenium.bidi.HasBiDi; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.NavigationResult; import org.openqa.selenium.bidi.log.ConsoleLogEntry; @@ -96,11 +95,10 @@ void tearDownDeployment() { @Test @NoDriverBeforeTest void ensureBiDiSessionCreation() { - try (BiDi biDi = ((HasBiDi) localDriver).getBiDi()) { - BiDiSessionStatus status = biDi.getBidiSessionStatus(); - assertThat(status).isNotNull(); - assertThat(status.getMessage()).isNotEmpty(); - } + BiDi biDi = BiDi.from(localDriver); + BiDiSessionStatus status = biDi.getBidiSessionStatus(); + assertThat(status).isNotNull(); + assertThat(status.getMessage()).isNotEmpty(); } @Test