1use std::sync::Arc;
2use tauri::{
3 http,
4 plugin::{Builder, TauriPlugin},
5 Manager, Runtime, UriSchemeContext,
6};
7
8pub use config::{Config, Http, Protocol, Remote, Source};
9
10#[cfg(desktop)]
11mod desktop;
12
13mod config;
14mod error;
15
16pub use error::{Error, Result};
17
18#[cfg(desktop)]
19use desktop::WebviewBundle;
20
21pub trait WebviewBundleExtra<R: Runtime> {
23 fn webview_bundle(&self) -> &WebviewBundle<R>;
24 fn wvb(&self) -> &WebviewBundle<R> {
25 self.webview_bundle()
26 }
27}
28
29impl<R: Runtime, T: Manager<R>> WebviewBundleExtra<R> for T {
30 fn webview_bundle(&self) -> &WebviewBundle<R> {
31 self.state::<WebviewBundle<R>>().inner()
32 }
33}
34
35pub fn init<R: Runtime>(config: Config<R>) -> TauriPlugin<R> {
37 let config = Arc::new(config);
38 let c = config.clone();
39 let mut builder = Builder::<R>::new("webview-bundle").setup(move |app, _api| {
40 #[cfg(desktop)]
41 let webview_bundle = desktop::init(app, c)?;
42 app.manage(webview_bundle);
43 Ok(())
44 });
45 for protocol_config in &config.protocols {
46 let scheme = protocol_config.scheme().to_string();
47 builder = builder.register_asynchronous_uri_scheme_protocol(
48 protocol_config.scheme(),
49 move |ctx: UriSchemeContext<R>, req, res| {
50 let protocol = ctx
51 .app_handle()
52 .webview_bundle()
53 .get_protocol(&scheme)
54 .unwrap_or_else(|| panic!("protocol not found: {scheme}"))
55 .clone();
56 tauri::async_runtime::spawn(async move {
57 match protocol.handle(req).await {
58 Ok(resp) => res.respond(resp),
59 Err(e) => {
60 let resp = http::Response::builder()
61 .status(http::StatusCode::INTERNAL_SERVER_ERROR)
62 .header(http::header::CONTENT_TYPE, "text/plain")
63 .body(
64 format!("webview bundle protocol error: {e}")
65 .as_bytes()
66 .to_vec(),
67 )
68 .unwrap();
69 res.respond(resp);
70 }
71 }
72 });
73 },
74 )
75 }
76 builder.build()
77}