0
# JavaScript Domain
1
2
JavaScript domain implementation for script injection, binding management, and runtime code evaluation. Provides capabilities for executing JavaScript code, managing runtime bindings between browser and Java, and controlling script evaluation on new documents.
3
4
## Capabilities
5
6
### Runtime Control
7
8
Enable and disable the Chrome DevTools Runtime domain for JavaScript operations.
9
10
```java { .api }
11
public Command<Void> enableRuntime();
12
public Command<Void> disableRuntime();
13
```
14
15
Usage example:
16
```java
17
v111Javascript javascript = domains.javascript();
18
19
// Enable runtime for JavaScript operations
20
devTools.send(javascript.enableRuntime());
21
22
// Later disable when done
23
devTools.send(javascript.disableRuntime());
24
```
25
26
### Page Control
27
28
Enable and disable the Chrome DevTools Page domain for document-level script management.
29
30
```java { .api }
31
public Command<Void> enablePage();
32
public Command<Void> disablePage();
33
```
34
35
Usage example:
36
```java
37
// Enable page domain for script injection
38
devTools.send(javascript.enablePage());
39
40
// Later disable when done
41
devTools.send(javascript.disablePage());
42
```
43
44
### JavaScript Binding Management
45
46
Create and manage JavaScript bindings that allow communication between browser JavaScript and Java code.
47
48
```java { .api }
49
public Command<Void> doAddJsBinding(String scriptName);
50
public Command<Void> doRemoveJsBinding(String scriptName);
51
public Event<BindingCalled> bindingCalledEvent();
52
public String extractPayload(BindingCalled event);
53
```
54
55
Usage example:
56
```java
57
// Add a JavaScript binding
58
devTools.send(javascript.doAddJsBinding("javaCallback"));
59
60
// Listen for binding calls
61
devTools.addListener(javascript.bindingCalledEvent(), bindingEvent -> {
62
String payload = javascript.extractPayload(bindingEvent);
63
64
// Handle the callback from JavaScript
65
System.out.println("JavaScript called Java with: " + payload);
66
67
// Process the payload (could be JSON, plain text, etc.)
68
if (payload.startsWith("{")) {
69
// Handle JSON payload
70
JsonObject data = JsonParser.parseString(payload).getAsJsonObject();
71
String action = data.get("action").getAsString();
72
// Handle different actions...
73
}
74
});
75
76
// Now JavaScript in the page can call:
77
// window.javaCallback('{"action": "getData", "id": 123}');
78
79
// Remove binding when done
80
devTools.send(javascript.doRemoveJsBinding("javaCallback"));
81
```
82
83
### Script Injection on New Documents
84
85
Add and remove scripts that automatically execute when new documents load.
86
87
```java { .api }
88
public Command<ScriptIdentifier> addScriptToEvaluateOnNewDocument(String script);
89
public Command<Void> removeScriptToEvaluateOnNewDocument(ScriptIdentifier id);
90
```
91
92
Usage example:
93
```java
94
// Add script to run on every new page
95
String initScript = """
96
// Override console.log to capture all logs
97
window.originalConsoleLog = console.log;
98
console.log = function(...args) {
99
// Call our Java binding with log data
100
if (window.javaCallback) {
101
window.javaCallback(JSON.stringify({
102
type: 'console.log',
103
args: args.map(arg => String(arg))
104
}));
105
}
106
// Still call original console.log
107
window.originalConsoleLog.apply(console, args);
108
};
109
110
// Add custom properties
111
window.automationActive = true;
112
window.testStartTime = Date.now();
113
""";
114
115
ScriptIdentifier scriptId = devTools.send(javascript.addScriptToEvaluateOnNewDocument(initScript));
116
117
// Later remove the script
118
devTools.send(javascript.removeScriptToEvaluateOnNewDocument(scriptId));
119
```
120
121
### Advanced Binding Example
122
123
Complete example showing bidirectional communication between Java and JavaScript:
124
125
```java
126
public class JavaScriptBridge {
127
private final DevTools devTools;
128
private final v111Javascript javascript;
129
130
public void setupBridge() {
131
// Enable domains
132
devTools.send(javascript.enableRuntime());
133
devTools.send(javascript.enablePage());
134
135
// Add binding for JavaScript -> Java communication
136
devTools.send(javascript.doAddJsBinding("sendToJava"));
137
138
// Listen for calls from JavaScript
139
devTools.addListener(javascript.bindingCalledEvent(), this::handleJavaScriptCall);
140
141
// Inject bridge script on new documents
142
String bridgeScript = """
143
window.javaScriptBridge = {
144
sendMessage: function(type, data) {
145
window.sendToJava(JSON.stringify({type: type, data: data}));
146
},
147
148
onMessageFromJava: null, // Will be set by page JavaScript
149
150
// Built-in message handlers
151
handleJavaMessage: function(message) {
152
if (this.onMessageFromJava) {
153
this.onMessageFromJava(message);
154
}
155
}
156
};
157
""";
158
159
devTools.send(javascript.addScriptToEvaluateOnNewDocument(bridgeScript));
160
}
161
162
private void handleJavaScriptCall(BindingCalled event) {
163
String payload = javascript.extractPayload(event);
164
165
try {
166
JsonObject message = JsonParser.parseString(payload).getAsJsonObject();
167
String type = message.get("type").getAsString();
168
JsonElement data = message.get("data");
169
170
switch (type) {
171
case "userAction":
172
handleUserAction(data.getAsJsonObject());
173
break;
174
case "pageReady":
175
handlePageReady();
176
break;
177
case "error":
178
handlePageError(data.getAsString());
179
break;
180
}
181
} catch (Exception e) {
182
System.err.println("Error parsing JavaScript message: " + e.getMessage());
183
}
184
}
185
186
// Send message from Java to JavaScript
187
public void sendMessageToPage(String type, Object data) {
188
String script = String.format(
189
"if (window.javaScriptBridge) { " +
190
" window.javaScriptBridge.handleJavaMessage({type: '%s', data: %s}); " +
191
"}",
192
type,
193
new Gson().toJson(data)
194
);
195
196
// Execute script in current page context
197
devTools.send(Runtime.evaluate(script, Optional.empty(), Optional.empty(),
198
Optional.empty(), Optional.empty(), Optional.empty(),
199
Optional.empty(), Optional.empty(), Optional.empty(),
200
Optional.empty(), Optional.empty(), Optional.empty()));
201
}
202
}
203
```
204
205
## Types
206
207
### Script Management Types
208
209
```java { .api }
210
class ScriptIdentifier {
211
// Represents a unique identifier for an injected script
212
// Returned by addScriptToEvaluateOnNewDocument
213
// Used to remove scripts with removeScriptToEvaluateOnNewDocument
214
}
215
```
216
217
### Binding Event Types
218
219
```java { .api }
220
class BindingCalled {
221
public String getName(); // Name of the binding that was called
222
public String getPayload(); // Data passed from JavaScript to Java
223
public Optional<Integer> getExecutionContextId(); // Context where binding was called
224
}
225
```
226
227
## Integration with Runtime Domain
228
229
The JavaScript domain integrates closely with the Runtime domain for script execution:
230
231
```java
232
import org.openqa.selenium.devtools.v111.runtime.Runtime;
233
import org.openqa.selenium.devtools.v111.runtime.model.RemoteObject;
234
235
// Execute JavaScript and get result
236
String expression = "document.title";
237
Runtime.EvaluateResponse result = devTools.send(
238
Runtime.evaluate(expression, Optional.empty(), Optional.empty(),
239
Optional.empty(), Optional.empty(), Optional.empty(),
240
Optional.empty(), Optional.empty(), Optional.empty(),
241
Optional.empty(), Optional.empty(), Optional.empty())
242
);
243
244
RemoteObject resultObject = result.getResult();
245
if (resultObject.getValue().isPresent()) {
246
System.out.println("Page title: " + resultObject.getValue().get());
247
}
248
```