From 8d5c10ff62b38a91ae788cc8c37496cf981a376d Mon Sep 17 00:00:00 2001 From: titusfortner Date: Tue, 29 Nov 2022 17:57:34 -0600 Subject: [PATCH] [java][cdp] add support for Chrome 108 and remove support for Chrome 105 --- Rakefile | 2 +- .../openqa/selenium/devtools/v108/BUILD.bazel | 71 ++++++ .../selenium/devtools/v108/V108CdpInfo.java | 29 +++ .../selenium/devtools/v108/V108Domains.java | 70 ++++++ .../selenium/devtools/v108/V108Events.java | 116 +++++++++ .../devtools/v108/V108Javascript.java | 86 +++++++ .../selenium/devtools/v108/V108Log.java | 88 +++++++ .../selenium/devtools/v108/V108Network.java | 236 ++++++++++++++++++ .../selenium/devtools/v108/V108Target.java | 110 ++++++++ .../org/openqa/selenium/devtools/versions.bzl | 2 +- 10 files changed, 808 insertions(+), 2 deletions(-) create mode 100644 java/src/org/openqa/selenium/devtools/v108/BUILD.bazel create mode 100644 java/src/org/openqa/selenium/devtools/v108/V108CdpInfo.java create mode 100644 java/src/org/openqa/selenium/devtools/v108/V108Domains.java create mode 100644 java/src/org/openqa/selenium/devtools/v108/V108Events.java create mode 100644 java/src/org/openqa/selenium/devtools/v108/V108Javascript.java create mode 100644 java/src/org/openqa/selenium/devtools/v108/V108Log.java create mode 100644 java/src/org/openqa/selenium/devtools/v108/V108Network.java create mode 100644 java/src/org/openqa/selenium/devtools/v108/V108Target.java diff --git a/Rakefile b/Rakefile index e4e9967e775c7..ea137d664a929 100644 --- a/Rakefile +++ b/Rakefile @@ -98,9 +98,9 @@ task '//java/test/org/openqa/selenium/environment/webserver:webserver:uber' => [ JAVA_RELEASE_TARGETS = %w[ //java/src/org/openqa/selenium/chrome:chrome.publish //java/src/org/openqa/selenium/chromium:chromium.publish - //java/src/org/openqa/selenium/devtools/v105:v105.publish //java/src/org/openqa/selenium/devtools/v106:v106.publish //java/src/org/openqa/selenium/devtools/v107:v107.publish + //java/src/org/openqa/selenium/devtools/v108:v108.publish //java/src/org/openqa/selenium/devtools/v85:v85.publish //java/src/org/openqa/selenium/edge:edge.publish //java/src/org/openqa/selenium/firefox:firefox.publish diff --git a/java/src/org/openqa/selenium/devtools/v108/BUILD.bazel b/java/src/org/openqa/selenium/devtools/v108/BUILD.bazel new file mode 100644 index 0000000000000..1e5492eecb0a0 --- /dev/null +++ b/java/src/org/openqa/selenium/devtools/v108/BUILD.bazel @@ -0,0 +1,71 @@ +load("@rules_jvm_external//:defs.bzl", "artifact") +load("//common:defs.bzl", "copy_file") +load("//java:defs.bzl", "java_export", "java_library") +load("//java:version.bzl", "SE_VERSION") + +cdp_version = "v108" + +java_export( + name = cdp_version, + srcs = glob(["*.java"]), + maven_coordinates = "org.seleniumhq.selenium:selenium-devtools-%s:%s" % (cdp_version, SE_VERSION), + opens_to = [ + "org.openqa.selenium.json", + ], + pom_template = "//java/src/org/openqa/selenium:template-pom", + visibility = [ + "//visibility:public", + ], + exports = [ + ":cdp", + ], + deps = [ + ":cdp", + "//java:auto-service", + "//java/src/org/openqa/selenium:core", + "//java/src/org/openqa/selenium/json", + "//java/src/org/openqa/selenium/remote", + artifact("com.google.guava:guava"), + ], +) + +java_library( + name = "cdp", + srcs = [ + ":create-cdp-srcs", + ], + tags = [ + "no-lint", + ], + deps = [ + "//java/src/org/openqa/selenium:core", + "//java/src/org/openqa/selenium/json", + "//java/src/org/openqa/selenium/remote", + artifact("com.google.guava:guava"), + ], +) + +genrule( + name = "create-cdp-srcs", + srcs = [ + ":browser_protocol", + ":js_protocol", + ], + outs = ["cdp.srcjar"], + cmd = "$(location //java/src/org/openqa/selenium/devtools:cdp-client-generator) $(location :browser_protocol) $(location :js_protocol) %s $@" % cdp_version, + tools = [ + "//java/src/org/openqa/selenium/devtools:cdp-client-generator", + ], +) + +copy_file( + name = "browser_protocol", + src = "//common/devtools/chromium/%s:browser_protocol" % cdp_version, + out = "browser_protocol.json", +) + +copy_file( + name = "js_protocol", + src = "//common/devtools/chromium/%s:js_protocol" % cdp_version, + out = "js_protocol.json", +) diff --git a/java/src/org/openqa/selenium/devtools/v108/V108CdpInfo.java b/java/src/org/openqa/selenium/devtools/v108/V108CdpInfo.java new file mode 100644 index 0000000000000..582047e7b0e5a --- /dev/null +++ b/java/src/org/openqa/selenium/devtools/v108/V108CdpInfo.java @@ -0,0 +1,29 @@ +// 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.devtools.v108; + +import com.google.auto.service.AutoService; +import org.openqa.selenium.devtools.CdpInfo; + +@AutoService(CdpInfo.class) +public class V108CdpInfo extends CdpInfo { + + public V108CdpInfo() { + super(108, V108Domains::new); + } +} diff --git a/java/src/org/openqa/selenium/devtools/v108/V108Domains.java b/java/src/org/openqa/selenium/devtools/v108/V108Domains.java new file mode 100644 index 0000000000000..be5e1568ba73b --- /dev/null +++ b/java/src/org/openqa/selenium/devtools/v108/V108Domains.java @@ -0,0 +1,70 @@ +// 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.devtools.v108; + +import org.openqa.selenium.devtools.DevTools; +import org.openqa.selenium.devtools.idealized.Domains; +import org.openqa.selenium.devtools.idealized.Events; +import org.openqa.selenium.devtools.idealized.Javascript; +import org.openqa.selenium.devtools.idealized.Network; +import org.openqa.selenium.devtools.idealized.log.Log; +import org.openqa.selenium.devtools.idealized.target.Target; +import org.openqa.selenium.internal.Require; + +public class V108Domains implements Domains { + + private final V108Javascript js; + private final V108Events events; + private final V108Log log; + private final V108Network network; + private final V108Target target; + + public V108Domains(DevTools devtools) { + Require.nonNull("DevTools", devtools); + events = new V108Events(devtools); + js = new V108Javascript(devtools); + log = new V108Log(); + network = new V108Network(devtools); + target = new V108Target(); + } + + @Override + public Events events() { + return events; + } + + @Override + public Javascript javascript() { + return js; + } + + @Override + public Network network() { + return network; + } + + @Override + public Target target() { + return target; + } + + @Override + public Log log() { + return log; + } +} diff --git a/java/src/org/openqa/selenium/devtools/v108/V108Events.java b/java/src/org/openqa/selenium/devtools/v108/V108Events.java new file mode 100644 index 0000000000000..2d8cd07991f1a --- /dev/null +++ b/java/src/org/openqa/selenium/devtools/v108/V108Events.java @@ -0,0 +1,116 @@ +// 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.devtools.v108; + +import com.google.common.collect.ImmutableList; + +import org.openqa.selenium.JavascriptException; +import org.openqa.selenium.devtools.Command; +import org.openqa.selenium.devtools.DevTools; +import org.openqa.selenium.devtools.Event; +import org.openqa.selenium.devtools.events.ConsoleEvent; +import org.openqa.selenium.devtools.idealized.Events; +import org.openqa.selenium.devtools.idealized.runtime.model.RemoteObject; +import org.openqa.selenium.devtools.v108.runtime.Runtime; +import org.openqa.selenium.devtools.v108.runtime.model.ConsoleAPICalled; +import org.openqa.selenium.devtools.v108.runtime.model.ExceptionDetails; +import org.openqa.selenium.devtools.v108.runtime.model.ExceptionThrown; +import org.openqa.selenium.devtools.v108.runtime.model.StackTrace; + +import java.time.Instant; +import java.util.List; +import java.util.Optional; + +public class V108Events extends Events { + + public V108Events(DevTools devtools) { + super(devtools); + } + + @Override + protected Command enableRuntime() { + return Runtime.enable(); + } + + @Override + protected Command disableRuntime() { + return Runtime.disable(); + } + + @Override + protected Event consoleEvent() { + return Runtime.consoleAPICalled(); + } + + @Override + protected Event exceptionThrownEvent() { + return Runtime.exceptionThrown(); + } + + @Override + protected ConsoleEvent toConsoleEvent(ConsoleAPICalled event) { + long ts = event.getTimestamp().toJson().longValue(); + + List modifiedArgs = event.getArgs().stream() + .map(obj -> new RemoteObject( + obj.getType().toString(), + obj.getValue().orElse(null))) + .collect(ImmutableList.toImmutableList()); + + return new ConsoleEvent( + event.getType().toString(), + Instant.ofEpochMilli(ts), + modifiedArgs); + } + + @Override + protected JavascriptException toJsException(ExceptionThrown event) { + ExceptionDetails details = event.getExceptionDetails(); + Optional maybeTrace = details.getStackTrace(); + Optional + maybeException = details.getException(); + + String message = maybeException + .flatMap(obj -> obj.getDescription().map(String::toString)) + .orElseGet(details::getText); + + JavascriptException exception = new JavascriptException(message); + + if (!maybeTrace.isPresent()) { + StackTraceElement element = new StackTraceElement( + "unknown", + "unknown", + details.getUrl().orElse("unknown"), + details.getLineNumber()); + exception.setStackTrace(new StackTraceElement[]{element}); + return exception; + } + + StackTrace trace = maybeTrace.get(); + + exception.setStackTrace(trace.getCallFrames().stream() + .map(frame -> new StackTraceElement( + "", + frame.getFunctionName(), + frame.getUrl(), + frame.getLineNumber())) + .toArray(StackTraceElement[]::new)); + + return exception; + } +} diff --git a/java/src/org/openqa/selenium/devtools/v108/V108Javascript.java b/java/src/org/openqa/selenium/devtools/v108/V108Javascript.java new file mode 100644 index 0000000000000..4d6472f9e60ea --- /dev/null +++ b/java/src/org/openqa/selenium/devtools/v108/V108Javascript.java @@ -0,0 +1,86 @@ +// 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.devtools.v108; + +import org.openqa.selenium.devtools.Command; +import org.openqa.selenium.devtools.DevTools; +import org.openqa.selenium.devtools.Event; +import org.openqa.selenium.devtools.idealized.Javascript; +import org.openqa.selenium.devtools.v108.page.Page; +import org.openqa.selenium.devtools.v108.page.model.ScriptIdentifier; +import org.openqa.selenium.devtools.v108.runtime.Runtime; +import org.openqa.selenium.devtools.v108.runtime.model.BindingCalled; + +import java.util.Optional; + +public class V108Javascript extends Javascript { + + public V108Javascript(DevTools devtools) { + super(devtools); + } + + @Override + protected Command enableRuntime() { + return Runtime.enable(); + } + + @Override + protected Command disableRuntime() { + return Runtime.disable(); + } + + @Override + protected Command doAddJsBinding(String scriptName) { + return Runtime.addBinding(scriptName, Optional.empty(), Optional.empty()); + } + + @Override + protected Command doRemoveJsBinding(String scriptName) { + return Runtime.removeBinding(scriptName); + } + + @Override + protected Command enablePage() { + return Page.enable(); + } + + @Override + protected Command disablePage() { + return Page.disable(); + } + + @Override + protected Command addScriptToEvaluateOnNewDocument(String script) { + return Page.addScriptToEvaluateOnNewDocument(script, Optional.empty(), Optional.empty()); + } + + @Override + protected Command removeScriptToEvaluateOnNewDocument(ScriptIdentifier id) { + return Page.removeScriptToEvaluateOnNewDocument(id); + } + + @Override + protected Event bindingCalledEvent() { + return Runtime.bindingCalled(); + } + + @Override + protected String extractPayload(BindingCalled event) { + return event.getPayload(); + } +} diff --git a/java/src/org/openqa/selenium/devtools/v108/V108Log.java b/java/src/org/openqa/selenium/devtools/v108/V108Log.java new file mode 100644 index 0000000000000..6dcad87d678ba --- /dev/null +++ b/java/src/org/openqa/selenium/devtools/v108/V108Log.java @@ -0,0 +1,88 @@ +// 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.devtools.v108; + +import org.openqa.selenium.devtools.Command; +import org.openqa.selenium.devtools.ConverterFunctions; +import org.openqa.selenium.devtools.Event; +import org.openqa.selenium.devtools.v108.log.Log; +import org.openqa.selenium.devtools.v108.log.model.LogEntry; +import org.openqa.selenium.devtools.v108.runtime.model.Timestamp; +import org.openqa.selenium.json.JsonInput; + +import java.util.function.Function; +import java.util.logging.Level; + +public class V108Log implements org.openqa.selenium.devtools.idealized.log.Log { + + @Override + public Command enable() { + return Log.enable(); + } + + @Override + public Command clear() { + return Log.clear(); + } + + @Override + public Event entryAdded() { + return new Event<>( + Log.entryAdded().getMethod(), + input -> { + Function mapper = ConverterFunctions.map( + "entry", + LogEntry.class); + LogEntry entry = mapper.apply(input); + + return new org.openqa.selenium.devtools.idealized.log.model.LogEntry( + entry.getSource().toString(), + new org.openqa.selenium.logging.LogEntry( + fromCdpLevel(entry.getLevel()), + fromCdpTimestamp(entry.getTimestamp()), + entry.getText())); + }); + } + + private Level fromCdpLevel(LogEntry.Level level) { + switch (level.toString()) { + case "verbose": + return Level.FINEST; + + case "info": + return Level.INFO; + + case "warning": + return Level.WARNING; + + case "error": + return Level.SEVERE; + + default: + return Level.INFO; + } + } + + private long fromCdpTimestamp(Timestamp timestamp) { + try { + return Long.parseLong(timestamp.toString()); + } catch (NumberFormatException e) { + return System.currentTimeMillis(); + } + } +} diff --git a/java/src/org/openqa/selenium/devtools/v108/V108Network.java b/java/src/org/openqa/selenium/devtools/v108/V108Network.java new file mode 100644 index 0000000000000..21afebf9afad2 --- /dev/null +++ b/java/src/org/openqa/selenium/devtools/v108/V108Network.java @@ -0,0 +1,236 @@ +// 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.devtools.v108; + +import com.google.common.collect.ImmutableList; +import com.google.common.io.ByteStreams; +import org.openqa.selenium.UsernameAndPassword; +import org.openqa.selenium.devtools.Command; +import org.openqa.selenium.devtools.DevTools; +import org.openqa.selenium.devtools.DevToolsException; +import org.openqa.selenium.devtools.Event; +import org.openqa.selenium.devtools.idealized.Network; +import org.openqa.selenium.devtools.v108.fetch.Fetch; +import org.openqa.selenium.devtools.v108.fetch.model.AuthChallengeResponse; +import org.openqa.selenium.devtools.v108.fetch.model.AuthRequired; +import org.openqa.selenium.devtools.v108.fetch.model.HeaderEntry; +import org.openqa.selenium.devtools.v108.fetch.model.RequestPattern; +import org.openqa.selenium.devtools.v108.fetch.model.RequestPaused; +import org.openqa.selenium.devtools.v108.fetch.model.RequestStage; +import org.openqa.selenium.devtools.v108.network.model.Request; +import org.openqa.selenium.internal.Either; +import org.openqa.selenium.remote.http.HttpRequest; +import org.openqa.selenium.remote.http.HttpResponse; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.AbstractMap; +import java.util.Base64; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.logging.Logger; + +import static java.net.HttpURLConnection.HTTP_OK; + +public class V108Network extends Network { + + private static final Logger LOG = Logger.getLogger(V108Network.class.getName()); + + public V108Network(DevTools devTools) { + super(devTools); + } + + @Override + protected Command setUserAgentOverride(UserAgent userAgent) { + return org.openqa.selenium.devtools.v108.network.Network.setUserAgentOverride( + userAgent.userAgent(), userAgent.acceptLanguage(), userAgent.platform(), Optional.empty()); + } + + @Override + protected Command enableNetworkCaching() { + return org.openqa.selenium.devtools.v108.network.Network.setCacheDisabled(false); + } + + @Override + protected Command disableNetworkCaching() { + return org.openqa.selenium.devtools.v108.network.Network.setCacheDisabled(true); + } + + @Override + protected Command enableFetchForAllPatterns() { + return Fetch.enable( + Optional.of(ImmutableList.of( + new RequestPattern(Optional.of("*"), Optional.empty(), Optional.of(RequestStage.REQUEST)), + new RequestPattern(Optional.of("*"), Optional.empty(), + Optional.of(RequestStage.RESPONSE)))), + Optional.of(true)); + } + + @Override + protected Command disableFetch() { + return Fetch.disable(); + } + + @Override + protected Event authRequiredEvent() { + return Fetch.authRequired(); + } + + @Override + protected String getUriFrom(AuthRequired authRequired) { + return authRequired.getAuthChallenge().getOrigin(); + } + + @Override + protected Command continueWithAuth(AuthRequired authRequired, + UsernameAndPassword credentials) { + return Fetch.continueWithAuth( + authRequired.getRequestId(), + new AuthChallengeResponse( + AuthChallengeResponse.Response.PROVIDECREDENTIALS, + Optional.of(credentials.username()), + Optional.ofNullable(credentials.password()))); + } + + @Override + protected Command cancelAuth(AuthRequired authRequired) { + return Fetch.continueWithAuth( + authRequired.getRequestId(), + new AuthChallengeResponse(AuthChallengeResponse.Response.CANCELAUTH, Optional.empty(), + Optional.empty())); + } + + @Override + public Event requestPausedEvent() { + return Fetch.requestPaused(); + } + + @Override + public Either createSeMessages(RequestPaused pausedReq) { + if (pausedReq.getResponseStatusCode().isPresent() || pausedReq.getResponseErrorReason() + .isPresent()) { + String body; + boolean bodyIsBase64Encoded; + + try { + Fetch.GetResponseBodyResponse + base64Body = + devTools.send(Fetch.getResponseBody(pausedReq.getRequestId())); + body = base64Body.getBody(); + bodyIsBase64Encoded = + base64Body.getBase64Encoded() != null && base64Body.getBase64Encoded(); + } catch (DevToolsException e) { + // Redirects don't seem to have bodies + int code = pausedReq.getResponseStatusCode().orElse(HTTP_OK); + if (code < 300 && code > 399) { + LOG.warning("Unable to get body for request id " + pausedReq.getRequestId()); + } + + body = null; + bodyIsBase64Encoded = false; + } + + List> headers = new LinkedList<>(); + pausedReq.getResponseHeaders().ifPresent(resHeaders -> + resHeaders.forEach(header -> headers.add( + new AbstractMap.SimpleEntry<>(header.getName(), + header.getValue())))); + + HttpResponse res = createHttpResponse( + pausedReq.getResponseStatusCode(), + body, + bodyIsBase64Encoded, + headers); + + return Either.right(res); + } + + Request cdpReq = pausedReq.getRequest(); + + HttpRequest req = createHttpRequest( + cdpReq.getMethod(), + cdpReq.getUrl(), + cdpReq.getHeaders(), + cdpReq.getPostData()); + + return Either.left(req); + } + + @Override + protected String getRequestId(RequestPaused pausedReq) { + return pausedReq.getRequestId().toString(); + } + + @Override + protected Command continueWithoutModification(RequestPaused pausedRequest) { + return Fetch.continueRequest( + pausedRequest.getRequestId(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty()); + } + + @Override + protected Command continueRequest(RequestPaused pausedReq, HttpRequest req) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try (InputStream is = req.getContent().get()) { + ByteStreams.copy(is, bos); + } catch (IOException e) { + return continueWithoutModification(pausedReq); + } + + List headers = new LinkedList<>(); + req.getHeaderNames().forEach( + name -> req.getHeaders(name).forEach(value -> headers.add(new HeaderEntry(name, value)))); + + return Fetch.continueRequest( + pausedReq.getRequestId(), + Optional.empty(), + Optional.of(req.getMethod().toString()), + Optional.of(Base64.getEncoder().encodeToString(bos.toByteArray())), + Optional.of(headers), + Optional.empty()); + } + + @Override + protected Command fulfillRequest(RequestPaused pausedReq, HttpResponse res) { + List headers = new LinkedList<>(); + res.getHeaderNames().forEach( + name -> res.getHeaders(name).forEach(value -> headers.add(new HeaderEntry(name, value)))); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try (InputStream is = res.getContent().get()) { + ByteStreams.copy(is, bos); + } catch (IOException e) { + bos.reset(); + } + + return Fetch.fulfillRequest( + pausedReq.getRequestId(), + res.getStatus(), + Optional.of(headers), + Optional.empty(), + Optional.of(Base64.getEncoder().encodeToString(bos.toByteArray())), + Optional.empty()); + } +} diff --git a/java/src/org/openqa/selenium/devtools/v108/V108Target.java b/java/src/org/openqa/selenium/devtools/v108/V108Target.java new file mode 100644 index 0000000000000..322c35503cc34 --- /dev/null +++ b/java/src/org/openqa/selenium/devtools/v108/V108Target.java @@ -0,0 +1,110 @@ +// 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.devtools.v108; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import org.openqa.selenium.devtools.Command; +import org.openqa.selenium.devtools.ConverterFunctions; +import org.openqa.selenium.devtools.Event; +import org.openqa.selenium.devtools.idealized.browser.model.BrowserContextID; +import org.openqa.selenium.devtools.idealized.target.model.SessionID; +import org.openqa.selenium.devtools.idealized.target.model.TargetID; +import org.openqa.selenium.devtools.v108.target.Target; +import org.openqa.selenium.devtools.v108.target.model.TargetInfo; +import org.openqa.selenium.json.JsonInput; +import org.openqa.selenium.json.TypeToken; + +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public class V108Target implements org.openqa.selenium.devtools.idealized.target.Target { + + @Override + public Command detachFromTarget(Optional sessionId, + Optional targetId) { + return Target.detachFromTarget( + sessionId.map( + id -> new org.openqa.selenium.devtools.v108.target.model.SessionID(id.toString())), + targetId.map( + id -> new org.openqa.selenium.devtools.v108.target.model.TargetID(id.toString()))); + } + + @Override + public Command> getTargets() { + Function> mapper = ConverterFunctions.map( + "targetInfos", + new TypeToken>() { + }.getType()); + + return new Command<>( + Target.getTargets(Optional.empty()).getMethod(), + ImmutableMap.of(), + input -> { + List infos = mapper.apply(input); + return infos.stream() + .map(info -> new org.openqa.selenium.devtools.idealized.target.model.TargetInfo( + new TargetID(info.getTargetId().toString()), + info.getType(), + info.getTitle(), + info.getUrl(), + info.getAttached(), + info.getOpenerId().map(id -> new TargetID(id.toString())), + info.getBrowserContextId().map(id -> new BrowserContextID(id.toString())) + )) + .collect(ImmutableList.toImmutableList()); + }); + } + + @Override + public Command attachToTarget(TargetID targetId) { + Function mapper = + ConverterFunctions.map("sessionId", + org.openqa.selenium.devtools.v108.target.model.SessionID.class); + + return new Command<>( + "Target.attachToTarget", + ImmutableMap.of( + "targetId", + new org.openqa.selenium.devtools.v108.target.model.TargetID(targetId.toString()), + "flatten", true), + input -> { + org.openqa.selenium.devtools.v108.target.model.SessionID id = mapper.apply(input); + return new SessionID(id.toString()); + }); + } + + @Override + public Command setAutoAttach() { + return Target.setAutoAttach(true, false, Optional.of(true), Optional.empty()); + } + + @Override + public Event detached() { + return new Event<>( + "Target.detachedFromTarget", + input -> { + Function converter = + ConverterFunctions.map("targetId", + org.openqa.selenium.devtools.v108.target.model.TargetID.class); + return new TargetID(converter.apply(input).toString()); + } + ); + } +} diff --git a/java/src/org/openqa/selenium/devtools/versions.bzl b/java/src/org/openqa/selenium/devtools/versions.bzl index da8385f7d8316..05cebeaeae84c 100644 --- a/java/src/org/openqa/selenium/devtools/versions.bzl +++ b/java/src/org/openqa/selenium/devtools/versions.bzl @@ -1,8 +1,8 @@ CDP_VERSIONS = [ "v85", # Required by Firefox - "v105", "v106", "v107", + "v108", ] CDP_DEPS = ["//java/src/org/openqa/selenium/devtools/%s" % v for v in CDP_VERSIONS]