Skip to content

Commit

Permalink
refactor(core)!: pass webview label to uri scheme protocol handlers (#…
Browse files Browse the repository at this point in the history
…11163)

* refactor!(core): pass webview label to uri scheme protocol handlers

close #10691

* Add `UriSchemeContext`

* doctests
  • Loading branch information
amrbashir authored Sep 29, 2024
1 parent 12de4fa commit 354be36
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 25 deletions.
9 changes: 9 additions & 0 deletions .changes/custom-protocol-label.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"tauri": "patch:breaking"
---

Changed uri scheme protocol handler to take `UriSchemeContext` as first argument instead of `AppHandle`. `UriSchemeContext` can be used to access an app handle or the webview label that made the request. The following methods are affected:
- `tauri::Builder::register_uri_scheme_protocol`
- `tauri::Builder::register_asynchronous_uri_scheme_protocol`
- `tauri::plugin::Builder::register_uri_scheme_protocol`
- `tauri::plugin::Builder::register_asynchronous_uri_scheme_protocol`
34 changes: 28 additions & 6 deletions crates/tauri/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,7 @@ tauri::Builder::default()
}

/// 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.
Expand All @@ -1677,7 +1678,7 @@ tauri::Builder::default()
/// # Examples
/// ```
/// tauri::Builder::default()
/// .register_uri_scheme_protocol("app-files", |_app, request| {
/// .register_uri_scheme_protocol("app-files", |_ctx, request| {
/// // skip leading `/`
/// if let Ok(data) = std::fs::read(&request.uri().path()[1..]) {
/// http::Response::builder()
Expand All @@ -1696,7 +1697,10 @@ tauri::Builder::default()
pub fn register_uri_scheme_protocol<
N: Into<String>,
T: Into<Cow<'static, [u8]>>,
H: Fn(&AppHandle<R>, http::Request<Vec<u8>>) -> http::Response<T> + Send + Sync + 'static,
H: Fn(UriSchemeContext<'_, R>, http::Request<Vec<u8>>) -> http::Response<T>
+ Send
+ Sync
+ 'static,
>(
mut self,
uri_scheme: N,
Expand All @@ -1705,8 +1709,8 @@ tauri::Builder::default()
self.uri_scheme_protocols.insert(
uri_scheme.into(),
Arc::new(UriSchemeProtocol {
protocol: Box::new(move |app, request, responder| {
responder.respond(protocol(app, request))
protocol: Box::new(move |ctx, request, responder| {
responder.respond(protocol(ctx, request))
}),
}),
);
Expand All @@ -1724,7 +1728,7 @@ tauri::Builder::default()
/// # Examples
/// ```
/// tauri::Builder::default()
/// .register_asynchronous_uri_scheme_protocol("app-files", |_app, request, responder| {
/// .register_asynchronous_uri_scheme_protocol("app-files", |_ctx, request, responder| {
/// // skip leading `/`
/// let path = request.uri().path()[1..].to_string();
/// std::thread::spawn(move || {
Expand All @@ -1749,7 +1753,7 @@ tauri::Builder::default()
#[must_use]
pub fn register_asynchronous_uri_scheme_protocol<
N: Into<String>,
H: Fn(&AppHandle<R>, http::Request<Vec<u8>>, UriSchemeResponder) + Send + Sync + 'static,
H: Fn(UriSchemeContext<'_, R>, http::Request<Vec<u8>>, UriSchemeResponder) + Send + Sync + 'static,
>(
mut self,
uri_scheme: N,
Expand Down Expand Up @@ -2001,6 +2005,24 @@ impl UriSchemeResponder {
}
}

/// Uri scheme protocol context
pub struct UriSchemeContext<'a, R: Runtime> {
pub(crate) app_handle: &'a AppHandle<R>,
pub(crate) webview_label: &'a str,
}

impl<'a, R: Runtime> UriSchemeContext<'a, R> {
/// Get a reference to an [`AppHandle`].
pub fn app_handle(&self) -> &'a AppHandle<R> {
self.app_handle
}

/// Get the webview label that made the uri scheme request.
pub fn webview_label(&self) -> &'a str {
self.webview_label
}
}

#[cfg(target_os = "macos")]
fn init_app_menu<R: Runtime>(menu: &Menu<R>) -> crate::Result<()> {
menu.inner().init_for_nsapp();
Expand Down
4 changes: 2 additions & 2 deletions crates/tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ pub use self::utils::TitleBarStyle;
pub use self::event::{Event, EventId, EventTarget};
pub use {
self::app::{
App, AppHandle, AssetResolver, Builder, CloseRequestApi, RunEvent, UriSchemeResponder,
WebviewEvent, WindowEvent,
App, AppHandle, AssetResolver, Builder, CloseRequestApi, RunEvent, UriSchemeContext,
UriSchemeResponder, WebviewEvent, WindowEvent,
},
self::manager::Asset,
self::runtime::{
Expand Down
21 changes: 12 additions & 9 deletions crates/tauri/src/manager/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use crate::{
pattern::PatternJavascript,
sealed::ManagerBase,
webview::PageLoadPayload,
AppHandle, Emitter, EventLoopMessage, EventTarget, Manager, Runtime, Scopes, Webview, Window,
Emitter, EventLoopMessage, EventTarget, Manager, Runtime, Scopes, UriSchemeContext, Webview,
Window,
};

use super::{
Expand Down Expand Up @@ -61,7 +62,7 @@ pub struct UriSchemeProtocol<R: Runtime> {
/// Handler for protocol
#[allow(clippy::type_complexity)]
pub protocol:
Box<dyn Fn(&AppHandle<R>, http::Request<Vec<u8>>, UriSchemeResponder) + Send + Sync>,
Box<dyn Fn(UriSchemeContext<'_, R>, http::Request<Vec<u8>>, UriSchemeResponder) + Send + Sync>,
}

pub struct WebviewManager<R: Runtime> {
Expand Down Expand Up @@ -210,13 +211,15 @@ impl<R: Runtime> WebviewManager<R> {
for (uri_scheme, protocol) in &*self.uri_scheme_protocols.lock().unwrap() {
registered_scheme_protocols.push(uri_scheme.clone());
let protocol = protocol.clone();
let app_handle = Mutex::new(manager.app_handle().clone());
pending.register_uri_scheme_protocol(uri_scheme.clone(), move |p, responder| {
(protocol.protocol)(
&app_handle.lock().unwrap(),
p,
UriSchemeResponder(responder),
)
let app_handle = manager.app_handle().clone();
let webview_label = label.to_string();

pending.register_uri_scheme_protocol(uri_scheme.clone(), move |request, responder| {
let context = UriSchemeContext {
app_handle: &app_handle,
webview_label: webview_label.as_str(),
};
(protocol.protocol)(context, request, UriSchemeResponder(responder))
});
}

Expand Down
18 changes: 11 additions & 7 deletions crates/tauri/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
manager::webview::UriSchemeProtocol,
utils::config::PluginConfig,
webview::PageLoadPayload,
AppHandle, Error, RunEvent, Runtime, Webview, Window,
AppHandle, Error, RunEvent, Runtime, UriSchemeContext, Webview, Window,
};
use serde::{
de::{Deserialize, DeserializeOwned, Deserializer, Error as DeError},
Expand Down Expand Up @@ -527,6 +527,7 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
}

/// 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.
Expand All @@ -547,7 +548,7 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
///
/// fn init<R: Runtime>() -> TauriPlugin<R> {
/// Builder::new("myplugin")
/// .register_uri_scheme_protocol("myscheme", |app, req| {
/// .register_uri_scheme_protocol("myscheme", |_ctx, req| {
/// http::Response::builder().body(Vec::new()).unwrap()
/// })
/// .build()
Expand All @@ -557,7 +558,10 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
pub fn register_uri_scheme_protocol<
N: Into<String>,
T: Into<Cow<'static, [u8]>>,
H: Fn(&AppHandle<R>, http::Request<Vec<u8>>) -> http::Response<T> + Send + Sync + 'static,
H: Fn(UriSchemeContext<'_, R>, http::Request<Vec<u8>>) -> http::Response<T>
+ Send
+ Sync
+ 'static,
>(
mut self,
uri_scheme: N,
Expand All @@ -566,8 +570,8 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
self.uri_scheme_protocols.insert(
uri_scheme.into(),
Arc::new(UriSchemeProtocol {
protocol: Box::new(move |app, request, responder| {
responder.respond(protocol(app, request))
protocol: Box::new(move |ctx, request, responder| {
responder.respond(protocol(ctx, request))
}),
}),
);
Expand All @@ -589,7 +593,7 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
///
/// fn init<R: Runtime>() -> TauriPlugin<R> {
/// Builder::new("myplugin")
/// .register_asynchronous_uri_scheme_protocol("app-files", |_app, request, responder| {
/// .register_asynchronous_uri_scheme_protocol("app-files", |_ctx, request, responder| {
/// // skip leading `/`
/// let path = request.uri().path()[1..].to_string();
/// std::thread::spawn(move || {
Expand All @@ -616,7 +620,7 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
#[must_use]
pub fn register_asynchronous_uri_scheme_protocol<
N: Into<String>,
H: Fn(&AppHandle<R>, http::Request<Vec<u8>>, UriSchemeResponder) + Send + Sync + 'static,
H: Fn(UriSchemeContext<'_, R>, http::Request<Vec<u8>>, UriSchemeResponder) + Send + Sync + 'static,
>(
mut self,
uri_scheme: N,
Expand Down
2 changes: 1 addition & 1 deletion examples/streaming/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ fn main() {
download_video();

tauri::Builder::default()
.register_asynchronous_uri_scheme_protocol("stream", move |_app, request, responder| {
.register_asynchronous_uri_scheme_protocol("stream", move |_ctx, request, responder| {
match get_stream_response(request) {
Ok(http_response) => responder.respond(http_response),
Err(e) => responder.respond(
Expand Down

0 comments on commit 354be36

Please sign in to comment.