bitwarden_ipc/wasm/
ipc_client.rs1use std::{collections::HashMap, sync::Arc};
2
3use bitwarden_threading::cancellation_token::wasm::{AbortSignal, AbortSignalExt};
4use wasm_bindgen::prelude::*;
5
6use super::communication_backend::JsCommunicationBackend;
7use crate::{
8 IpcClientImpl,
9 crypto_provider::noise::crypto_provider::NoiseCryptoProvider,
10 error::{AlreadyRunningError, ReceiveError, SubscribeError},
11 ipc_client::IpcClientSubscription,
12 ipc_client_trait::IpcClient,
13 message::{IncomingMessage, OutgoingMessage},
14 traits::InMemorySessionRepository,
15 wasm::{
16 JsSessionRepository, RawJsSessionRepository,
17 generic_session_repository::GenericSessionRepository,
18 },
19};
20
21#[wasm_bindgen(js_name = IpcClient)]
24pub struct JsIpcClient {
25 #[wasm_bindgen(skip)]
26 pub client: Arc<dyn IpcClient>,
31}
32
33#[wasm_bindgen(js_name = IpcClientSubscription)]
36pub struct JsIpcClientSubscription {
37 subscription: IpcClientSubscription,
38}
39
40#[bitwarden_ffi::wasm_export]
41#[wasm_bindgen(js_class = IpcClientSubscription)]
42impl JsIpcClientSubscription {
43 #[wasm_only(
44 note = "Use the `subscribe` method on `IpcClient` to create a subscription instance."
45 )]
46 #[allow(missing_docs)]
47 pub async fn receive(
48 &mut self,
49 abort_signal: Option<AbortSignal>,
50 ) -> Result<IncomingMessage, ReceiveError> {
51 let cancellation_token = abort_signal.map(|signal| signal.to_cancellation_token());
52 self.subscription.receive(cancellation_token).await
53 }
54}
55
56#[bitwarden_ffi::wasm_export]
57#[wasm_bindgen(js_class = IpcClient)]
58impl JsIpcClient {
59 #[wasm_only]
62 #[wasm_bindgen(js_name = newWithSdkInMemorySessions)]
63 pub fn new_with_sdk_in_memory_sessions(
64 communication_provider: &JsCommunicationBackend,
65 ) -> JsIpcClient {
66 JsIpcClient {
67 client: Arc::new(IpcClientImpl::new(
68 NoiseCryptoProvider,
69 communication_provider.clone(),
70 GenericSessionRepository::InMemory(Arc::new(InMemorySessionRepository::new(
71 HashMap::new(),
72 ))),
73 )),
74 }
75 }
76
77 #[wasm_only]
80 #[wasm_bindgen(js_name = newWithClientManagedSessions)]
81 pub fn new_with_client_managed_sessions(
82 communication_provider: &JsCommunicationBackend,
83 session_repository: RawJsSessionRepository,
84 ) -> JsIpcClient {
85 JsIpcClient {
86 client: Arc::new(IpcClientImpl::new(
87 NoiseCryptoProvider,
88 communication_provider.clone(),
89 GenericSessionRepository::JsSessionRepository(Arc::new(JsSessionRepository::new(
90 session_repository,
91 ))),
92 )),
93 }
94 }
95
96 #[wasm_only]
97 #[allow(missing_docs)]
98 pub async fn start(
99 &self,
100 abort_signal: Option<AbortSignal>,
101 ) -> Result<(), AlreadyRunningError> {
102 self.client
103 .start(abort_signal.map(|signal| signal.to_cancellation_token()))
104 .await
105 }
106
107 #[wasm_only]
108 #[wasm_bindgen(js_name = isRunning)]
109 #[allow(missing_docs)]
110 pub fn is_running(&self) -> bool {
111 self.client.is_running()
112 }
113
114 #[wasm_only]
115 #[allow(missing_docs)]
116 pub async fn send(&self, message: OutgoingMessage) -> Result<(), JsError> {
117 self.client
118 .send(message)
119 .await
120 .map_err(|e| JsError::new(&e.to_string()))
121 }
122
123 #[wasm_only]
124 #[allow(missing_docs)]
125 pub async fn subscribe(&self) -> Result<JsIpcClientSubscription, SubscribeError> {
126 let subscription = self.client.subscribe(None).await?;
127 Ok(JsIpcClientSubscription { subscription })
128 }
129}