0
# JavaScript Operations
1
2
JavaScript evaluation, runtime bindings, and script injection capabilities for advanced browser interaction using Chrome DevTools Protocol v110.
3
4
## Capabilities
5
6
### JavaScript Domain Wrapper
7
8
High-level wrapper for CDP JavaScript/Runtime functionality providing type-safe access to script execution and runtime bindings.
9
10
```java { .api }
11
/**
12
* JavaScript domain wrapper for CDP v110 runtime operations
13
*/
14
public class v110Javascript extends Javascript<ScriptIdentifier, BindingCalled> {
15
/**
16
* Initialize JavaScript domain with DevTools session
17
* @param devtools Active DevTools session
18
*/
19
public v110Javascript(DevTools devtools);
20
}
21
```
22
23
### Runtime Domain Control
24
25
Enable and disable runtime domain for JavaScript operations.
26
27
```java { .api }
28
/**
29
* Enable runtime domain for JavaScript execution
30
* @return Command to enable runtime
31
*/
32
protected Command<Void> enableRuntime();
33
34
/**
35
* Disable runtime domain
36
* @return Command to disable runtime
37
*/
38
protected Command<Void> disableRuntime();
39
```
40
41
### JavaScript Bindings
42
43
Create bidirectional communication between Java and JavaScript through runtime bindings.
44
45
```java { .api }
46
/**
47
* Add JavaScript binding to runtime
48
* @param scriptName Name of binding in JavaScript global scope
49
* @return Command to add binding
50
*/
51
protected Command<Void> doAddJsBinding(String scriptName);
52
53
/**
54
* Remove JavaScript binding from runtime
55
* @param scriptName Name of binding to remove
56
* @return Command to remove binding
57
*/
58
protected Command<Void> doRemoveJsBinding(String scriptName);
59
60
/**
61
* Get binding called events
62
* @return Event stream for binding calls
63
*/
64
protected Event<BindingCalled> bindingCalledEvent();
65
66
/**
67
* Extract payload from binding event
68
* @param event Binding called event
69
* @return String payload from JavaScript
70
*/
71
protected String extractPayload(BindingCalled event);
72
```
73
74
**Usage Example:**
75
76
```java
77
import org.openqa.selenium.devtools.v110.v110Javascript;
78
import org.openqa.selenium.devtools.v110.runtime.model.BindingCalled;
79
80
v110Javascript javascript = new v110Javascript(devTools);
81
82
// Enable runtime and add binding
83
devTools.send(javascript.enableRuntime());
84
devTools.send(javascript.doAddJsBinding("javaCallback"));
85
86
// Listen for binding calls
87
devTools.addListener(javascript.bindingCalledEvent(), event -> {
88
String payload = javascript.extractPayload(event);
89
System.out.println("JavaScript called Java with: " + payload);
90
91
// Process the call and potentially respond
92
handleJavaScriptCallback(payload);
93
});
94
95
// Navigate to page and use binding
96
driver.get("https://example.com");
97
driver.executeScript("javaCallback('Hello from JavaScript!');");
98
```
99
100
### Page Domain Control
101
102
Enable page domain for script injection and page-level operations.
103
104
```java { .api }
105
/**
106
* Enable page domain
107
* @return Command to enable page domain
108
*/
109
protected Command<Void> enablePage();
110
111
/**
112
* Disable page domain
113
* @return Command to disable page domain
114
*/
115
protected Command<Void> disablePage();
116
```
117
118
### Script Injection
119
120
Inject JavaScript code to be evaluated on new document creation.
121
122
```java { .api }
123
/**
124
* Add script to evaluate on new document
125
* @param script JavaScript code to inject
126
* @return Command returning script identifier
127
*/
128
protected Command<ScriptIdentifier> addScriptToEvaluateOnNewDocument(String script);
129
130
/**
131
* Remove previously added script
132
* @param id Script identifier to remove
133
* @return Command to remove script
134
*/
135
protected Command<Void> removeScriptToEvaluateOnNewDocument(ScriptIdentifier id);
136
```
137
138
**Usage Example:**
139
140
```java
141
import org.openqa.selenium.devtools.v110.page.model.ScriptIdentifier;
142
143
// Enable page domain
144
devTools.send(javascript.enablePage());
145
146
// Add script that runs on every page load
147
String initScript = """
148
window.myApp = {
149
initialized: true,
150
version: '1.0.0',
151
log: function(msg) {
152
console.log('[MyApp] ' + msg);
153
}
154
};
155
window.myApp.log('Application initialized');
156
""";
157
158
ScriptIdentifier scriptId = devTools.send(
159
javascript.addScriptToEvaluateOnNewDocument(initScript)
160
);
161
162
// Navigate - script will run automatically
163
driver.get("https://example.com");
164
165
// Later remove the script
166
devTools.send(javascript.removeScriptToEvaluateOnNewDocument(scriptId));
167
```
168
169
### High-Level JavaScript Operations
170
171
Convenient methods for common JavaScript operations (inherited from base Javascript class).
172
173
```java { .api }
174
/**
175
* Add JavaScript binding with automatic event handling
176
* @param bindingName Name for JavaScript binding
177
* @param handler Function to handle binding calls
178
*/
179
public void addJsBinding(String bindingName, Consumer<String> handler);
180
181
/**
182
* Remove JavaScript binding
183
* @param bindingName Name of binding to remove
184
*/
185
public void removeJsBinding(String bindingName);
186
187
/**
188
* Pin script for evaluation on new documents
189
* @param scriptName Name/identifier for script
190
* @param script JavaScript code to pin
191
*/
192
public void pin(String scriptName, String script);
193
194
/**
195
* Unpin previously pinned script
196
* @param scriptName Name of script to unpin
197
*/
198
public void unpin(String scriptName);
199
```
200
201
## CDP Domain Classes
202
203
### Runtime Domain
204
205
Direct access to CDP Runtime domain for low-level JavaScript operations.
206
207
```java { .api }
208
import org.openqa.selenium.devtools.v110.runtime.Runtime;
209
210
/**
211
* Enable runtime domain
212
*/
213
public static Command<Void> enable();
214
215
/**
216
* Disable runtime domain
217
*/
218
public static Command<Void> disable();
219
220
/**
221
* Add runtime binding
222
*/
223
public static Command<Void> addBinding(
224
String name,
225
Optional<ExecutionContextId> executionContextId,
226
Optional<String> executionContextName
227
);
228
229
/**
230
* Remove runtime binding
231
*/
232
public static Command<Void> removeBinding(String name);
233
234
/**
235
* Binding called event
236
*/
237
public static Event<BindingCalled> bindingCalled();
238
239
/**
240
* Evaluate JavaScript expression
241
*/
242
public static Command<EvaluateResponse> evaluate(
243
String expression,
244
Optional<String> objectGroup,
245
Optional<Boolean> includeCommandLineAPI,
246
Optional<Boolean> silent,
247
Optional<ExecutionContextId> contextId,
248
Optional<Boolean> returnByValue,
249
Optional<Boolean> generatePreview,
250
Optional<Boolean> userGesture,
251
Optional<Boolean> awaitPromise,
252
Optional<Boolean> throwOnSideEffect,
253
Optional<TimeDelta> timeout,
254
Optional<Boolean> disableBreaks,
255
Optional<Boolean> replMode,
256
Optional<Boolean> allowUnsafeEvalBlockedByCSP
257
);
258
```
259
260
### Page Domain
261
262
Direct access to CDP Page domain for page-level script operations.
263
264
```java { .api }
265
import org.openqa.selenium.devtools.v110.page.Page;
266
267
/**
268
* Enable page domain
269
*/
270
public static Command<Void> enable();
271
272
/**
273
* Disable page domain
274
*/
275
public static Command<Void> disable();
276
277
/**
278
* Add script to evaluate on new document
279
*/
280
public static Command<ScriptIdentifier> addScriptToEvaluateOnNewDocument(
281
String source,
282
Optional<String> worldName,
283
Optional<Boolean> includeCommandLineAPI
284
);
285
286
/**
287
* Remove script to evaluate on new document
288
*/
289
public static Command<Void> removeScriptToEvaluateOnNewDocument(ScriptIdentifier identifier);
290
```
291
292
## Model Classes
293
294
### Script and Binding Models
295
296
```java { .api }
297
import org.openqa.selenium.devtools.v110.page.model.*;
298
import org.openqa.selenium.devtools.v110.runtime.model.*;
299
300
/**
301
* Script identifier for page-level scripts
302
*/
303
public class ScriptIdentifier {
304
String toString();
305
}
306
307
/**
308
* Runtime binding called event
309
*/
310
public class BindingCalled {
311
/**
312
* Binding name that was called
313
*/
314
String getName();
315
316
/**
317
* Payload sent from JavaScript
318
*/
319
String getPayload();
320
321
/**
322
* Execution context where binding was called
323
*/
324
ExecutionContextId getExecutionContextId();
325
}
326
327
/**
328
* JavaScript evaluation response
329
*/
330
public class EvaluateResponse {
331
/**
332
* Evaluation result as remote object
333
*/
334
RemoteObject getResult();
335
336
/**
337
* Exception details if evaluation threw
338
*/
339
Optional<ExceptionDetails> getExceptionDetails();
340
}
341
342
/**
343
* JavaScript execution context identifier
344
*/
345
public class ExecutionContextId {
346
Integer getValue();
347
String toString();
348
}
349
```
350
351
### Runtime Object Models
352
353
```java { .api }
354
/**
355
* Remote object representing JavaScript values
356
*/
357
public class RemoteObject {
358
/**
359
* Object type (object, function, undefined, string, number, boolean, symbol, bigint)
360
*/
361
RemoteObjectType getType();
362
363
/**
364
* Object subtype for more specific type information
365
*/
366
Optional<RemoteObjectSubtype> getSubtype();
367
368
/**
369
* Primitive value (for strings, numbers, booleans)
370
*/
371
Optional<Object> getValue();
372
373
/**
374
* String description of the object
375
*/
376
Optional<String> getDescription();
377
378
/**
379
* Unique object identifier for further operations
380
*/
381
Optional<RemoteObjectId> getObjectId();
382
}
383
384
/**
385
* Exception details from JavaScript evaluation
386
*/
387
public class ExceptionDetails {
388
String getText();
389
Optional<String> getUrl();
390
Integer getLineNumber();
391
Integer getColumnNumber();
392
Optional<RemoteObject> getException();
393
}
394
```
395
396
## Advanced Usage Examples
397
398
### Bidirectional Communication
399
400
```java
401
v110Javascript javascript = new v110Javascript(devTools);
402
devTools.send(javascript.enableRuntime());
403
404
// Set up bidirectional communication
405
javascript.addJsBinding("sendToJava", payload -> {
406
System.out.println("Received from JavaScript: " + payload);
407
408
// Send response back to JavaScript
409
String response = processPayload(payload);
410
driver.executeScript("window.javaResponse = arguments[0];", response);
411
});
412
413
// Navigate and establish communication
414
driver.get("https://example.com");
415
416
// JavaScript can now call: sendToJava("some data")
417
// And receive responses via: window.javaResponse
418
```
419
420
### Script Injection for Testing
421
422
```java
423
// Enable page domain
424
devTools.send(javascript.enablePage());
425
426
// Inject testing utilities
427
String testingScript = """
428
window.testUtils = {
429
waitForElement: function(selector, timeout = 5000) {
430
return new Promise((resolve, reject) => {
431
const startTime = Date.now();
432
const check = () => {
433
const element = document.querySelector(selector);
434
if (element) {
435
resolve(element);
436
} else if (Date.now() - startTime > timeout) {
437
reject(new Error('Element not found: ' + selector));
438
} else {
439
setTimeout(check, 100);
440
}
441
};
442
check();
443
});
444
},
445
446
simulateEvent: function(element, eventType) {
447
const event = new Event(eventType, { bubbles: true });
448
element.dispatchEvent(event);
449
}
450
};
451
""";
452
453
ScriptIdentifier testUtilsScript = devTools.send(
454
javascript.addScriptToEvaluateOnNewDocument(testingScript)
455
);
456
457
// Now all pages will have testUtils available
458
```
459
460
### Runtime Evaluation
461
462
```java
463
import org.openqa.selenium.devtools.v110.runtime.Runtime;
464
import org.openqa.selenium.devtools.v110.runtime.model.EvaluateResponse;
465
466
// Enable runtime
467
devTools.send(Runtime.enable());
468
469
// Evaluate JavaScript expression
470
EvaluateResponse response = devTools.send(Runtime.evaluate(
471
"document.title + ' - ' + location.href",
472
Optional.empty(), // objectGroup
473
Optional.empty(), // includeCommandLineAPI
474
Optional.of(false), // silent
475
Optional.empty(), // contextId
476
Optional.of(true), // returnByValue
477
Optional.empty(), // generatePreview
478
Optional.empty(), // userGesture
479
Optional.empty(), // awaitPromise
480
Optional.empty(), // throwOnSideEffect
481
Optional.empty(), // timeout
482
Optional.empty(), // disableBreaks
483
Optional.empty(), // replMode
484
Optional.empty() // allowUnsafeEvalBlockedByCSP
485
));
486
487
if (response.getExceptionDetails().isPresent()) {
488
System.err.println("JavaScript error: " +
489
response.getExceptionDetails().get().getText());
490
} else {
491
Object result = response.getResult().getValue().orElse(null);
492
System.out.println("JavaScript result: " + result);
493
}
494
```
495
496
## Error Handling
497
498
JavaScript operations may encounter various error conditions:
499
500
```java
501
import org.openqa.selenium.devtools.DevToolsException;
502
import org.openqa.selenium.JavascriptException;
503
504
// Handle runtime enablement failures
505
try {
506
devTools.send(javascript.enableRuntime());
507
} catch (DevToolsException e) {
508
System.err.println("Failed to enable runtime: " + e.getMessage());
509
}
510
511
// Handle binding setup failures
512
try {
513
javascript.addJsBinding("myBinding", payload -> {
514
// Handle binding call
515
});
516
} catch (DevToolsException e) {
517
System.err.println("Failed to add binding: " + e.getMessage());
518
}
519
520
// Handle JavaScript evaluation errors
521
devTools.addListener(Runtime.evaluate("invalid.javascript.code",
522
Optional.empty(), Optional.empty(), Optional.of(false),
523
Optional.empty(), Optional.of(true), Optional.empty(),
524
Optional.empty(), Optional.empty(), Optional.empty(),
525
Optional.empty(), Optional.empty(), Optional.empty(),
526
Optional.empty()), response -> {
527
528
if (response.getExceptionDetails().isPresent()) {
529
ExceptionDetails details = response.getExceptionDetails().get();
530
System.err.printf("JavaScript Error at %s:%d - %s%n",
531
details.getUrl().orElse("unknown"),
532
details.getLineNumber(),
533
details.getText());
534
}
535
});
536
```