From 3270a99579d33d0087a32f5c4b8f8d1a288b32db Mon Sep 17 00:00:00 2001 From: Simon Stewart Date: Mon, 11 May 2020 14:55:01 +0100 Subject: [PATCH] [grid + cdp] Expose URL for CDP on capabilities --- .../selenium/grid/node/config/BUILD.bazel | 1 + .../config/DriverServiceSessionFactory.java | 56 ++++++++++++++----- .../selenium/grid/node/local/LocalNode.java | 48 +++++++++++++++- 3 files changed, 91 insertions(+), 14 deletions(-) diff --git a/java/server/src/org/openqa/selenium/grid/node/config/BUILD.bazel b/java/server/src/org/openqa/selenium/grid/node/config/BUILD.bazel index 860c4f20098cd..70a287dabd4ef 100644 --- a/java/server/src/org/openqa/selenium/grid/node/config/BUILD.bazel +++ b/java/server/src/org/openqa/selenium/grid/node/config/BUILD.bazel @@ -8,6 +8,7 @@ java_library( "//java/server/test/org/openqa/selenium/grid/node/config:__subpackages__", ], deps = [ + "//java/client/src/org/openqa/selenium/chromium", "//java/client/src/org/openqa/selenium/remote", "//java/server/src/org/openqa/selenium/grid/config", "//java/server/src/org/openqa/selenium/grid/data", diff --git a/java/server/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java b/java/server/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java index 599cbf667d158..88c41874f4451 100644 --- a/java/server/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java +++ b/java/server/src/org/openqa/selenium/grid/node/config/DriverServiceSessionFactory.java @@ -17,8 +17,11 @@ package org.openqa.selenium.grid.node.config; +import com.google.common.collect.ImmutableMap; import org.openqa.selenium.Capabilities; import org.openqa.selenium.ImmutableCapabilities; +import org.openqa.selenium.PersistentCapabilities; +import org.openqa.selenium.chromium.ChromiumDevToolsLocator; import org.openqa.selenium.grid.data.CreateSessionRequest; import org.openqa.selenium.grid.node.ActiveSession; import org.openqa.selenium.grid.node.ProtocolConvertingSession; @@ -35,6 +38,8 @@ import org.openqa.selenium.remote.tracing.Status; import org.openqa.selenium.remote.tracing.Tracer; +import java.net.URI; +import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -98,20 +103,33 @@ public Optional apply(CreateSessionRequest sessionRequest) { Response response = result.createResponse(); + // TODO: This is a nasty hack. Try and make it elegant. + + Capabilities caps = new ImmutableCapabilities((Map) response.getValue()); + Optional reportedUri = ChromiumDevToolsLocator.getReportedUri("goog:chromeOptions", caps); + if (reportedUri.isPresent()) { + caps = addCdpCapability(caps, reportedUri.get()); + } else { + reportedUri = ChromiumDevToolsLocator.getReportedUri("ms:edgeOptions", caps); + if (reportedUri.isPresent()) { + caps = addCdpCapability(caps, reportedUri.get()); + } + } + return Optional.of( - new ProtocolConvertingSession( - tracer, - client, - new SessionId(response.getSessionId()), - service.getUrl(), - downstream, - upstream, - new ImmutableCapabilities((Map)response.getValue())) { - @Override - public void stop() { - service.stop(); - } - }); + new ProtocolConvertingSession( + tracer, + client, + new SessionId(response.getSessionId()), + service.getUrl(), + downstream, + upstream, + caps) { + @Override + public void stop() { + service.stop(); + } + }); } catch (Exception e) { span.setAttribute("error", true); span.setStatus(Status.UNKNOWN.withDescription(e.getMessage())); @@ -122,4 +140,16 @@ public void stop() { return Optional.empty(); } } + + private Capabilities addCdpCapability(Capabilities caps, URI uri) { + Object raw = caps.getCapability("se:options"); + if (!(raw instanceof Map)) { + return new PersistentCapabilities(caps).setCapability("se:options", ImmutableMap.of("cdp", uri)); + } + + //noinspection unchecked + Map current = new HashMap<>((Map) raw); + current.put("cdp", uri); + return new PersistentCapabilities(caps).setCapability("se:options", ImmutableMap.copyOf(current)); + } } diff --git a/java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java b/java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java index 2935572d7cb44..d80fa102cbe9a 100644 --- a/java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java +++ b/java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java @@ -27,7 +27,9 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import org.openqa.selenium.Capabilities; +import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.NoSuchSessionException; +import org.openqa.selenium.PersistentCapabilities; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.concurrent.Regularly; import org.openqa.selenium.events.EventBus; @@ -54,12 +56,14 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.net.URI; +import java.net.URISyntaxException; import java.time.Clock; import java.time.Duration; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.logging.Logger; @@ -301,7 +305,49 @@ public void stop(SessionId id) throws NoSuchSessionException { } private Session createExternalSession(ActiveSession other, URI externalUri) { - return new Session(other.getId(), externalUri, other.getCapabilities()); + Capabilities toUse = ImmutableCapabilities.copyOf(other.getCapabilities()); + + // Rewrite the se:options if necessary + Object rawSeleniumOptions = other.getCapabilities().getCapability("se:options"); + if (rawSeleniumOptions instanceof Map) { + @SuppressWarnings("unchecked") Map original = (Map) rawSeleniumOptions; + Map updated = new TreeMap<>(original); + + Object cdp = original.get("cdp"); + String cdpPath = String.format("/session/%s/se/cdp", other.getId()); + if (cdp instanceof URI) { + updated.put("cdp", rewrite((URI) cdp, cdpPath)); + } else if (cdp instanceof String) { + updated.put("cdp", rewrite((String) cdp, cdpPath)); + } + + toUse = new PersistentCapabilities(toUse).setCapability("se:options", updated); + } + + return new Session(other.getId(), externalUri, toUse); + } + + private URI rewrite(String from, String path) { + try { + return rewrite(new URI(from), path); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + private URI rewrite(URI from, String path) { + try { + return new URI( + from.getScheme(), + externalUri.getUserInfo(), + externalUri.getHost(), + externalUri.getPort(), + path, + null, + null); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } } private void killSession(SessionSlot slot) {