or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

domain-management.mdindex.mdjavascript-integration.mdlogging-operations.mdnetwork-operations.mdruntime-events.mdtarget-management.md

javascript-integration.mddocs/

0

# JavaScript Injection & Bindings

1

2

JavaScript code injection, binding management, and script execution coordination with full lifecycle control and event monitoring through the v115Javascript class.

3

4

## Capabilities

5

6

### JavaScript Domain

7

8

Manages JavaScript code injection and bidirectional communication between browser and Java code through bindings.

9

10

```java { .api }

11

/**

12

* JavaScript domain for script injection and binding management

13

* Extends the idealized Javascript class with CDP v115 specific implementations

14

*/

15

public class v115Javascript extends Javascript<ScriptIdentifier, BindingCalled> {

16

/**

17

* Creates JavaScript domain with DevTools connection

18

* @param devtools DevTools instance for CDP communication

19

*/

20

public v115Javascript(DevTools devtools);

21

22

/**

23

* Enable runtime domain for JavaScript execution

24

* @return Command to enable runtime domain

25

*/

26

protected Command<Void> enableRuntime();

27

28

/**

29

* Disable runtime domain and stop JavaScript functionality

30

* @return Command to disable runtime domain

31

*/

32

protected Command<Void> disableRuntime();

33

34

/**

35

* Add JavaScript binding for bidirectional communication

36

* @param scriptName Name of the binding function to create

37

* @return Command to add the binding

38

*/

39

protected Command<Void> doAddJsBinding(String scriptName);

40

41

/**

42

* Remove JavaScript binding

43

* @param scriptName Name of the binding function to remove

44

* @return Command to remove the binding

45

*/

46

protected Command<Void> doRemoveJsBinding(String scriptName);

47

48

/**

49

* Enable page domain for script injection

50

* @return Command to enable page domain

51

*/

52

protected Command<Void> enablePage();

53

54

/**

55

* Disable page domain and stop script injection

56

* @return Command to disable page domain

57

*/

58

protected Command<Void> disablePage();

59

60

/**

61

* Add script to evaluate on every new document load

62

* @param script JavaScript code to inject

63

* @return Command returning ScriptIdentifier for the injected script

64

*/

65

protected Command<ScriptIdentifier> addScriptToEvaluateOnNewDocument(String script);

66

67

/**

68

* Remove previously injected script

69

* @param id ScriptIdentifier of the script to remove

70

* @return Command to remove the script

71

*/

72

protected Command<Void> removeScriptToEvaluateOnNewDocument(ScriptIdentifier id);

73

74

/**

75

* Get binding called event stream for monitoring binding invocations

76

* @return Event stream for binding called events

77

*/

78

protected Event<BindingCalled> bindingCalledEvent();

79

80

/**

81

* Extract payload from binding called event

82

* @param event BindingCalled event from CDP

83

* @return String payload sent from JavaScript

84

*/

85

protected String extractPayload(BindingCalled event);

86

}

87

```

88

89

### Script Injection

90

91

Inject JavaScript code that runs on every new document, useful for setting up global functions and variables.

92

93

```java { .api }

94

/**

95

* Pin script for execution on new documents (inherited from Javascript base class)

96

* @param exposeScriptAs Name to expose the script as (for management)

97

* @param script JavaScript code to inject

98

* @return ScriptId for managing the injected script

99

*/

100

public ScriptId pin(String exposeScriptAs, String script);

101

```

102

103

**Usage Examples:**

104

105

```java

106

import org.openqa.selenium.devtools.v115.v115Javascript;

107

import org.openqa.selenium.devtools.idealized.ScriptId;

108

109

// Create JavaScript domain

110

v115Javascript javascript = new v115Javascript(devTools);

111

112

// Inject global utility functions

113

ScriptId utilsScript = javascript.pin("utils", """

114

window.myUtils = {

115

getCurrentTimestamp: function() {

116

return Date.now();

117

},

118

119

highlightElement: function(selector) {

120

const element = document.querySelector(selector);

121

if (element) {

122

element.style.border = '3px solid red';

123

return true;

124

}

125

return false;

126

},

127

128

getPageInfo: function() {

129

return {

130

title: document.title,

131

url: window.location.href,

132

elementCount: document.querySelectorAll('*').length

133

};

134

}

135

};

136

137

console.log('Utility functions loaded');

138

""");

139

140

// Navigate to pages - script will be available immediately

141

driver.get("https://example.com");

142

143

// Use the injected functions

144

Object timestamp = driver.executeScript("return window.myUtils.getCurrentTimestamp();");

145

Boolean highlighted = (Boolean) driver.executeScript(

146

"return window.myUtils.highlightElement('h1');"

147

);

148

149

System.out.println("Timestamp: " + timestamp);

150

System.out.println("Highlighted: " + highlighted);

151

```

152

153

### JavaScript Bindings

154

155

Create bidirectional communication channels between browser JavaScript and Java code.

156

157

```java { .api }

158

/**

159

* Add JavaScript binding (inherited from Javascript base class)

160

* @param scriptName Name of the function to create in browser global scope

161

*/

162

public void addJsBinding(String scriptName);

163

164

/**

165

* Remove JavaScript binding (inherited from Javascript base class)

166

* @param scriptName Name of the binding function to remove

167

*/

168

public void removeJsBinding(String scriptName);

169

170

/**

171

* Add listener for binding calls (inherited from Javascript base class)

172

* @param listener Consumer to handle binding invocations with payload

173

*/

174

public void addBindingCalledListener(Consumer<String> listener);

175

```

176

177

**Usage Examples:**

178

179

```java

180

import java.util.concurrent.CompletableFuture;

181

import java.util.concurrent.TimeUnit;

182

183

// Create JavaScript domain

184

v115Javascript javascript = new v115Javascript(devTools);

185

186

// Set up data collection from browser

187

CompletableFuture<String> dataFuture = new CompletableFuture<>();

188

189

// Add binding and listener

190

javascript.addJsBinding("sendDataToJava");

191

javascript.addBindingCalledListener(payload -> {

192

System.out.println("Received from browser: " + payload);

193

dataFuture.complete(payload);

194

});

195

196

// Navigate and inject collection script

197

driver.get("https://example.com");

198

199

driver.executeScript("""

200

// Collect page data and send to Java

201

const data = {

202

title: document.title,

203

links: Array.from(document.links).length,

204

images: Array.from(document.images).length,

205

scripts: Array.from(document.scripts).length,

206

timestamp: Date.now()

207

};

208

209

// Send to Java via binding

210

window.sendDataToJava(JSON.stringify(data));

211

""");

212

213

// Wait for data from browser

214

try {

215

String pageData = dataFuture.get(5, TimeUnit.SECONDS);

216

System.out.println("Page analysis complete: " + pageData);

217

} catch (Exception e) {

218

System.err.println("Timeout waiting for page data");

219

}

220

221

// Clean up

222

javascript.removeJsBinding("sendDataToJava");

223

```

224

225

### Domain Control

226

227

Control JavaScript domain lifecycle and disable functionality when needed.

228

229

```java { .api }

230

/**

231

* Disable JavaScript domain (inherited from Javascript base class)

232

* Stops runtime and page domains, removes all bindings and scripts

233

*/

234

public void disable();

235

```

236

237

**Usage Examples:**

238

239

```java

240

// JavaScript functionality is automatically enabled when used

241

javascript.addJsBinding("myBinding");

242

ScriptId script = javascript.pin("myScript", "console.log('loaded');");

243

244

// Disable when automation is complete

245

javascript.disable();

246

```

247

248

## Advanced Binding Patterns

249

250

### Request/Response Pattern

251

252

Implement request/response communication using bindings and promises:

253

254

```java

255

// Java side - set up request handler

256

javascript.addJsBinding("handleRequest");

257

Map<String, CompletableFuture<String>> pendingRequests = new ConcurrentHashMap<>();

258

259

javascript.addBindingCalledListener(payload -> {

260

try {

261

ObjectMapper mapper = new ObjectMapper();

262

JsonNode request = mapper.readTree(payload);

263

String requestId = request.get("id").asText();

264

String operation = request.get("operation").asText();

265

266

// Process request

267

String response = processRequest(operation, request.get("data"));

268

269

// Send response back to browser

270

driver.executeScript("""

271

if (window.pendingRequests && window.pendingRequests['%s']) {

272

window.pendingRequests['%s'].resolve('%s');

273

delete window.pendingRequests['%s'];

274

}

275

""".formatted(requestId, requestId, response, requestId));

276

277

} catch (Exception e) {

278

System.err.println("Error processing request: " + e.getMessage());

279

}

280

});

281

282

// Inject client-side request helper

283

javascript.pin("requestHelper", """

284

window.pendingRequests = {};

285

286

window.sendRequest = function(operation, data) {

287

const requestId = 'req_' + Date.now() + '_' + Math.random();

288

289

return new Promise((resolve, reject) => {

290

window.pendingRequests[requestId] = { resolve, reject };

291

292

const request = {

293

id: requestId,

294

operation: operation,

295

data: data

296

};

297

298

window.handleRequest(JSON.stringify(request));

299

300

// Timeout after 10 seconds

301

setTimeout(() => {

302

if (window.pendingRequests[requestId]) {

303

delete window.pendingRequests[requestId];

304

reject(new Error('Request timeout'));

305

}

306

}, 10000);

307

});

308

};

309

""");

310

```

311

312

### Event Broadcasting

313

314

Broadcast events from Java to all pages:

315

316

```java

317

// Set up event broadcasting

318

javascript.pin("eventSystem", """

319

window.eventHandlers = {};

320

321

window.addEventListener = function(eventType, handler) {

322

if (!window.eventHandlers[eventType]) {

323

window.eventHandlers[eventType] = [];

324

}

325

window.eventHandlers[eventType].push(handler);

326

};

327

328

window.broadcastEvent = function(eventType, data) {

329

const handlers = window.eventHandlers[eventType] || [];

330

handlers.forEach(handler => {

331

try {

332

handler(data);

333

} catch (e) {

334

console.error('Event handler error:', e);

335

}

336

});

337

};

338

""");

339

340

// Broadcast events from Java

341

public void broadcastEvent(String eventType, Object data) {

342

String script = String.format(

343

"window.broadcastEvent('%s', %s);",

344

eventType,

345

objectToJson(data)

346

);

347

driver.executeScript(script);

348

}

349

```

350

351

## Error Handling

352

353

### Binding Call Failures

354

355

Binding calls can fail if the browser context is invalid or the binding doesn't exist. The system provides graceful degradation:

356

357

```java

358

// Bindings are automatically cleaned up when pages navigate

359

// Always check binding availability before use

360

driver.executeScript("""

361

if (typeof window.myBinding === 'function') {

362

window.myBinding('data');

363

} else {

364

console.warn('Binding not available');

365

}

366

""");

367

```

368

369

### Script Injection Failures

370

371

Script injection can fail if the page domain is not enabled or if the script is malformed:

372

373

```java

374

try {

375

ScriptId script = javascript.pin("myScript", "invalid javascript syntax");

376

} catch (Exception e) {

377

System.err.println("Script injection failed: " + e.getMessage());

378

}

379

```