bitwarden_core/key_management/
state_bridge.rs1use std::sync::{Arc, Mutex};
9
10use bitwarden_crypto::{
11 EncString, Kdf, KeyId, SymmetricCryptoKey, safe::PasswordProtectedKeyEnvelope,
12};
13#[cfg(feature = "wasm")]
14use wasm_bindgen::prelude::*;
15
16use crate::{
17 Client,
18 key_management::{
19 MasterPasswordUnlockData, V2UpgradeToken, WebAuthnPrfUnlockData,
20 account_cryptographic_state::WrappedAccountCryptographicState,
21 },
22};
23
24pub struct StateBridge {
26 implementation: Mutex<Option<Arc<dyn StateBridgeImpl + Send + Sync>>>,
27}
28
29impl StateBridge {
30 pub fn new() -> Self {
32 Self {
33 implementation: Mutex::new(None),
34 }
35 }
36
37 pub fn is_registered(&self) -> bool {
39 self.implementation
40 .lock()
41 .expect("Mutex is not poisoned")
42 .is_some()
43 }
44
45 pub fn register(&self, implementation: Box<dyn StateBridgeImpl + Send + Sync>) {
47 *self.implementation.lock().expect("Mutex is not poisoned") = Some(implementation.into());
48 }
49}
50
51impl Default for StateBridge {
52 fn default() -> Self {
53 Self::new()
54 }
55}
56
57#[derive(Clone)]
60#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
61#[cfg_attr(feature = "wasm", wasm_bindgen)]
62pub struct StateBridgeClient {
63 pub(crate) client: crate::Client,
64}
65
66impl Client {
67 pub fn km_state_bridge(&self) -> StateBridgeClient {
69 StateBridgeClient {
70 client: self.clone(),
71 }
72 }
73}
74
75impl StateBridgeClient {
76 pub fn is_bridge_registered(&self) -> bool {
78 self.client.internal.state_bridge.is_registered()
79 }
80
81 pub fn register_bridge(&self, bridge_impl: Box<dyn StateBridgeImpl + Send + Sync>) {
83 self.client.internal.state_bridge.register(bridge_impl);
84 }
85}
86
87#[cfg(target_arch = "wasm32")]
88#[wasm_bindgen]
89extern "C" {
90 #[wasm_bindgen(typescript_type = "WasmStateBridge")]
94 pub type RawWasmStateBridge;
95}
96
97#[cfg(target_arch = "wasm32")]
98use bitwarden_threading::ThreadBoundRunner;
99
100#[cfg(target_arch = "wasm32")]
101pub struct WasmStateBridge(pub(crate) ThreadBoundRunner<RawWasmStateBridge>);
105
106#[cfg(target_arch = "wasm32")]
107#[wasm_bindgen]
108impl StateBridgeClient {
109 pub fn register_bridge_impl(&self, bridge_impl: RawWasmStateBridge) {
111 self.client
112 .internal
113 .state_bridge
114 .register(Box::new(WasmStateBridge(ThreadBoundRunner::new(
115 bridge_impl,
116 ))));
117 }
118}
119
120#[cfg(feature = "uniffi")]
121pub struct UniffiStateBridge(pub(crate) Arc<dyn StateBridgeForeignImpl>);
125
126#[cfg(feature = "uniffi")]
127#[uniffi::export]
128impl StateBridgeClient {
129 pub fn register_bridge_impl(&self, bridge_impl: Arc<dyn StateBridgeForeignImpl>) {
131 self.client
132 .internal
133 .state_bridge
134 .register(Box::new(UniffiStateBridge(bridge_impl)));
135 }
136}
137
138bitwarden_state_bridge_macro::state_bridge! {
146 user_key: SymmetricCryptoKey as ts "SymmetricKey",
147 user_key_id: KeyId as ts "KeyId",
148 persistent_pin_envelope: PasswordProtectedKeyEnvelope as ts "PasswordProtectedKeyEnvelope",
149 ephemeral_pin_envelope: PasswordProtectedKeyEnvelope as ts "PasswordProtectedKeyEnvelope",
150 encrypted_pin: EncString as ts "EncString",
151 v2_upgrade_token: V2UpgradeToken as ts "V2UpgradeToken",
152 account_cryptographic_state: WrappedAccountCryptographicState as ts "WrappedAccountCryptographicState",
153 masterpassword_unlock_data: MasterPasswordUnlockData as ts "MasterPasswordUnlockData",
154 webauthn_prf_unlock_data: WebAuthnPrfUnlockData as ts "WebAuthnPrfUnlockData",
155 kdf_config: Kdf as ts "Kdf",
156}