Skip to content

Commit 3f35b45

Browse files
Expose wry navigation_handler via WindowBuilder closes #4080 (#5686)
Co-authored-by: silvanshade <silvanshade@users.noreply.github.com> Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
1 parent 146a794 commit 3f35b45

File tree

8 files changed

+121
-25
lines changed

8 files changed

+121
-25
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": minor
3+
---
4+
5+
Added `Window::on_navigation`.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-runtime": minor
3+
---
4+
5+
Added `navigation_handler` field on `PendingWindow`.

.changes/wry-navigation-handler.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-runtime-wry": minor
3+
---
4+
5+
Implement the webview navigation handler.

core/tauri-runtime-wry/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3061,6 +3061,11 @@ fn create_webview<T: UserEvent>(
30613061
webview_builder = webview_builder
30623062
.with_file_drop_handler(create_file_drop_handler(window_event_listeners.clone()));
30633063
}
3064+
if let Some(navigation_handler) = pending.navigation_handler {
3065+
webview_builder = webview_builder.with_navigation_handler(move |url| {
3066+
Url::parse(&url).map(&navigation_handler).unwrap_or(true)
3067+
});
3068+
}
30643069
if let Some(user_agent) = webview_attributes.user_agent {
30653070
webview_builder = webview_builder.with_user_agent(&user_agent);
30663071
}

core/tauri-runtime/src/window.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
};
1313
use serde::{Deserialize, Deserializer, Serialize};
1414
use tauri_utils::{config::WindowConfig, Theme};
15+
use url::Url;
1516

1617
use std::{
1718
collections::{HashMap, HashSet},
@@ -232,6 +233,9 @@ pub struct PendingWindow<T: UserEvent, R: Runtime<T>> {
232233

233234
/// A HashMap mapping JS event names with associated listener ids.
234235
pub js_event_listeners: Arc<Mutex<HashMap<JsEventListenerKey, HashSet<u64>>>>,
236+
237+
/// A handler to decide if incoming url is allowed to navigate.
238+
pub navigation_handler: Option<Box<dyn Fn(Url) -> bool + Send>>,
235239
}
236240

237241
pub fn is_label_valid(label: &str) -> bool {
@@ -271,6 +275,7 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
271275
url: "tauri://localhost".to_string(),
272276
menu_ids: Arc::new(Mutex::new(menu_ids)),
273277
js_event_listeners: Default::default(),
278+
navigation_handler: Default::default(),
274279
})
275280
}
276281
}
@@ -300,6 +305,7 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
300305
url: "tauri://localhost".to_string(),
301306
menu_ids: Arc::new(Mutex::new(menu_ids)),
302307
js_event_listeners: Default::default(),
308+
navigation_handler: Default::default(),
303309
})
304310
}
305311
}

core/tauri/src/window.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use std::{
4949
};
5050

5151
pub(crate) type WebResourceRequestHandler = dyn Fn(&HttpRequest, &mut HttpResponse) + Send + Sync;
52+
pub(crate) type NavigationHandler = dyn Fn(Url) -> bool + Send;
5253

5354
#[derive(Clone, Serialize)]
5455
struct WindowCreatedEvent {
@@ -109,6 +110,7 @@ pub struct WindowBuilder<'a, R: Runtime> {
109110
pub(crate) window_builder: <R::Dispatcher as Dispatch<EventLoopMessage>>::WindowBuilder,
110111
pub(crate) webview_attributes: WebviewAttributes,
111112
web_resource_request_handler: Option<Box<WebResourceRequestHandler>>,
113+
navigation_handler: Option<Box<NavigationHandler>>,
112114
}
113115

114116
impl<'a, R: Runtime> fmt::Debug for WindowBuilder<'a, R> {
@@ -182,6 +184,7 @@ impl<'a, R: Runtime> WindowBuilder<'a, R> {
182184
window_builder: <R::Dispatcher as Dispatch<EventLoopMessage>>::WindowBuilder::new(),
183185
webview_attributes: WebviewAttributes::new(url),
184186
web_resource_request_handler: None,
187+
navigation_handler: None,
185188
}
186189
}
187190

@@ -230,6 +233,33 @@ impl<'a, R: Runtime> WindowBuilder<'a, R> {
230233
self
231234
}
232235

236+
/// Defines a closure to be executed when the webview navigates to a URL. Returning `false` cancels the navigation.
237+
///
238+
/// # Examples
239+
///
240+
/// ```rust,no_run
241+
/// use tauri::{
242+
/// utils::config::{Csp, CspDirectiveSources, WindowUrl},
243+
/// http::header::HeaderValue,
244+
/// window::WindowBuilder,
245+
/// };
246+
/// use std::collections::HashMap;
247+
/// tauri::Builder::default()
248+
/// .setup(|app| {
249+
/// WindowBuilder::new(app, "core", WindowUrl::App("index.html".into()))
250+
/// .on_navigation(|url| {
251+
/// // allow the production URL or localhost on dev
252+
/// url.scheme() == "tauri" || (cfg!(dev) && url.host_str() == Some("localhost"))
253+
/// })
254+
/// .build()?;
255+
/// Ok(())
256+
/// });
257+
/// ```
258+
pub fn on_navigation<F: Fn(Url) -> bool + Send + 'static>(mut self, f: F) -> Self {
259+
self.navigation_handler.replace(Box::new(f));
260+
self
261+
}
262+
233263
/// Creates a new webview window.
234264
pub fn build(mut self) -> crate::Result<Window<R>> {
235265
let web_resource_request_handler = self.web_resource_request_handler.take();
@@ -239,12 +269,13 @@ impl<'a, R: Runtime> WindowBuilder<'a, R> {
239269
self.label.clone(),
240270
)?;
241271
let labels = self.manager.labels().into_iter().collect::<Vec<_>>();
242-
let pending = self.manager.prepare_window(
272+
let mut pending = self.manager.prepare_window(
243273
self.app_handle.clone(),
244274
pending,
245275
&labels,
246276
web_resource_request_handler,
247277
)?;
278+
pending.navigation_handler = self.navigation_handler.take();
248279
let window = match &mut self.runtime {
249280
RuntimeOrDispatch::Runtime(runtime) => runtime.create_window(pending),
250281
RuntimeOrDispatch::RuntimeHandle(handle) => handle.create_window(pending),

examples/api/src-tauri/Cargo.lock

Lines changed: 60 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tooling/cli/Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)