Bug 1676679 - support virtual authenticator functions in webdriver r=webdriver-reviewers,jgraham,whimboo

Depends on D185198

Differential Revision: https://phabricator.services.mozilla.com/D162624
This commit is contained in:
Dana Keeler 2023-08-09 20:47:56 +00:00
Родитель 3aafc7b14f
Коммит 113ef375b0
9 изменённых файлов: 442 добавлений и 25 удалений

Просмотреть файл

@ -129,6 +129,52 @@ impl Default for PrintMargins {
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum WebAuthnProtocol {
#[serde(rename = "ctap1/u2f")]
Ctap1U2f,
#[serde(rename = "ctap2")]
Ctap2,
#[serde(rename = "ctap2_1")]
Ctap2_1,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub enum AuthenticatorTransport {
Usb,
Nfc,
Ble,
SmartCard,
Hybrid,
Internal,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct AuthenticatorParameters {
pub protocol: WebAuthnProtocol,
pub transport: AuthenticatorTransport,
pub has_resident_key: bool,
pub has_user_verification: bool,
pub is_user_consenting: bool,
pub is_user_verified: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct CredentialParameters {
pub credential_id: String,
pub is_resident_credential: bool,
pub rp_id: String,
pub private_key: String,
pub user_handle: String,
pub sign_count: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct UserVerificationParameters {
pub is_user_verified: bool,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ScreenshotOptions {
pub id: Option<String>,
@ -296,6 +342,20 @@ pub enum Command {
TakeFullScreenshot(ScreenshotOptions),
#[serde(rename = "WebDriver:TakeScreenshot")]
TakeScreenshot(ScreenshotOptions),
#[serde(rename = "WebAuthn:AddVirtualAuthenticator")]
WebAuthnAddVirtualAuthenticator(AuthenticatorParameters),
#[serde(rename = "WebAuthn:RemoveVirtualAuthenticator")]
WebAuthnRemoveVirtualAuthenticator,
#[serde(rename = "WebAuthn:AddCredential")]
WebAuthnAddCredential(CredentialParameters),
#[serde(rename = "WebAuthn:GetCredentials")]
WebAuthnGetCredentials,
#[serde(rename = "WebAuthn:RemoveCredential")]
WebAuthnRemoveCredential,
#[serde(rename = "WebAuthn:RemoveAllCredentials")]
WebAuthnRemoveAllCredentials,
#[serde(rename = "WebAuthn:SetUserVerified")]
WebAuthnSetUserVerified(UserVerificationParameters),
}
#[cfg(test)]

Просмотреть файл

@ -184,6 +184,26 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> {
Ok(true)
}
fn webauthn_virtual_authenticators(&mut self, _: &Capabilities) -> WebDriverResult<bool> {
Ok(true)
}
fn webauthn_extension_uvm(&mut self, _: &Capabilities) -> WebDriverResult<bool> {
Ok(false)
}
fn webauthn_extension_prf(&mut self, _: &Capabilities) -> WebDriverResult<bool> {
Ok(false)
}
fn webauthn_extension_large_blob(&mut self, _: &Capabilities) -> WebDriverResult<bool> {
Ok(false)
}
fn webauthn_extension_cred_blob(&mut self, _: &Capabilities) -> WebDriverResult<bool> {
Ok(false)
}
fn validate_custom(&mut self, name: &str, value: &Value) -> WebDriverResult<()> {
if !name.starts_with("moz:") {
return Ok(());

Просмотреть файл

@ -17,11 +17,15 @@ use marionette_rs::common::{
use marionette_rs::marionette::AppStatus;
use marionette_rs::message::{Command, Message, MessageId, Request};
use marionette_rs::webdriver::{
Command as MarionetteWebDriverCommand, Keys as MarionetteKeys, Locator as MarionetteLocator,
NewWindow as MarionetteNewWindow, PrintMargins as MarionettePrintMargins,
PrintOrientation as MarionettePrintOrientation, PrintPage as MarionettePrintPage,
PrintParameters as MarionettePrintParameters, ScreenshotOptions, Script as MarionetteScript,
Selector as MarionetteSelector, Url as MarionetteUrl, WindowRect as MarionetteWindowRect,
AuthenticatorParameters as MarionetteAuthenticatorParameters,
AuthenticatorTransport as MarionetteAuthenticatorTransport,
Command as MarionetteWebDriverCommand, CredentialParameters as MarionetteCredentialParameters,
Keys as MarionetteKeys, Locator as MarionetteLocator, NewWindow as MarionetteNewWindow,
PrintMargins as MarionettePrintMargins, PrintOrientation as MarionettePrintOrientation,
PrintPage as MarionettePrintPage, PrintParameters as MarionettePrintParameters,
ScreenshotOptions, Script as MarionetteScript, Selector as MarionetteSelector,
Url as MarionetteUrl, UserVerificationParameters as MarionetteUserVerificationParameters,
WebAuthnProtocol as MarionetteWebAuthnProtocol, WindowRect as MarionetteWindowRect,
};
use mozdevice::AndroidStorageInput;
use serde::de::{self, Deserialize, Deserializer};
@ -49,18 +53,21 @@ use webdriver::command::WebDriverCommand::{
GetWindowRect, GoBack, GoForward, IsDisplayed, IsEnabled, IsSelected, MaximizeWindow,
MinimizeWindow, NewSession, NewWindow, PerformActions, Print, Refresh, ReleaseActions,
SendAlertText, SetTimeouts, SetWindowRect, Status, SwitchToFrame, SwitchToParentFrame,
SwitchToWindow, TakeElementScreenshot, TakeScreenshot,
SwitchToWindow, TakeElementScreenshot, TakeScreenshot, WebAuthnAddCredential,
WebAuthnAddVirtualAuthenticator, WebAuthnGetCredentials, WebAuthnRemoveAllCredentials,
WebAuthnRemoveCredential, WebAuthnRemoveVirtualAuthenticator, WebAuthnSetUserVerified,
};
use webdriver::command::{
ActionsParameters, AddCookieParameters, GetNamedCookieParameters, GetParameters,
JavascriptCommandParameters, LocatorParameters, NewSessionParameters, NewWindowParameters,
PrintMargins, PrintOrientation, PrintPage, PrintParameters, SendKeysParameters,
SwitchToFrameParameters, SwitchToWindowParameters, TimeoutsParameters, WindowRectParameters,
ActionsParameters, AddCookieParameters, AuthenticatorParameters, AuthenticatorTransport,
GetNamedCookieParameters, GetParameters, JavascriptCommandParameters, LocatorParameters,
NewSessionParameters, NewWindowParameters, PrintMargins, PrintOrientation, PrintPage,
PrintParameters, SendKeysParameters, SwitchToFrameParameters, SwitchToWindowParameters,
TimeoutsParameters, UserVerificationParameters, WebAuthnProtocol, WindowRectParameters,
};
use webdriver::command::{WebDriverCommand, WebDriverMessage};
use webdriver::common::{
Cookie, Date, FrameId, LocatorStrategy, ShadowRoot, WebElement, ELEMENT_KEY, FRAME_KEY,
SHADOW_KEY, WINDOW_KEY,
Cookie, CredentialParameters, Date, FrameId, LocatorStrategy, ShadowRoot, WebElement,
ELEMENT_KEY, FRAME_KEY, SHADOW_KEY, WINDOW_KEY,
};
use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
use webdriver::response::{
@ -447,7 +454,14 @@ impl MarionetteSession {
| GetAlertText
| TakeScreenshot
| Print(_)
| TakeElementScreenshot(_) => {
| TakeElementScreenshot(_)
| WebAuthnAddVirtualAuthenticator(_)
| WebAuthnRemoveVirtualAuthenticator
| WebAuthnAddCredential(_)
| WebAuthnGetCredentials
| WebAuthnRemoveCredential
| WebAuthnRemoveAllCredentials
| WebAuthnSetUserVerified(_) => {
WebDriverResponse::Generic(resp.into_value_response(true)?)
}
GetTimeouts => {
@ -949,6 +963,27 @@ fn try_convert_to_marionette_message(
Print(ref x) => Some(Command::WebDriver(MarionetteWebDriverCommand::Print(
x.to_marionette()?,
))),
WebAuthnAddVirtualAuthenticator(ref x) => Some(Command::WebDriver(
MarionetteWebDriverCommand::WebAuthnAddVirtualAuthenticator(x.to_marionette()?),
)),
WebAuthnRemoveVirtualAuthenticator => Some(Command::WebDriver(
MarionetteWebDriverCommand::WebAuthnRemoveVirtualAuthenticator,
)),
WebAuthnAddCredential(ref x) => Some(Command::WebDriver(
MarionetteWebDriverCommand::WebAuthnAddCredential(x.to_marionette()?),
)),
WebAuthnGetCredentials => Some(Command::WebDriver(
MarionetteWebDriverCommand::WebAuthnGetCredentials,
)),
WebAuthnRemoveCredential => Some(Command::WebDriver(
MarionetteWebDriverCommand::WebAuthnRemoveCredential,
)),
WebAuthnRemoveAllCredentials => Some(Command::WebDriver(
MarionetteWebDriverCommand::WebAuthnRemoveAllCredentials,
)),
WebAuthnSetUserVerified(ref x) => Some(Command::WebDriver(
MarionetteWebDriverCommand::WebAuthnSetUserVerified(x.to_marionette()?),
)),
Refresh => Some(Command::WebDriver(MarionetteWebDriverCommand::Refresh)),
ReleaseActions => Some(Command::WebDriver(
MarionetteWebDriverCommand::ReleaseActions,
@ -1467,6 +1502,63 @@ impl ToMarionette<MarionettePrintMargins> for PrintMargins {
}
}
impl ToMarionette<MarionetteAuthenticatorParameters> for AuthenticatorParameters {
fn to_marionette(&self) -> WebDriverResult<MarionetteAuthenticatorParameters> {
Ok(MarionetteAuthenticatorParameters {
protocol: self.protocol.to_marionette()?,
transport: self.transport.to_marionette()?,
has_resident_key: self.has_resident_key,
has_user_verification: self.has_user_verification,
is_user_consenting: self.is_user_consenting,
is_user_verified: self.is_user_verified,
})
}
}
impl ToMarionette<MarionetteAuthenticatorTransport> for AuthenticatorTransport {
fn to_marionette(&self) -> WebDriverResult<MarionetteAuthenticatorTransport> {
Ok(match self {
AuthenticatorTransport::Usb => MarionetteAuthenticatorTransport::Usb,
AuthenticatorTransport::Nfc => MarionetteAuthenticatorTransport::Nfc,
AuthenticatorTransport::Ble => MarionetteAuthenticatorTransport::Ble,
AuthenticatorTransport::SmartCard => MarionetteAuthenticatorTransport::SmartCard,
AuthenticatorTransport::Hybrid => MarionetteAuthenticatorTransport::Hybrid,
AuthenticatorTransport::Internal => MarionetteAuthenticatorTransport::Internal,
})
}
}
impl ToMarionette<MarionetteCredentialParameters> for CredentialParameters {
fn to_marionette(&self) -> WebDriverResult<MarionetteCredentialParameters> {
Ok(MarionetteCredentialParameters {
credential_id: self.credential_id.clone(),
is_resident_credential: self.is_resident_credential,
rp_id: self.rp_id.clone(),
private_key: self.private_key.clone(),
user_handle: self.user_handle.clone(),
sign_count: self.sign_count,
})
}
}
impl ToMarionette<MarionetteUserVerificationParameters> for UserVerificationParameters {
fn to_marionette(&self) -> WebDriverResult<MarionetteUserVerificationParameters> {
Ok(MarionetteUserVerificationParameters {
is_user_verified: self.is_user_verified,
})
}
}
impl ToMarionette<MarionetteWebAuthnProtocol> for WebAuthnProtocol {
fn to_marionette(&self) -> WebDriverResult<MarionetteWebAuthnProtocol> {
Ok(match self {
WebAuthnProtocol::Ctap1U2f => MarionetteWebAuthnProtocol::Ctap1U2f,
WebAuthnProtocol::Ctap2 => MarionetteWebAuthnProtocol::Ctap2,
WebAuthnProtocol::Ctap2_1 => MarionetteWebAuthnProtocol::Ctap2_1,
})
}
}
impl ToMarionette<Map<String, Value>> for ActionsParameters {
fn to_marionette(&self) -> WebDriverResult<Map<String, Value>> {
Ok(try_opt!(

Просмотреть файл

@ -48,10 +48,11 @@ from .protocol import (AccessibilityProtocolPart,
def do_delayed_imports():
global errors, marionette, Addons
global errors, marionette, Addons, WebAuthn
from marionette_driver import marionette, errors
from marionette_driver.addons import Addons
from marionette_driver.webauthn import WebAuthn
def _switch_to_window(marionette, handle):
@ -590,28 +591,28 @@ class MarionetteGenerateTestReportProtocolPart(GenerateTestReportProtocolPart):
class MarionetteVirtualAuthenticatorProtocolPart(VirtualAuthenticatorProtocolPart):
def setup(self):
self.marionette = self.parent.marionette
self.webauthn = WebAuthn(self.parent.marionette)
def add_virtual_authenticator(self, config):
raise NotImplementedError("add_virtual_authenticator not yet implemented")
return self.webauthn.add_virtual_authenticator(config)
def remove_virtual_authenticator(self, authenticator_id):
raise NotImplementedError("remove_virtual_authenticator not yet implemented")
self.webauthn.remove_virtual_authenticator(authenticator_id)
def add_credential(self, authenticator_id, credential):
raise NotImplementedError("add_credential not yet implemented")
self.webauthn.add_credential(authenticator_id, credential)
def get_credentials(self, authenticator_id):
raise NotImplementedError("get_credentials not yet implemented")
return self.webauthn.get_credentials(authenticator_id)
def remove_credential(self, authenticator_id, credential_id):
raise NotImplementedError("remove_credential not yet implemented")
self.webauthn.remove_credential(authenticator_id, credential_id)
def remove_all_credentials(self, authenticator_id):
raise NotImplementedError("remove_all_credentials not yet implemented")
self.webauthn.remove_all_credentials(authenticator_id)
def set_user_verified(self, authenticator_id, uv):
raise NotImplementedError("set_user_verified not yet implemented")
self.webauthn.set_user_verified(authenticator_id, uv)
class MarionetteSetPermissionProtocolPart(SetPermissionProtocolPart):

Просмотреть файл

@ -53,6 +53,25 @@ pub trait BrowserCapabilities {
/// Whether a WebSocket URL for the created session has to be returned
fn web_socket_url(&mut self, _: &Capabilities) -> WebDriverResult<bool>;
/// Indicates whether the endpoint node supports all Virtual Authenticators commands.
fn webauthn_virtual_authenticators(&mut self, _: &Capabilities) -> WebDriverResult<bool>;
/// Indicates whether the endpoint node WebAuthn WebDriver implementation supports the User
/// Verification Method extension.
fn webauthn_extension_uvm(&mut self, _: &Capabilities) -> WebDriverResult<bool>;
/// Indicates whether the endpoint node WebAuthn WebDriver implementation supports the prf
/// extension.
fn webauthn_extension_prf(&mut self, _: &Capabilities) -> WebDriverResult<bool>;
/// Indicates whether the endpoint node WebAuthn WebDriver implementation supports the
/// largeBlob extension.
fn webauthn_extension_large_blob(&mut self, _: &Capabilities) -> WebDriverResult<bool>;
/// Indicates whether the endpoint node WebAuthn WebDriver implementation supports the credBlob
/// extension.
fn webauthn_extension_cred_blob(&mut self, _: &Capabilities) -> WebDriverResult<bool>;
fn accept_proxy(
&mut self,
proxy_settings: &Map<String, Value>,
@ -136,7 +155,12 @@ impl SpecNewSessionParameters {
x @ "acceptInsecureCerts"
| x @ "setWindowRect"
| x @ "strictFileInteractability"
| x @ "webSocketUrl" => {
| x @ "webSocketUrl"
| x @ "webauthn:virtualAuthenticators"
| x @ "webauthn:extension:uvm"
| x @ "webauthn:extension:prf"
| x @ "webauthn:extension:largeBlob"
| x @ "webauthn:extension:credBlob" => {
if !value.is_boolean() {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
@ -533,6 +557,51 @@ impl CapabilitiesMatching for SpecNewSessionParameters {
return false;
}
}
"webauthn:virtualAuthenticators" => {
if value.as_bool().unwrap_or(false)
&& !browser_capabilities
.webauthn_virtual_authenticators(merged)
.unwrap_or(false)
{
return false;
}
}
"webauthn:extension:uvm" => {
if value.as_bool().unwrap_or(false)
&& !browser_capabilities
.webauthn_extension_uvm(merged)
.unwrap_or(false)
{
return false;
}
}
"webauthn:extension:prf" => {
if value.as_bool().unwrap_or(false)
&& !browser_capabilities
.webauthn_extension_prf(merged)
.unwrap_or(false)
{
return false;
}
}
"webauthn:extension:largeBlob" => {
if value.as_bool().unwrap_or(false)
&& !browser_capabilities
.webauthn_extension_large_blob(merged)
.unwrap_or(false)
{
return false;
}
}
"webauthn:extension:credBlob" => {
if value.as_bool().unwrap_or(false)
&& !browser_capabilities
.webauthn_extension_cred_blob(merged)
.unwrap_or(false)
{
return false;
}
}
name => {
if name.contains(':') {
if !browser_capabilities

Просмотреть файл

@ -7,7 +7,9 @@ use crate::capabilities::{
BrowserCapabilities, Capabilities, CapabilitiesMatching, LegacyNewSessionParameters,
SpecNewSessionParameters,
};
use crate::common::{Date, FrameId, LocatorStrategy, ShadowRoot, WebElement, MAX_SAFE_INTEGER};
use crate::common::{
CredentialParameters, Date, FrameId, LocatorStrategy, ShadowRoot, WebElement, MAX_SAFE_INTEGER,
};
use crate::error::{ErrorStatus, WebDriverError, WebDriverResult};
use crate::httpapi::{Route, VoidWebDriverExtensionRoute, WebDriverExtensionRoute};
use crate::Parameters;
@ -79,6 +81,13 @@ pub enum WebDriverCommand<T: WebDriverExtensionCommand> {
Print(PrintParameters),
Status,
Extension(T),
WebAuthnAddVirtualAuthenticator(AuthenticatorParameters),
WebAuthnRemoveVirtualAuthenticator,
WebAuthnAddCredential(CredentialParameters),
WebAuthnGetCredentials,
WebAuthnRemoveCredential,
WebAuthnRemoveAllCredentials,
WebAuthnSetUserVerified(UserVerificationParameters),
}
pub trait WebDriverExtensionCommand: Clone + Send {
@ -401,6 +410,21 @@ impl<U: WebDriverExtensionRoute> WebDriverMessage<U> {
Route::Print => WebDriverCommand::Print(serde_json::from_str(raw_body)?),
Route::Status => WebDriverCommand::Status,
Route::Extension(ref extension) => extension.command(params, &body_data)?,
Route::WebAuthnAddVirtualAuthenticator => {
WebDriverCommand::WebAuthnAddVirtualAuthenticator(serde_json::from_str(raw_body)?)
}
Route::WebAuthnRemoveVirtualAuthenticator => {
WebDriverCommand::WebAuthnRemoveVirtualAuthenticator
}
Route::WebAuthnAddCredential => {
WebDriverCommand::WebAuthnAddCredential(serde_json::from_str(raw_body)?)
}
Route::WebAuthnGetCredentials => WebDriverCommand::WebAuthnGetCredentials,
Route::WebAuthnRemoveCredential => WebDriverCommand::WebAuthnRemoveCredential,
Route::WebAuthnRemoveAllCredentials => WebDriverCommand::WebAuthnRemoveAllCredentials,
Route::WebAuthnSetUserVerified => {
WebDriverCommand::WebAuthnSetUserVerified(serde_json::from_str(raw_body)?)
}
};
Ok(WebDriverMessage::new(session_id, command))
}
@ -630,6 +654,52 @@ impl Default for PrintMargins {
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum WebAuthnProtocol {
#[serde(rename = "ctap1/u2f")]
Ctap1U2f,
#[serde(rename = "ctap2")]
Ctap2,
#[serde(rename = "ctap2_1")]
Ctap2_1,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub enum AuthenticatorTransport {
Usb,
Nfc,
Ble,
SmartCard,
Hybrid,
Internal,
}
fn default_as_true() -> bool {
true
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AuthenticatorParameters {
pub protocol: WebAuthnProtocol,
pub transport: AuthenticatorTransport,
#[serde(default)]
pub has_resident_key: bool,
#[serde(default)]
pub has_user_verification: bool,
#[serde(default = "default_as_true")]
pub is_user_consenting: bool,
#[serde(default)]
pub is_user_verified: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct UserVerificationParameters {
#[serde(rename = "isUserVerified")]
pub is_user_verified: bool,
}
fn deserialize_to_positive_f64<'de, D>(deserializer: D) -> Result<f64, D::Error>
where
D: Deserializer<'de>,
@ -1310,6 +1380,47 @@ mod tests {
assert!(serde_json::from_value::<PrintParameters>(json!({"scale": 3})).is_err());
}
#[test]
fn test_json_authenticator() {
let params = AuthenticatorParameters {
protocol: WebAuthnProtocol::Ctap1U2f,
transport: AuthenticatorTransport::Usb,
has_resident_key: false,
has_user_verification: false,
is_user_consenting: false,
is_user_verified: false,
};
assert_de(
&params,
json!({"protocol": "ctap1/u2f", "transport": "usb", "hasResidentKey": false, "hasUserVerification": false, "isUserConsenting": false, "isUserVerified": false}),
);
}
#[test]
fn test_json_credential() {
let encoded_string = base64::encode_config(b"hello internet~", base64::URL_SAFE);
let params = CredentialParameters {
credential_id: r"c3VwZXIgcmVhZGVy".to_string(),
is_resident_credential: true,
rp_id: "valid.rpid".to_string(),
private_key: encoded_string.clone(),
user_handle: encoded_string.clone(),
sign_count: 0,
};
assert_de(
&params,
json!({"credentialId": r"c3VwZXIgcmVhZGVy", "isResidentCredential": true, "rpId": "valid.rpid", "privateKey": encoded_string, "userHandle": encoded_string, "signCount": 0}),
);
}
#[test]
fn test_json_user_verification() {
let params = UserVerificationParameters {
is_user_verified: false,
};
assert_de(&params, json!({"isUserVerified": false}));
}
#[test]
fn test_json_send_keys_parameters_with_value() {
assert_de(

Просмотреть файл

@ -32,6 +32,23 @@ pub struct Cookie {
pub same_site: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct CredentialParameters {
#[serde(rename = "credentialId")]
pub credential_id: String,
#[serde(rename = "isResidentCredential")]
pub is_resident_credential: bool,
#[serde(rename = "rpId")]
pub rp_id: String,
#[serde(rename = "privateKey")]
pub private_key: String,
#[serde(rename = "userHandle")]
#[serde(default)]
pub user_handle: String,
#[serde(rename = "signCount")]
pub sign_count: u64,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Date(pub u64);

Просмотреть файл

@ -308,6 +308,41 @@ pub fn standard_routes<U: WebDriverExtensionRoute>() -> Vec<(Method, &'static st
Route::ReleaseActions,
),
(Method::POST, "/session/{sessionId}/print", Route::Print),
(
Method::POST,
"/sessions/{sessionId}/webauthn/authenticator",
Route::WebAuthnAddVirtualAuthenticator,
),
(
Method::DELETE,
"/sessions/{sessionId}/webauthn/authenticator/{authenticatorId}",
Route::WebAuthnRemoveVirtualAuthenticator,
),
(
Method::POST,
"/sessions/{sessionId}/webauthn/authenticator/{authenticatorId}/credential",
Route::WebAuthnAddCredential,
),
(
Method::GET,
"/sessions/{sessionId}/webauthn/authenticator/{authenticatorId}/credentials",
Route::WebAuthnGetCredentials,
),
(
Method::DELETE,
"/sessions/{sessionId}/webauthn/authenticator/{authenticatorId}/credentials/{credentialId}",
Route::WebAuthnRemoveCredential,
),
(
Method::DELETE,
"/sessions/{sessionId}/webauthn/authenticator/{authenticatorId}/credentials",
Route::WebAuthnRemoveAllCredentials,
),
(
Method::POST,
"/sessions/{sessionId}/webauthn/authenticator/{authenticatorId}/uv",
Route::WebAuthnSetUserVerified,
),
(Method::GET, "/status", Route::Status),
]
}
@ -381,6 +416,13 @@ pub enum Route<U: WebDriverExtensionRoute> {
Print,
Status,
Extension(U),
WebAuthnAddVirtualAuthenticator,
WebAuthnRemoveVirtualAuthenticator,
WebAuthnAddCredential,
WebAuthnGetCredentials,
WebAuthnRemoveCredential,
WebAuthnRemoveAllCredentials,
WebAuthnSetUserVerified,
}
pub trait WebDriverExtensionRoute: Clone + Send + PartialEq {

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use crate::common::Cookie;
use crate::common::{Cookie, CredentialParameters};
use serde::ser::{Serialize, Serializer};
use serde_json::Value;
@ -16,6 +16,8 @@ pub enum WebDriverResponse {
DeleteSession,
ElementRect(ElementRectResponse),
Generic(ValueResponse),
WebAuthnAddVirtualAuthenticator(u64),
WebAuthnGetCredentials(GetCredentialsResponse),
NewSession(NewSessionResponse),
Timeouts(TimeoutsResponse),
Void,
@ -78,6 +80,9 @@ pub struct ElementRectResponse {
pub height: f64,
}
#[derive(Debug, PartialEq, Serialize)]
pub struct GetCredentialsResponse(pub Vec<CredentialParameters>);
#[derive(Debug, PartialEq, Serialize)]
pub struct NewSessionResponse {
#[serde(rename = "sessionId")]