Skip to content

Commit

Permalink
feat(core/plugin): add register_uri_scheme_protocol, closes #7330 (#…
Browse files Browse the repository at this point in the history
…7350)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
closes #7330
  • Loading branch information
amrbashir committed Jul 12, 2023
1 parent 71a0240 commit fdaee9a
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changes/plugin-custom-protocol.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'tauri': 'minor:feat'
---

Add `tauri::plugin::Builder::register_uri_scheme_protocol`
9 changes: 9 additions & 0 deletions core/tauri/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1462,6 +1462,15 @@ impl<R: Runtime> Builder<R> {
///
/// * `uri_scheme` The URI scheme to register, such as `example`.
/// * `protocol` the protocol associated with the given URI scheme. It's a function that takes an URL such as `example://localhost/asset.css`.
///
/// # Examples
///
/// ```rust
/// tauri::Builder::default()
/// .register_uri_scheme_protocol("myscheme", |app, req| {
/// tauri::http::ResponseBuilder::new().body(Vec::new())
/// });
/// ```
#[must_use]
pub fn register_uri_scheme_protocol<
N: Into<String>,
Expand Down
20 changes: 17 additions & 3 deletions core/tauri/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ pub struct InnerWindowManager<R: Runtime> {

package_info: PackageInfo,
/// The webview protocols available to all windows.
uri_scheme_protocols: HashMap<String, Arc<CustomProtocol<R>>>,
uri_scheme_protocols: Mutex<HashMap<String, Arc<CustomProtocol<R>>>>,
/// The menu set to all windows.
menu: Option<Menu>,
/// Menu event listeners to all windows.
Expand Down Expand Up @@ -321,7 +321,7 @@ impl<R: Runtime> WindowManager<R> {
tray_icon: context.system_tray_icon,
package_info: context.package_info,
pattern: context.pattern,
uri_scheme_protocols,
uri_scheme_protocols: Mutex::new(uri_scheme_protocols),
menu,
menu_event_listeners: Arc::new(menu_event_listeners),
window_event_listeners: Arc::new(window_event_listeners),
Expand Down Expand Up @@ -350,6 +350,20 @@ impl<R: Runtime> WindowManager<R> {
self.inner.invoke_responder.clone()
}

pub(crate) fn register_uri_scheme_protocol<N: Into<String>>(
&self,
uri_scheme: N,
protocol: Arc<CustomProtocol<R>>,
) {
let uri_scheme = uri_scheme.into();
self
.inner
.uri_scheme_protocols
.lock()
.unwrap()
.insert(uri_scheme, protocol);
}

/// Get the base path to serve data from.
///
/// * In dev mode, this will be based on the `devPath` configuration value.
Expand Down Expand Up @@ -461,7 +475,7 @@ impl<R: Runtime> WindowManager<R> {

let mut registered_scheme_protocols = Vec::new();

for (uri_scheme, protocol) in &self.inner.uri_scheme_protocols {
for (uri_scheme, protocol) in &*self.inner.uri_scheme_protocols.lock().unwrap() {
registered_scheme_protocols.push(uri_scheme.clone());
let protocol = protocol.clone();
let app_handle = Mutex::new(app_handle.clone());
Expand Down
68 changes: 65 additions & 3 deletions core/tauri/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
//! The Tauri plugin extension to expand Tauri functionality.

use crate::{
utils::config::PluginConfig, AppHandle, Invoke, InvokeHandler, PageLoadPayload, RunEvent,
Runtime, Window,
http::{Request as HttpRequest, Response as HttpResponse},
manager::CustomProtocol,
utils::config::PluginConfig,
AppHandle, Invoke, InvokeHandler, PageLoadPayload, RunEvent, Runtime, Window,
};
use serde::de::DeserializeOwned;
use serde_json::Value as JsonValue;
use tauri_macros::default_runtime;

use std::{collections::HashMap, fmt};
use std::{collections::HashMap, fmt, sync::Arc};

/// The result type of Tauri plugin module.
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
Expand Down Expand Up @@ -146,6 +148,7 @@ pub struct Builder<R: Runtime, C: DeserializeOwned = ()> {
on_webview_ready: Box<OnWebviewReady<R>>,
on_event: Box<OnEvent<R>>,
on_drop: Option<Box<OnDrop<R>>>,
uri_scheme_protocols: HashMap<String, Arc<CustomProtocol<R>>>,
}

impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
Expand All @@ -161,6 +164,7 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
on_webview_ready: Box::new(|_| ()),
on_event: Box::new(|_, _| ()),
on_drop: None,
uri_scheme_protocols: Default::default(),
}
}

Expand Down Expand Up @@ -411,6 +415,57 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
self
}

/// Registers a URI scheme protocol available to all webviews.
/// Leverages [setURLSchemeHandler](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/2875766-seturlschemehandler) on macOS,
/// [AddWebResourceRequestedFilter](https://docs.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2.addwebresourcerequestedfilter?view=webview2-dotnet-1.0.774.44) on Windows
/// and [webkit-web-context-register-uri-scheme](https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebContext.html#webkit-web-context-register-uri-scheme) on Linux.
///
/// # Known limitations
///
/// URI scheme protocols are registered when the webview is created. Due to this limitation, if the plugin is registed after a webview has been created, this protocol won't be available.
///
/// # Arguments
///
/// * `uri_scheme` The URI scheme to register, such as `example`.
/// * `protocol` the protocol associated with the given URI scheme. It's a function that takes an URL such as `example://localhost/asset.css`.
///
/// # Examples
///
/// ```rust
/// use tauri::{plugin::{Builder, TauriPlugin}, Runtime};
///
/// fn init<R: Runtime>() -> TauriPlugin<R> {
/// Builder::new("myplugin")
/// .register_uri_scheme_protocol("myscheme", |app, req| {
/// tauri::http::ResponseBuilder::new().body(Vec::new())
/// })
/// .build()
/// }
/// ```
#[must_use]
pub fn register_uri_scheme_protocol<
N: Into<String>,
H: Fn(
&AppHandle<R>,
&HttpRequest,
) -> std::result::Result<HttpResponse, Box<dyn std::error::Error>>
+ Send
+ Sync
+ 'static,
>(
mut self,
uri_scheme: N,
protocol: H,
) -> Self {
self.uri_scheme_protocols.insert(
uri_scheme.into(),
Arc::new(CustomProtocol {
protocol: Box::new(protocol),
}),
);
self
}

/// Builds the [TauriPlugin].
pub fn build(self) -> TauriPlugin<R, C> {
TauriPlugin {
Expand All @@ -424,6 +479,7 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
on_webview_ready: self.on_webview_ready,
on_event: self.on_event,
on_drop: self.on_drop,
uri_scheme_protocols: self.uri_scheme_protocols,
}
}
}
Expand All @@ -440,6 +496,7 @@ pub struct TauriPlugin<R: Runtime, C: DeserializeOwned = ()> {
on_webview_ready: Box<OnWebviewReady<R>>,
on_event: Box<OnEvent<R>>,
on_drop: Option<Box<OnDrop<R>>>,
uri_scheme_protocols: HashMap<String, Arc<CustomProtocol<R>>>,
}

impl<R: Runtime, C: DeserializeOwned> Drop for TauriPlugin<R, C> {
Expand All @@ -463,6 +520,11 @@ impl<R: Runtime, C: DeserializeOwned> Plugin<R> for TauriPlugin<R, C> {
if let Some(s) = self.setup_with_config.take() {
(s)(app, serde_json::from_value(config)?)?;
}
for (uri_scheme, protocol) in &self.uri_scheme_protocols {
app
.manager
.register_uri_scheme_protocol(uri_scheme, protocol.clone())
}
Ok(())
}

Expand Down

0 comments on commit fdaee9a

Please sign in to comment.