Chrome DevTools Protocol (CDP) bindings for Java - version 110, enabling advanced browser automation features like network interception, console event handling, JavaScript execution, and target management.
—
JavaScript evaluation, runtime bindings, and script injection capabilities for advanced browser interaction using Chrome DevTools Protocol v110.
High-level wrapper for CDP JavaScript/Runtime functionality providing type-safe access to script execution and runtime bindings.
/**
* JavaScript domain wrapper for CDP v110 runtime operations
*/
public class v110Javascript extends Javascript<ScriptIdentifier, BindingCalled> {
/**
* Initialize JavaScript domain with DevTools session
* @param devtools Active DevTools session
*/
public v110Javascript(DevTools devtools);
}Enable and disable runtime domain for JavaScript operations.
/**
* Enable runtime domain for JavaScript execution
* @return Command to enable runtime
*/
protected Command<Void> enableRuntime();
/**
* Disable runtime domain
* @return Command to disable runtime
*/
protected Command<Void> disableRuntime();Create bidirectional communication between Java and JavaScript through runtime bindings.
/**
* Add JavaScript binding to runtime
* @param scriptName Name of binding in JavaScript global scope
* @return Command to add binding
*/
protected Command<Void> doAddJsBinding(String scriptName);
/**
* Remove JavaScript binding from runtime
* @param scriptName Name of binding to remove
* @return Command to remove binding
*/
protected Command<Void> doRemoveJsBinding(String scriptName);
/**
* Get binding called events
* @return Event stream for binding calls
*/
protected Event<BindingCalled> bindingCalledEvent();
/**
* Extract payload from binding event
* @param event Binding called event
* @return String payload from JavaScript
*/
protected String extractPayload(BindingCalled event);Usage Example:
import org.openqa.selenium.devtools.v110.v110Javascript;
import org.openqa.selenium.devtools.v110.runtime.model.BindingCalled;
v110Javascript javascript = new v110Javascript(devTools);
// Enable runtime and add binding
devTools.send(javascript.enableRuntime());
devTools.send(javascript.doAddJsBinding("javaCallback"));
// Listen for binding calls
devTools.addListener(javascript.bindingCalledEvent(), event -> {
String payload = javascript.extractPayload(event);
System.out.println("JavaScript called Java with: " + payload);
// Process the call and potentially respond
handleJavaScriptCallback(payload);
});
// Navigate to page and use binding
driver.get("https://example.com");
driver.executeScript("javaCallback('Hello from JavaScript!');");Enable page domain for script injection and page-level operations.
/**
* Enable page domain
* @return Command to enable page domain
*/
protected Command<Void> enablePage();
/**
* Disable page domain
* @return Command to disable page domain
*/
protected Command<Void> disablePage();Inject JavaScript code to be evaluated on new document creation.
/**
* Add script to evaluate on new document
* @param script JavaScript code to inject
* @return Command returning script identifier
*/
protected Command<ScriptIdentifier> addScriptToEvaluateOnNewDocument(String script);
/**
* Remove previously added script
* @param id Script identifier to remove
* @return Command to remove script
*/
protected Command<Void> removeScriptToEvaluateOnNewDocument(ScriptIdentifier id);Usage Example:
import org.openqa.selenium.devtools.v110.page.model.ScriptIdentifier;
// Enable page domain
devTools.send(javascript.enablePage());
// Add script that runs on every page load
String initScript = """
window.myApp = {
initialized: true,
version: '1.0.0',
log: function(msg) {
console.log('[MyApp] ' + msg);
}
};
window.myApp.log('Application initialized');
""";
ScriptIdentifier scriptId = devTools.send(
javascript.addScriptToEvaluateOnNewDocument(initScript)
);
// Navigate - script will run automatically
driver.get("https://example.com");
// Later remove the script
devTools.send(javascript.removeScriptToEvaluateOnNewDocument(scriptId));Convenient methods for common JavaScript operations (inherited from base Javascript class).
/**
* Add JavaScript binding with automatic event handling
* @param bindingName Name for JavaScript binding
* @param handler Function to handle binding calls
*/
public void addJsBinding(String bindingName, Consumer<String> handler);
/**
* Remove JavaScript binding
* @param bindingName Name of binding to remove
*/
public void removeJsBinding(String bindingName);
/**
* Pin script for evaluation on new documents
* @param scriptName Name/identifier for script
* @param script JavaScript code to pin
*/
public void pin(String scriptName, String script);
/**
* Unpin previously pinned script
* @param scriptName Name of script to unpin
*/
public void unpin(String scriptName);Direct access to CDP Runtime domain for low-level JavaScript operations.
import org.openqa.selenium.devtools.v110.runtime.Runtime;
/**
* Enable runtime domain
*/
public static Command<Void> enable();
/**
* Disable runtime domain
*/
public static Command<Void> disable();
/**
* Add runtime binding
*/
public static Command<Void> addBinding(
String name,
Optional<ExecutionContextId> executionContextId,
Optional<String> executionContextName
);
/**
* Remove runtime binding
*/
public static Command<Void> removeBinding(String name);
/**
* Binding called event
*/
public static Event<BindingCalled> bindingCalled();
/**
* Evaluate JavaScript expression
*/
public static Command<EvaluateResponse> evaluate(
String expression,
Optional<String> objectGroup,
Optional<Boolean> includeCommandLineAPI,
Optional<Boolean> silent,
Optional<ExecutionContextId> contextId,
Optional<Boolean> returnByValue,
Optional<Boolean> generatePreview,
Optional<Boolean> userGesture,
Optional<Boolean> awaitPromise,
Optional<Boolean> throwOnSideEffect,
Optional<TimeDelta> timeout,
Optional<Boolean> disableBreaks,
Optional<Boolean> replMode,
Optional<Boolean> allowUnsafeEvalBlockedByCSP
);Direct access to CDP Page domain for page-level script operations.
import org.openqa.selenium.devtools.v110.page.Page;
/**
* Enable page domain
*/
public static Command<Void> enable();
/**
* Disable page domain
*/
public static Command<Void> disable();
/**
* Add script to evaluate on new document
*/
public static Command<ScriptIdentifier> addScriptToEvaluateOnNewDocument(
String source,
Optional<String> worldName,
Optional<Boolean> includeCommandLineAPI
);
/**
* Remove script to evaluate on new document
*/
public static Command<Void> removeScriptToEvaluateOnNewDocument(ScriptIdentifier identifier);import org.openqa.selenium.devtools.v110.page.model.*;
import org.openqa.selenium.devtools.v110.runtime.model.*;
/**
* Script identifier for page-level scripts
*/
public class ScriptIdentifier {
String toString();
}
/**
* Runtime binding called event
*/
public class BindingCalled {
/**
* Binding name that was called
*/
String getName();
/**
* Payload sent from JavaScript
*/
String getPayload();
/**
* Execution context where binding was called
*/
ExecutionContextId getExecutionContextId();
}
/**
* JavaScript evaluation response
*/
public class EvaluateResponse {
/**
* Evaluation result as remote object
*/
RemoteObject getResult();
/**
* Exception details if evaluation threw
*/
Optional<ExceptionDetails> getExceptionDetails();
}
/**
* JavaScript execution context identifier
*/
public class ExecutionContextId {
Integer getValue();
String toString();
}/**
* Remote object representing JavaScript values
*/
public class RemoteObject {
/**
* Object type (object, function, undefined, string, number, boolean, symbol, bigint)
*/
RemoteObjectType getType();
/**
* Object subtype for more specific type information
*/
Optional<RemoteObjectSubtype> getSubtype();
/**
* Primitive value (for strings, numbers, booleans)
*/
Optional<Object> getValue();
/**
* String description of the object
*/
Optional<String> getDescription();
/**
* Unique object identifier for further operations
*/
Optional<RemoteObjectId> getObjectId();
}
/**
* Exception details from JavaScript evaluation
*/
public class ExceptionDetails {
String getText();
Optional<String> getUrl();
Integer getLineNumber();
Integer getColumnNumber();
Optional<RemoteObject> getException();
}v110Javascript javascript = new v110Javascript(devTools);
devTools.send(javascript.enableRuntime());
// Set up bidirectional communication
javascript.addJsBinding("sendToJava", payload -> {
System.out.println("Received from JavaScript: " + payload);
// Send response back to JavaScript
String response = processPayload(payload);
driver.executeScript("window.javaResponse = arguments[0];", response);
});
// Navigate and establish communication
driver.get("https://example.com");
// JavaScript can now call: sendToJava("some data")
// And receive responses via: window.javaResponse// Enable page domain
devTools.send(javascript.enablePage());
// Inject testing utilities
String testingScript = """
window.testUtils = {
waitForElement: function(selector, timeout = 5000) {
return new Promise((resolve, reject) => {
const startTime = Date.now();
const check = () => {
const element = document.querySelector(selector);
if (element) {
resolve(element);
} else if (Date.now() - startTime > timeout) {
reject(new Error('Element not found: ' + selector));
} else {
setTimeout(check, 100);
}
};
check();
});
},
simulateEvent: function(element, eventType) {
const event = new Event(eventType, { bubbles: true });
element.dispatchEvent(event);
}
};
""";
ScriptIdentifier testUtilsScript = devTools.send(
javascript.addScriptToEvaluateOnNewDocument(testingScript)
);
// Now all pages will have testUtils availableimport org.openqa.selenium.devtools.v110.runtime.Runtime;
import org.openqa.selenium.devtools.v110.runtime.model.EvaluateResponse;
// Enable runtime
devTools.send(Runtime.enable());
// Evaluate JavaScript expression
EvaluateResponse response = devTools.send(Runtime.evaluate(
"document.title + ' - ' + location.href",
Optional.empty(), // objectGroup
Optional.empty(), // includeCommandLineAPI
Optional.of(false), // silent
Optional.empty(), // contextId
Optional.of(true), // returnByValue
Optional.empty(), // generatePreview
Optional.empty(), // userGesture
Optional.empty(), // awaitPromise
Optional.empty(), // throwOnSideEffect
Optional.empty(), // timeout
Optional.empty(), // disableBreaks
Optional.empty(), // replMode
Optional.empty() // allowUnsafeEvalBlockedByCSP
));
if (response.getExceptionDetails().isPresent()) {
System.err.println("JavaScript error: " +
response.getExceptionDetails().get().getText());
} else {
Object result = response.getResult().getValue().orElse(null);
System.out.println("JavaScript result: " + result);
}JavaScript operations may encounter various error conditions:
import org.openqa.selenium.devtools.DevToolsException;
import org.openqa.selenium.JavascriptException;
// Handle runtime enablement failures
try {
devTools.send(javascript.enableRuntime());
} catch (DevToolsException e) {
System.err.println("Failed to enable runtime: " + e.getMessage());
}
// Handle binding setup failures
try {
javascript.addJsBinding("myBinding", payload -> {
// Handle binding call
});
} catch (DevToolsException e) {
System.err.println("Failed to add binding: " + e.getMessage());
}
// Handle JavaScript evaluation errors
devTools.addListener(Runtime.evaluate("invalid.javascript.code",
Optional.empty(), Optional.empty(), Optional.of(false),
Optional.empty(), Optional.of(true), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty()), response -> {
if (response.getExceptionDetails().isPresent()) {
ExceptionDetails details = response.getExceptionDetails().get();
System.err.printf("JavaScript Error at %s:%d - %s%n",
details.getUrl().orElse("unknown"),
details.getLineNumber(),
details.getText());
}
});Install with Tessl CLI
npx tessl i tessl/maven-org-seleniumhq-selenium--selenium-devtools-v110