Java bindings for Chrome DevTools Protocol version 101, enabling browser automation and debugging capabilities through CDP integration
—
The target domain provides browser target and session management capabilities for handling multiple tabs, windows, browser contexts, and complex automation scenarios requiring fine-grained control over browser instances.
Target management implementation that provides commands for attaching to, detaching from, and monitoring browser targets.
/**
* Target management for browser contexts and sessions in CDP version 101
* Implements the Target interface for managing browser targets and sessions
*/
public class V101Target implements Target {
/**
* Creates a new target handler instance
*/
public V101Target();
/**
* Detach from a specific target
* @param sessionId Optional session ID to detach from
* @param targetId Optional target ID to detach from
* @return Command to execute the detachment operation
*/
public Command<Void> detachFromTarget(Optional<SessionID> sessionId, Optional<TargetID> targetId);
/**
* Get information about all available targets
* @return Command that returns a list of target information objects
*/
public Command<List<TargetInfo>> getTargets();
/**
* Attach to a specific target for debugging and control
* @param targetId ID of the target to attach to
* @return Command that returns a session ID for the attached target
*/
public Command<SessionID> attachToTarget(TargetID targetId);
/**
* Enable automatic attachment to new targets as they are created
* @return Command to enable auto-attach functionality
*/
public Command<Void> setAutoAttach();
/**
* Get an event stream for target detachment notifications
* @return Event that fires when targets are detached
*/
public Event<TargetID> detached();
}Usage Examples:
import org.openqa.selenium.devtools.v101.V101Target;
import org.openqa.selenium.devtools.idealized.target.model.*;
// Create target handler
V101Target target = new V101Target();
// Enable auto-attach for new targets
devTools.send(target.setAutoAttach());
// Get all available targets
List<TargetInfo> targets = devTools.send(target.getTargets());
System.out.println("Found " + targets.size() + " targets:");
for (TargetInfo targetInfo : targets) {
System.out.println("Target: " + targetInfo.getType() +
" - " + targetInfo.getTitle() +
" (" + targetInfo.getUrl() + ")");
}
// Find and attach to a specific page target
Optional<TargetInfo> pageTarget = targets.stream()
.filter(t -> "page".equals(t.getType()))
.filter(t -> t.getUrl().contains("example.com"))
.findFirst();
if (pageTarget.isPresent()) {
SessionID sessionId = devTools.send(target.attachToTarget(pageTarget.get().getTargetId()));
System.out.println("Attached to target with session ID: " + sessionId);
// Use the session for target-specific operations
// Detach when done
devTools.send(target.detachFromTarget(Optional.of(sessionId), Optional.of(pageTarget.get().getTargetId())));
}
// Listen for target detachment events
devTools.addListener(target.detached(), targetId -> {
System.out.println("Target detached: " + targetId);
});Information about a browser target including its type, state, and relationships.
/**
* Represents information about a browser target
* Contains target identification, type, state, and relationship data
*/
public class TargetInfo {
/**
* Get the unique identifier for this target
* @return TargetID uniquely identifying this target
*/
public TargetID getTargetId();
/**
* Get the type of target (page, background_page, service_worker, etc.)
* @return String representing the target type
*/
public String getType();
/**
* Get the title of the target (usually the page title)
* @return String containing the target title
*/
public String getTitle();
/**
* Get the URL associated with this target
* @return String containing the target URL
*/
public String getUrl();
/**
* Check if this target has an attached debugging client
* @return Boolean indicating if target is attached
*/
public Boolean getAttached();
/**
* Get the ID of the target that opened this target
* @return Optional TargetID of the opener target
*/
public Optional<TargetID> getOpenerId();
/**
* Get the browser context ID this target belongs to
* @return Optional BrowserContextID for the target's context
*/
public Optional<BrowserContextID> getBrowserContextId();
}Target Types:
"page" - Regular web page or tab"background_page" - Extension background page"service_worker" - Service worker instance"shared_worker" - Shared worker instance"browser" - Browser instance itself"other" - Other target typesUsage Example:
// Analyze target hierarchy and relationships
List<TargetInfo> targets = devTools.send(target.getTargets());
for (TargetInfo targetInfo : targets) {
System.out.println("=== Target Info ===");
System.out.println("ID: " + targetInfo.getTargetId());
System.out.println("Type: " + targetInfo.getType());
System.out.println("Title: " + targetInfo.getTitle());
System.out.println("URL: " + targetInfo.getUrl());
System.out.println("Attached: " + targetInfo.getAttached());
if (targetInfo.getOpenerId().isPresent()) {
System.out.println("Opened by: " + targetInfo.getOpenerId().get());
}
if (targetInfo.getBrowserContextId().isPresent()) {
System.out.println("Browser Context: " + targetInfo.getBrowserContextId().get());
}
System.out.println();
}Type-safe wrappers for various target-related identifiers.
/**
* Wrapper for target identifiers ensuring type safety
*/
public class TargetID {
/**
* Create a target ID from a string identifier
* @param id String representation of the target ID
*/
public TargetID(String id);
/**
* Get the string representation of this target ID
* @return String ID that can be used in CDP commands
*/
public String toString();
}
/**
* Wrapper for session identifiers ensuring type safety
*/
public class SessionID {
/**
* Create a session ID from a string identifier
* @param id String representation of the session ID
*/
public SessionID(String id);
/**
* Get the string representation of this session ID
* @return String ID that can be used in CDP commands
*/
public String toString();
}
/**
* Wrapper for browser context identifiers ensuring type safety
*/
public class BrowserContextID {
/**
* Create a browser context ID from a string identifier
* @param id String representation of the context ID
*/
public BrowserContextID(String id);
/**
* Get the string representation of this browser context ID
* @return String ID that can be used in CDP commands
*/
public String toString();
}The underlying CDP Target domain commands used by V101Target:
// From org.openqa.selenium.devtools.v101.target.Target
public static Command<GetTargetsResponse> getTargets();
public static Command<AttachToTargetResponse> attachToTarget(TargetID targetId, Optional<Boolean> flatten);
public static Command<Void> detachFromTarget(Optional<SessionID> sessionId, Optional<TargetID> targetId);
public static Command<Void> setAutoAttach(Boolean autoAttach, Boolean waitForDebuggerOnStart, Optional<Boolean> flatten);
public static Event<DetachedFromTargetEvent> detachedFromTarget();Response Types:
/**
* Response from Target.getTargets command
*/
public class GetTargetsResponse {
public List<TargetInfo> getTargetInfos();
}
/**
* Response from Target.attachToTarget command
*/
public class AttachToTargetResponse {
public SessionID getSessionId();
}
/**
* Event data when a target is detached
*/
public class DetachedFromTargetEvent {
public SessionID getSessionId();
public Optional<TargetID> getTargetId();
}// Manage multiple browser tabs/windows
List<TargetInfo> allTargets = devTools.send(target.getTargets());
// Filter for page targets only
List<TargetInfo> pageTargets = allTargets.stream()
.filter(t -> "page".equals(t.getType()))
.collect(Collectors.toList());
System.out.println("Found " + pageTargets.size() + " page targets");
// Attach to each page target for monitoring
Map<TargetID, SessionID> activeSessions = new HashMap<>();
for (TargetInfo pageTarget : pageTargets) {
try {
SessionID sessionId = devTools.send(target.attachToTarget(pageTarget.getTargetId()));
activeSessions.put(pageTarget.getTargetId(), sessionId);
System.out.println("Attached to: " + pageTarget.getTitle());
} catch (Exception e) {
System.err.println("Failed to attach to target " + pageTarget.getTargetId() + ": " + e.getMessage());
}
}
// Later, detach from all sessions
activeSessions.forEach((targetId, sessionId) -> {
try {
devTools.send(target.detachFromTarget(Optional.of(sessionId), Optional.of(targetId)));
System.out.println("Detached from target: " + targetId);
} catch (Exception e) {
System.err.println("Failed to detach from target " + targetId + ": " + e.getMessage());
}
});// Advanced target discovery with filtering and categorization
public class TargetManager {
private final V101Target target;
private final DevTools devTools;
public TargetManager(DevTools devTools) {
this.devTools = devTools;
this.target = new V101Target();
}
public List<TargetInfo> findPagesByURL(String urlPattern) {
List<TargetInfo> targets = devTools.send(target.getTargets());
return targets.stream()
.filter(t -> "page".equals(t.getType()))
.filter(t -> t.getUrl().matches(urlPattern))
.collect(Collectors.toList());
}
public List<TargetInfo> findTargetsByType(String targetType) {
List<TargetInfo> targets = devTools.send(target.getTargets());
return targets.stream()
.filter(t -> targetType.equals(t.getType()))
.collect(Collectors.toList());
}
public Map<String, List<TargetInfo>> categorizeTargets() {
List<TargetInfo> targets = devTools.send(target.getTargets());
return targets.stream()
.collect(Collectors.groupingBy(TargetInfo::getType));
}
public Optional<TargetInfo> findMainPage() {
List<TargetInfo> targets = devTools.send(target.getTargets());
return targets.stream()
.filter(t -> "page".equals(t.getType()))
.filter(t -> !t.getOpenerId().isPresent()) // No opener = main page
.findFirst();
}
}
// Usage
TargetManager targetManager = new TargetManager(devTools);
// Find all pages matching a pattern
List<TargetInfo> apiPages = targetManager.findPagesByURL(".*api\\.example\\.com.*");
// Categorize all targets
Map<String, List<TargetInfo>> targetsByType = targetManager.categorizeTargets();
targetsByType.forEach((type, targets) -> {
System.out.println(type + ": " + targets.size() + " targets");
});
// Find the main page
Optional<TargetInfo> mainPage = targetManager.findMainPage();
if (mainPage.isPresent()) {
System.out.println("Main page: " + mainPage.get().getTitle());
}// Set up automatic attachment monitoring for new targets
devTools.send(target.setAutoAttach());
// Listen for new targets being created and attached
devTools.addListener(target.detached(), targetId -> {
System.out.println("Target detached: " + targetId);
// Could trigger cleanup or reconnection logic here
handleTargetDetachment(targetId);
});
// Periodically check target status
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
try {
List<TargetInfo> currentTargets = devTools.send(target.getTargets());
System.out.println("Current target count: " + currentTargets.size());
// Monitor for unexpected target changes
long pageCount = currentTargets.stream()
.filter(t -> "page".equals(t.getType()))
.count();
if (pageCount == 0) {
System.err.println("Warning: No page targets found!");
}
} catch (Exception e) {
System.err.println("Error checking targets: " + e.getMessage());
}
}, 0, 5, TimeUnit.SECONDS);// Robust target management with error handling
public class RobustTargetManager {
private final V101Target target;
private final DevTools devTools;
private final Set<SessionID> activeSessions = ConcurrentHashMap.newKeySet();
public SessionID attachToTargetSafely(TargetID targetId) {
try {
SessionID sessionId = devTools.send(target.attachToTarget(targetId));
activeSessions.add(sessionId);
return sessionId;
} catch (Exception e) {
System.err.println("Failed to attach to target " + targetId + ": " + e.getMessage());
return null;
}
}
public void detachFromTargetSafely(SessionID sessionId, TargetID targetId) {
try {
devTools.send(target.detachFromTarget(Optional.of(sessionId), Optional.of(targetId)));
activeSessions.remove(sessionId);
} catch (Exception e) {
System.err.println("Failed to detach from target " + targetId + ": " + e.getMessage());
}
}
public void cleanupAllSessions() {
for (SessionID sessionId : activeSessions) {
try {
devTools.send(target.detachFromTarget(Optional.of(sessionId), Optional.empty()));
} catch (Exception e) {
System.err.println("Error during cleanup of session " + sessionId + ": " + e.getMessage());
}
}
activeSessions.clear();
}
public List<TargetInfo> getTargetsSafely() {
try {
return devTools.send(target.getTargets());
} catch (Exception e) {
System.err.println("Error getting targets: " + e.getMessage());
return Collections.emptyList();
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-seleniumhq-selenium--selenium-devtools-v101