Implementation:SeleniumHQ Selenium DevTools AddListener
| Knowledge Sources | |
|---|---|
| Domains | Browser_Automation, DevTools, Event_Driven |
| Last Updated | 2026-02-11 00:00 GMT |
Overview
Concrete tool for subscribing to asynchronous CDP events with typed callbacks provided by the Selenium DevTools Java API.
Description
DevTools.addListener(Event<X>, Consumer<X>) registers a callback that is invoked whenever a matching CDP event arrives. The simple Consumer<X> form wraps the handler as a BiConsumer<Long, X> that discards the sequence number. The BiConsumer<Long, X> form provides the event sequence number, which is a globally auto-incrementing counter shared across all events and can be used to determine the relative order of events.
The Event<X> class encapsulates the event method name (e.g., "Network.requestWillBeSent") and a Function<JsonInput, X> mapper for deserializing the event parameters.
Internally, Connection.addListener() stores the handler in a HashMap<Event<?>, List<BiConsumer<Long, ?>>> protected by a ReentrantReadWriteLock. Event dispatch happens on daemon threads from a cached thread pool. The Connection.handle() method acquires the read lock using tryLock() (falling back to blocking lock()) to avoid deadlocks when event handlers wait for other events during processing.
clearListeners() removes all registered event listeners and also disables all CDP domains via getDomains().disableAll().
Usage
Register listeners after creating a CDP session and enabling the relevant domain. Handlers must be thread-safe as they execute on background threads. Call clearListeners() when monitoring is no longer needed.
Code Reference
Source Location
- Repository: Selenium
- File:
java/src/org/openqa/selenium/devtools/DevTools.java(L110-138) - File:
java/src/org/openqa/selenium/devtools/Event.java(L24-46) - File:
java/src/org/openqa/selenium/devtools/Connection.java(L212-233, L296-365)
Signature
// DevTools listener methods
public class DevTools implements Closeable {
public <X> void addListener(Event<X> event, Consumer<X> handler);
public <X> void addListener(Event<X> event, BiConsumer<Long, X> handler);
public void clearListeners();
}
// Event class
public class Event<X> {
public Event(String method, Function<JsonInput, X> mapper);
public String getMethod();
}
// Connection listener methods
public class Connection implements Closeable {
public <X> void addListener(Event<X> event, BiConsumer<Long, X> handler);
public void clearListeners();
}
Import
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.Event;
import java.util.function.Consumer;
import java.util.function.BiConsumer;
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| event | Event<X> | Yes | Typed CDP event descriptor with method name and JSON mapper |
| handler | Consumer<X> or BiConsumer<Long, X> | Yes | Callback invoked with deserialized event data (and optional sequence number) |
Outputs
| Name | Type | Description |
|---|---|---|
| (void) | void | Listener registered; handler invoked asynchronously on daemon background thread when matching events arrive |
Threading Model
| Aspect | Detail |
|---|---|
| Dispatch thread | Daemon threads from cached thread pool named "CDP Connection" |
| Lock strategy | ReadWriteLock; readers use tryLock() to avoid deadlock with writers |
| Sequence numbering | Global AtomicLong counter shared across all events |
| Handler safety | Handlers must be thread-safe; multiple events may dispatch concurrently |
Usage Examples
Listen for Network Requests
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v120.network.Network;
import org.openqa.selenium.devtools.v120.log.Log;
DevTools devTools = driver.getDevTools();
devTools.createSession();
// Enable domains first (required for events to fire)
devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty()));
devTools.send(Log.enable());
// Listen for network requests (simple Consumer form)
devTools.addListener(Network.requestWillBeSent(), request -> {
System.out.println("Request: " + request.getRequest().getUrl());
});
// Listen for console log entries
devTools.addListener(Log.entryAdded(), entry -> {
System.out.println("Log: " + entry.getText());
});
driver.get("https://example.com");
Listen with Sequence Number
// BiConsumer form provides sequence number for ordering
devTools.addListener(Network.responseReceived(), (sequence, response) -> {
System.out.println("Sequence #" + sequence + ": " + response.getResponse().getUrl());
});
Clear All Listeners
// Removes all listeners and disables all CDP domains
devTools.clearListeners();