Skip to content

Commit 44d398a

Browse files
authored
Synchronize on the underlying websocket (#10976)
This means that we can use the JDK11 websocket safely in a multi-threaded environment.
1 parent 1a5b24c commit 44d398a

1 file changed

Lines changed: 34 additions & 4 deletions

File tree

java/src/org/openqa/selenium/remote/http/jdk/JdkHttpClient.java

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.openqa.selenium.Credentials;
2222
import org.openqa.selenium.TimeoutException;
2323
import org.openqa.selenium.UsernameAndPassword;
24+
import org.openqa.selenium.WebDriverException;
2425
import org.openqa.selenium.remote.http.BinaryMessage;
2526
import org.openqa.selenium.remote.http.ClientConfig;
2627
import org.openqa.selenium.remote.http.CloseMessage;
@@ -46,27 +47,34 @@
4647
import java.net.http.HttpResponse.BodyHandlers;
4748
import java.net.http.HttpTimeoutException;
4849
import java.nio.ByteBuffer;
50+
import java.time.Duration;
4951
import java.util.List;
5052
import java.util.Objects;
53+
import java.util.concurrent.CancellationException;
5154
import java.util.concurrent.CompletableFuture;
5255
import java.util.concurrent.CompletionStage;
56+
import java.util.concurrent.CompletionStage;
57+
import java.util.concurrent.ExecutionException;
58+
import java.util.concurrent.TimeUnit;
59+
import java.util.function.Supplier;
5360

5461
import static java.net.http.HttpClient.Redirect.ALWAYS;
5562

5663
public class JdkHttpClient implements HttpClient {
5764
private final JdkHttpMessages messages;
5865
private final java.net.http.HttpClient client;
66+
private final Duration readTimeout;
5967

6068
JdkHttpClient(ClientConfig config) {
6169
Objects.requireNonNull(config, "Client config must be set");
6270

6371
this.messages = new JdkHttpMessages(config);
72+
this.readTimeout = config.readTimeout();
6473

6574
java.net.http.HttpClient.Builder builder = java.net.http.HttpClient.newBuilder()
6675
.connectTimeout(config.connectionTimeout())
6776
.followRedirects(ALWAYS);
6877

69-
7078
Credentials credentials = config.credentials();
7179
if (credentials != null) {
7280
if (!(credentials instanceof UsernameAndPassword)) {
@@ -148,18 +156,40 @@ public void onError(java.net.http.WebSocket webSocket, Throwable error) {
148156
return new WebSocket() {
149157
@Override
150158
public WebSocket send(Message message) {
159+
Supplier<CompletableFuture<java.net.http.WebSocket>> makeCall;
160+
151161
if (message instanceof BinaryMessage) {
152162
BinaryMessage binaryMessage = (BinaryMessage) message;
153-
underlyingSocket.sendBinary(ByteBuffer.wrap(binaryMessage.data()), true);
163+
makeCall = () -> underlyingSocket.sendBinary(ByteBuffer.wrap(binaryMessage.data()), true);
154164
} else if (message instanceof TextMessage) {
155165
TextMessage textMessage = (TextMessage) message;
156-
underlyingSocket.sendText(textMessage.text(), true);
166+
makeCall = () -> underlyingSocket.sendText(textMessage.text(), true);
157167
} else if (message instanceof CloseMessage) {
158168
CloseMessage closeMessage = (CloseMessage) message;
159-
underlyingSocket.sendClose(closeMessage.code(), closeMessage.reason());
169+
makeCall = () -> underlyingSocket.sendClose(closeMessage.code(), closeMessage.reason());
160170
} else {
161171
throw new IllegalArgumentException("Unsupport message type: " + message);
162172
}
173+
174+
synchronized (underlyingSocket) {
175+
CompletableFuture<java.net.http.WebSocket> future = makeCall.get();
176+
try {
177+
future.get(readTimeout.toMillis(), TimeUnit.MILLISECONDS);
178+
} catch (CancellationException e) {
179+
throw new WebDriverException(e.getMessage(), e);
180+
} catch (ExecutionException e) {
181+
Throwable cause = e.getCause();
182+
if (cause == null) {
183+
throw new WebDriverException(e);
184+
}
185+
throw new WebDriverException(cause);
186+
} catch (InterruptedException e) {
187+
Thread.currentThread().interrupt();
188+
throw new WebDriverException(e.getMessage());
189+
} catch (java.util.concurrent.TimeoutException e) {
190+
throw new TimeoutException(e);
191+
}
192+
}
163193
return this;
164194
}
165195

0 commit comments

Comments
 (0)