CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-seleniumhq-selenium--selenium-devtools-v102

Java bindings for Chrome DevTools Protocol version 102, providing programmatic access to Chrome browser debugging and automation capabilities

Pending
Overview
Eval results
Files

target-management.mddocs/

Target Management

Manages browser targets (tabs, windows, workers), attachment/detachment operations, and target information retrieval. This domain enables control over multiple browser contexts and automation of complex multi-target scenarios.

Capabilities

V102Target Class

Main class for browser target management. Implements the idealized Target interface to provide v102-specific implementations for target operations and information retrieval.

/**
 * Manages browser targets (tabs, windows, workers)
 */
public class V102Target implements org.openqa.selenium.devtools.idealized.target.Target {
    /**
     * Detaches from a specific target using session ID or target ID
     * @param sessionId Optional session identifier for the target connection
     * @param targetId Optional target identifier to detach from
     * @return Command to detach from target
     */
    public Command<Void> detachFromTarget(Optional<SessionID> sessionId, Optional<TargetID> targetId);
    
    /**
     * Retrieves information about all available targets
     * @return Command returning list of target information objects
     */
    public Command<List<org.openqa.selenium.devtools.idealized.target.model.TargetInfo>> getTargets();
    
    /**
     * Attaches to a specific target for DevTools communication
     * @param targetId Target identifier to attach to
     * @return Command returning session ID for the new attachment
     */
    public Command<SessionID> attachToTarget(TargetID targetId);
    
    /**
     * Sets automatic attachment for new targets as they are created
     * Enables automatic DevTools connection to new tabs/windows
     * @return Command to enable auto-attach for new targets
     */
    public Command<Void> setAutoAttach();
    
    /**
     * Returns the target detached event for monitoring target disconnections
     * @return Event for target detachment notifications
     */
    public Event<TargetID> detached();
}

Usage Examples:

Basic Target Discovery

import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v102.V102Domains;
import org.openqa.selenium.devtools.idealized.target.model.TargetInfo;
import org.openqa.selenium.devtools.idealized.target.model.TargetID;
import org.openqa.selenium.devtools.idealized.target.model.SessionID;
import java.util.List;

// Setup
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
V102Domains domains = new V102Domains(devTools);

// Get all available targets
List<TargetInfo> targets = devTools.send(domains.target().getTargets());

System.out.println("Available targets:");
for (TargetInfo target : targets) {
    System.out.println(String.format(
        "Target: %s - %s (%s) - %s",
        target.getTargetId(),
        target.getTitle(),
        target.getType(),
        target.getUrl()
    ));
}

// Find page targets
targets.stream()
    .filter(target -> "page".equals(target.getType()))
    .forEach(target -> {
        System.out.println("Page target: " + target.getTitle() + " - " + target.getUrl());
    });

Target Attachment and Communication

// Attach to specific targets for independent communication
List<TargetInfo> targets = devTools.send(domains.target().getTargets());

for (TargetInfo target : targets) {
    if ("page".equals(target.getType()) && !target.getAttached()) {
        // Attach to unattached page targets
        SessionID sessionId = devTools.send(domains.target().attachToTarget(target.getTargetId()));
        System.out.println("Attached to target " + target.getTargetId() + " with session " + sessionId);
        
        // Now you can send commands to this specific target using the sessionId
        // (This requires more advanced DevTools session management)
    }
}

Auto-Attach for New Targets

// Enable automatic attachment to new targets
devTools.send(domains.target().setAutoAttach());

// Listen for target detachment events
devTools.addListener(domains.target().detached(), (targetId) -> {
    System.out.println("Target detached: " + targetId);
});

// Open new tab - will be automatically attached
driver.executeScript("window.open('https://example.com', '_blank');");

// List targets again to see the new one
List<TargetInfo> updatedTargets = devTools.send(domains.target().getTargets());
System.out.println("Targets after opening new tab: " + updatedTargets.size());

Multi-Target Management

import java.util.Map;
import java.util.HashMap;

// Track attached targets and their sessions
Map<TargetID, SessionID> attachedTargets = new HashMap<>();

// Get initial targets
List<TargetInfo> targets = devTools.send(domains.target().getTargets());

// Attach to all page targets
for (TargetInfo target : targets) {
    if ("page".equals(target.getType()) && !target.getAttached()) {
        try {
            SessionID sessionId = devTools.send(domains.target().attachToTarget(target.getTargetId()));
            attachedTargets.put(target.getTargetId(), sessionId);
            System.out.println("Attached to: " + target.getTitle());
        } catch (Exception e) {
            System.err.println("Failed to attach to target " + target.getTargetId() + ": " + e.getMessage());
        }
    }
}

// Monitor for target detachment
devTools.addListener(domains.target().detached(), (targetId) -> {
    if (attachedTargets.containsKey(targetId)) {
        SessionID sessionId = attachedTargets.remove(targetId);
        System.out.println("Target " + targetId + " detached (was session " + sessionId + ")");
    }
});

// Detach from specific targets when done
for (Map.Entry<TargetID, SessionID> entry : attachedTargets.entrySet()) {
    devTools.send(domains.target().detachFromTarget(
        Optional.of(entry.getValue()),
        Optional.of(entry.getKey())
    ));
}

Target Filtering and Selection

import java.util.Optional;

// Find specific types of targets
List<TargetInfo> targets = devTools.send(domains.target().getTargets());

// Find the main page target
Optional<TargetInfo> mainPage = targets.stream()
    .filter(target -> "page".equals(target.getType()))
    .filter(target -> target.getUrl().startsWith("https://"))
    .findFirst();

if (mainPage.isPresent()) {
    System.out.println("Main page: " + mainPage.get().getTitle());
}

// Find service worker targets
List<TargetInfo> serviceWorkers = targets.stream()
    .filter(target -> "service_worker".equals(target.getType()))
    .collect(Collectors.toList());

System.out.println("Service workers: " + serviceWorkers.size());

// Find background pages (extensions)
List<TargetInfo> backgroundPages = targets.stream()
    .filter(target -> "background_page".equals(target.getType()))
    .collect(Collectors.toList());

System.out.println("Background pages: " + backgroundPages.size());

CDP Protocol Classes

The V102Target class interacts with generated CDP protocol classes:

Target Domain

// Generated CDP target classes (available at runtime)
class Target {
    static Command<GetTargetsResponse> getTargets();
    static Command<AttachToTargetResponse> attachToTarget(TargetID targetId, boolean flatten);
    static Command<Void> detachFromTarget(Optional<SessionID> sessionId, Optional<TargetID> targetId);
    static Command<Void> setAutoAttach(boolean autoAttach, boolean waitForDebuggerOnStart, Optional<Boolean> flatten);
    static Event<DetachedFromTargetEvent> detachedFromTarget();
}

// Target information from CDP
class TargetInfo {
    TargetID getTargetId();
    String getType();
    String getTitle();
    String getUrl();
    boolean getAttached();
    Optional<TargetID> getOpenerId();
    Optional<BrowserContextID> getBrowserContextId();
}

// Target and session identifiers
class TargetID {
    TargetID(String id);
    String toString();
}

class SessionID {
    SessionID(String id);
    String toString();
}

class BrowserContextID {
    BrowserContextID(String id);
    String toString();
}

Target Event Data

// Detachment event data
class DetachedFromTargetEvent {
    Optional<SessionID> getSessionId();
    Optional<TargetID> getTargetId();
}

High-Level Target Types

Different types of targets you may encounter:

  • page: Regular web pages and tabs
  • service_worker: Service worker instances
  • shared_worker: Shared worker instances
  • background_page: Extension background pages
  • webview: Embedded webview instances
  • iframe: Frame targets (when site isolation is enabled)
  • other: Other miscellaneous targets

Target Management Patterns

Target Lifecycle Monitoring

// Monitor complete target lifecycle
devTools.send(domains.target().setAutoAttach());

// Track target creation through getTargets polling
Set<TargetID> knownTargets = new HashSet<>();
List<TargetInfo> initialTargets = devTools.send(domains.target().getTargets());
initialTargets.forEach(target -> knownTargets.add(target.getTargetId()));

// Listen for detachment
devTools.addListener(domains.target().detached(), (targetId) -> {
    knownTargets.remove(targetId);
    System.out.println("Target lifecycle ended: " + targetId);
});

// Periodically check for new targets
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
    try {
        List<TargetInfo> currentTargets = devTools.send(domains.target().getTargets());
        for (TargetInfo target : currentTargets) {
            if (!knownTargets.contains(target.getTargetId())) {
                knownTargets.add(target.getTargetId());
                System.out.println("New target detected: " + target.getTitle());
            }
        }
    } catch (Exception e) {
        System.err.println("Error checking targets: " + e.getMessage());
    }
}, 1, 1, TimeUnit.SECONDS);

Selective Target Attachment

// Attach only to specific target types or URLs
List<TargetInfo> targets = devTools.send(domains.target().getTargets());

for (TargetInfo target : targets) {
    boolean shouldAttach = false;
    
    // Attach to main application pages
    if ("page".equals(target.getType()) && 
        target.getUrl().contains("myapp.com")) {
        shouldAttach = true;
    }
    
    // Attach to service workers for the application
    if ("service_worker".equals(target.getType()) && 
        target.getUrl().contains("myapp.com")) {
        shouldAttach = true;
    }
    
    if (shouldAttach && !target.getAttached()) {
        try {
            SessionID sessionId = devTools.send(domains.target().attachToTarget(target.getTargetId()));
            System.out.println("Attached to " + target.getType() + ": " + target.getTitle());
        } catch (Exception e) {
            System.err.println("Failed to attach to target: " + e.getMessage());
        }
    }
}

Target Information Analysis

// Analyze target relationships and hierarchy
List<TargetInfo> targets = devTools.send(domains.target().getTargets());

// Group targets by opener (parent-child relationships)
Map<Optional<TargetID>, List<TargetInfo>> targetsByOpener = targets.stream()
    .collect(Collectors.groupingBy(TargetInfo::getOpenerId));

// Print target hierarchy
targetsByOpener.forEach((openerId, targetList) -> {
    if (openerId.isPresent()) {
        System.out.println("Targets opened by " + openerId.get() + ":");
    } else {
        System.out.println("Root targets:");
    }
    
    targetList.forEach(target -> {
        System.out.println("  " + target.getType() + ": " + target.getTitle());
    });
});

// Find browser context information
targets.forEach(target -> {
    target.getBrowserContextId().ifPresent(contextId -> {
        System.out.println("Target " + target.getTargetId() + " in context " + contextId);
    });
});

Error Handling in Target Operations

// Robust target attachment with error handling
public SessionID safeAttachToTarget(TargetID targetId) {
    try {
        // Verify target still exists
        List<TargetInfo> targets = devTools.send(domains.target().getTargets());
        boolean targetExists = targets.stream()
            .anyMatch(target -> target.getTargetId().equals(targetId));
        
        if (!targetExists) {
            throw new IllegalArgumentException("Target " + targetId + " no longer exists");
        }
        
        // Attempt attachment
        SessionID sessionId = devTools.send(domains.target().attachToTarget(targetId));
        System.out.println("Successfully attached to target " + targetId);
        return sessionId;
        
    } catch (Exception e) {
        System.err.println("Failed to attach to target " + targetId + ": " + e.getMessage());
        throw new RuntimeException("Target attachment failed", e);
    }
}

// Safe detachment
public void safeDetachFromTarget(SessionID sessionId, TargetID targetId) {
    try {
        devTools.send(domains.target().detachFromTarget(
            Optional.of(sessionId),
            Optional.of(targetId)
        ));
        System.out.println("Successfully detached from target " + targetId);
    } catch (Exception e) {
        System.err.println("Failed to detach from target " + targetId + ": " + e.getMessage());
        // Continue execution - detachment failures are often not critical
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-seleniumhq-selenium--selenium-devtools-v102

docs

console-logging.md

domain-management.md

index.md

javascript-execution.md

network-operations.md

runtime-events.md

target-management.md

tile.json