fission_shell_winit/
biometric.rs1use fission_core::{
2 BiometricAuthenticateRequest, BiometricAuthenticateResult, BiometricAvailability,
3 BiometricError, BiometricKind, AUTHENTICATE_BIOMETRIC, CANCEL_BIOMETRIC_AUTHENTICATION,
4 GET_BIOMETRIC_AVAILABILITY,
5};
6use fission_shell::async_host::AsyncRegistry;
7use std::sync::Arc;
8
9pub trait BiometricHost: Send + Sync + 'static {
11 fn availability(&self) -> Result<BiometricAvailability, BiometricError>;
13 fn authenticate(
18 &self,
19 request: BiometricAuthenticateRequest,
20 ) -> Result<BiometricAuthenticateResult, BiometricError>;
21 fn cancel_authentication(&self) -> Result<(), BiometricError>;
23}
24
25#[derive(Debug, Default)]
27pub struct UnsupportedBiometricHost;
28
29impl BiometricHost for UnsupportedBiometricHost {
30 fn availability(&self) -> Result<BiometricAvailability, BiometricError> {
31 Ok(BiometricAvailability {
32 reason: Some("biometric authentication is not supported by this host".into()),
33 ..Default::default()
34 })
35 }
36
37 fn authenticate(
38 &self,
39 _request: BiometricAuthenticateRequest,
40 ) -> Result<BiometricAuthenticateResult, BiometricError> {
41 Err(BiometricError::unsupported("authenticate"))
42 }
43
44 fn cancel_authentication(&self) -> Result<(), BiometricError> {
45 Err(BiometricError::unsupported("cancel_authentication"))
46 }
47}
48
49#[derive(Debug, Clone)]
51pub struct MemoryBiometricHost {
52 availability: BiometricAvailability,
53 result: BiometricAuthenticateResult,
54}
55
56impl MemoryBiometricHost {
57 pub fn new(availability: BiometricAvailability, result: BiometricAuthenticateResult) -> Self {
58 Self {
59 availability,
60 result,
61 }
62 }
63}
64
65impl Default for MemoryBiometricHost {
66 fn default() -> Self {
67 Self {
68 availability: BiometricAvailability {
69 supported: true,
70 enrolled: true,
71 strong: true,
72 weak: true,
73 device_credential: true,
74 kinds: vec![BiometricKind::Face, BiometricKind::Fingerprint],
75 reason: None,
76 },
77 result: BiometricAuthenticateResult {
78 verified: true,
79 kind: Some(BiometricKind::Face),
80 used_device_credential: false,
81 },
82 }
83 }
84}
85
86impl BiometricHost for MemoryBiometricHost {
87 fn availability(&self) -> Result<BiometricAvailability, BiometricError> {
88 Ok(self.availability.clone())
89 }
90
91 fn authenticate(
92 &self,
93 _request: BiometricAuthenticateRequest,
94 ) -> Result<BiometricAuthenticateResult, BiometricError> {
95 Ok(self.result.clone())
96 }
97
98 fn cancel_authentication(&self) -> Result<(), BiometricError> {
99 Ok(())
100 }
101}
102
103pub(crate) fn register_biometric_capabilities(
104 async_registry: &mut AsyncRegistry,
105 host: Arc<dyn BiometricHost>,
106) {
107 let availability_host = host.clone();
108 async_registry.register_operation_capability(GET_BIOMETRIC_AVAILABILITY, move |(), _| {
109 let host = availability_host.clone();
110 async move { host.availability() }
111 });
112
113 let authenticate_host = host.clone();
114 async_registry.register_operation_capability(AUTHENTICATE_BIOMETRIC, move |request, _| {
115 let host = authenticate_host.clone();
116 async move { host.authenticate(request) }
117 });
118
119 async_registry.register_operation_capability(CANCEL_BIOMETRIC_AUTHENTICATION, move |(), _| {
120 let host = host.clone();
121 async move { host.cancel_authentication() }
122 });
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn unsupported_host_reports_unavailable() {
131 let host = UnsupportedBiometricHost;
132 let availability = host.availability().unwrap();
133
134 assert!(!availability.supported);
135 assert!(host
136 .authenticate(BiometricAuthenticateRequest::default())
137 .is_err());
138 }
139
140 #[test]
141 fn memory_host_authenticates() {
142 let host = MemoryBiometricHost::default();
143 let availability = host.availability().unwrap();
144 assert!(availability.supported);
145
146 let result = host
147 .authenticate(BiometricAuthenticateRequest {
148 reason: "Unlock".into(),
149 ..Default::default()
150 })
151 .unwrap();
152 assert!(result.verified);
153 }
154}