Skip to content

Commit 5c92f4d

Browse files
committed
[grid] Adding vnc endpoints for live view in the UI
1 parent 20eb10f commit 5c92f4d

File tree

3 files changed

+41
-15
lines changed

3 files changed

+41
-15
lines changed

java/server/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java

+17-5
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public class DriverServiceSessionFactory implements SessionFactory {
6767
private final Predicate<Capabilities> predicate;
6868
private final DriverService.Builder<?, ?> builder;
6969
private final Capabilities stereotype;
70-
private final BrowserOptionsMutator browserOptionsMutator;
70+
private final SessionCapabilitiesMutator sessionCapabilitiesMutator;
7171

7272
public DriverServiceSessionFactory(
7373
Tracer tracer,
@@ -80,7 +80,7 @@ public DriverServiceSessionFactory(
8080
this.stereotype = ImmutableCapabilities.copyOf(Require.nonNull("Stereotype", stereotype));
8181
this.predicate = Require.nonNull("Accepted capabilities predicate", predicate);
8282
this.builder = Require.nonNull("Driver service builder", builder);
83-
this.browserOptionsMutator = new BrowserOptionsMutator(this.stereotype);
83+
this.sessionCapabilitiesMutator = new SessionCapabilitiesMutator(this.stereotype);
8484
}
8585

8686
@Override
@@ -101,7 +101,8 @@ public Either<WebDriverException, ActiveSession> apply(CreateSessionRequest sess
101101

102102
try (Span span = tracer.getCurrentContext().createSpan("driver_service_factory.apply")) {
103103

104-
Capabilities capabilities = browserOptionsMutator.apply(sessionRequest.getDesiredCapabilities());
104+
Capabilities capabilities = sessionCapabilitiesMutator
105+
.apply(sessionRequest.getDesiredCapabilities());
105106

106107
Optional<Platform> platformName = Optional.ofNullable(capabilities.getPlatformName());
107108
if (platformName.isPresent()) {
@@ -142,14 +143,13 @@ public Either<WebDriverException, ActiveSession> apply(CreateSessionRequest sess
142143
attributeMap.put(AttributeKey.DRIVER_RESPONSE.getKey(),
143144
EventAttribute.setValue(response.toString()));
144145

145-
// TODO: This is a nasty hack. Try and make it elegant.
146-
147146
Capabilities caps = new ImmutableCapabilities((Map<?, ?>) response.getValue());
148147
if (platformName.isPresent()) {
149148
caps = setInitialPlatform(caps, platformName.get());
150149
}
151150

152151
caps = readDevToolsEndpointAndVersion(caps);
152+
caps = readVncEndpoint(capabilities, caps);
153153

154154
span.addEvent("Driver service created session", attributeMap);
155155
return Either.right(
@@ -214,6 +214,7 @@ public DevToolsInfo(URI cdpEndpoint, String version) {
214214
.filter(Optional::isPresent)
215215
.map(Optional::get)
216216
.findFirst();
217+
217218
if (maybeInfo.isPresent()) {
218219
DevToolsInfo info = maybeInfo.get();
219220
return new PersistentCapabilities(caps)
@@ -223,6 +224,17 @@ public DevToolsInfo(URI cdpEndpoint, String version) {
223224
return caps;
224225
}
225226

227+
private Capabilities readVncEndpoint(Capabilities requestedCaps, Capabilities returnedCaps) {
228+
String seVncEnabledCap = "se:vncEnabled";
229+
String seVncEnabled = String.valueOf(requestedCaps.getCapability(seVncEnabledCap));
230+
if (Boolean.parseBoolean(seVncEnabled)) {
231+
returnedCaps = new PersistentCapabilities(returnedCaps)
232+
.setCapability("se:vncLocalAddress", "ws://localhost:7900/websockify")
233+
.setCapability(seVncEnabledCap, true);
234+
}
235+
return returnedCaps;
236+
}
237+
226238
// We set the platform to ANY before sending the caps to the driver because some drivers will
227239
// reject session requests when they cannot parse the platform.
228240
private Capabilities generalizePlatform(Capabilities caps) {

java/server/src/org/openqa/selenium/grid/node/config/BrowserOptionsMutator.java renamed to java/server/src/org/openqa/selenium/grid/node/config/SessionCapabilitiesMutator.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,34 @@
2121

2222
import org.openqa.selenium.Capabilities;
2323
import org.openqa.selenium.ImmutableCapabilities;
24+
import org.openqa.selenium.PersistentCapabilities;
2425

2526
import java.util.HashMap;
2627
import java.util.Map;
2728
import java.util.Objects;
2829
import java.util.function.Function;
2930

30-
public class BrowserOptionsMutator implements Function<Capabilities, Capabilities> {
31+
public class SessionCapabilitiesMutator implements Function<Capabilities, Capabilities> {
3132

3233
private static final ImmutableMap<String, String> BROWSER_OPTIONS = ImmutableMap.of(
3334
"chrome", "goog:chromeOptions",
3435
"firefox", "moz:firefoxOptions",
3536
"microsoftedge", "ms:edgeOptions");
37+
private static final String SE_VNC_ENABLED = "se:vncEnabled";
3638
private final Capabilities slotStereotype;
3739

3840

39-
public BrowserOptionsMutator(Capabilities slotStereotype) {
41+
public SessionCapabilitiesMutator(Capabilities slotStereotype) {
4042
this.slotStereotype = slotStereotype;
4143
}
4244

4345
@Override
4446
public Capabilities apply(Capabilities capabilities) {
47+
if (slotStereotype.getCapability(SE_VNC_ENABLED) != null) {
48+
capabilities = new PersistentCapabilities(capabilities)
49+
.setCapability(SE_VNC_ENABLED, slotStereotype.getCapability(SE_VNC_ENABLED));
50+
}
51+
4552
if (!Objects.equals(slotStereotype.getBrowserName(), capabilities.getBrowserName())) {
4653
return capabilities;
4754
}

java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java

+15-8
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@
8181
import java.util.HashMap;
8282
import java.util.List;
8383
import java.util.Map;
84-
import java.util.Optional;
8584
import java.util.Set;
8685
import java.util.UUID;
8786
import java.util.concurrent.ExecutionException;
@@ -341,10 +340,9 @@ public Either<WebDriverException, CreateSessionResponse> newSession(CreateSessio
341340

342341
// The session we return has to look like it came from the node, since we might be dealing
343342
// with a webdriver implementation that only accepts connections from localhost
344-
Session externalSession = createExternalSession(
345-
session,
346-
externalUri,
347-
slotToUse.isSupportingCdp() || caps.getCapability("se:cdp") != null);
343+
boolean isSupportingCdp = slotToUse.isSupportingCdp() ||
344+
caps.getCapability("se:cdp") != null;
345+
Session externalSession = createExternalSession(session, externalUri, isSupportingCdp);
348346
return Either.right(new CreateSessionResponse(
349347
externalSession,
350348
getEncoder(session.getDownstreamDialect()).apply(externalSession)));
@@ -446,22 +444,31 @@ public void stop(SessionId id) throws NoSuchSessionException {
446444
tempFileSystems.invalidate(id);
447445
}
448446

449-
private Session createExternalSession(ActiveSession other, URI externalUri, boolean isSupportingCdp) {
447+
private Session createExternalSession(ActiveSession other, URI externalUri,
448+
boolean isSupportingCdp) {
450449
Capabilities toUse = ImmutableCapabilities.copyOf(other.getCapabilities());
451450

452-
// Rewrite the se:options if necessary to send the cdp url back
451+
// Add se:cdp if necessary to send the cdp url back
453452
if (isSupportingCdp) {
454453
String cdpPath = String.format("/session/%s/se/cdp", other.getId());
455454
toUse = new PersistentCapabilities(toUse).setCapability("se:cdp", rewrite(cdpPath));
456455
}
457456

457+
// If enabled, set the VNC endpoint for live view
458+
boolean isVncEnabled = toUse.getCapability("se:vncLocalAddress") != null;
459+
if (isVncEnabled) {
460+
String vncPath = String.format("/session/%s/se/vnc", other.getId());
461+
toUse = new PersistentCapabilities(toUse).setCapability("se:vnc", rewrite(vncPath));
462+
}
463+
458464
return new Session(other.getId(), externalUri, other.getStereotype(), toUse, Instant.now());
459465
}
460466

461467
private URI rewrite(String path) {
462468
try {
469+
String scheme = "https".equals(gridUri.getScheme()) ? "wss" : "ws";
463470
return new URI(
464-
"ws",
471+
scheme,
465472
gridUri.getUserInfo(),
466473
gridUri.getHost(),
467474
gridUri.getPort(),

0 commit comments

Comments
 (0)