Skip to content

Commit

Permalink
refactor(core): clear uri_scheme_protocol registration function nam…
Browse files Browse the repository at this point in the history
…es (#1617)

* refactor(core): clear `custom_protocol` registration function names

* fix

* fix clippy

* improve docs

* clippy

* renames
  • Loading branch information
lucasfernog committed Apr 25, 2021
1 parent d623d95 commit a868cb7
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 116 deletions.
2 changes: 1 addition & 1 deletion .changes/multi-custom-protocols.md
Expand Up @@ -2,4 +2,4 @@
"tauri": patch
---

Adds APIs to determine global and window-specific custom protocol handlers.
Adds APIs to determine global and webview-specific URI scheme handlers.
16 changes: 8 additions & 8 deletions core/tauri/src/api/dir.rs
Expand Up @@ -120,22 +120,22 @@ mod test {
if first.path.extension() == Some(OsStr::new("txt")) {
// check the fields for the first DiskEntry
assert_eq!(first.path, file_one);
assert_eq!(first.children.is_some(), false);
assert!(first.children.is_none());
assert_eq!(first.name, name_from_path(file_one));

// check the fields for the third DiskEntry
assert_eq!(second.path, file_two);
assert_eq!(second.children.is_some(), false);
assert!(second.children.is_none());
assert_eq!(second.name, name_from_path(file_two));
} else {
// check the fields for the second DiskEntry
assert_eq!(first.path, file_two);
assert_eq!(first.children.is_some(), false);
assert!(first.children.is_none());
assert_eq!(first.name, name_from_path(file_two));

// check the fields for the third DiskEntry
assert_eq!(second.path, file_one);
assert_eq!(second.children.is_some(), false);
assert!(second.children.is_none());
assert_eq!(second.name, name_from_path(file_one));
}
}
Expand Down Expand Up @@ -165,22 +165,22 @@ mod test {
if first.path.extension() == Some(OsStr::new("txt")) {
// check the fields for the first DiskEntry
assert_eq!(first.path, PathBuf::from("test/api/test.txt"));
assert_eq!(first.children.is_some(), false);
assert!(first.children.is_none());
assert_eq!(first.name, Some("test.txt".to_string()));

// check the fields for the second DiskEntry
assert_eq!(second.path, PathBuf::from("test/api/test_binary"));
assert_eq!(second.children.is_some(), false);
assert!(second.children.is_none());
assert_eq!(second.name, Some("test_binary".to_string()));
} else {
// check the fields for the first DiskEntry
assert_eq!(second.path, PathBuf::from("test/api/test.txt"));
assert_eq!(second.children.is_some(), false);
assert!(second.children.is_none());
assert_eq!(second.name, Some("test.txt".to_string()));

// check the fields for the second DiskEntry
assert_eq!(first.path, PathBuf::from("test/api/test_binary"));
assert_eq!(first.children.is_some(), false);
assert!(first.children.is_none());
assert_eq!(first.name, Some("test_binary".to_string()));
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/tauri/src/event.rs
Expand Up @@ -242,7 +242,7 @@ mod test {
let l = listeners.inner.handlers.lock().unwrap();

// check if the generated key is in the map
assert_eq!(l.contains_key(&key), true);
assert!(l.contains_key(&key));
}

// check to see if listen inputs a handler function properly into the LISTENERS map.
Expand Down
2 changes: 1 addition & 1 deletion core/tauri/src/lib.rs
Expand Up @@ -49,7 +49,7 @@ use std::path::PathBuf;
// Export types likely to be used by the application.
pub use {
api::config::WindowUrl,
hooks::{InvokeMessage, PageLoadPayload},
hooks::{InvokeHandler, InvokeMessage, OnPageLoad, PageLoadPayload, SetupHook},
runtime::app::{App, Builder},
runtime::webview::Attributes,
runtime::window::export::Window,
Expand Down
30 changes: 19 additions & 11 deletions core/tauri/src/runtime/app.rs
Expand Up @@ -124,8 +124,8 @@ where
/// All passed plugins
plugins: PluginStore<Args<E, L, A, R>>,

/// The custom protocols available to all windows.
custom_protocols: HashMap<String, Arc<CustomProtocol>>,
/// The webview protocols available to all windows.
uri_scheme_protocols: HashMap<String, Arc<CustomProtocol>>,
}

impl<E, L, A, R> Builder<E, L, A, R>
Expand All @@ -143,7 +143,7 @@ where
on_page_load: Box::new(|_, _| ()),
pending_windows: Default::default(),
plugins: PluginStore::default(),
custom_protocols: Default::default(),
uri_scheme_protocols: Default::default(),
}
}

Expand Down Expand Up @@ -192,19 +192,27 @@ where
self
}

/// Adds a custom protocol available to all windows.
pub fn custom_protocol<
/// 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.
///
/// # 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`.
pub fn register_global_uri_scheme_protocol<
N: Into<String>,
H: Fn(&str) -> crate::Result<Vec<u8>> + Send + Sync + 'static,
>(
mut self,
name: N,
handler: H,
uri_scheme: N,
protocol: H,
) -> Self {
self.custom_protocols.insert(
name.into(),
self.uri_scheme_protocols.insert(
uri_scheme.into(),
Arc::new(CustomProtocol {
handler: Box::new(handler),
protocol: Box::new(protocol),
}),
);
self
Expand All @@ -217,7 +225,7 @@ where
self.plugins,
self.invoke_handler,
self.on_page_load,
self.custom_protocols,
self.uri_scheme_protocols,
);

// set up all the windows defined in the config
Expand Down
34 changes: 17 additions & 17 deletions core/tauri/src/runtime/flavors/wry.rs
Expand Up @@ -44,7 +44,7 @@ impl TryFrom<Icon> for WryIcon {
#[derive(Default, Clone)]
pub struct WryAttributes {
attributes: wry::Attributes,
custom_protocols: Arc<Mutex<HashMap<String, wry::CustomProtocol>>>,
uri_scheme_protocols: Arc<Mutex<HashMap<String, wry::CustomProtocol>>>,
}

impl AttributesBase for WryAttributes {}
Expand Down Expand Up @@ -197,24 +197,24 @@ impl Attributes for WryAttributes {
self
}

fn has_custom_protocol(&self, name: &str) -> bool {
self.custom_protocols.lock().unwrap().contains_key(name)
fn has_uri_scheme_protocol(&self, name: &str) -> bool {
self.uri_scheme_protocols.lock().unwrap().contains_key(name)
}

fn custom_protocol<
fn register_uri_scheme_protocol<
N: Into<String>,
H: Fn(&str) -> crate::Result<Vec<u8>> + Send + Sync + 'static,
>(
self,
name: N,
handler: H,
uri_scheme: N,
protocol: H,
) -> Self {
let name = name.into();
self.custom_protocols.lock().unwrap().insert(
name.clone(),
let uri_scheme = uri_scheme.into();
self.uri_scheme_protocols.lock().unwrap().insert(
uri_scheme.clone(),
wry::CustomProtocol {
name,
handler: Box::new(move |data| (handler)(data).map_err(|_| wry::Error::InitScriptError)),
name: uri_scheme,
handler: Box::new(move |data| (protocol)(data).map_err(|_| wry::Error::InitScriptError)),
},
);
self
Expand Down Expand Up @@ -276,9 +276,9 @@ impl Dispatch for WryDispatcher {
let file_drop_handler = file_drop_handler
.map(|handler| create_file_drop_handler(proxy.clone(), label.clone(), handler));

let custom_protocols = {
let uri_scheme_protocols = {
let mut lock = attributes
.custom_protocols
.uri_scheme_protocols
.lock()
.expect("poisoned custom protocols");
std::mem::take(&mut *lock)
Expand All @@ -289,7 +289,7 @@ impl Dispatch for WryDispatcher {
.add_window_with_configs(
attributes.attributes,
rpc_handler,
custom_protocols.into_iter().map(|(_, p)| p).collect(),
uri_scheme_protocols.into_iter().map(|(_, p)| p).collect(),
file_drop_handler,
)
.map_err(|e| crate::Error::CreateWebview(e.to_string()))?;
Expand Down Expand Up @@ -490,9 +490,9 @@ impl Runtime for Wry {
let file_drop_handler = file_drop_handler
.map(|handler| create_file_drop_handler(proxy.clone(), label.clone(), handler));

let custom_protocols = {
let uri_scheme_protocols = {
let mut lock = attributes
.custom_protocols
.uri_scheme_protocols
.lock()
.expect("poisoned custom protocols");
std::mem::take(&mut *lock)
Expand All @@ -503,7 +503,7 @@ impl Runtime for Wry {
.add_window_with_configs(
attributes.attributes,
rpc_handler,
custom_protocols.into_iter().map(|(_, p)| p).collect(),
uri_scheme_protocols.into_iter().map(|(_, p)| p).collect(),
file_drop_handler,
)
.map_err(|e| crate::Error::CreateWebview(e.to_string()))?;
Expand Down
24 changes: 13 additions & 11 deletions core/tauri/src/runtime/manager.rs
Expand Up @@ -51,8 +51,8 @@ pub struct InnerWindowManager<P: Params> {
/// A list of salts that are valid for the current application.
salts: Mutex<HashSet<Uuid>>,
package_info: PackageInfo,
/// The custom protocols available to all windows.
custom_protocols: HashMap<String, std::sync::Arc<CustomProtocol>>,
/// The webview protocols protocols available to all windows.
uri_scheme_protocols: HashMap<String, std::sync::Arc<CustomProtocol>>,
}

/// A [Zero Sized Type] marker representing a full [`Params`].
Expand Down Expand Up @@ -104,7 +104,7 @@ impl<P: Params> WindowManager<P> {
plugins: PluginStore<P>,
invoke_handler: Box<InvokeHandler<P>>,
on_page_load: Box<OnPageLoad<P>>,
custom_protocols: HashMap<String, std::sync::Arc<CustomProtocol>>,
uri_scheme_protocols: HashMap<String, std::sync::Arc<CustomProtocol>>,
) -> Self {
Self {
inner: Arc::new(InnerWindowManager {
Expand All @@ -118,7 +118,7 @@ impl<P: Params> WindowManager<P> {
default_window_icon: context.default_window_icon,
salts: Mutex::default(),
package_info: context.package_info,
custom_protocols,
uri_scheme_protocols,
}),
_marker: Args::default(),
}
Expand Down Expand Up @@ -179,15 +179,17 @@ impl<P: Params> WindowManager<P> {
}
}

for (name, protocol) in &self.inner.custom_protocols {
if !attributes.has_custom_protocol(name) {
for (uri_scheme, protocol) in &self.inner.uri_scheme_protocols {
if !attributes.has_uri_scheme_protocol(uri_scheme) {
let protocol = protocol.clone();
attributes = attributes.custom_protocol(name.clone(), move |p| (protocol.handler)(p));
attributes = attributes
.register_uri_scheme_protocol(uri_scheme.clone(), move |p| (protocol.protocol)(p));
}
}

if !attributes.has_custom_protocol("tauri") {
attributes = attributes.custom_protocol("tauri", self.prepare_custom_protocol().handler);
if !attributes.has_uri_scheme_protocol("tauri") {
attributes = attributes
.register_uri_scheme_protocol("tauri", self.prepare_uri_scheme_protocol().protocol);
}

let local_app_data = resolve_path(
Expand Down Expand Up @@ -233,10 +235,10 @@ impl<P: Params> WindowManager<P> {
})
}

fn prepare_custom_protocol(&self) -> CustomProtocol {
fn prepare_uri_scheme_protocol(&self) -> CustomProtocol {
let assets = self.inner.assets.clone();
CustomProtocol {
handler: Box::new(move |path| {
protocol: Box::new(move |path| {
let mut path = path
.split('?')
// ignore query string
Expand Down
26 changes: 17 additions & 9 deletions core/tauri/src/runtime/webview.rs
Expand Up @@ -92,17 +92,25 @@ pub trait Attributes: AttributesBase {
/// Sets the webview url.
fn url(self, url: String) -> Self;

/// Whether the custom protocol handler is defined or not.
fn has_custom_protocol(&self, name: &str) -> bool;

/// Adds a custom protocol handler.
fn custom_protocol<
/// Whether the webview URI scheme protocol is defined or not.
fn has_uri_scheme_protocol(&self, name: &str) -> bool;

/// Registers a webview protocol handler.
/// 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.
///
/// # 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`.
fn register_uri_scheme_protocol<
N: Into<String>,
H: Fn(&str) -> crate::Result<Vec<u8>> + Send + Sync + 'static,
>(
self,
name: N,
handler: H,
uri_scheme: N,
protocol: H,
) -> Self;

/// The full attributes.
Expand All @@ -117,10 +125,10 @@ pub struct RpcRequest {
pub params: Option<JsonValue>,
}

/// Uses a custom handler to resolve file requests
/// Uses a custom URI scheme handler to resolve file requests
pub struct CustomProtocol {
/// Handler for protocol
pub handler: Box<dyn Fn(&str) -> crate::Result<Vec<u8>> + Send + Sync>,
pub protocol: Box<dyn Fn(&str) -> crate::Result<Vec<u8>> + Send + Sync>,
}

/// The file drop event payload.
Expand Down

0 comments on commit a868cb7

Please sign in to comment.