Skip to content

Commit

Permalink
[java] cancel the pending responses while disabling network #12576
Browse files Browse the repository at this point in the history
  • Loading branch information
joerg1985 committed Aug 27, 2023
1 parent bbe2ac5 commit fc5509b
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 11 deletions.
10 changes: 9 additions & 1 deletion java/src/org/openqa/selenium/devtools/DevTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ public void close() {

public void disconnectSession() {
if (cdpSession != null) {
try {
// ensure network interception does cancel the wait for responses
getDomains().network().disable();
} catch (Exception e) {
// Exceptions should not prevent closing the connection and the web driver
LOG.log(Level.WARNING, "Exception while disabling network", e);
}

SessionID id = cdpSession;
cdpSession = null;
try {
Expand All @@ -71,7 +79,7 @@ public void disconnectSession() {
timeout);
} catch (Exception e) {
// Exceptions should not prevent closing the connection and the web driver
LOG.warning("Exception while detaching from target: " + e.getMessage());
LOG.log(Level.WARNING, "Exception while detaching from target", e);
}
}
}
Expand Down
39 changes: 29 additions & 10 deletions java/src/org/openqa/selenium/devtools/idealized/Network.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
Expand All @@ -45,6 +46,7 @@
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.DevToolsException;
import org.openqa.selenium.devtools.Event;
import org.openqa.selenium.devtools.NetworkInterceptor;
import org.openqa.selenium.internal.Either;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.remote.http.Contents;
Expand All @@ -57,21 +59,33 @@ public abstract class Network<AUTHREQUIRED, REQUESTPAUSED> {

private static final Logger LOG = Logger.getLogger(Network.class.getName());

private static final HttpResponse STOP_PROCESSING =
new HttpResponse()
.addHeader("Selenium-Interceptor", "Stop")
.setContent(Contents.utf8String("Interception is stopped"));

private final Map<Predicate<URI>, Supplier<Credentials>> authHandlers = new LinkedHashMap<>();
private final Filter defaultFilter = next -> next::execute;
private volatile Filter filter = defaultFilter;
protected final DevTools devTools;

private final AtomicBoolean fetchEnabled = new AtomicBoolean();
private final Map<String, CompletableFuture<HttpResponse>> pendingResponses =
new ConcurrentHashMap<>();

public Network(DevTools devtools) {
this.devTools = Require.nonNull("DevTools", devtools);
}

public void disable() {
fetchEnabled.set(false);
devTools.send(disableFetch());
devTools.send(enableNetworkCaching());
try {
devTools.send(disableFetch());
devTools.send(enableNetworkCaching());
} finally {
// we stopped the fetch we will not receive any pending responses
pendingResponses.values().forEach(cf -> cf.cancel(false));
}

synchronized (authHandlers) {
authHandlers.clear();
Expand Down Expand Up @@ -183,8 +197,6 @@ public void prepareToInterceptTraffic() {
devTools.send(cancelAuth(authRequired));
});

Map<String, CompletableFuture<HttpResponse>> responses = new ConcurrentHashMap<>();

devTools.addListener(
requestPausedEvent(),
pausedRequest -> {
Expand All @@ -194,7 +206,7 @@ public void prepareToInterceptTraffic() {

if (message.isRight()) {
HttpResponse res = message.right();
CompletableFuture<HttpResponse> future = responses.remove(id);
CompletableFuture<HttpResponse> future = pendingResponses.remove(id);

if (future == null) {
devTools.send(continueWithoutModification(pausedRequest));
Expand All @@ -210,18 +222,22 @@ public void prepareToInterceptTraffic() {
.andFinally(
req -> {
// Convert the selenium request to a CDP one and fulfill.

CompletableFuture<HttpResponse> res = new CompletableFuture<>();
responses.put(id, res);

devTools.send(continueRequest(pausedRequest, req));
CompletableFuture<HttpResponse> res = new CompletableFuture<>();
// Save the future after the browser accepted the continueRequest
pendingResponses.put(id, res);

// Wait for the CDP response and send that back.
try {
return res.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new WebDriverException(e);
} catch (CancellationException e) {
// The interception was intentionally stopped, network().disable() has
// been called
pendingResponses.remove(id);
return STOP_PROCESSING;
} catch (ExecutionException e) {
if (fetchEnabled.get()) {
LOG.log(WARNING, e, () -> "Unable to process request");
Expand All @@ -231,9 +247,12 @@ public void prepareToInterceptTraffic() {
})
.execute(message.left());

if ("Continue".equals(forBrowser.getHeader("Selenium-Interceptor"))) {
if (forBrowser == NetworkInterceptor.PROCEED_WITH_REQUEST) {
devTools.send(continueWithoutModification(pausedRequest));
return;
} else if (forBrowser == STOP_PROCESSING) {
// The interception was intentionally stopped, network().disable() has been called
return;
}

devTools.send(fulfillRequest(pausedRequest, forBrowser));
Expand Down

0 comments on commit fc5509b

Please sign in to comment.