## 🚀 Feature Proposal

Add support for the WebAuthn Automation API, a standard WebDriver extension that allows developers to create virtual authenticators to test websites using WebAuthn.

https://w3c.github.io/webauthn/#sctn-automation

_note: the above link may not work until https://github.com/w3c/webauthn/pull/1340 is merged_

## Motivation

At the moment there is no practical way to write e2e tests for pages using WebAuthn. Since this is a standard WebDriver API, the cost of implementing a layer on java is low.

## Example

For a page like this

```html
<button id="signup">Sign up with webauthn</button>
<span id="result"></span>
```

```javascript
document.getElmentById("signup").addEventListener("click", () => {
  navigator.credentials.create({...}).then(credentials => {
    document.getElementById("result").innerText = "Success!";
  })
});
```

A test could be written like so:

```java
// HasVirtualAuthenticator is an interface that augments a RemoteWebDriver.
HasVirtualAuthenticator virtualAuthenticatorManager = ((HasVirtualAuthenticator) driver);
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions();
VirtualAuthenticator authenticator =
    virtualAuthenticatorManager.addVirtualAuthenticator(options);
driver.findElement(By.id("signup")).click();
WebElement result = driver.findElement(By.id("result"));
new WebDriverWait(driver, 60, 1000).until(
    driver -> !result.getText().equals(""));
assertThat(result.getText()).isEqualTo("Success!");
```

## Implementation

We can implement the AddVirtualAuthenticator and RemoveVirtualAuthenticator methods first since they're the most useful and follow up with the others in subsequent PRs.
defineCommand(GET_COOKIE, get("/session/:sessionId/cookie/:name"));
    defineCommand(ADD_COOKIE, post("/session/:sessionId/cookie"));
    defineCommand(DELETE_ALL_COOKIES, delete("/session/:sessionId/cookie"));
    defineCommand(DELETE_COOKIE, delete("/session/:sessionId/cookie/:name"));
    defineCommand(SET_TIMEOUT, post("/session/:sessionId/timeouts"));
    defineCommand(SET_SCRIPT_TIMEOUT, post("/session/:sessionId/timeouts/async_script"));
    defineCommand(IMPLICITLY_WAIT, post("/session/:sessionId/timeouts/implicit_wait"));
    defineCommand(GET_APP_CACHE_STATUS, get("/session/:sessionId/application_cache/status"));
    defineCommand(IS_BROWSER_ONLINE, get("/session/:sessionId/browser_connection"));
    defineCommand(SET_BROWSER_ONLINE, post("/session/:sessionId/browser_connection"));
    defineCommand(GET_LOCATION, get("/session/:sessionId/location"));
    defineCommand(SET_LOCATION, post("/session/:sessionId/location"));
    defineCommand(GET_SCREEN_ORIENTATION, get("/session/:sessionId/orientation"));
    defineCommand(SET_SCREEN_ORIENTATION, post("/session/:sessionId/orientation"));
    defineCommand(GET_SCREEN_ROTATION, get("/session/:sessionId/rotation"));
    defineCommand(SET_SCREEN_ROTATION, post("/session/:sessionId/rotation"));
    defineCommand(IME_GET_AVAILABLE_ENGINES, get("/session/:sessionId/ime/available_engines"));
    defineCommand(IME_GET_ACTIVE_ENGINE, get("/session/:sessionId/ime/active_engine"));
    defineCommand(IME_IS_ACTIVATED, get("/session/:sessionId/ime/activated"));
    defineCommand(IME_DEACTIVATE, post("/session/:sessionId/ime/deactivate"));
    defineCommand(IME_ACTIVATE_ENGINE, post("/session/:sessionId/ime/activate"));
    
    defineCommand(GET_NETWORK_CONNECTION, get("/session/:sessionId/network_connection"));
    defineCommand(SET_NETWORK_CONNECTION, post("/session/:sessionId/network_connection"));
    defineCommand(SWITCH_TO_CONTEXT, post("/session/:sessionId/context"));
    defineCommand(GET_CURRENT_CONTEXT_HANDLE, get("/session/:sessionId/context"));
    defineCommand(GET_CONTEXT_HANDLES, get("/session/:sessionId/contexts"));
  }
  @Override
  public HttpRequest encode(Command command) {