diff --git a/.bazelrc b/.bazelrc index ea23ac61e3548..7e3cbf4e89025 100644 --- a/.bazelrc +++ b/.bazelrc @@ -16,9 +16,9 @@ build --java_runtime_version=remotejdk_17 build --tool_java_language_version=17 build --tool_java_runtime_version=remotejdk_17 -# We target java 8 by default +# We target java 11 by default -build --javacopt="--release 8" +build --javacopt="--release 11" # Require java dependencies to be used and first-order diff --git a/.github/workflows/ci-ruby.yml b/.github/workflows/ci-ruby.yml index 80ced414f5fef..2eaf0b03da68e 100644 --- a/.github/workflows/ci-ruby.yml +++ b/.github/workflows/ci-ruby.yml @@ -125,6 +125,7 @@ jobs: browser: ${{ matrix.browser }} cache-key: rb-remote-${{ matrix.browser }}-test os: ${{ matrix.os }} + java-version: 11 run: > bazel test --define browser=${{ matrix.browser }} diff --git a/java/maven_deps.bzl b/java/maven_deps.bzl index b087e59e98841..447a4b47c744d 100644 --- a/java/maven_deps.bzl +++ b/java/maven_deps.bzl @@ -75,15 +75,6 @@ def selenium_java_deps(): "org.apache.commons:commons-exec:1.3", "org.apache.logging.log4j:log4j-core:2.20.0", "org.assertj:assertj-core:3.24.2", - maven.artifact( - group = "org.asynchttpclient", - artifact = "async-http-client", - version = "2.12.3", - exclusions = [ - "io.netty:netty-transport-native-epoll", - "io.netty:netty-transport-native-kqueue", - ], - ), "org.bouncycastle:bcpkix-jdk15on:1.70", "org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5", "org.hamcrest:hamcrest:2.2", diff --git a/java/maven_install.json b/java/maven_install.json index f64de36870318..8ba656db743fb 100644 --- a/java/maven_install.json +++ b/java/maven_install.json @@ -1,7 +1,7 @@ { "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", - "__INPUT_ARTIFACTS_HASH": 1617623649, - "__RESOLVED_ARTIFACTS_HASH": 2144519154, + "__INPUT_ARTIFACTS_HASH": -486878249, + "__RESOLVED_ARTIFACTS_HASH": 1235473565, "artifacts": { "com.beust:jcommander": { "shasums": { @@ -178,20 +178,6 @@ }, "version": "3.2.0" }, - "com.sun.activation:jakarta.activation": { - "shasums": { - "jar": "02156773e4ae9d048d14a56ad35d644bee9f1052a791d072df3ded3c656e6e1a", - "sources": "f8f52ce9df5d5d29c1778183d48214624caa36be202a7eff2cef5a0519f2aa53" - }, - "version": "1.2.2" - }, - "com.typesafe.netty:netty-reactive-streams": { - "shasums": { - "jar": "eafc52d500b49e891db095ee7baac0420aea8a97015ab7671ba1f1ccabf799d2", - "sources": "76df17cc7c4fac9c470e557b5cca224df51ba878ec9fd3fd8f0f89878cbf98ab" - }, - "version": "2.0.4" - }, "commons-codec:commons-codec": { "shasums": { "jar": "b3e9f6d63a790109bf0d056611fbed1cf69055826defeb9894a71369d246ed63", @@ -629,20 +615,6 @@ }, "version": "3.24.2" }, - "org.asynchttpclient:async-http-client": { - "shasums": { - "jar": "107a4ace7a3586f8e8a027c6d7e9933c9ae56eeb1a6df347eed2e7b552e4e5ed", - "sources": "fd7d5e61cb6e5adbb06c14b72c10c88e18ebfaf22d401a521eae14123b537900" - }, - "version": "2.12.3" - }, - "org.asynchttpclient:async-http-client-netty-utils": { - "shasums": { - "jar": "e0bb76bbca0c85c68cab25dbed7989b00db5da8627cf69258f398d7d89bc9067", - "sources": "0b66a2867a3e4ea1e101e64d961d677bc6fbbbefa462b8fac461ef9101bec435" - }, - "version": "2.12.3" - }, "org.bouncycastle:bcpkix-jdk15on": { "shasums": { "jar": "e5b9cb821df57f70b0593358e89c0e8d7266515da9d088af6c646f63d433c07c", @@ -966,10 +938,6 @@ "com.graphql-java:java-dataloader": [ "org.slf4j:slf4j-api" ], - "com.typesafe.netty:netty-reactive-streams": [ - "io.netty:netty-handler", - "org.reactivestreams:reactive-streams" - ], "io.grpc:grpc-context": [ "io.grpc:grpc-api" ], @@ -1190,22 +1158,6 @@ "org.assertj:assertj-core": [ "net.bytebuddy:byte-buddy" ], - "org.asynchttpclient:async-http-client": [ - "com.sun.activation:jakarta.activation", - "com.typesafe.netty:netty-reactive-streams", - "io.netty:netty-codec-http", - "io.netty:netty-codec-socks", - "io.netty:netty-handler", - "io.netty:netty-handler-proxy", - "org.asynchttpclient:async-http-client-netty-utils", - "org.reactivestreams:reactive-streams", - "org.slf4j:slf4j-api" - ], - "org.asynchttpclient:async-http-client-netty-utils": [ - "com.sun.activation:jakarta.activation", - "io.netty:netty-buffer", - "org.slf4j:slf4j-api" - ], "org.bouncycastle:bcpkix-jdk15on": [ "org.bouncycastle:bcprov-jdk15on", "org.bouncycastle:bcutil-jdk15on" @@ -1613,14 +1565,6 @@ "org.dataloader.stats", "org.dataloader.stats.context" ], - "com.sun.activation:jakarta.activation": [ - "com.sun.activation.registries", - "com.sun.activation.viewers", - "javax.activation" - ], - "com.typesafe.netty:netty-reactive-streams": [ - "com.typesafe.netty" - ], "commons-codec:commons-codec": [ "org.apache.commons.codec", "org.apache.commons.codec.binary", @@ -2384,42 +2328,6 @@ "org.assertj.core.util.introspection", "org.assertj.core.util.xml" ], - "org.asynchttpclient:async-http-client": [ - "org.asynchttpclient", - "org.asynchttpclient.channel", - "org.asynchttpclient.config", - "org.asynchttpclient.cookie", - "org.asynchttpclient.exception", - "org.asynchttpclient.filter", - "org.asynchttpclient.handler", - "org.asynchttpclient.handler.resumable", - "org.asynchttpclient.netty", - "org.asynchttpclient.netty.channel", - "org.asynchttpclient.netty.future", - "org.asynchttpclient.netty.handler", - "org.asynchttpclient.netty.handler.intercept", - "org.asynchttpclient.netty.request", - "org.asynchttpclient.netty.request.body", - "org.asynchttpclient.netty.ssl", - "org.asynchttpclient.netty.timeout", - "org.asynchttpclient.netty.ws", - "org.asynchttpclient.ntlm", - "org.asynchttpclient.oauth", - "org.asynchttpclient.proxy", - "org.asynchttpclient.request.body", - "org.asynchttpclient.request.body.generator", - "org.asynchttpclient.request.body.multipart", - "org.asynchttpclient.request.body.multipart.part", - "org.asynchttpclient.resolver", - "org.asynchttpclient.spnego", - "org.asynchttpclient.uri", - "org.asynchttpclient.util", - "org.asynchttpclient.webdav", - "org.asynchttpclient.ws" - ], - "org.asynchttpclient:async-http-client-netty-utils": [ - "org.asynchttpclient.netty.util" - ], "org.bouncycastle:bcpkix-jdk15on": [ "org.bouncycastle.cert", "org.bouncycastle.cert.bc", @@ -3187,10 +3095,6 @@ "com.graphql-java:graphql-java:jar:sources", "com.graphql-java:java-dataloader", "com.graphql-java:java-dataloader:jar:sources", - "com.sun.activation:jakarta.activation", - "com.sun.activation:jakarta.activation:jar:sources", - "com.typesafe.netty:netty-reactive-streams", - "com.typesafe.netty:netty-reactive-streams:jar:sources", "commons-codec:commons-codec", "commons-codec:commons-codec:jar:sources", "commons-io:commons-io", @@ -3318,10 +3222,6 @@ "org.apiguardian:apiguardian-api:jar:sources", "org.assertj:assertj-core", "org.assertj:assertj-core:jar:sources", - "org.asynchttpclient:async-http-client", - "org.asynchttpclient:async-http-client-netty-utils", - "org.asynchttpclient:async-http-client-netty-utils:jar:sources", - "org.asynchttpclient:async-http-client:jar:sources", "org.bouncycastle:bcpkix-jdk15on", "org.bouncycastle:bcpkix-jdk15on:jar:sources", "org.bouncycastle:bcprov-jdk15on", @@ -3448,10 +3348,6 @@ "com.graphql-java:graphql-java:jar:sources", "com.graphql-java:java-dataloader", "com.graphql-java:java-dataloader:jar:sources", - "com.sun.activation:jakarta.activation", - "com.sun.activation:jakarta.activation:jar:sources", - "com.typesafe.netty:netty-reactive-streams", - "com.typesafe.netty:netty-reactive-streams:jar:sources", "commons-codec:commons-codec", "commons-codec:commons-codec:jar:sources", "commons-io:commons-io", @@ -3579,10 +3475,6 @@ "org.apiguardian:apiguardian-api:jar:sources", "org.assertj:assertj-core", "org.assertj:assertj-core:jar:sources", - "org.asynchttpclient:async-http-client", - "org.asynchttpclient:async-http-client-netty-utils", - "org.asynchttpclient:async-http-client-netty-utils:jar:sources", - "org.asynchttpclient:async-http-client:jar:sources", "org.bouncycastle:bcpkix-jdk15on", "org.bouncycastle:bcpkix-jdk15on:jar:sources", "org.bouncycastle:bcprov-jdk15on", diff --git a/java/spotbugs-excludes.xml b/java/spotbugs-excludes.xml index 26c908dffa18e..979a69248dad9 100644 --- a/java/spotbugs-excludes.xml +++ b/java/spotbugs-excludes.xml @@ -145,11 +145,26 @@ + + + + + + + + + + + + + + + @@ -165,6 +180,11 @@ + + + + + diff --git a/java/src/org/openqa/selenium/chrome/ChromeDriverInfo.java b/java/src/org/openqa/selenium/chrome/ChromeDriverInfo.java index d1e8ed0ba2026..2378ccee1b4ad 100644 --- a/java/src/org/openqa/selenium/chrome/ChromeDriverInfo.java +++ b/java/src/org/openqa/selenium/chrome/ChromeDriverInfo.java @@ -20,8 +20,6 @@ import static org.openqa.selenium.remote.Browser.CHROME; import com.google.auto.service.AutoService; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import java.util.Optional; import org.openqa.selenium.Capabilities; import org.openqa.selenium.ImmutableCapabilities; @@ -43,17 +41,6 @@ public String getDisplayName() { @Override public Capabilities getCanonicalCapabilities() { - if (!"jdk-http-client".equalsIgnoreCase(System.getProperty("webdriver.http.factory", ""))) { - // Allowing any origin "*" through remote-allow-origins might sound risky but an attacker - // would need to know the port used to start DevTools to establish a connection. Given - // these sessions are relatively short-lived, the risk is reduced. Only set when the Java - // 11 client is not used. - return new ImmutableCapabilities( - CapabilityType.BROWSER_NAME, - CHROME.browserName(), - ChromeOptions.CAPABILITY, - ImmutableMap.of("args", ImmutableList.of("--remote-allow-origins=*"))); - } return new ImmutableCapabilities(CapabilityType.BROWSER_NAME, CHROME.browserName()); } diff --git a/java/src/org/openqa/selenium/chromium/ChromiumOptions.java b/java/src/org/openqa/selenium/chromium/ChromiumOptions.java index 14e1464d92d93..6846aedfc618c 100644 --- a/java/src/org/openqa/selenium/chromium/ChromiumOptions.java +++ b/java/src/org/openqa/selenium/chromium/ChromiumOptions.java @@ -76,13 +76,6 @@ public class ChromiumOptions> public ChromiumOptions(String capabilityType, String browserType, String capability) { this.capabilityName = capability; setCapability(capabilityType, browserType); - if (!"jdk-http-client".equalsIgnoreCase(System.getProperty("webdriver.http.factory", ""))) { - // Allowing any origin "*" might sound risky but an attacker would need to know - // the port used to start DevTools to establish a connection. Given these sessions - // are relatively short-lived, the risk is reduced. Only set when the Java 11 client - // is not used. - addArguments("--remote-allow-origins=*"); - } } /** diff --git a/java/src/org/openqa/selenium/edge/EdgeDriverInfo.java b/java/src/org/openqa/selenium/edge/EdgeDriverInfo.java index 2d3f74af50126..da23e005cf6b4 100644 --- a/java/src/org/openqa/selenium/edge/EdgeDriverInfo.java +++ b/java/src/org/openqa/selenium/edge/EdgeDriverInfo.java @@ -20,8 +20,6 @@ import static org.openqa.selenium.remote.Browser.EDGE; import com.google.auto.service.AutoService; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import java.util.Optional; import org.openqa.selenium.Capabilities; import org.openqa.selenium.ImmutableCapabilities; @@ -43,17 +41,6 @@ public String getDisplayName() { @Override public Capabilities getCanonicalCapabilities() { - if (!"jdk-http-client".equalsIgnoreCase(System.getProperty("webdriver.http.factory", ""))) { - // Allowing any origin "*" through remote-allow-origins might sound risky but an attacker - // would need to know the port used to start DevTools to establish a connection. Given - // these sessions are relatively short-lived, the risk is reduced. Only set when the Java - // 11 client is not used. - return new ImmutableCapabilities( - CapabilityType.BROWSER_NAME, - EDGE.browserName(), - EdgeOptions.CAPABILITY, - ImmutableMap.of("args", ImmutableList.of("--remote-allow-origins=*"))); - } return new ImmutableCapabilities(CapabilityType.BROWSER_NAME, EDGE.browserName()); } diff --git a/java/src/org/openqa/selenium/grid/BUILD.bazel b/java/src/org/openqa/selenium/grid/BUILD.bazel index 4c30d21144552..e61f15f4f3399 100644 --- a/java/src/org/openqa/selenium/grid/BUILD.bazel +++ b/java/src/org/openqa/selenium/grid/BUILD.bazel @@ -110,7 +110,6 @@ maven_bom( "//java/src/org/openqa/selenium/json:json", "//java/src/org/openqa/selenium/lift:lift", "//java/src/org/openqa/selenium/manager:manager", - "//java/src/org/openqa/selenium/remote/http/jdk:jdk", "//java/src/org/openqa/selenium/remote/http:http", "//java/src/org/openqa/selenium/remote:remote", "//java/src/org/openqa/selenium/safari:safari", diff --git a/java/src/org/openqa/selenium/remote/BUILD.bazel b/java/src/org/openqa/selenium/remote/BUILD.bazel index b4e98e1f9561a..4556e6c86192e 100644 --- a/java/src/org/openqa/selenium/remote/BUILD.bazel +++ b/java/src/org/openqa/selenium/remote/BUILD.bazel @@ -55,7 +55,7 @@ java_library( "//java/src/org/openqa/selenium/json", "//java/src/org/openqa/selenium/manager", "//java/src/org/openqa/selenium/os", - "//java/src/org/openqa/selenium/remote/http/netty", + "//java/src/org/openqa/selenium/remote/http/jdk", "//java/src/org/openqa/selenium/remote/tracing", "//java/src/org/openqa/selenium/remote/tracing/opentelemetry", "//java/src/org/openqa/selenium/support/decorators", diff --git a/java/src/org/openqa/selenium/remote/http/HttpClient.java b/java/src/org/openqa/selenium/remote/http/HttpClient.java index 926051306c07b..ee7f8613a64ea 100644 --- a/java/src/org/openqa/selenium/remote/http/HttpClient.java +++ b/java/src/org/openqa/selenium/remote/http/HttpClient.java @@ -71,7 +71,7 @@ static Factory create(String name) { *

{@see create} */ static Factory createDefault() { - return create(System.getProperty("webdriver.http.factory", "netty")); + return create(System.getProperty("webdriver.http.factory", "jdk-http-client")); } /** diff --git a/java/src/org/openqa/selenium/remote/http/jdk/BUILD.bazel b/java/src/org/openqa/selenium/remote/http/jdk/BUILD.bazel index 4679882dcdbc7..7253c0af9094f 100644 --- a/java/src/org/openqa/selenium/remote/http/jdk/BUILD.bazel +++ b/java/src/org/openqa/selenium/remote/http/jdk/BUILD.bazel @@ -1,17 +1,11 @@ -load("//java:defs.bzl", "java_export") -load("//java:version.bzl", "SE_VERSION") +load("//java:defs.bzl", "java_library") -java_export( +java_library( name = "jdk", srcs = glob(["*.java"]), - javacopts = [ - "--release", - "11", # Deliberately targeting Java 11 for widest possible support - ], - maven_coordinates = "org.seleniumhq.selenium:selenium-http-jdk-client:%s" % SE_VERSION, - pom_template = "//java/src/org/openqa/selenium:template-pom", visibility = [ - "//visibility:public", + "//java/src/org/openqa/selenium/remote:__pkg__", + "//java/test/org/openqa/selenium/remote/http:__subpackages__", ], deps = [ "//java:auto-service", diff --git a/java/src/org/openqa/selenium/remote/http/netty/BUILD.bazel b/java/src/org/openqa/selenium/remote/http/netty/BUILD.bazel index 21fbc3f7518cf..0336674853d5f 100644 --- a/java/src/org/openqa/selenium/remote/http/netty/BUILD.bazel +++ b/java/src/org/openqa/selenium/remote/http/netty/BUILD.bazel @@ -14,7 +14,6 @@ java_library( "//java/src/org/openqa/selenium/remote/http", artifact("com.google.guava:guava"), # artifact("com.typesafe.netty:netty-reactive-streams"), - artifact("org.asynchttpclient:async-http-client"), artifact("io.netty:netty-buffer"), artifact("io.netty:netty-codec-http"), artifact("io.netty:netty-transport"), diff --git a/java/src/org/openqa/selenium/remote/http/netty/NettyClient.java b/java/src/org/openqa/selenium/remote/http/netty/NettyClient.java deleted file mode 100644 index 363690847da5b..0000000000000 --- a/java/src/org/openqa/selenium/remote/http/netty/NettyClient.java +++ /dev/null @@ -1,127 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.openqa.selenium.remote.http.netty; - -import com.google.auto.service.AutoService; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import io.netty.util.concurrent.DefaultThreadFactory; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.function.BiFunction; -import org.asynchttpclient.AsyncHttpClient; -import org.asynchttpclient.DefaultAsyncHttpClientConfig; -import org.asynchttpclient.Dsl; -import org.asynchttpclient.config.AsyncHttpClientConfigDefaults; -import org.openqa.selenium.internal.Require; -import org.openqa.selenium.remote.http.ClientConfig; -import org.openqa.selenium.remote.http.HttpClient; -import org.openqa.selenium.remote.http.HttpClientName; -import org.openqa.selenium.remote.http.HttpHandler; -import org.openqa.selenium.remote.http.HttpRequest; -import org.openqa.selenium.remote.http.HttpResponse; -import org.openqa.selenium.remote.http.WebSocket; - -public class NettyClient implements HttpClient { - - private static final Timer TIMER; - private static final AsyncHttpClient client = createHttpClient(ClientConfig.defaultConfig()); - - static { - ThreadFactory threadFactory = new DefaultThreadFactory("netty-client-timer", true); - TIMER = - new HashedWheelTimer( - threadFactory, - AsyncHttpClientConfigDefaults.defaultHashedWheelTimerTickDuration(), - TimeUnit.MILLISECONDS, - AsyncHttpClientConfigDefaults.defaultHashedWheelTimerSize()); - } - - private final ClientConfig config; - private final HttpHandler handler; - private final BiFunction toWebSocket; - - private NettyClient(ClientConfig config) { - this.config = Require.nonNull("HTTP client config", config); - this.handler = new NettyHttpHandler(config, client); - this.toWebSocket = NettyWebSocket.create(config, client); - } - - /** - * Converts a long to an int, clamping the maximum and minimum values to fit in an integer without - * overflowing. - */ - static int toClampedInt(long value) { - return (int) Math.max(Integer.MIN_VALUE, Math.min(Integer.MAX_VALUE, value)); - } - - private static AsyncHttpClient createHttpClient(ClientConfig config) { - DefaultAsyncHttpClientConfig.Builder builder = - new DefaultAsyncHttpClientConfig.Builder() - .setThreadFactory(new DefaultThreadFactory("AsyncHttpClient", true)) - .setUseInsecureTrustManager(true) - .setAggregateWebSocketFrameFragments(true) - .setWebSocketMaxBufferSize(Integer.MAX_VALUE) - .setWebSocketMaxFrameSize(Integer.MAX_VALUE) - .setNettyTimer(TIMER) - .setRequestTimeout(toClampedInt(config.readTimeout().toMillis())) - .setConnectTimeout(toClampedInt(config.connectionTimeout().toMillis())) - .setReadTimeout(toClampedInt(config.readTimeout().toMillis())) - .setFollowRedirect(true) - .setMaxRedirects(100) - .setUseProxyProperties(true) - .setUseProxySelector(true) - .setMaxRequestRetry(0); - - return Dsl.asyncHttpClient(builder); - } - - @Override - public HttpResponse execute(HttpRequest request) { - return handler.execute(request); - } - - @Override - public WebSocket openSocket(HttpRequest request, WebSocket.Listener listener) { - Require.nonNull("Request to send", request); - Require.nonNull("WebSocket listener", listener); - - return toWebSocket.apply(request, listener); - } - - @Override - public void close() { - // no-op -- closing the client when the JVM shuts down - } - - @AutoService(HttpClient.Factory.class) - @HttpClientName("netty") - public static class Factory implements HttpClient.Factory { - - @Override - public HttpClient createClient(ClientConfig config) { - Require.nonNull("Client config", config); - - if (config.baseUri() != null && "unix".equals(config.baseUri().getScheme())) { - return new NettyDomainSocketClient(config); - } - - return new NettyClient(config); - } - } -} diff --git a/java/src/org/openqa/selenium/remote/http/netty/NettyHttpHandler.java b/java/src/org/openqa/selenium/remote/http/netty/NettyHttpHandler.java deleted file mode 100644 index b5fd588eeb22f..0000000000000 --- a/java/src/org/openqa/selenium/remote/http/netty/NettyHttpHandler.java +++ /dev/null @@ -1,79 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.openqa.selenium.remote.http.netty; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import org.asynchttpclient.AsyncHttpClient; -import org.asynchttpclient.Response; -import org.openqa.selenium.internal.Require; -import org.openqa.selenium.remote.http.ClientConfig; -import org.openqa.selenium.remote.http.HttpHandler; -import org.openqa.selenium.remote.http.HttpRequest; -import org.openqa.selenium.remote.http.HttpResponse; -import org.openqa.selenium.remote.http.RemoteCall; - -public class NettyHttpHandler extends RemoteCall { - - private final HttpHandler handler; - private final AsyncHttpClient client; - - public NettyHttpHandler(ClientConfig config, AsyncHttpClient client) { - super(config); - this.client = client; - this.handler = config.filter().andFinally(this::makeCall); - } - - @Override - public HttpResponse execute(HttpRequest request) { - return handler.execute(request); - } - - private HttpResponse makeCall(HttpRequest request) { - Require.nonNull("Request", request); - - Future whenResponse = - client.executeRequest(NettyMessages.toNettyRequest(getConfig(), request)); - - try { - Response response = - whenResponse.get(getConfig().readTimeout().toMillis(), TimeUnit.MILLISECONDS); - return NettyMessages.toSeleniumResponse(response); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("NettyHttpHandler request interrupted", e); - } catch (TimeoutException e) { - throw new org.openqa.selenium.TimeoutException(e); - } catch (ExecutionException e) { - Throwable cause = e.getCause(); - if (cause instanceof UncheckedIOException) { - throw (UncheckedIOException) cause; - } - - if (cause instanceof IOException) { - throw new UncheckedIOException((IOException) cause); - } - - throw new RuntimeException("NettyHttpHandler request execution error", e); - } - } -} diff --git a/java/src/org/openqa/selenium/remote/http/netty/NettyMessages.java b/java/src/org/openqa/selenium/remote/http/netty/NettyMessages.java deleted file mode 100644 index 14af46f076171..0000000000000 --- a/java/src/org/openqa/selenium/remote/http/netty/NettyMessages.java +++ /dev/null @@ -1,146 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.openqa.selenium.remote.http.netty; - -import static org.asynchttpclient.Dsl.request; -import static org.openqa.selenium.remote.http.Contents.empty; -import static org.openqa.selenium.remote.http.Contents.memoize; -import static org.openqa.selenium.remote.http.netty.NettyClient.toClampedInt; - -import com.google.common.base.Strings; -import java.net.InetSocketAddress; -import java.net.URI; -import org.asynchttpclient.Dsl; -import org.asynchttpclient.Realm; -import org.asynchttpclient.Request; -import org.asynchttpclient.RequestBuilder; -import org.asynchttpclient.Response; -import org.asynchttpclient.proxy.ProxyServer; -import org.openqa.selenium.Credentials; -import org.openqa.selenium.UsernameAndPassword; -import org.openqa.selenium.remote.http.AddSeleniumUserAgent; -import org.openqa.selenium.remote.http.ClientConfig; -import org.openqa.selenium.remote.http.HttpMethod; -import org.openqa.selenium.remote.http.HttpRequest; -import org.openqa.selenium.remote.http.HttpResponse; - -class NettyMessages { - - private NettyMessages() { - // Utility classes. - } - - protected static Request toNettyRequest(ClientConfig config, HttpRequest request) { - - URI baseUrl = config.baseUri(); - int timeout = toClampedInt(config.readTimeout().toMillis()); - Credentials credentials = config.credentials(); - - String rawUrl = getRawUrl(baseUrl, request.getUri()); - - RequestBuilder builder = - request(request.getMethod().toString(), rawUrl) - .setReadTimeout(timeout) - .setRequestTimeout(timeout); - - for (String name : request.getQueryParameterNames()) { - for (String value : request.getQueryParameters(name)) { - builder.addQueryParam(name, value); - } - } - - // Netty tends to timeout when a GET request has a 'Content-Length' header - if (request.getMethod().equals(HttpMethod.GET) && request.getHeader("Content-Length") != null) { - request.removeHeader("Content-Length"); - } - - request.forEachHeader(builder::addHeader); - if (request.getHeader("User-Agent") == null) { - builder.addHeader("User-Agent", AddSeleniumUserAgent.USER_AGENT); - } - - Realm.Builder realmBuilder = null; - String info = baseUrl.getUserInfo(); - if (!Strings.isNullOrEmpty(info)) { - String[] parts = info.split(":", 2); - String user = parts[0]; - String pass = parts.length > 1 ? parts[1] : null; - realmBuilder = Dsl.basicAuthRealm(user, pass).setUsePreemptiveAuth(true); - builder.setRealm(realmBuilder); - } else if (credentials != null) { - if (!(credentials instanceof UsernameAndPassword)) { - throw new IllegalArgumentException("Credentials must be a user name and password"); - } - UsernameAndPassword uap = (UsernameAndPassword) credentials; - realmBuilder = Dsl.basicAuthRealm(uap.username(), uap.password()).setUsePreemptiveAuth(true); - builder.setRealm(realmBuilder); - } - - if (config.proxy() != null) { - InetSocketAddress address = (InetSocketAddress) config.proxy().address(); - ProxyServer.Builder proxyBuilder = - new ProxyServer.Builder(address.getHostName(), address.getPort()); - if (realmBuilder != null) { - proxyBuilder.setRealm(realmBuilder); - } - builder.setProxyServer(proxyBuilder); - } - - if (request.getMethod().equals(HttpMethod.POST)) { - builder.setBody(request.getContent().get()); - } - - return builder.build(); - } - - public static HttpResponse toSeleniumResponse(Response response) { - HttpResponse toReturn = new HttpResponse(); - - toReturn.setStatus(response.getStatusCode()); - - toReturn.setContent( - !response.hasResponseBody() ? empty() : memoize(response::getResponseBodyAsStream)); - - response - .getHeaders() - .names() - .forEach( - name -> response.getHeaders(name).forEach(value -> toReturn.addHeader(name, value))); - - return toReturn; - } - - private static String getRawUrl(URI baseUrl, String uri) { - String rawUrl; - if (uri.startsWith("ws://")) { - rawUrl = "http://" + uri.substring("ws://".length()); - } else if (uri.startsWith("wss://")) { - rawUrl = "https://" + uri.substring("wss://".length()); - } else if (uri.startsWith("http://") || uri.startsWith("https://")) { - rawUrl = uri; - } else { - String base = baseUrl.toString(); - if (base.endsWith("/")) { - rawUrl = base.substring(0, base.length() - 1) + uri; - } else { - rawUrl = base + uri; - } - } - return rawUrl; - } -} diff --git a/java/src/org/openqa/selenium/remote/http/netty/NettyWebSocket.java b/java/src/org/openqa/selenium/remote/http/netty/NettyWebSocket.java deleted file mode 100644 index 6e3f07f040208..0000000000000 --- a/java/src/org/openqa/selenium/remote/http/netty/NettyWebSocket.java +++ /dev/null @@ -1,174 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.openqa.selenium.remote.http.netty; - -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.asynchttpclient.AsyncHttpClient; -import org.asynchttpclient.ListenableFuture; -import org.asynchttpclient.Request; -import org.asynchttpclient.ws.WebSocketListener; -import org.asynchttpclient.ws.WebSocketUpgradeHandler; -import org.openqa.selenium.internal.Require; -import org.openqa.selenium.remote.http.BinaryMessage; -import org.openqa.selenium.remote.http.ClientConfig; -import org.openqa.selenium.remote.http.CloseMessage; -import org.openqa.selenium.remote.http.ConnectionFailedException; -import org.openqa.selenium.remote.http.Filter; -import org.openqa.selenium.remote.http.HttpRequest; -import org.openqa.selenium.remote.http.HttpResponse; -import org.openqa.selenium.remote.http.Message; -import org.openqa.selenium.remote.http.TextMessage; -import org.openqa.selenium.remote.http.WebSocket; - -class NettyWebSocket implements WebSocket { - - private static final Logger LOG = Logger.getLogger(NettyWebSocket.class.getName()); - - private final org.asynchttpclient.ws.WebSocket socket; - - private NettyWebSocket(AsyncHttpClient client, Request request, Listener listener) { - Require.nonNull("HTTP client", client); - Require.nonNull("WebSocket listener", listener); - - try { - URL origUrl = new URL(request.getUrl()); - String wsScheme = "https".equalsIgnoreCase(origUrl.getProtocol()) ? "wss" : "ws"; - - URI wsUri = - new URI( - wsScheme, null, origUrl.getHost(), origUrl.getPort(), origUrl.getPath(), null, null); - ListenableFuture future = - client - .prepareGet(wsUri.toString()) - .execute( - new WebSocketUpgradeHandler.Builder() - .addWebSocketListener( - new WebSocketListener() { - @Override - public void onOpen(org.asynchttpclient.ws.WebSocket websocket) {} - - @Override - public void onClose( - org.asynchttpclient.ws.WebSocket websocket, - int code, - String reason) { - listener.onClose(code, reason); - } - - @Override - public void onError(Throwable t) { - listener.onError(t); - } - - @Override - public void onBinaryFrame( - byte[] payload, boolean finalFragment, int rsv) { - if (payload != null) { - listener.onBinary(payload); - } - } - - @Override - public void onTextFrame( - String payload, boolean finalFragment, int rsv) { - if (payload != null) { - listener.onText(payload); - } - } - }) - .build()); - socket = - future - .toCompletableFuture() - .exceptionally( - t -> { - LOG.log(Level.WARNING, t.getMessage(), t); - return null; - }) - .get(); - - if (socket == null) { - throw new ConnectionFailedException( - "Unable to establish websocket connection to " + request.getUrl()); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LOG.log(Level.WARNING, "NettyWebSocket initial request interrupted", e); - throw new ConnectionFailedException("NettyWebSocket initial request interrupted", e); - } catch (ExecutionException | MalformedURLException | URISyntaxException e) { - throw new ConnectionFailedException("NettyWebSocket initial request execution error", e); - } - } - - static BiFunction create( - ClientConfig config, AsyncHttpClient client) { - Filter filter = config.filter(); - - Function filterRequest = - req -> { - AtomicReference ref = new AtomicReference<>(); - filter - .andFinally( - in -> { - ref.set(in); - return new HttpResponse(); - }) - .execute(req); - return ref.get(); - }; - - return (req, listener) -> { - HttpRequest filtered = filterRequest.apply(req); - Request nettyReq = NettyMessages.toNettyRequest(config, filtered); - return new NettyWebSocket(client, nettyReq, listener); - }; - } - - @Override - public WebSocket send(Message message) { - if (message instanceof BinaryMessage) { - socket.sendBinaryFrame(((BinaryMessage) message).data()); - } else if (message instanceof CloseMessage) { - socket.sendCloseFrame(((CloseMessage) message).code(), ((CloseMessage) message).reason()); - } else if (message instanceof TextMessage) { - socket.sendTextFrame(((TextMessage) message).text()); - } - - return this; - } - - @Override - public WebSocket sendText(CharSequence data) { - socket.sendTextFrame(data.toString()); - return this; - } - - @Override - public void close() { - socket.sendCloseFrame(1000, "WebDriver closing socket"); - } -} diff --git a/java/test/org/openqa/selenium/chrome/ChromeOptionsTest.java b/java/test/org/openqa/selenium/chrome/ChromeOptionsTest.java index 39e0d58ae9562..c02881213494c 100644 --- a/java/test/org/openqa/selenium/chrome/ChromeOptionsTest.java +++ b/java/test/org/openqa/selenium/chrome/ChromeOptionsTest.java @@ -147,7 +147,7 @@ void mergingOptionsMergesArguments() { .asInstanceOf(MAP) .extractingByKey("args") .asInstanceOf(LIST) - .containsExactly("--remote-allow-origins=*", "verbose", "silent"); + .containsExactly("verbose", "silent"); } @Test @@ -263,7 +263,7 @@ void mergingOptionsWithMutableCapabilities() { .asInstanceOf(MAP) .extractingByKey("args") .asInstanceOf(LIST) - .containsExactly("--remote-allow-origins=*", "verbose", "silent"); + .containsExactly("verbose", "silent"); assertThat(map) .asInstanceOf(MAP) @@ -328,7 +328,7 @@ void mergingOptionsWithOptionsAsMutableCapabilities() { .asInstanceOf(MAP) .extractingByKey("args") .asInstanceOf(LIST) - .containsExactly("--remote-allow-origins=*", "verbose", "silent"); + .containsExactly("verbose", "silent"); assertThat(map).asInstanceOf(MAP).containsEntry("opt1", "val1"); diff --git a/java/test/org/openqa/selenium/devtools/DevToolsReuseTest.java b/java/test/org/openqa/selenium/devtools/DevToolsReuseTest.java index f37abcaaa1bdd..7af36fe5d8d63 100644 --- a/java/test/org/openqa/selenium/devtools/DevToolsReuseTest.java +++ b/java/test/org/openqa/selenium/devtools/DevToolsReuseTest.java @@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.remote.Augmenter; @@ -26,6 +27,7 @@ class DevToolsReuseTest extends DevToolsTestBase { @Test + @Disabled("JDK HTTP Client cannot get reused") public void shouldBeAbleToCloseDevToolsAndCreateNewInstance() { WebDriver driver = new Augmenter().augment(this.driver); diff --git a/java/test/org/openqa/selenium/remote/http/BUILD.bazel b/java/test/org/openqa/selenium/remote/http/BUILD.bazel index d84861402521d..66bb20460f80e 100644 --- a/java/test/org/openqa/selenium/remote/http/BUILD.bazel +++ b/java/test/org/openqa/selenium/remote/http/BUILD.bazel @@ -14,7 +14,7 @@ java_test_suite( "//java:auto-service", "//java/src/org/openqa/selenium:core", "//java/src/org/openqa/selenium/remote/http", - "//java/src/org/openqa/selenium/remote/http/netty", + "//java/src/org/openqa/selenium/remote/http/jdk", "//java/test/org/openqa/selenium/environment", "//java/test/org/openqa/selenium/testing:annotations", artifact("org.assertj:assertj-core"), diff --git a/java/test/org/openqa/selenium/remote/http/HttpClientFactoryTest.java b/java/test/org/openqa/selenium/remote/http/HttpClientFactoryTest.java index 590937432ef71..961c3bf92fdb7 100644 --- a/java/test/org/openqa/selenium/remote/http/HttpClientFactoryTest.java +++ b/java/test/org/openqa/selenium/remote/http/HttpClientFactoryTest.java @@ -48,13 +48,15 @@ public void restoreSystemProperty() { @Test void canCreateDefaultHttpClientFactory() { HttpClient.Factory factory = HttpClient.Factory.createDefault(); - assertThat(factory.getClass().getAnnotation(HttpClientName.class).value()).isEqualTo("netty"); + assertThat(factory.getClass().getAnnotation(HttpClientName.class).value()) + .isEqualTo("jdk-http-client"); } @Test void canCreateHttpClientFactoryByName() { - HttpClient.Factory factory = HttpClient.Factory.create("netty"); - assertThat(factory.getClass().getAnnotation(HttpClientName.class).value()).isEqualTo("netty"); + HttpClient.Factory factory = HttpClient.Factory.create("jdk-http-client"); + assertThat(factory.getClass().getAnnotation(HttpClientName.class).value()) + .isEqualTo("jdk-http-client"); } @Test diff --git a/java/test/org/openqa/selenium/remote/http/RetryRequestTest.java b/java/test/org/openqa/selenium/remote/http/RetryRequestTest.java index 4b14fdb013bec..769e05ca3ccb9 100644 --- a/java/test/org/openqa/selenium/remote/http/RetryRequestTest.java +++ b/java/test/org/openqa/selenium/remote/http/RetryRequestTest.java @@ -33,7 +33,6 @@ import org.junit.jupiter.api.Test; import org.openqa.selenium.environment.webserver.AppServer; import org.openqa.selenium.environment.webserver.NettyAppServer; -import org.openqa.selenium.remote.http.netty.NettyClient; class RetryRequestTest { @@ -47,7 +46,7 @@ public void setUp() throws MalformedURLException { .baseUrl(URI.create("http://localhost:2345").toURL()) .withRetries() .readTimeout(Duration.ofSeconds(1)); - client = new NettyClient.Factory().createClient(config); + client = HttpClient.Factory.createDefault().createClient(config); } @Test diff --git a/java/test/org/openqa/selenium/remote/http/netty/BUILD.bazel b/java/test/org/openqa/selenium/remote/http/netty/BUILD.bazel deleted file mode 100644 index 066f9cc836f08..0000000000000 --- a/java/test/org/openqa/selenium/remote/http/netty/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -load("@rules_jvm_external//:defs.bzl", "artifact") -load("//java:defs.bzl", "JUNIT5_DEPS", "java_test_suite") - -java_test_suite( - name = "medium-tests", - size = "medium", - srcs = glob(["*.java"]), - deps = [ - "//java/src/org/openqa/selenium/remote/http", - "//java/src/org/openqa/selenium/remote/http/netty", - "//java/test/org/openqa/selenium/remote/internal:test-lib", - "//java/test/org/openqa/selenium/testing:annotations", - artifact("org.junit.jupiter:junit-jupiter-api"), - ] + JUNIT5_DEPS, -) diff --git a/java/test/org/openqa/selenium/remote/http/netty/NettyClientTest.java b/java/test/org/openqa/selenium/remote/http/netty/NettyClientTest.java deleted file mode 100644 index f12947fcad530..0000000000000 --- a/java/test/org/openqa/selenium/remote/http/netty/NettyClientTest.java +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.openqa.selenium.remote.http.netty; - -import org.junit.jupiter.api.Tag; -import org.openqa.selenium.remote.http.HttpClient; -import org.openqa.selenium.remote.internal.HttpClientTestBase; - -@Tag("UnitTests") -class NettyClientTest extends HttpClientTestBase { - @Override - protected HttpClient.Factory createFactory() { - return new NettyClient.Factory(); - } -} diff --git a/java/test/org/openqa/selenium/remote/http/netty/NettyDomainSocketTest.java b/java/test/org/openqa/selenium/remote/http/netty/NettyDomainSocketTest.java deleted file mode 100644 index dc29d6e27ffb2..0000000000000 --- a/java/test/org/openqa/selenium/remote/http/netty/NettyDomainSocketTest.java +++ /dev/null @@ -1,29 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.openqa.selenium.remote.http.netty; - -import org.openqa.selenium.remote.http.HttpClient; -import org.openqa.selenium.remote.internal.DomainSocketsTestBase; - -class NettyDomainSocketTest extends DomainSocketsTestBase { - - @Override - protected HttpClient.Factory createFactory() { - return new NettyClient.Factory(); - } -} diff --git a/java/test/org/openqa/selenium/remote/http/netty/NettyWebSocketTest.java b/java/test/org/openqa/selenium/remote/http/netty/NettyWebSocketTest.java deleted file mode 100644 index 65c74c358d220..0000000000000 --- a/java/test/org/openqa/selenium/remote/http/netty/NettyWebSocketTest.java +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.openqa.selenium.remote.http.netty; - -import org.openqa.selenium.remote.http.HttpClient; -import org.openqa.selenium.remote.internal.WebSocketTestBase; - -class NettyWebSocketTest extends WebSocketTestBase { - @Override - protected HttpClient.Factory createFactory() { - return new NettyClient.Factory(); - } -}