1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use crate::errors;
6 use crate::platform::monitor::{FidoDev, Monitor};
7 use crate::statecallback::StateCallback;
8 use runloop::RunLoop;
9 
10 pub struct Transaction {
11     // Handle to the thread loop.
12     thread: Option<RunLoop>,
13 }
14 
15 impl Transaction {
new<F, T>( timeout: u64, callback: StateCallback<crate::Result<T>>, new_device_cb: F, ) -> crate::Result<Self> where F: Fn(FidoDev, &dyn Fn() -> bool) + Sync + Send + 'static, T: 'static,16     pub fn new<F, T>(
17         timeout: u64,
18         callback: StateCallback<crate::Result<T>>,
19         new_device_cb: F,
20     ) -> crate::Result<Self>
21     where
22         F: Fn(FidoDev, &dyn Fn() -> bool) + Sync + Send + 'static,
23         T: 'static,
24     {
25         let thread = RunLoop::new_with_timeout(
26             move |alive| {
27                 // Create a new device monitor.
28                 let mut monitor = Monitor::new(new_device_cb);
29 
30                 // Start polling for new devices.
31                 try_or!(monitor.run(alive), |_| callback
32                     .call(Err(errors::AuthenticatorError::Platform)));
33 
34                 // Send an error, if the callback wasn't called already.
35                 callback.call(Err(errors::AuthenticatorError::U2FToken(
36                     errors::U2FTokenError::NotAllowed,
37                 )));
38             },
39             timeout,
40         )
41         .map_err(|_| errors::AuthenticatorError::Platform)?;
42 
43         Ok(Self {
44             thread: Some(thread),
45         })
46     }
47 
cancel(&mut self)48     pub fn cancel(&mut self) {
49         // This must never be None.
50         self.thread.take().unwrap().cancel();
51     }
52 }
53