Skip to content

Commit fc5509b

Browse files
committed
[java] cancel the pending responses while disabling network #12576
1 parent bbe2ac5 commit fc5509b

File tree

2 files changed

+38
-11
lines changed

2 files changed

+38
-11
lines changed

java/src/org/openqa/selenium/devtools/DevTools.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ public void close() {
6262

6363
public void disconnectSession() {
6464
if (cdpSession != null) {
65+
try {
66+
// ensure network interception does cancel the wait for responses
67+
getDomains().network().disable();
68+
} catch (Exception e) {
69+
// Exceptions should not prevent closing the connection and the web driver
70+
LOG.log(Level.WARNING, "Exception while disabling network", e);
71+
}
72+
6573
SessionID id = cdpSession;
6674
cdpSession = null;
6775
try {
@@ -71,7 +79,7 @@ public void disconnectSession() {
7179
timeout);
7280
} catch (Exception e) {
7381
// Exceptions should not prevent closing the connection and the web driver
74-
LOG.warning("Exception while detaching from target: " + e.getMessage());
82+
LOG.log(Level.WARNING, "Exception while detaching from target", e);
7583
}
7684
}
7785
}

java/src/org/openqa/selenium/devtools/idealized/Network.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.List;
3131
import java.util.Map;
3232
import java.util.Optional;
33+
import java.util.concurrent.CancellationException;
3334
import java.util.concurrent.CompletableFuture;
3435
import java.util.concurrent.ConcurrentHashMap;
3536
import java.util.concurrent.ExecutionException;
@@ -45,6 +46,7 @@
4546
import org.openqa.selenium.devtools.DevTools;
4647
import org.openqa.selenium.devtools.DevToolsException;
4748
import org.openqa.selenium.devtools.Event;
49+
import org.openqa.selenium.devtools.NetworkInterceptor;
4850
import org.openqa.selenium.internal.Either;
4951
import org.openqa.selenium.internal.Require;
5052
import org.openqa.selenium.remote.http.Contents;
@@ -57,21 +59,33 @@ public abstract class Network<AUTHREQUIRED, REQUESTPAUSED> {
5759

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

62+
private static final HttpResponse STOP_PROCESSING =
63+
new HttpResponse()
64+
.addHeader("Selenium-Interceptor", "Stop")
65+
.setContent(Contents.utf8String("Interception is stopped"));
66+
6067
private final Map<Predicate<URI>, Supplier<Credentials>> authHandlers = new LinkedHashMap<>();
6168
private final Filter defaultFilter = next -> next::execute;
6269
private volatile Filter filter = defaultFilter;
6370
protected final DevTools devTools;
6471

6572
private final AtomicBoolean fetchEnabled = new AtomicBoolean();
73+
private final Map<String, CompletableFuture<HttpResponse>> pendingResponses =
74+
new ConcurrentHashMap<>();
6675

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

7180
public void disable() {
7281
fetchEnabled.set(false);
73-
devTools.send(disableFetch());
74-
devTools.send(enableNetworkCaching());
82+
try {
83+
devTools.send(disableFetch());
84+
devTools.send(enableNetworkCaching());
85+
} finally {
86+
// we stopped the fetch we will not receive any pending responses
87+
pendingResponses.values().forEach(cf -> cf.cancel(false));
88+
}
7589

7690
synchronized (authHandlers) {
7791
authHandlers.clear();
@@ -183,8 +197,6 @@ public void prepareToInterceptTraffic() {
183197
devTools.send(cancelAuth(authRequired));
184198
});
185199

186-
Map<String, CompletableFuture<HttpResponse>> responses = new ConcurrentHashMap<>();
187-
188200
devTools.addListener(
189201
requestPausedEvent(),
190202
pausedRequest -> {
@@ -194,7 +206,7 @@ public void prepareToInterceptTraffic() {
194206

195207
if (message.isRight()) {
196208
HttpResponse res = message.right();
197-
CompletableFuture<HttpResponse> future = responses.remove(id);
209+
CompletableFuture<HttpResponse> future = pendingResponses.remove(id);
198210

199211
if (future == null) {
200212
devTools.send(continueWithoutModification(pausedRequest));
@@ -210,18 +222,22 @@ public void prepareToInterceptTraffic() {
210222
.andFinally(
211223
req -> {
212224
// Convert the selenium request to a CDP one and fulfill.
213-
214-
CompletableFuture<HttpResponse> res = new CompletableFuture<>();
215-
responses.put(id, res);
216-
217225
devTools.send(continueRequest(pausedRequest, req));
226+
CompletableFuture<HttpResponse> res = new CompletableFuture<>();
227+
// Save the future after the browser accepted the continueRequest
228+
pendingResponses.put(id, res);
218229

219230
// Wait for the CDP response and send that back.
220231
try {
221232
return res.get();
222233
} catch (InterruptedException e) {
223234
Thread.currentThread().interrupt();
224235
throw new WebDriverException(e);
236+
} catch (CancellationException e) {
237+
// The interception was intentionally stopped, network().disable() has
238+
// been called
239+
pendingResponses.remove(id);
240+
return STOP_PROCESSING;
225241
} catch (ExecutionException e) {
226242
if (fetchEnabled.get()) {
227243
LOG.log(WARNING, e, () -> "Unable to process request");
@@ -231,9 +247,12 @@ public void prepareToInterceptTraffic() {
231247
})
232248
.execute(message.left());
233249

234-
if ("Continue".equals(forBrowser.getHeader("Selenium-Interceptor"))) {
250+
if (forBrowser == NetworkInterceptor.PROCEED_WITH_REQUEST) {
235251
devTools.send(continueWithoutModification(pausedRequest));
236252
return;
253+
} else if (forBrowser == STOP_PROCESSING) {
254+
// The interception was intentionally stopped, network().disable() has been called
255+
return;
237256
}
238257

239258
devTools.send(fulfillRequest(pausedRequest, forBrowser));

0 commit comments

Comments
 (0)