RemoteWebDriver BiDirectional API

The following examples demonstrate how to leverage BiDi APIs with Remote WebDriver.

Register Basic Auth

Some applications make use of browser authentication to secure pages. With Selenium, you can automate the input of basic auth credentials whenever they arise.

    driver = new Augmenter().addDriverAugmentation("chrome",
                                                   HasAuthentication.class,
                                                   (caps, exec) -> (whenThisMatches, useTheseCredentials) -> {
                                                     devToolsAtomicReference.get()
                                                       .createSessionIfThereIsNotOne();
                                                     devToolsAtomicReference.get().getDomains()
                                                       .network()
                                                       .addAuthHandler(whenThisMatches,
                                                                       useTheseCredentials);

                                                   }).augment(driver);

    DevTools devTools = ((HasDevTools) driver).getDevTools();
    devTools.createSession();
    devToolsAtomicReference.set(devTools);
    ((HasAuthentication) driver).register(UsernameAndPassword.of("admin", "admin"));

Mutation Observation

Mutation Observation is the ability to capture events via WebDriver BiDi when there are DOM mutations on a specific element in the DOM.

    driver = augmenter.
      addDriverAugmentation("chrome", HasLogEvents.class, (caps, exec) -> new HasLogEvents() {
        @Override
        public <X> void onLogEvent(EventType<X> kind) {
          kind.initializeListener(augmentedDriver.get());
        }
      }).augment(driver);

    DevTools devTools = ((HasDevTools) driver).getDevTools();
    devTools.createSession();

    if (driver instanceof HasLogEvents) {
      augmentedDriver.set(driver);
    } else {
      throw new Exception("Not an instance of HasLogEvents");
    }

    ((HasLogEvents) driver).onLogEvent(domMutation(mutation -> {
      if ("cheese".equals(mutation.getAttributeName())) {
        seen.set(mutation);
        latch.countDown();
      }
    }));

Listen to console.log events

Listen to the console.log events and register callbacks to process the event.

    driver = new Augmenter().augment(driver);
    DevTools devTools = ((HasDevTools) driver).getDevTools();
    devTools.createSession();

    // Use as per Devtools version
    devTools.send(org.openqa.selenium.devtools.v85.runtime.Runtime.enable());
    devTools.send(Log.enable());

    // https://chromedevtools.github.io/devtools-protocol/tot/Console/ states that post deprecation either Runtime or Log domain is to be used
    // Depending on the implementation, events from either of the domains can be fired for console logs.

    devTools.addListener(Log.entryAdded(),
                         logEntry -> {
                           System.out.println("log: " + logEntry.getText());
                           System.out.println("level: " + logEntry.getLevel());
                           latch.countDown();
                         });

    // Use as per Devtools version
    devTools.addListener(org.openqa.selenium.devtools.v85.runtime.Runtime.consoleAPICalled(),
                         consoleLog -> System.out.println("Type: " + consoleLog.getType()));

Actions causing JS exceptions

    driver = new Augmenter().augment(driver);
    DevTools devTools = ((HasDevTools) driver).getDevTools();
    devTools.createSession();

    List<JavascriptException> jsExceptionsList = new ArrayList<>();
    Consumer<JavascriptException> addEntry = jsExceptionsList::add;
    devTools.getDomains().events().addJavascriptExceptionListener(addEntry);

Network Interception

If you want to capture network events coming into the browser and you want manipulate them you are able to do it with the following examples.

    driver = new Augmenter().augment(driver);
    DevTools devTools = ((HasDevTools) driver).getDevTools();
    devTools.createSession();

    // Intercept and change response if the request uri contains "google"
    NetworkInterceptor interceptor = new NetworkInterceptor(
      driver,
      Route.matching(req -> req.getUri().contains("google"))
        .to(() -> req -> new HttpResponse()
          .setStatus(200)
          .addHeader("Content-Type", MediaType.HTML_UTF_8.toString())
          .setContent(utf8String("Creamy, delicious cheese!"))));

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