Skip to content

Commit

Permalink
[cdp] Try a new approach for adding new CDP versions
Browse files Browse the repository at this point in the history
  • Loading branch information
shs96c committed Sep 8, 2020
1 parent 106d0a8 commit 61e5794
Show file tree
Hide file tree
Showing 54 changed files with 1,289 additions and 1,842 deletions.
58 changes: 4 additions & 54 deletions java/client/src/org/openqa/selenium/chromium/ChromiumDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

package org.openqa.selenium.chromium;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.openqa.selenium.BuildInfo;
import org.openqa.selenium.Capabilities;
Expand All @@ -29,10 +28,7 @@
import org.openqa.selenium.devtools.CdpVersionFinder;
import org.openqa.selenium.devtools.Connection;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.DevToolsException;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.idealized.fetch.Fetch;
import org.openqa.selenium.devtools.idealized.fetch.model.RequestPattern;
import org.openqa.selenium.devtools.noop.NoOpCdpInfo;
import org.openqa.selenium.html5.LocalStorage;
import org.openqa.selenium.html5.Location;
Expand All @@ -52,12 +48,9 @@
import org.openqa.selenium.remote.html5.RemoteLocationContext;
import org.openqa.selenium.remote.html5.RemoteWebStorage;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.mobile.RemoteNetworkConnection;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
Expand Down Expand Up @@ -95,8 +88,6 @@ public class ChromiumDriver extends RemoteWebDriver implements
private final RemoteNetworkConnection networkConnection;
private final Optional<Connection> connection;
private final Optional<DevTools> devTools;
private final Map<Predicate<URI>, Supplier<Credentials>> allKnownCredentials = new LinkedHashMap<>();
private boolean authenticationInitialized = false;

protected ChromiumDriver(CommandExecutor commandExecutor, Capabilities capabilities, String capabilityKey) {
super(commandExecutor, capabilities);
Expand Down Expand Up @@ -127,7 +118,7 @@ protected ChromiumDriver(CommandExecutor commandExecutor, Capabilities capabilit
return new NoOpCdpInfo();
});

devTools = connection.map(conn -> new DevTools(cdpInfo.getDomains(), conn));
devTools = connection.map(conn -> new DevTools(cdpInfo::getDomains, conn));
}

@Override
Expand All @@ -140,57 +131,16 @@ public void setFileDetector(FileDetector detector) {
@Override
public <X> void onLogEvent(EventType<X> kind) {
Require.nonNull("Event type", kind);
kind.initializeLogger(this);
kind.initializeListener(this);
}

@Override
public void register(Predicate<URI> whenThisMatches, Supplier<Credentials> useTheseCredentials) {
Require.nonNull("Check to use to see how we should authenticate", whenThisMatches);
Require.nonNull("Credentials to use when authenticating", useTheseCredentials);

allKnownCredentials.put(whenThisMatches, useTheseCredentials);

if (!authenticationInitialized) {
DevTools devTools = this.devTools.orElseThrow(() -> new DevToolsException("Unable to make devtools connection"));
devTools.createSessionIfThereIsNotOne();

RequestPattern pattern = new RequestPattern(Optional.of("*"), Optional.empty());

Fetch fetch = devTools.getDomains().fetch();

// TODO: This will fight with NetworkInterceptor...
devTools.addListener(
fetch.requestPaused(),
requestPaused -> {
Optional<HttpRequest> maybeRequest = requestPaused.getRequest();
if (!maybeRequest.isPresent()) {
devTools.send(fetch.continueRequest(requestPaused.getRequestId()));
return;
}
devTools.send(fetch.continueRequest(requestPaused.getRequestId()));
});
devTools.addListener(
fetch.authRequired(),
authRequest -> {
try {
URI uri = new URI(authRequest.getChallenge().getOrigin());
Optional<Credentials> maybeCredentials = allKnownCredentials.entrySet().stream()
.filter(entry -> entry.getKey().test(uri))
.map(entry -> entry.getValue().get())
.findFirst();

if (!maybeCredentials.isPresent()) {
devTools.send(fetch.cancelAuth(authRequest.getRequestId()));
} else {
devTools.send(fetch.authorize(authRequest.getRequestId(), maybeCredentials.get()));
}
} catch (URISyntaxException e) {
throw new DevToolsException(e);
}
}
);
devTools.send(fetch.enable(Optional.of(ImmutableList.of(pattern)), true));
}
getDevTools().createSessionIfThereIsNotOne();
getDevTools().getDomains().network().addAuthHandler(whenThisMatches, useTheseCredentials);
}

@Override
Expand Down
3 changes: 1 addition & 2 deletions java/client/src/org/openqa/selenium/devtools/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ java_export(
[
"*.java",
"events/*.java",
"idealized/**/*.java",
],
exclude = PROTOTYPE_SOURCES + GENERATOR_SOURCES,
),
Expand All @@ -43,13 +44,11 @@ java_export(
],
exports = [
":devtools-prototypes",
"//java/client/src/org/openqa/selenium/devtools/idealized",
],
deps = [
":devtools-prototypes",
"//java:auto-service",
"//java/client/src/org/openqa/selenium:core",
"//java/client/src/org/openqa/selenium/devtools/idealized",
"//java/client/src/org/openqa/selenium/json",
"//java/client/src/org/openqa/selenium/remote",
artifact("com.google.guava:guava"),
Expand Down
11 changes: 6 additions & 5 deletions java/client/src/org/openqa/selenium/devtools/CdpInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
import org.openqa.selenium.devtools.idealized.Domains;
import org.openqa.selenium.internal.Require;

import java.util.function.Supplier;
import java.util.function.Function;

public abstract class CdpInfo implements Comparable<CdpInfo> {

private final int majorVersion;
private final Supplier<Domains> domains;
private final Function<DevTools, Domains> domains;

public CdpInfo(int majorVersion, Supplier<Domains> domains) {
public CdpInfo(int majorVersion, Function<DevTools, Domains> domains) {
this.majorVersion = majorVersion;
this.domains = Require.nonNull("Domain supplier", domains);
}
Expand All @@ -36,8 +36,9 @@ public int getMajorVersion() {
return majorVersion;
}

public Domains getDomains() {
return domains.get();
public Domains getDomains(DevTools devTools) {
Require.nonNull("DevTools", devTools);
return domains.apply(devTools);
}

@Override
Expand Down
5 changes: 3 additions & 2 deletions java/client/src/org/openqa/selenium/devtools/DevTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.function.Function;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

Expand All @@ -41,9 +42,9 @@ public class DevTools implements Closeable {
private final Connection connection;
private SessionID cdpSession = null;

public DevTools(Domains protocol, Connection connection) {
this.protocol = Require.nonNull("CDP protocol", protocol);
public DevTools(Function<DevTools, Domains> protocol, Connection connection) {
this.connection = Require.nonNull("WebSocket connection", connection);
this.protocol = Require.nonNull("CDP protocol", protocol).apply(this);
}

public Domains getDomains() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,14 @@
import org.openqa.selenium.logging.EventType;
import org.openqa.selenium.logging.HasLogEvents;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.function.Consumer;

import static org.openqa.selenium.json.Json.MAP_TYPE;

public class CdpEventTypes {

private static final WeakHashMap<WebDriver, Set<String>> PINNED_SCRIPTS = new WeakHashMap<>();
private static final Json JSON = new Json();

private CdpEventTypes() {
Expand All @@ -56,18 +52,13 @@ public void consume(ConsoleEvent event) {
}

@Override
public void initializeLogger(HasLogEvents loggable) {
public void initializeListener(HasLogEvents loggable) {
Require.precondition(loggable instanceof HasDevTools, "Loggable must implement HasDevTools");

DevTools tools = ((HasDevTools) loggable).getDevTools();
tools.createSession();
tools.createSessionIfThereIsNotOne();

tools.send(tools.getDomains().runtime().enable());
tools.addListener(
tools.getDomains().runtime().consoleAPICalled(),
event -> {
consume(new ConsoleEvent(event.getType(), event.getTimestamp(), event.getArgs()));
});
tools.getDomains().events().addConsoleListener(handler);
}
};
}
Expand Down Expand Up @@ -120,33 +111,22 @@ public void consume(Void event) {
}

@Override
public void initializeLogger(HasLogEvents loggable) {
public void initializeListener(HasLogEvents loggable) {
Require.precondition(loggable instanceof WebDriver, "Loggable must be a WebDriver");
Require.precondition(loggable instanceof HasDevTools, "Loggable must implement HasDevTools");

DevTools tools = ((HasDevTools) loggable).getDevTools();
tools.createSession();

WebDriver driver = (WebDriver) loggable;
Set<String> scripts = PINNED_SCRIPTS.computeIfAbsent(driver, ignored -> new HashSet<>());
if (!scripts.contains(script)) {
// Pin the script
tools.send(tools.getDomains().runtime().enable());
tools.send(tools.getDomains().runtime().addBinding("__webdriver_attribute"));

tools.send(tools.getDomains().page().enable());
tools.send(tools.getDomains().page().addScriptToEvaluateOnNewDocument(script));
tools.createSessionIfThereIsNotOne();

// And add the script to the current page
((JavascriptExecutor) driver).executeScript(script);
tools.getDomains().javascript().pin("__webdriver_attribute", script);

scripts.add(script);
}
WebDriver driver = (WebDriver) loggable;
// And add the script to the current page
((JavascriptExecutor) driver).executeScript(script);

tools.addListener(
tools.getDomains().runtime().bindingCalled(),
bindingCalled -> {
Map<String, Object> values = JSON.toType(bindingCalled.getPayload(), MAP_TYPE);
tools.getDomains().javascript().addBindingCalledListener(
(Consumer<String>) json -> {
Map<String, Object> values = JSON.toType(json, MAP_TYPE);
String id = (String) values.get("target");

List<WebElement> elements = driver.findElements(By.cssSelector(String.format("*[data-__webdriver_id='%s']", id)));
Expand All @@ -159,10 +139,8 @@ public void initializeLogger(HasLogEvents loggable) {
String.valueOf(values.get("oldValue")));
handler.accept(event);
}
}
);
});
}
};
}

}
16 changes: 0 additions & 16 deletions java/client/src/org/openqa/selenium/devtools/idealized/BUILD.bazel

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,25 @@

package org.openqa.selenium.devtools.idealized;

import org.openqa.selenium.devtools.idealized.fetch.Fetch;
import org.openqa.selenium.devtools.idealized.log.Log;
import org.openqa.selenium.devtools.idealized.page.Page;
import org.openqa.selenium.devtools.idealized.runtime.RuntimeDomain;
import org.openqa.selenium.devtools.idealized.target.Target;

import java.util.Map;

/**
* The idealized set of CDP domains that Selenium itself needs. Should you
* need domains from a specific version of the CDP, then depend upon that
* version of the CDP and use the domains directly.
*/
public interface Domains {

Fetch fetch();
Events<?> events();

Log log();
Javascript<?, ?> javascript();

Page page();
Network<?, ?> network();

Target target();

RuntimeDomain runtime();
Log log();
}
Loading

0 comments on commit 61e5794

Please sign in to comment.