From 4ad053312fdcc63fd0052a1a9611e999fa4e60c7 Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Wed, 29 Jun 2022 10:50:59 +0300 Subject: [PATCH] #10810 pick the right target using given window handle (#10811) * #10810 pick the right target using given window handle * #10810 leave parameterless methods createSession() and createSessionIfThereIsNotOne() for backward compatibility * #10810 log the exception properly * #10810 split code to smaller methods Co-authored-by: Diego Molina --- .../selenium/chromium/ChromiumDriver.java | 2 +- .../openqa/selenium/devtools/DevTools.java | 55 +++++++++++++------ .../selenium/devtools/NetworkInterceptor.java | 2 +- .../devtools/events/CdpEventTypes.java | 4 +- .../selenium/devtools/DevToolsTestBase.java | 2 +- .../grid/router/DistributedCdpTest.java | 2 +- 6 files changed, 45 insertions(+), 22 deletions(-) diff --git a/java/src/org/openqa/selenium/chromium/ChromiumDriver.java b/java/src/org/openqa/selenium/chromium/ChromiumDriver.java index 17e7069f10fd8..471a221a007fc 100644 --- a/java/src/org/openqa/selenium/chromium/ChromiumDriver.java +++ b/java/src/org/openqa/selenium/chromium/ChromiumDriver.java @@ -164,7 +164,7 @@ public void register(Predicate whenThisMatches, Supplier useTh Require.nonNull("Check to use to see how we should authenticate", whenThisMatches); Require.nonNull("Credentials to use when authenticating", useTheseCredentials); - getDevTools().createSessionIfThereIsNotOne(); + getDevTools().createSessionIfThereIsNotOne(getWindowHandle()); getDevTools().getDomains().network().addAuthHandler(whenThisMatches, useTheseCredentials); } diff --git a/java/src/org/openqa/selenium/devtools/DevTools.java b/java/src/org/openqa/selenium/devtools/DevTools.java index 4e8a331ffcc11..e8f80361c7043 100644 --- a/java/src/org/openqa/selenium/devtools/DevTools.java +++ b/java/src/org/openqa/selenium/devtools/DevTools.java @@ -17,6 +17,7 @@ package org.openqa.selenium.devtools; +import org.openqa.selenium.WebDriver; import org.openqa.selenium.devtools.idealized.Domains; import org.openqa.selenium.devtools.idealized.target.model.SessionID; import org.openqa.selenium.devtools.idealized.target.model.TargetID; @@ -32,10 +33,13 @@ import java.util.concurrent.TimeoutException; import java.util.function.Consumer; import java.util.function.Function; +import java.util.logging.Level; +import java.util.logging.Logger; import static java.util.concurrent.TimeUnit.MILLISECONDS; public class DevTools implements Closeable { + private static final Logger log = Logger.getLogger(DevTools.class.getName()); private final Domains protocol; private final Duration timeout = Duration.ofSeconds(10); @@ -85,22 +89,27 @@ public void clearListeners() { } public void createSessionIfThereIsNotOne() { + createSessionIfThereIsNotOne(null); + } + + public void createSessionIfThereIsNotOne(String windowHandle) { if (cdpSession == null) { - createSession(); + createSession(windowHandle); } } public void createSession() { - // Figure out the targets. - List infos = connection.sendAndWait(cdpSession, getDomains().target().getTargets(), timeout); + createSession(null); + } - // Grab the first "page" type, and glom on to that. - // TODO: Find out which one might be the current one - TargetID targetId = infos.stream() - .filter(info -> "page".equals(info.getType())) - .map(TargetInfo::getTargetId) - .findAny() - .orElseThrow(() -> new DevToolsException("Unable to find target id of a page")); + /** + * Create CDP session on given window/tab (aka target). + * If windowHandle is null, then _some_ target will be selected. It might be a problem only if you have multiple windows/tabs opened. + * + * @param windowHandle result of {@link WebDriver#getWindowHandle()}, optional. + */ + public void createSession(String windowHandle) { + TargetID targetId = findTarget(windowHandle); // Start the session. cdpSession = connection @@ -114,7 +123,7 @@ public void createSession() { // Clear the existing logs connection.send(cdpSession, getDomains().log().clear()) .exceptionally(t -> { - t.printStackTrace(); + log.log(Level.SEVERE, t.getMessage(), t); return null; }) ).get(timeout.toMillis(), MILLISECONDS); @@ -122,16 +131,30 @@ public void createSession() { Thread.currentThread().interrupt(); throw new IllegalStateException("Thread has been interrupted", e); } catch (ExecutionException e) { - Throwable cause = e; - if (e.getCause() != null) { - cause = e.getCause(); - } - throw new DevToolsException(cause); + throw new DevToolsException(unwrapCause(e)); } catch (TimeoutException e) { throw new org.openqa.selenium.TimeoutException(e); } } + private TargetID findTarget(String windowHandle) { + // Figure out the targets. + List infos = connection.sendAndWait(cdpSession, getDomains().target().getTargets(), timeout); + + // Grab the first "page" type, and glom on to that. + // Find out which one might be the current one (using given window handle like "CDwindow-24426957AC62D8BC83E58C184C38AF2D") + return infos.stream() + .filter(info -> "page".equals(info.getType())) + .map(TargetInfo::getTargetId) + .filter(id -> windowHandle == null || windowHandle.contains(id.toString())) + .findAny() + .orElseThrow(() -> new DevToolsException("Unable to find target id of a page")); + } + + private Throwable unwrapCause(ExecutionException e) { + return e.getCause() != null ? e.getCause() : e; + } + public SessionID getCdpSession() { return cdpSession; } diff --git a/java/src/org/openqa/selenium/devtools/NetworkInterceptor.java b/java/src/org/openqa/selenium/devtools/NetworkInterceptor.java index d76fb2118daaa..65820ddc6d1f3 100644 --- a/java/src/org/openqa/selenium/devtools/NetworkInterceptor.java +++ b/java/src/org/openqa/selenium/devtools/NetworkInterceptor.java @@ -91,7 +91,7 @@ public NetworkInterceptor(WebDriver driver, Filter filter) { } this.tools = ((HasDevTools) driver).getDevTools(); - tools.createSessionIfThereIsNotOne(); + tools.createSessionIfThereIsNotOne(driver.getWindowHandle()); tools.getDomains().network().interceptTrafficWith(filter); } diff --git a/java/src/org/openqa/selenium/devtools/events/CdpEventTypes.java b/java/src/org/openqa/selenium/devtools/events/CdpEventTypes.java index 960a2b289f805..da5245e5884ae 100644 --- a/java/src/org/openqa/selenium/devtools/events/CdpEventTypes.java +++ b/java/src/org/openqa/selenium/devtools/events/CdpEventTypes.java @@ -59,7 +59,7 @@ public void initializeListener(WebDriver webDriver) { Require.precondition(webDriver instanceof HasDevTools, "Loggable must implement HasDevTools"); DevTools tools = ((HasDevTools) webDriver).getDevTools(); - tools.createSessionIfThereIsNotOne(); + tools.createSessionIfThereIsNotOne(webDriver.getWindowHandle()); tools.getDomains().events().addConsoleListener(handler); } @@ -91,7 +91,7 @@ public void initializeListener(WebDriver driver) { Require.precondition(driver instanceof HasDevTools, "Loggable must implement HasDevTools"); DevTools tools = ((HasDevTools) driver).getDevTools(); - tools.createSessionIfThereIsNotOne(); + tools.createSessionIfThereIsNotOne(driver.getWindowHandle()); tools.getDomains().javascript().pin("__webdriver_attribute", script); diff --git a/java/test/org/openqa/selenium/devtools/DevToolsTestBase.java b/java/test/org/openqa/selenium/devtools/DevToolsTestBase.java index 163ea004a9357..14a7b925c200d 100644 --- a/java/test/org/openqa/selenium/devtools/DevToolsTestBase.java +++ b/java/test/org/openqa/selenium/devtools/DevToolsTestBase.java @@ -35,7 +35,7 @@ public void setUp() { assumeThat(isFirefoxVersionOlderThan(87, driver)).isFalse(); devTools = ((HasDevTools) driver).getDevTools(); - devTools.createSessionIfThereIsNotOne(); + devTools.createSessionIfThereIsNotOne(driver.getWindowHandle()); try { devTools.clearListeners(); diff --git a/java/test/org/openqa/selenium/grid/router/DistributedCdpTest.java b/java/test/org/openqa/selenium/grid/router/DistributedCdpTest.java index f2ebac0324262..03c0b7b8c3434 100644 --- a/java/test/org/openqa/selenium/grid/router/DistributedCdpTest.java +++ b/java/test/org/openqa/selenium/grid/router/DistributedCdpTest.java @@ -79,7 +79,7 @@ public void ensureBasicFunctionality() { driver = new Augmenter().augment(driver); try (DevTools devTools = ((HasDevTools) driver).getDevTools()) { - devTools.createSessionIfThereIsNotOne(); + devTools.createSessionIfThereIsNotOne(driver.getWindowHandle()); Network network = devTools.getDomains().network(); network.setUserAgent("Cheese-Browser 4000");