Skip to content

Commit

Permalink
Merge branch 'trunk' into sm_rpm_fix
Browse files Browse the repository at this point in the history
  • Loading branch information
diemol committed Mar 26, 2024
2 parents 3a43350 + 907b219 commit 6774b6a
Show file tree
Hide file tree
Showing 19 changed files with 166 additions and 242 deletions.
10 changes: 2 additions & 8 deletions java/src/org/openqa/selenium/bidi/BiDiProvider.java
Expand Up @@ -56,14 +56,8 @@ public HasBiDi getImplementation(Capabilities caps, ExecuteMethod executeMethod)
}

private Optional<URI> getBiDiUrl(Capabilities caps) {
Object bidiCapability;
if (caps.asMap().containsKey("se:bidi")) {
// Session is created remotely
bidiCapability = caps.getCapability("se:bidi");
} else {
bidiCapability = caps.getCapability("webSocketUrl");
}
Optional<String> webSocketUrl = Optional.ofNullable((String) bidiCapability);
Object biDiCapability = caps.getCapability("webSocketUrl");
Optional<String> webSocketUrl = Optional.ofNullable((String) biDiCapability);

return webSocketUrl.map(
uri -> {
Expand Down
6 changes: 2 additions & 4 deletions java/src/org/openqa/selenium/devtools/idealized/Network.java
Expand Up @@ -21,8 +21,6 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.logging.Level.WARNING;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Base64;
Expand Down Expand Up @@ -293,13 +291,13 @@ protected HttpResponse createHttpResponse(
String body,
Boolean bodyIsBase64Encoded,
List<Map.Entry<String, String>> headers) {
Supplier<InputStream> content;
Contents.Supplier content;

if (body == null) {
content = Contents.empty();
} else if (bodyIsBase64Encoded != null && bodyIsBase64Encoded) {
byte[] decoded = Base64.getDecoder().decode(body);
content = () -> new ByteArrayInputStream(decoded);
content = Contents.bytes(decoded);
} else {
content = Contents.string(body, UTF_8);
}
Expand Down
3 changes: 1 addition & 2 deletions java/src/org/openqa/selenium/grid/data/SessionRequest.java
Expand Up @@ -41,7 +41,6 @@
import org.openqa.selenium.json.TypeToken;
import org.openqa.selenium.remote.Dialect;
import org.openqa.selenium.remote.NewSessionPayload;
import org.openqa.selenium.remote.http.Contents;
import org.openqa.selenium.remote.http.HttpRequest;

public class SessionRequest {
Expand All @@ -61,7 +60,7 @@ public SessionRequest(RequestId requestId, HttpRequest request, Instant enqueued
this.enqueued = Require.nonNull("Enqueued time", enqueued);
Require.nonNull("Request", request);

try (NewSessionPayload payload = NewSessionPayload.create(Contents.reader(request))) {
try (NewSessionPayload payload = NewSessionPayload.create(request.getContent())) {
desiredCapabilities =
payload.stream()
.filter(capabilities -> !capabilities.asMap().isEmpty())
Expand Down
Expand Up @@ -171,7 +171,7 @@ private Optional<Consumer<Message>> findBiDiEndpoint(
Consumer<SessionId> sessionConsumer,
SessionId sessionId) {
try {
URI uri = new URI(String.valueOf(caps.getCapability("webSocketUrl")));
URI uri = new URI(String.valueOf(caps.getCapability("se:gridWebSocketUrl")));
return Optional.of(uri)
.map(bidi -> createWsEndPoint(bidi, downstream, sessionConsumer, sessionId));
} catch (URISyntaxException e) {
Expand Down
Expand Up @@ -22,7 +22,6 @@
import static org.openqa.selenium.remote.tracing.Tags.EXCEPTION;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.time.Duration;
import java.time.Instant;
Expand Down Expand Up @@ -186,7 +185,6 @@ public Either<WebDriverException, ActiveSession> apply(CreateSessionRequest sess
}

caps = readDevToolsEndpointAndVersion(caps);
caps = readBiDiEndpoint(caps);
caps = readVncEndpoint(capabilities, caps);

span.addEvent("Driver service created session", attributeMap);
Expand Down Expand Up @@ -281,29 +279,6 @@ public DevToolsInfo(URI cdpEndpoint, String version) {
return caps;
}

private Capabilities readBiDiEndpoint(Capabilities caps) {

Optional<String> webSocketUrl =
Optional.ofNullable((String) caps.getCapability("webSocketUrl"));

Optional<URI> websocketUri =
webSocketUrl.map(
uri -> {
try {
return new URI(uri);
} catch (URISyntaxException e) {
LOG.warning(e.getMessage());
}
return null;
});

if (websocketUri.isPresent()) {
return new PersistentCapabilities(caps).setCapability("se:bidi", websocketUri.get());
}

return caps;
}

private Capabilities readVncEndpoint(Capabilities requestedCaps, Capabilities returnedCaps) {
String seVncEnabledCap = "se:vncEnabled";
String seNoVncPortCap = "se:noVncPort";
Expand Down
28 changes: 21 additions & 7 deletions java/src/org/openqa/selenium/grid/node/local/LocalNode.java
Expand Up @@ -805,20 +805,34 @@ private Session createExternalSession(
}

// Check if the user wants to use BiDi
boolean webSocketUrl = toUse.asMap().containsKey("webSocketUrl");
// Add se:bidi if necessary to send the bidi url back
boolean bidiSupported = isSupportingBiDi || toUse.getCapability("se:bidi") != null;
if (bidiSupported && bidiEnabled && webSocketUrl) {
// This will be null if the user has not set the capability.
Object webSocketUrl = toUse.getCapability("webSocketUrl");

// In case of Firefox versions that do not support webSocketUrl, it returns the capability as it
// is i.e. boolean value. So need to check if it is a string.
// Check if the Node supports BiDi and if the client wants to use BiDi.
boolean bidiSupported = isSupportingBiDi && (webSocketUrl instanceof String);
if (bidiSupported && bidiEnabled) {
String biDiUrl = (String) other.getCapabilities().getCapability("webSocketUrl");
URI uri = null;
try {
uri = new URI(biDiUrl);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Unable to create URI from " + uri);
}
String bidiPath = String.format("/session/%s/se/bidi", other.getId());
toUse = new PersistentCapabilities(toUse).setCapability("se:bidi", rewrite(bidiPath));
toUse =
new PersistentCapabilities(toUse)
.setCapability("se:gridWebSocketUrl", uri)
.setCapability("webSocketUrl", rewrite(bidiPath));
} else {
// Remove any se:bidi* from the response, BiDi is not supported nor enabled
// Remove any "webSocketUrl" from the response, BiDi is not supported nor enabled
MutableCapabilities bidiFiltered = new MutableCapabilities();
toUse
.asMap()
.forEach(
(key, value) -> {
if (!key.startsWith("se:bidi")) {
if (!key.startsWith("webSocketUrl")) {
bidiFiltered.setCapability(key, value);
}
});
Expand Down
43 changes: 25 additions & 18 deletions java/src/org/openqa/selenium/netty/server/RequestConverter.java
Expand Up @@ -44,6 +44,7 @@
import java.util.List;
import java.util.logging.Logger;
import org.openqa.selenium.internal.Debug;
import org.openqa.selenium.remote.http.Contents;
import org.openqa.selenium.remote.http.HttpMethod;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;
Expand All @@ -55,6 +56,7 @@ class RequestConverter extends SimpleChannelInboundHandler<HttpObject> {
private static final List<io.netty.handler.codec.http.HttpMethod> SUPPORTED_METHODS =
Arrays.asList(DELETE, GET, POST, OPTIONS);
private volatile FileBackedOutputStream buffer;
private volatile int length;
private volatile HttpRequest request;

@Override
Expand Down Expand Up @@ -91,6 +93,7 @@ protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Ex
AttributeKey.HTTP_FLAVOR.getKey(), nettyRequest.protocolVersion().majorVersion());

buffer = null;
length = -1;
}

if (msg instanceof HttpContent) {
Expand All @@ -100,10 +103,12 @@ protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Ex
if (nBytes > 0) {
if (buffer == null) {
buffer = new FileBackedOutputStream(3 * 1024 * 1024, true);
length = 0;
}

try {
buf.readBytes(buffer, nBytes);
length += nBytes;
} finally {
buf.release();
}
Expand All @@ -114,29 +119,31 @@ protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Ex

if (buffer != null) {
ByteSource source = buffer.asByteSource();
int len = length;

request.setContent(
() -> {
try {
return source.openBufferedStream();
} catch (IOException e) {
throw new UncheckedIOException(e);
new Contents.Supplier() {
@Override
public InputStream get() {
try {
return source.openBufferedStream();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

@Override
public int length() {
return len;
}

@Override
public void close() throws IOException {
buffer.reset();
}
});
} else {
request.setContent(
() ->
new InputStream() {
@Override
public int read() throws IOException {
return -1;
}

@Override
public int read(byte[] b, int off, int len) throws IOException {
return -1;
}
});
request.setContent(Contents.empty());
}

ctx.fireChannelRead(request);
Expand Down
60 changes: 17 additions & 43 deletions java/src/org/openqa/selenium/remote/NewSessionPayload.java
Expand Up @@ -21,15 +21,10 @@
import static org.openqa.selenium.json.Json.LIST_OF_MAPS_TYPE;
import static org.openqa.selenium.json.Json.MAP_TYPE;

import com.google.common.io.FileBackedOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -50,32 +45,19 @@
import org.openqa.selenium.json.Json;
import org.openqa.selenium.json.JsonInput;
import org.openqa.selenium.json.JsonOutput;
import org.openqa.selenium.remote.http.Contents;

public class NewSessionPayload implements Closeable {

private static final Dialect DEFAULT_DIALECT = Dialect.W3C;
private static final Predicate<String> ACCEPTED_W3C_PATTERNS = new AcceptedW3CCapabilityKeys();

private final Json json = new Json();
private final FileBackedOutputStream backingStore;
private final Contents.Supplier supplier;
private final Set<Dialect> dialects;

private NewSessionPayload(Reader source) {
// Dedicate up to 10% of all RAM or 20% of available RAM (whichever is smaller) to storing this
// payload.
int threshold =
(int)
Math.min(
Integer.MAX_VALUE,
Math.min(
Runtime.getRuntime().freeMemory() / 5, Runtime.getRuntime().maxMemory() / 10));

backingStore = new FileBackedOutputStream(threshold);
try (Writer writer = new OutputStreamWriter(backingStore, UTF_8)) {
source.transferTo(writer);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
private NewSessionPayload(Contents.Supplier supplier) {
this.supplier = supplier;

Set<Dialect> dialects = new LinkedHashSet<>();
try {
Expand All @@ -89,12 +71,6 @@ private NewSessionPayload(Reader source) {
} catch (IOException e) {
throw new UncheckedIOException(e);
}

try {
source.close();
} catch (IOException e) {
// Ignore
}
}

public static NewSessionPayload create(Capabilities caps) {
Expand All @@ -120,12 +96,15 @@ public static NewSessionPayload create(Map<String, ?> source) {
Require.precondition(
source.containsKey("capabilities"), "New session payload must contain capabilities");

String json = new Json().toJson(Require.nonNull("Payload", source));
return new NewSessionPayload(new StringReader(json));
return new NewSessionPayload(Contents.asJson(Require.nonNull("Payload", source)));
}

public static NewSessionPayload create(Contents.Supplier supplier) {
return new NewSessionPayload(supplier);
}

public static NewSessionPayload create(Reader source) {
return new NewSessionPayload(source);
public Contents.Supplier getSupplier() {
return supplier;
}

private void validate() throws IOException {
Expand Down Expand Up @@ -213,8 +192,7 @@ public void writeTo(Appendable appendable) throws IOException {
}

private void writeMetaData(JsonOutput out) throws IOException {
try (Reader reader =
new InputStreamReader(backingStore.asByteSource().openBufferedStream(), UTF_8);
try (Reader reader = Contents.reader(supplier, UTF_8);
JsonInput input = json.newInput(reader)) {
input.beginObject();
while (input.hasNext()) {
Expand Down Expand Up @@ -253,8 +231,7 @@ public Set<Dialect> getDownstreamDialects() {
public Map<String, Object> getMetadata() {
Set<String> ignoredMetadataKeys = Set.of("capabilities");

try (Reader reader =
new InputStreamReader(backingStore.asByteSource().openBufferedStream(), UTF_8);
try (Reader reader = Contents.reader(supplier, UTF_8);
JsonInput input = json.newInput(reader)) {
Map<String, Object> toReturn = new LinkedHashMap<>();

Expand Down Expand Up @@ -284,7 +261,7 @@ public Map<String, Object> getMetadata() {
@Override
public void close() {
try {
backingStore.reset();
supplier.close();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Expand Down Expand Up @@ -324,8 +301,7 @@ private Stream<Map<String, Object>> getW3C() throws IOException {
}

private boolean isW3C() throws IOException {
try (Reader reader =
new InputStreamReader(backingStore.asByteSource().openBufferedStream(), UTF_8);
try (Reader reader = Contents.reader(supplier, UTF_8);
JsonInput input = json.newInput(reader)) {
input.beginObject();
while (input.hasNext()) {
Expand All @@ -341,8 +317,7 @@ private boolean isW3C() throws IOException {
}

private Map<String, Object> getAlwaysMatch() throws IOException {
try (Reader reader =
new InputStreamReader(backingStore.asByteSource().openBufferedStream(), UTF_8);
try (Reader reader = Contents.reader(supplier, UTF_8);
JsonInput input = json.newInput(reader)) {
input.beginObject();
while (input.hasNext()) {
Expand All @@ -367,8 +342,7 @@ private Map<String, Object> getAlwaysMatch() throws IOException {
}

private Collection<Map<String, Object>> getFirstMatches() throws IOException {
try (Reader reader =
new InputStreamReader(backingStore.asByteSource().openBufferedStream(), UTF_8);
try (Reader reader = Contents.reader(supplier, UTF_8);
JsonInput input = json.newInput(reader)) {
input.beginObject();
while (input.hasNext()) {
Expand Down

0 comments on commit 6774b6a

Please sign in to comment.