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