1use std::{
10 future::Future,
11 sync::{Arc, Mutex},
12};
13
14use http::HeaderMap;
15use serde::{
16 de::{DeserializeOwned, IntoDeserializer},
17 Deserialize, Serialize,
18};
19use serde_json::Value as JsonValue;
20pub use serialize_to_javascript::Options as SerializeOptions;
21use tauri_macros::default_runtime;
22use tauri_utils::acl::resolved::ResolvedCommand;
23
24use crate::{webview::Webview, Runtime, StateManager};
25
26mod authority;
27#[cfg(feature = "dynamic-acl")]
28mod capability_builder;
29pub(crate) mod channel;
30mod command;
31pub(crate) mod format_callback;
32pub(crate) mod protocol;
33
34pub use authority::{
35 CommandScope, GlobalScope, Origin, RuntimeAuthority, ScopeObject, ScopeObjectMatch, ScopeValue,
36};
37#[cfg(feature = "dynamic-acl")]
38pub use capability_builder::{CapabilityBuilder, RuntimeCapability};
39pub use channel::{Channel, JavaScriptChannelId};
40pub use command::{private, CommandArg, CommandItem};
41
42pub type InvokeHandler<R> = dyn Fn(Invoke<R>) -> bool + Send + Sync + 'static;
44
45pub type InvokeResponder<R> =
47 dyn Fn(&Webview<R>, &str, &InvokeResponse, CallbackFn, CallbackFn) + Send + Sync + 'static;
48pub type OwnedInvokeResponder<R> =
50 dyn FnOnce(Webview<R>, String, InvokeResponse, CallbackFn, CallbackFn) + Send + 'static;
51
52#[derive(Debug, Clone)]
58#[cfg_attr(test, derive(PartialEq))]
59pub enum InvokeBody {
60 Json(JsonValue),
62 Raw(Vec<u8>),
64}
65
66impl Default for InvokeBody {
67 fn default() -> Self {
68 Self::Json(Default::default())
69 }
70}
71
72impl From<JsonValue> for InvokeBody {
73 fn from(value: JsonValue) -> Self {
74 Self::Json(value)
75 }
76}
77
78impl From<Vec<u8>> for InvokeBody {
79 fn from(value: Vec<u8>) -> Self {
80 Self::Raw(value)
81 }
82}
83
84impl InvokeBody {
85 #[cfg(mobile)]
86 pub(crate) fn into_json(self) -> JsonValue {
87 match self {
88 Self::Json(v) => v,
89 Self::Raw(v) => {
90 JsonValue::Array(v.into_iter().map(|n| JsonValue::Number(n.into())).collect())
91 }
92 }
93 }
94}
95
96#[derive(Debug, Clone)]
98#[cfg_attr(test, derive(PartialEq))]
99pub enum InvokeResponseBody {
100 Json(String),
102 Raw(Vec<u8>),
104}
105
106impl From<String> for InvokeResponseBody {
107 fn from(value: String) -> Self {
108 Self::Json(value)
109 }
110}
111
112impl From<Vec<u8>> for InvokeResponseBody {
113 fn from(value: Vec<u8>) -> Self {
114 Self::Raw(value)
115 }
116}
117
118impl From<InvokeBody> for InvokeResponseBody {
119 fn from(value: InvokeBody) -> Self {
120 match value {
121 InvokeBody::Json(v) => Self::Json(serde_json::to_string(&v).unwrap()),
122 InvokeBody::Raw(v) => Self::Raw(v),
123 }
124 }
125}
126
127impl IpcResponse for InvokeResponseBody {
128 fn body(self) -> crate::Result<InvokeResponseBody> {
129 Ok(self)
130 }
131}
132
133impl InvokeResponseBody {
134 pub fn deserialize<T: DeserializeOwned>(self) -> serde_json::Result<T> {
136 match self {
137 Self::Json(v) => serde_json::from_str(&v),
138 Self::Raw(v) => T::deserialize(v.into_deserializer()),
139 }
140 }
141}
142
143#[derive(Debug)]
148pub struct Request<'a> {
149 body: &'a InvokeBody,
150 headers: &'a HeaderMap,
151}
152
153impl Request<'_> {
154 pub fn body(&self) -> &InvokeBody {
156 self.body
157 }
158
159 pub fn headers(&self) -> &HeaderMap {
161 self.headers
162 }
163}
164
165impl<'a, R: Runtime> CommandArg<'a, R> for Request<'a> {
166 fn from_command(command: CommandItem<'a, R>) -> Result<Self, InvokeError> {
168 Ok(Self {
169 body: command.message.payload(),
170 headers: command.message.headers(),
171 })
172 }
173}
174
175pub trait IpcResponse {
177 fn body(self) -> crate::Result<InvokeResponseBody>;
179}
180
181impl<T: Serialize> IpcResponse for T {
182 fn body(self) -> crate::Result<InvokeResponseBody> {
183 serde_json::to_string(&self)
184 .map(Into::into)
185 .map_err(Into::into)
186 }
187}
188
189pub struct Response {
191 body: InvokeResponseBody,
192}
193
194impl IpcResponse for Response {
195 fn body(self) -> crate::Result<InvokeResponseBody> {
196 Ok(self.body)
197 }
198}
199
200impl Response {
201 pub fn new(body: impl Into<InvokeResponseBody>) -> Self {
203 Self { body: body.into() }
204 }
205}
206
207#[default_runtime(crate::Wry, wry)]
211pub struct Invoke<R: Runtime> {
212 pub message: InvokeMessage<R>,
214
215 pub resolver: InvokeResolver<R>,
217
218 pub acl: Option<Vec<ResolvedCommand>>,
220}
221
222#[derive(Debug)]
224pub struct InvokeError(pub serde_json::Value);
225
226impl InvokeError {
227 #[inline(always)]
229 pub fn from_error<E: std::error::Error>(error: E) -> Self {
230 Self(serde_json::Value::String(error.to_string()))
231 }
232
233 #[inline(always)]
235 pub fn from_anyhow(error: anyhow::Error) -> Self {
236 Self(serde_json::Value::String(format!("{error:#}")))
237 }
238}
239
240impl<T: Serialize> From<T> for InvokeError {
241 #[inline]
242 fn from(value: T) -> Self {
243 serde_json::to_value(value)
244 .map(Self)
245 .unwrap_or_else(Self::from_error)
246 }
247}
248
249impl From<crate::Error> for InvokeError {
250 #[inline(always)]
251 fn from(error: crate::Error) -> Self {
252 Self(serde_json::Value::String(error.to_string()))
253 }
254}
255
256#[derive(Debug)]
258pub enum InvokeResponse {
259 Ok(InvokeResponseBody),
261 Err(InvokeError),
263}
264
265impl<T: IpcResponse, E: Into<InvokeError>> From<Result<T, E>> for InvokeResponse {
266 #[inline]
267 fn from(result: Result<T, E>) -> Self {
268 match result {
269 Ok(ok) => match ok.body() {
270 Ok(value) => Self::Ok(value),
271 Err(err) => Self::Err(InvokeError::from_error(err)),
272 },
273 Err(err) => Self::Err(err.into()),
274 }
275 }
276}
277
278impl From<InvokeError> for InvokeResponse {
279 fn from(error: InvokeError) -> Self {
280 Self::Err(error)
281 }
282}
283
284#[default_runtime(crate::Wry, wry)]
286pub struct InvokeResolver<R: Runtime> {
287 webview: Webview<R>,
288 responder: Arc<Mutex<Option<Box<OwnedInvokeResponder<R>>>>>,
289 cmd: String,
290 pub(crate) callback: CallbackFn,
291 pub(crate) error: CallbackFn,
292}
293
294impl<R: Runtime> Clone for InvokeResolver<R> {
295 fn clone(&self) -> Self {
296 Self {
297 webview: self.webview.clone(),
298 responder: self.responder.clone(),
299 cmd: self.cmd.clone(),
300 callback: self.callback,
301 error: self.error,
302 }
303 }
304}
305
306impl<R: Runtime> InvokeResolver<R> {
307 pub(crate) fn new(
308 webview: Webview<R>,
309 responder: Arc<Mutex<Option<Box<OwnedInvokeResponder<R>>>>>,
310 cmd: String,
311 callback: CallbackFn,
312 error: CallbackFn,
313 ) -> Self {
314 Self {
315 webview,
316 responder,
317 cmd,
318 callback,
319 error,
320 }
321 }
322
323 pub fn respond_async<T, F>(self, task: F)
325 where
326 T: IpcResponse,
327 F: Future<Output = Result<T, InvokeError>> + Send + 'static,
328 {
329 crate::async_runtime::spawn(async move {
330 Self::return_task(
331 self.webview,
332 self.responder,
333 task,
334 self.cmd,
335 self.callback,
336 self.error,
337 )
338 .await;
339 });
340 }
341
342 pub fn respond_async_serialized<F>(self, task: F)
344 where
345 F: Future<Output = Result<InvokeResponseBody, InvokeError>> + Send + 'static,
346 {
347 #[cfg(debug_assertions)]
350 {
351 self.respond_async_serialized_dyn(Box::pin(task))
352 }
353 #[cfg(not(debug_assertions))]
354 {
355 self.respond_async_serialized_inner(task)
356 }
357 }
358
359 #[cfg(debug_assertions)]
361 fn respond_async_serialized_dyn(
362 self,
363 task: std::pin::Pin<
364 Box<dyn Future<Output = Result<InvokeResponseBody, InvokeError>> + Send + 'static>,
365 >,
366 ) {
367 self.respond_async_serialized_inner(task)
368 }
369
370 fn respond_async_serialized_inner<F>(self, task: F)
372 where
373 F: Future<Output = Result<InvokeResponseBody, InvokeError>> + Send + 'static,
374 {
375 crate::async_runtime::spawn(async move {
376 let response = match task.await {
377 Ok(ok) => InvokeResponse::Ok(ok),
378 Err(err) => InvokeResponse::Err(err),
379 };
380 Self::return_result(
381 self.webview,
382 self.responder,
383 response,
384 self.cmd,
385 self.callback,
386 self.error,
387 )
388 });
389 }
390
391 pub fn respond<T: IpcResponse>(self, value: Result<T, InvokeError>) {
393 Self::return_result(
394 self.webview,
395 self.responder,
396 value.into(),
397 self.cmd,
398 self.callback,
399 self.error,
400 )
401 }
402
403 pub fn resolve<T: IpcResponse>(self, value: T) {
405 self.respond(Ok(value))
406 }
407
408 pub fn reject<T: Serialize>(self, value: T) {
410 Self::return_result(
411 self.webview,
412 self.responder,
413 Result::<(), _>::Err(value).into(),
414 self.cmd,
415 self.callback,
416 self.error,
417 )
418 }
419
420 pub fn invoke_error(self, error: InvokeError) {
422 Self::return_result(
423 self.webview,
424 self.responder,
425 error.into(),
426 self.cmd,
427 self.callback,
428 self.error,
429 )
430 }
431
432 pub async fn return_task<T, F>(
438 webview: Webview<R>,
439 responder: Arc<Mutex<Option<Box<OwnedInvokeResponder<R>>>>>,
440 task: F,
441 cmd: String,
442 success_callback: CallbackFn,
443 error_callback: CallbackFn,
444 ) where
445 T: IpcResponse,
446 F: Future<Output = Result<T, InvokeError>> + Send + 'static,
447 {
448 let result = task.await;
449 Self::return_closure(
450 webview,
451 responder,
452 || result,
453 cmd,
454 success_callback,
455 error_callback,
456 )
457 }
458
459 pub(crate) fn return_closure<T: IpcResponse, F: FnOnce() -> Result<T, InvokeError>>(
460 webview: Webview<R>,
461 responder: Arc<Mutex<Option<Box<OwnedInvokeResponder<R>>>>>,
462 f: F,
463 cmd: String,
464 success_callback: CallbackFn,
465 error_callback: CallbackFn,
466 ) {
467 Self::return_result(
468 webview,
469 responder,
470 f().into(),
471 cmd,
472 success_callback,
473 error_callback,
474 )
475 }
476
477 pub(crate) fn return_result(
478 webview: Webview<R>,
479 responder: Arc<Mutex<Option<Box<OwnedInvokeResponder<R>>>>>,
480 response: InvokeResponse,
481 cmd: String,
482 success_callback: CallbackFn,
483 error_callback: CallbackFn,
484 ) {
485 (responder.lock().unwrap().take().expect("resolver consumed"))(
486 webview,
487 cmd,
488 response,
489 success_callback,
490 error_callback,
491 );
492 }
493}
494
495#[default_runtime(crate::Wry, wry)]
497#[derive(Debug)]
498pub struct InvokeMessage<R: Runtime> {
499 pub(crate) webview: Webview<R>,
501 pub(crate) state: Arc<StateManager>,
503 pub(crate) command: String,
505 pub(crate) payload: InvokeBody,
507 pub(crate) headers: HeaderMap,
509}
510
511impl<R: Runtime> Clone for InvokeMessage<R> {
512 fn clone(&self) -> Self {
513 Self {
514 webview: self.webview.clone(),
515 state: self.state.clone(),
516 command: self.command.clone(),
517 payload: self.payload.clone(),
518 headers: self.headers.clone(),
519 }
520 }
521}
522
523impl<R: Runtime> InvokeMessage<R> {
524 pub(crate) fn new(
526 webview: Webview<R>,
527 state: Arc<StateManager>,
528 command: String,
529 payload: InvokeBody,
530 headers: HeaderMap,
531 ) -> Self {
532 Self {
533 webview,
534 state,
535 command,
536 payload,
537 headers,
538 }
539 }
540
541 #[inline(always)]
543 pub fn command(&self) -> &str {
544 &self.command
545 }
546
547 #[inline(always)]
549 pub fn webview(&self) -> Webview<R> {
550 self.webview.clone()
551 }
552
553 #[inline(always)]
555 pub fn webview_ref(&self) -> &Webview<R> {
556 &self.webview
557 }
558
559 #[inline(always)]
561 pub fn payload(&self) -> &InvokeBody {
562 &self.payload
563 }
564
565 #[inline(always)]
567 pub fn state(&self) -> Arc<StateManager> {
568 self.state.clone()
569 }
570
571 #[inline(always)]
573 pub fn state_ref(&self) -> &StateManager {
574 &self.state
575 }
576
577 #[inline(always)]
579 pub fn headers(&self) -> &HeaderMap {
580 &self.headers
581 }
582}
583
584#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)]
586pub struct CallbackFn(pub u32);
587
588#[cfg(test)]
589mod tests {
590 use super::*;
591
592 #[test]
593 fn deserialize_invoke_response_body() {
594 let json = InvokeResponseBody::Json("[1, 123, 1231]".to_string());
595 assert_eq!(json.deserialize::<Vec<u16>>().unwrap(), vec![1, 123, 1231]);
596
597 let json = InvokeResponseBody::Json("\"string value\"".to_string());
598 assert_eq!(json.deserialize::<String>().unwrap(), "string value");
599
600 let json = InvokeResponseBody::Json("\"string value\"".to_string());
601 assert!(json.deserialize::<Vec<u16>>().is_err());
602
603 let values = vec![1, 2, 3, 4, 5, 6, 1];
604 let raw = InvokeResponseBody::Raw(values.clone());
605 assert_eq!(raw.deserialize::<Vec<u8>>().unwrap(), values);
606 }
607}