Skip to content

Commit 938fb62

Browse files
authored
feat(core): expose custom protocol handler APIs (#1553)
1 parent be65f04 commit 938fb62

File tree

6 files changed

+152
-62
lines changed

6 files changed

+152
-62
lines changed

.changes/multi-custom-protocols.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch
3+
---
4+
5+
Adds APIs to determine global and window-specific custom protocol handlers.

core/tauri/src/runtime/app.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,19 @@ use crate::{
77
hooks::{InvokeHandler, InvokeMessage, OnPageLoad, PageLoadPayload, SetupHook},
88
plugin::{Plugin, PluginStore},
99
runtime::{
10-
flavors::wry::Wry, manager::WindowManager, tag::Tag, webview::Attributes,
11-
window::PendingWindow, Dispatch, Runtime,
10+
flavors::wry::Wry,
11+
manager::{Args, WindowManager},
12+
tag::Tag,
13+
webview::{Attributes, CustomProtocol},
14+
window::PendingWindow,
15+
Dispatch, Runtime,
1216
},
1317
sealed::{ManagerBase, RuntimeOrDispatch},
1418
Context, Manager, Params, Window,
1519
};
1620

17-
use crate::runtime::manager::Args;
21+
use std::{collections::HashMap, sync::Arc};
22+
1823
#[cfg(feature = "updater")]
1924
use crate::updater;
2025

@@ -118,6 +123,9 @@ where
118123

119124
/// All passed plugins
120125
plugins: PluginStore<Args<E, L, A, R>>,
126+
127+
/// The custom protocols available to all windows.
128+
custom_protocols: HashMap<String, Arc<CustomProtocol>>,
121129
}
122130

123131
impl<E, L, A, R> Builder<E, L, A, R>
@@ -135,6 +143,7 @@ where
135143
on_page_load: Box::new(|_, _| ()),
136144
pending_windows: Default::default(),
137145
plugins: PluginStore::default(),
146+
custom_protocols: Default::default(),
138147
}
139148
}
140149

@@ -183,13 +192,32 @@ where
183192
self
184193
}
185194

195+
/// Adds a custom protocol available to all windows.
196+
pub fn custom_protocol<
197+
N: Into<String>,
198+
H: Fn(&str) -> crate::Result<Vec<u8>> + Send + Sync + 'static,
199+
>(
200+
mut self,
201+
name: N,
202+
handler: H,
203+
) -> Self {
204+
self.custom_protocols.insert(
205+
name.into(),
206+
Arc::new(CustomProtocol {
207+
handler: Box::new(handler),
208+
}),
209+
);
210+
self
211+
}
212+
186213
/// Runs the configured Tauri application.
187214
pub fn run(mut self, context: Context<A>) -> crate::Result<()> {
188215
let manager = WindowManager::with_handlers(
189216
context,
190217
self.plugins,
191218
self.invoke_handler,
192219
self.on_page_load,
220+
self.custom_protocols,
193221
);
194222

195223
// set up all the windows defined in the config

core/tauri/src/runtime/flavors/wry.rs

Lines changed: 85 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,19 @@ use crate::{
88
api::config::WindowConfig,
99
runtime::{
1010
webview::{
11-
Attributes, AttributesBase, CustomProtocol, FileDropEvent, FileDropHandler, RpcRequest,
12-
WebviewRpcHandler,
11+
Attributes, AttributesBase, FileDropEvent, FileDropHandler, RpcRequest, WebviewRpcHandler,
1312
},
1413
window::{DetachedWindow, PendingWindow},
1514
Dispatch, Params, Runtime,
1615
},
1716
Icon,
1817
};
19-
use std::{convert::TryFrom, path::PathBuf};
18+
use std::{
19+
collections::HashMap,
20+
convert::TryFrom,
21+
path::PathBuf,
22+
sync::{Arc, Mutex},
23+
};
2024

2125
#[cfg(target_os = "windows")]
2226
use crate::api::path::{resolve_path, BaseDirectory};
@@ -41,16 +45,23 @@ impl TryFrom<Icon> for WryIcon {
4145
}
4246
}
4347

44-
impl AttributesBase for wry::Attributes {}
45-
impl Attributes for wry::Attributes {
48+
/// Wry attributes.
49+
#[derive(Default, Clone)]
50+
pub struct WryAttributes {
51+
attributes: wry::Attributes,
52+
custom_protocols: Arc<Mutex<HashMap<String, wry::CustomProtocol>>>,
53+
}
54+
55+
impl AttributesBase for WryAttributes {}
56+
impl Attributes for WryAttributes {
4657
type Icon = WryIcon;
4758

4859
fn new() -> Self {
4960
Default::default()
5061
}
5162

5263
fn with_config(config: WindowConfig) -> Self {
53-
let mut webview = wry::Attributes::default()
64+
let mut webview = WryAttributes::default()
5465
.title(config.title.to_string())
5566
.width(config.width)
5667
.height(config.height)
@@ -108,106 +119,132 @@ impl Attributes for wry::Attributes {
108119
}
109120

110121
fn initialization_script(mut self, init: &str) -> Self {
111-
self.initialization_scripts.push(init.to_string());
122+
self
123+
.attributes
124+
.initialization_scripts
125+
.push(init.to_string());
112126
self
113127
}
114128

115129
fn x(mut self, x: f64) -> Self {
116-
self.x = Some(x);
130+
self.attributes.x = Some(x);
117131
self
118132
}
119133

120134
fn y(mut self, y: f64) -> Self {
121-
self.y = Some(y);
135+
self.attributes.y = Some(y);
122136
self
123137
}
124138

125139
fn width(mut self, width: f64) -> Self {
126-
self.width = width;
140+
self.attributes.width = width;
127141
self
128142
}
129143

130144
fn height(mut self, height: f64) -> Self {
131-
self.height = height;
145+
self.attributes.height = height;
132146
self
133147
}
134148

135149
fn min_width(mut self, min_width: f64) -> Self {
136-
self.min_width = Some(min_width);
150+
self.attributes.min_width = Some(min_width);
137151
self
138152
}
139153

140154
fn min_height(mut self, min_height: f64) -> Self {
141-
self.min_height = Some(min_height);
155+
self.attributes.min_height = Some(min_height);
142156
self
143157
}
144158

145159
fn max_width(mut self, max_width: f64) -> Self {
146-
self.max_width = Some(max_width);
160+
self.attributes.max_width = Some(max_width);
147161
self
148162
}
149163

150164
fn max_height(mut self, max_height: f64) -> Self {
151-
self.max_height = Some(max_height);
165+
self.attributes.max_height = Some(max_height);
152166
self
153167
}
154168

155169
fn resizable(mut self, resizable: bool) -> Self {
156-
self.resizable = resizable;
170+
self.attributes.resizable = resizable;
157171
self
158172
}
159173

160174
fn title<S: Into<String>>(mut self, title: S) -> Self {
161-
self.title = title.into();
175+
self.attributes.title = title.into();
162176
self
163177
}
164178

165179
fn fullscreen(mut self, fullscreen: bool) -> Self {
166-
self.fullscreen = fullscreen;
180+
self.attributes.fullscreen = fullscreen;
167181
self
168182
}
169183

170184
fn maximized(mut self, maximized: bool) -> Self {
171-
self.maximized = maximized;
185+
self.attributes.maximized = maximized;
172186
self
173187
}
174188

175189
fn visible(mut self, visible: bool) -> Self {
176-
self.visible = visible;
190+
self.attributes.visible = visible;
177191
self
178192
}
179193

180194
fn transparent(mut self, transparent: bool) -> Self {
181-
self.transparent = transparent;
195+
self.attributes.transparent = transparent;
182196
self
183197
}
184198

185199
fn decorations(mut self, decorations: bool) -> Self {
186-
self.decorations = decorations;
200+
self.attributes.decorations = decorations;
187201
self
188202
}
189203

190204
fn always_on_top(mut self, always_on_top: bool) -> Self {
191-
self.always_on_top = always_on_top;
205+
self.attributes.always_on_top = always_on_top;
192206
self
193207
}
194208

195209
fn icon(mut self, icon: Self::Icon) -> Self {
196-
self.icon = Some(icon.0);
210+
self.attributes.icon = Some(icon.0);
197211
self
198212
}
199213

200214
fn has_icon(&self) -> bool {
201-
self.icon.is_some()
215+
self.attributes.icon.is_some()
202216
}
203217

204218
fn user_data_path(mut self, user_data_path: Option<PathBuf>) -> Self {
205-
self.user_data_path = user_data_path;
219+
self.attributes.user_data_path = user_data_path;
206220
self
207221
}
208222

209223
fn url(mut self, url: String) -> Self {
210-
self.url.replace(url);
224+
self.attributes.url.replace(url);
225+
self
226+
}
227+
228+
fn has_custom_protocol(&self, name: &str) -> bool {
229+
self.custom_protocols.lock().unwrap().contains_key(name)
230+
}
231+
232+
fn custom_protocol<
233+
N: Into<String>,
234+
H: Fn(&str) -> crate::Result<Vec<u8>> + Send + Sync + 'static,
235+
>(
236+
self,
237+
name: N,
238+
handler: H,
239+
) -> Self {
240+
let name = name.into();
241+
self.custom_protocols.lock().unwrap().insert(
242+
name.clone(),
243+
wry::CustomProtocol {
244+
name,
245+
handler: Box::new(move |data| (handler)(data).map_err(|_| wry::Error::InitScriptError)),
246+
},
247+
);
211248
self
212249
}
213250

@@ -245,7 +282,7 @@ pub struct WryDispatcher {
245282
impl Dispatch for WryDispatcher {
246283
type Runtime = Wry;
247284
type Icon = WryIcon;
248-
type Attributes = wry::Attributes;
285+
type Attributes = WryAttributes;
249286

250287
fn create_window<M: Params<Runtime = Self::Runtime>>(
251288
&mut self,
@@ -254,7 +291,6 @@ impl Dispatch for WryDispatcher {
254291
let PendingWindow {
255292
attributes,
256293
rpc_handler,
257-
custom_protocol,
258294
file_drop_handler,
259295
label,
260296
..
@@ -268,14 +304,20 @@ impl Dispatch for WryDispatcher {
268304
let file_drop_handler = file_drop_handler
269305
.map(|handler| create_file_drop_handler(proxy.clone(), label.clone(), handler));
270306

307+
let custom_protocols = {
308+
let mut lock = attributes
309+
.custom_protocols
310+
.lock()
311+
.expect("poisoned custom protocols");
312+
std::mem::take(&mut *lock)
313+
};
314+
271315
let window = self
272316
.application
273317
.add_window_with_configs(
274-
attributes,
318+
attributes.attributes,
275319
rpc_handler,
276-
custom_protocol
277-
.map(create_custom_protocol)
278-
.unwrap_or_default(),
320+
custom_protocols.into_iter().map(|(_, p)| p).collect(),
279321
file_drop_handler,
280322
)
281323
.map_err(|_| crate::Error::CreateWebview)?;
@@ -463,7 +505,6 @@ impl Runtime for Wry {
463505
let PendingWindow {
464506
attributes,
465507
rpc_handler,
466-
custom_protocol,
467508
file_drop_handler,
468509
label,
469510
..
@@ -477,14 +518,20 @@ impl Runtime for Wry {
477518
let file_drop_handler = file_drop_handler
478519
.map(|handler| create_file_drop_handler(proxy.clone(), label.clone(), handler));
479520

521+
let custom_protocols = {
522+
let mut lock = attributes
523+
.custom_protocols
524+
.lock()
525+
.expect("poisoned custom protocols");
526+
std::mem::take(&mut *lock)
527+
};
528+
480529
let window = self
481530
.inner
482531
.add_window_with_configs(
483-
attributes,
532+
attributes.attributes,
484533
rpc_handler,
485-
custom_protocol
486-
.map(create_custom_protocol)
487-
.unwrap_or_default(),
534+
custom_protocols.into_iter().map(|(_, p)| p).collect(),
488535
file_drop_handler,
489536
)
490537
.map_err(|_| crate::Error::CreateWebview)?;
@@ -542,13 +589,3 @@ fn create_file_drop_handler<M: Params<Runtime = Wry>>(
542589
)
543590
})
544591
}
545-
546-
/// Create a wry custom protocol from a tauri custom protocol.
547-
fn create_custom_protocol(custom_protocol: CustomProtocol) -> Vec<wry::CustomProtocol> {
548-
vec![wry::CustomProtocol {
549-
name: custom_protocol.name.clone(),
550-
handler: Box::new(move |data| {
551-
(custom_protocol.handler)(data).map_err(|_| wry::Error::InitScriptError)
552-
}),
553-
}]
554-
}

0 commit comments

Comments
 (0)