3030import java .util .List ;
3131import java .util .Map ;
3232import java .util .Optional ;
33+ import java .util .concurrent .CancellationException ;
3334import java .util .concurrent .CompletableFuture ;
3435import java .util .concurrent .ConcurrentHashMap ;
3536import java .util .concurrent .ExecutionException ;
4546import org .openqa .selenium .devtools .DevTools ;
4647import org .openqa .selenium .devtools .DevToolsException ;
4748import org .openqa .selenium .devtools .Event ;
49+ import org .openqa .selenium .devtools .NetworkInterceptor ;
4850import org .openqa .selenium .internal .Either ;
4951import org .openqa .selenium .internal .Require ;
5052import 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