0
# Target Management
1
2
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.
3
4
## Capabilities
5
6
### V102Target Class
7
8
Main class for browser target management. Implements the idealized Target interface to provide v102-specific implementations for target operations and information retrieval.
9
10
```java { .api }
11
/**
12
* Manages browser targets (tabs, windows, workers)
13
*/
14
public class V102Target implements org.openqa.selenium.devtools.idealized.target.Target {
15
/**
16
* Detaches from a specific target using session ID or target ID
17
* @param sessionId Optional session identifier for the target connection
18
* @param targetId Optional target identifier to detach from
19
* @return Command to detach from target
20
*/
21
public Command<Void> detachFromTarget(Optional<SessionID> sessionId, Optional<TargetID> targetId);
22
23
/**
24
* Retrieves information about all available targets
25
* @return Command returning list of target information objects
26
*/
27
public Command<List<org.openqa.selenium.devtools.idealized.target.model.TargetInfo>> getTargets();
28
29
/**
30
* Attaches to a specific target for DevTools communication
31
* @param targetId Target identifier to attach to
32
* @return Command returning session ID for the new attachment
33
*/
34
public Command<SessionID> attachToTarget(TargetID targetId);
35
36
/**
37
* Sets automatic attachment for new targets as they are created
38
* Enables automatic DevTools connection to new tabs/windows
39
* @return Command to enable auto-attach for new targets
40
*/
41
public Command<Void> setAutoAttach();
42
43
/**
44
* Returns the target detached event for monitoring target disconnections
45
* @return Event for target detachment notifications
46
*/
47
public Event<TargetID> detached();
48
}
49
```
50
51
**Usage Examples:**
52
53
### Basic Target Discovery
54
55
```java
56
import org.openqa.selenium.chrome.ChromeDriver;
57
import org.openqa.selenium.devtools.DevTools;
58
import org.openqa.selenium.devtools.v102.V102Domains;
59
import org.openqa.selenium.devtools.idealized.target.model.TargetInfo;
60
import org.openqa.selenium.devtools.idealized.target.model.TargetID;
61
import org.openqa.selenium.devtools.idealized.target.model.SessionID;
62
import java.util.List;
63
64
// Setup
65
ChromeDriver driver = new ChromeDriver();
66
DevTools devTools = driver.getDevTools();
67
devTools.createSession();
68
V102Domains domains = new V102Domains(devTools);
69
70
// Get all available targets
71
List<TargetInfo> targets = devTools.send(domains.target().getTargets());
72
73
System.out.println("Available targets:");
74
for (TargetInfo target : targets) {
75
System.out.println(String.format(
76
"Target: %s - %s (%s) - %s",
77
target.getTargetId(),
78
target.getTitle(),
79
target.getType(),
80
target.getUrl()
81
));
82
}
83
84
// Find page targets
85
targets.stream()
86
.filter(target -> "page".equals(target.getType()))
87
.forEach(target -> {
88
System.out.println("Page target: " + target.getTitle() + " - " + target.getUrl());
89
});
90
```
91
92
### Target Attachment and Communication
93
94
```java
95
// Attach to specific targets for independent communication
96
List<TargetInfo> targets = devTools.send(domains.target().getTargets());
97
98
for (TargetInfo target : targets) {
99
if ("page".equals(target.getType()) && !target.getAttached()) {
100
// Attach to unattached page targets
101
SessionID sessionId = devTools.send(domains.target().attachToTarget(target.getTargetId()));
102
System.out.println("Attached to target " + target.getTargetId() + " with session " + sessionId);
103
104
// Now you can send commands to this specific target using the sessionId
105
// (This requires more advanced DevTools session management)
106
}
107
}
108
```
109
110
### Auto-Attach for New Targets
111
112
```java
113
// Enable automatic attachment to new targets
114
devTools.send(domains.target().setAutoAttach());
115
116
// Listen for target detachment events
117
devTools.addListener(domains.target().detached(), (targetId) -> {
118
System.out.println("Target detached: " + targetId);
119
});
120
121
// Open new tab - will be automatically attached
122
driver.executeScript("window.open('https://example.com', '_blank');");
123
124
// List targets again to see the new one
125
List<TargetInfo> updatedTargets = devTools.send(domains.target().getTargets());
126
System.out.println("Targets after opening new tab: " + updatedTargets.size());
127
```
128
129
### Multi-Target Management
130
131
```java
132
import java.util.Map;
133
import java.util.HashMap;
134
135
// Track attached targets and their sessions
136
Map<TargetID, SessionID> attachedTargets = new HashMap<>();
137
138
// Get initial targets
139
List<TargetInfo> targets = devTools.send(domains.target().getTargets());
140
141
// Attach to all page targets
142
for (TargetInfo target : targets) {
143
if ("page".equals(target.getType()) && !target.getAttached()) {
144
try {
145
SessionID sessionId = devTools.send(domains.target().attachToTarget(target.getTargetId()));
146
attachedTargets.put(target.getTargetId(), sessionId);
147
System.out.println("Attached to: " + target.getTitle());
148
} catch (Exception e) {
149
System.err.println("Failed to attach to target " + target.getTargetId() + ": " + e.getMessage());
150
}
151
}
152
}
153
154
// Monitor for target detachment
155
devTools.addListener(domains.target().detached(), (targetId) -> {
156
if (attachedTargets.containsKey(targetId)) {
157
SessionID sessionId = attachedTargets.remove(targetId);
158
System.out.println("Target " + targetId + " detached (was session " + sessionId + ")");
159
}
160
});
161
162
// Detach from specific targets when done
163
for (Map.Entry<TargetID, SessionID> entry : attachedTargets.entrySet()) {
164
devTools.send(domains.target().detachFromTarget(
165
Optional.of(entry.getValue()),
166
Optional.of(entry.getKey())
167
));
168
}
169
```
170
171
### Target Filtering and Selection
172
173
```java
174
import java.util.Optional;
175
176
// Find specific types of targets
177
List<TargetInfo> targets = devTools.send(domains.target().getTargets());
178
179
// Find the main page target
180
Optional<TargetInfo> mainPage = targets.stream()
181
.filter(target -> "page".equals(target.getType()))
182
.filter(target -> target.getUrl().startsWith("https://"))
183
.findFirst();
184
185
if (mainPage.isPresent()) {
186
System.out.println("Main page: " + mainPage.get().getTitle());
187
}
188
189
// Find service worker targets
190
List<TargetInfo> serviceWorkers = targets.stream()
191
.filter(target -> "service_worker".equals(target.getType()))
192
.collect(Collectors.toList());
193
194
System.out.println("Service workers: " + serviceWorkers.size());
195
196
// Find background pages (extensions)
197
List<TargetInfo> backgroundPages = targets.stream()
198
.filter(target -> "background_page".equals(target.getType()))
199
.collect(Collectors.toList());
200
201
System.out.println("Background pages: " + backgroundPages.size());
202
```
203
204
## CDP Protocol Classes
205
206
The V102Target class interacts with generated CDP protocol classes:
207
208
### Target Domain
209
210
```java { .api }
211
// Generated CDP target classes (available at runtime)
212
class Target {
213
static Command<GetTargetsResponse> getTargets();
214
static Command<AttachToTargetResponse> attachToTarget(TargetID targetId, boolean flatten);
215
static Command<Void> detachFromTarget(Optional<SessionID> sessionId, Optional<TargetID> targetId);
216
static Command<Void> setAutoAttach(boolean autoAttach, boolean waitForDebuggerOnStart, Optional<Boolean> flatten);
217
static Event<DetachedFromTargetEvent> detachedFromTarget();
218
}
219
220
// Target information from CDP
221
class TargetInfo {
222
TargetID getTargetId();
223
String getType();
224
String getTitle();
225
String getUrl();
226
boolean getAttached();
227
Optional<TargetID> getOpenerId();
228
Optional<BrowserContextID> getBrowserContextId();
229
}
230
231
// Target and session identifiers
232
class TargetID {
233
TargetID(String id);
234
String toString();
235
}
236
237
class SessionID {
238
SessionID(String id);
239
String toString();
240
}
241
242
class BrowserContextID {
243
BrowserContextID(String id);
244
String toString();
245
}
246
```
247
248
### Target Event Data
249
250
```java { .api }
251
// Detachment event data
252
class DetachedFromTargetEvent {
253
Optional<SessionID> getSessionId();
254
Optional<TargetID> getTargetId();
255
}
256
```
257
258
### High-Level Target Types
259
260
Different types of targets you may encounter:
261
262
- **page**: Regular web pages and tabs
263
- **service_worker**: Service worker instances
264
- **shared_worker**: Shared worker instances
265
- **background_page**: Extension background pages
266
- **webview**: Embedded webview instances
267
- **iframe**: Frame targets (when site isolation is enabled)
268
- **other**: Other miscellaneous targets
269
270
## Target Management Patterns
271
272
### Target Lifecycle Monitoring
273
274
```java
275
// Monitor complete target lifecycle
276
devTools.send(domains.target().setAutoAttach());
277
278
// Track target creation through getTargets polling
279
Set<TargetID> knownTargets = new HashSet<>();
280
List<TargetInfo> initialTargets = devTools.send(domains.target().getTargets());
281
initialTargets.forEach(target -> knownTargets.add(target.getTargetId()));
282
283
// Listen for detachment
284
devTools.addListener(domains.target().detached(), (targetId) -> {
285
knownTargets.remove(targetId);
286
System.out.println("Target lifecycle ended: " + targetId);
287
});
288
289
// Periodically check for new targets
290
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
291
scheduler.scheduleAtFixedRate(() -> {
292
try {
293
List<TargetInfo> currentTargets = devTools.send(domains.target().getTargets());
294
for (TargetInfo target : currentTargets) {
295
if (!knownTargets.contains(target.getTargetId())) {
296
knownTargets.add(target.getTargetId());
297
System.out.println("New target detected: " + target.getTitle());
298
}
299
}
300
} catch (Exception e) {
301
System.err.println("Error checking targets: " + e.getMessage());
302
}
303
}, 1, 1, TimeUnit.SECONDS);
304
```
305
306
### Selective Target Attachment
307
308
```java
309
// Attach only to specific target types or URLs
310
List<TargetInfo> targets = devTools.send(domains.target().getTargets());
311
312
for (TargetInfo target : targets) {
313
boolean shouldAttach = false;
314
315
// Attach to main application pages
316
if ("page".equals(target.getType()) &&
317
target.getUrl().contains("myapp.com")) {
318
shouldAttach = true;
319
}
320
321
// Attach to service workers for the application
322
if ("service_worker".equals(target.getType()) &&
323
target.getUrl().contains("myapp.com")) {
324
shouldAttach = true;
325
}
326
327
if (shouldAttach && !target.getAttached()) {
328
try {
329
SessionID sessionId = devTools.send(domains.target().attachToTarget(target.getTargetId()));
330
System.out.println("Attached to " + target.getType() + ": " + target.getTitle());
331
} catch (Exception e) {
332
System.err.println("Failed to attach to target: " + e.getMessage());
333
}
334
}
335
}
336
```
337
338
### Target Information Analysis
339
340
```java
341
// Analyze target relationships and hierarchy
342
List<TargetInfo> targets = devTools.send(domains.target().getTargets());
343
344
// Group targets by opener (parent-child relationships)
345
Map<Optional<TargetID>, List<TargetInfo>> targetsByOpener = targets.stream()
346
.collect(Collectors.groupingBy(TargetInfo::getOpenerId));
347
348
// Print target hierarchy
349
targetsByOpener.forEach((openerId, targetList) -> {
350
if (openerId.isPresent()) {
351
System.out.println("Targets opened by " + openerId.get() + ":");
352
} else {
353
System.out.println("Root targets:");
354
}
355
356
targetList.forEach(target -> {
357
System.out.println(" " + target.getType() + ": " + target.getTitle());
358
});
359
});
360
361
// Find browser context information
362
targets.forEach(target -> {
363
target.getBrowserContextId().ifPresent(contextId -> {
364
System.out.println("Target " + target.getTargetId() + " in context " + contextId);
365
});
366
});
367
```
368
369
### Error Handling in Target Operations
370
371
```java
372
// Robust target attachment with error handling
373
public SessionID safeAttachToTarget(TargetID targetId) {
374
try {
375
// Verify target still exists
376
List<TargetInfo> targets = devTools.send(domains.target().getTargets());
377
boolean targetExists = targets.stream()
378
.anyMatch(target -> target.getTargetId().equals(targetId));
379
380
if (!targetExists) {
381
throw new IllegalArgumentException("Target " + targetId + " no longer exists");
382
}
383
384
// Attempt attachment
385
SessionID sessionId = devTools.send(domains.target().attachToTarget(targetId));
386
System.out.println("Successfully attached to target " + targetId);
387
return sessionId;
388
389
} catch (Exception e) {
390
System.err.println("Failed to attach to target " + targetId + ": " + e.getMessage());
391
throw new RuntimeException("Target attachment failed", e);
392
}
393
}
394
395
// Safe detachment
396
public void safeDetachFromTarget(SessionID sessionId, TargetID targetId) {
397
try {
398
devTools.send(domains.target().detachFromTarget(
399
Optional.of(sessionId),
400
Optional.of(targetId)
401
));
402
System.out.println("Successfully detached from target " + targetId);
403
} catch (Exception e) {
404
System.err.println("Failed to detach from target " + targetId + ": " + e.getMessage());
405
// Continue execution - detachment failures are often not critical
406
}
407
}
408
```