use std::sync::{Arc, Mutex};
use bitwarden_crypto::{EncString, SymmetricCryptoKey, safe::PasswordProtectedKeyEnvelope};
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;
use crate::{
Client,
key_management::{
MasterPasswordUnlockData, V2UpgradeToken,
account_cryptographic_state::WrappedAccountCryptographicState,
},
};
pub struct StateBridge {
implementation: Mutex<Option<Arc<dyn StateBridgeImpl + Send + Sync>>>,
}
impl StateBridge {
pub fn new() -> Self {
Self {
implementation: Mutex::new(None),
}
}
pub fn is_registered(&self) -> bool {
self.implementation
.lock()
.expect("Mutex is not poisoned")
.is_some()
}
pub fn register(&self, implementation: Box<dyn StateBridgeImpl + Send + Sync>) {
*self.implementation.lock().expect("Mutex is not poisoned") = Some(implementation.into());
}
}
impl Default for StateBridge {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
#[cfg_attr(feature = "wasm", wasm_bindgen)]
pub struct StateBridgeClient {
pub(crate) client: crate::Client,
}
impl Client {
pub fn km_state_bridge(&self) -> StateBridgeClient {
StateBridgeClient {
client: self.clone(),
}
}
}
impl StateBridgeClient {
pub fn is_bridge_registered(&self) -> bool {
self.client.internal.state_bridge.is_registered()
}
pub fn register_bridge(&self, bridge_impl: Box<dyn StateBridgeImpl + Send + Sync>) {
self.client.internal.state_bridge.register(bridge_impl);
}
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "WasmStateBridge")]
pub type RawWasmStateBridge;
}
#[cfg(target_arch = "wasm32")]
use bitwarden_threading::ThreadBoundRunner;
#[cfg(target_arch = "wasm32")]
pub struct WasmStateBridge(pub(crate) ThreadBoundRunner<RawWasmStateBridge>);
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
impl StateBridgeClient {
pub fn register_bridge_impl(&self, bridge_impl: RawWasmStateBridge) {
self.client
.internal
.state_bridge
.register(Box::new(WasmStateBridge(ThreadBoundRunner::new(
bridge_impl,
))));
}
}
bitwarden_state_bridge_macro::state_bridge! {
user_key: SymmetricCryptoKey as ts "SymmetricKey",
persistent_pin_envelope: PasswordProtectedKeyEnvelope as ts "PasswordProtectedKeyEnvelope",
ephemeral_pin_envelope: PasswordProtectedKeyEnvelope as ts "PasswordProtectedKeyEnvelope",
encrypted_pin: EncString as ts "EncString",
v2_upgrade_token: V2UpgradeToken as ts "V2UpgradeToken",
account_cryptographic_state: WrappedAccountCryptographicState as ts "WrappedAccountCryptographicState",
masterpassword_unlock_data: MasterPasswordUnlockData as ts "MasterPasswordUnlockData",
}