Chrome DevTools Protocol bindings for Selenium WebDriver version 111
—
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.
Enable and disable the Chrome DevTools Runtime domain for JavaScript operations.
public Command<Void> enableRuntime();
public Command<Void> disableRuntime();Usage example:
v111Javascript javascript = domains.javascript();
// Enable runtime for JavaScript operations
devTools.send(javascript.enableRuntime());
// Later disable when done
devTools.send(javascript.disableRuntime());Enable and disable the Chrome DevTools Page domain for document-level script management.
public Command<Void> enablePage();
public Command<Void> disablePage();Usage example:
// Enable page domain for script injection
devTools.send(javascript.enablePage());
// Later disable when done
devTools.send(javascript.disablePage());Create and manage JavaScript bindings that allow communication between browser JavaScript and Java code.
public Command<Void> doAddJsBinding(String scriptName);
public Command<Void> doRemoveJsBinding(String scriptName);
public Event<BindingCalled> bindingCalledEvent();
public String extractPayload(BindingCalled event);Usage example:
// Add a JavaScript binding
devTools.send(javascript.doAddJsBinding("javaCallback"));
// Listen for binding calls
devTools.addListener(javascript.bindingCalledEvent(), bindingEvent -> {
String payload = javascript.extractPayload(bindingEvent);
// Handle the callback from JavaScript
System.out.println("JavaScript called Java with: " + payload);
// Process the payload (could be JSON, plain text, etc.)
if (payload.startsWith("{")) {
// Handle JSON payload
JsonObject data = JsonParser.parseString(payload).getAsJsonObject();
String action = data.get("action").getAsString();
// Handle different actions...
}
});
// Now JavaScript in the page can call:
// window.javaCallback('{"action": "getData", "id": 123}');
// Remove binding when done
devTools.send(javascript.doRemoveJsBinding("javaCallback"));Add and remove scripts that automatically execute when new documents load.
public Command<ScriptIdentifier> addScriptToEvaluateOnNewDocument(String script);
public Command<Void> removeScriptToEvaluateOnNewDocument(ScriptIdentifier id);Usage example:
// Add script to run on every new page
String initScript = """
// Override console.log to capture all logs
window.originalConsoleLog = console.log;
console.log = function(...args) {
// Call our Java binding with log data
if (window.javaCallback) {
window.javaCallback(JSON.stringify({
type: 'console.log',
args: args.map(arg => String(arg))
}));
}
// Still call original console.log
window.originalConsoleLog.apply(console, args);
};
// Add custom properties
window.automationActive = true;
window.testStartTime = Date.now();
""";
ScriptIdentifier scriptId = devTools.send(javascript.addScriptToEvaluateOnNewDocument(initScript));
// Later remove the script
devTools.send(javascript.removeScriptToEvaluateOnNewDocument(scriptId));Complete example showing bidirectional communication between Java and JavaScript:
public class JavaScriptBridge {
private final DevTools devTools;
private final v111Javascript javascript;
public void setupBridge() {
// Enable domains
devTools.send(javascript.enableRuntime());
devTools.send(javascript.enablePage());
// Add binding for JavaScript -> Java communication
devTools.send(javascript.doAddJsBinding("sendToJava"));
// Listen for calls from JavaScript
devTools.addListener(javascript.bindingCalledEvent(), this::handleJavaScriptCall);
// Inject bridge script on new documents
String bridgeScript = """
window.javaScriptBridge = {
sendMessage: function(type, data) {
window.sendToJava(JSON.stringify({type: type, data: data}));
},
onMessageFromJava: null, // Will be set by page JavaScript
// Built-in message handlers
handleJavaMessage: function(message) {
if (this.onMessageFromJava) {
this.onMessageFromJava(message);
}
}
};
""";
devTools.send(javascript.addScriptToEvaluateOnNewDocument(bridgeScript));
}
private void handleJavaScriptCall(BindingCalled event) {
String payload = javascript.extractPayload(event);
try {
JsonObject message = JsonParser.parseString(payload).getAsJsonObject();
String type = message.get("type").getAsString();
JsonElement data = message.get("data");
switch (type) {
case "userAction":
handleUserAction(data.getAsJsonObject());
break;
case "pageReady":
handlePageReady();
break;
case "error":
handlePageError(data.getAsString());
break;
}
} catch (Exception e) {
System.err.println("Error parsing JavaScript message: " + e.getMessage());
}
}
// Send message from Java to JavaScript
public void sendMessageToPage(String type, Object data) {
String script = String.format(
"if (window.javaScriptBridge) { " +
" window.javaScriptBridge.handleJavaMessage({type: '%s', data: %s}); " +
"}",
type,
new Gson().toJson(data)
);
// Execute script in current page context
devTools.send(Runtime.evaluate(script, Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.empty()));
}
}class ScriptIdentifier {
// Represents a unique identifier for an injected script
// Returned by addScriptToEvaluateOnNewDocument
// Used to remove scripts with removeScriptToEvaluateOnNewDocument
}class BindingCalled {
public String getName(); // Name of the binding that was called
public String getPayload(); // Data passed from JavaScript to Java
public Optional<Integer> getExecutionContextId(); // Context where binding was called
}The JavaScript domain integrates closely with the Runtime domain for script execution:
import org.openqa.selenium.devtools.v111.runtime.Runtime;
import org.openqa.selenium.devtools.v111.runtime.model.RemoteObject;
// Execute JavaScript and get result
String expression = "document.title";
Runtime.EvaluateResponse result = devTools.send(
Runtime.evaluate(expression, Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.empty())
);
RemoteObject resultObject = result.getResult();
if (resultObject.getValue().isPresent()) {
System.out.println("Page title: " + resultObject.getValue().get());
}Install with Tessl CLI
npx tessl i tessl/maven-org-seleniumhq-selenium--selenium-devtools-v111