Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/desktop/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ type CustomEventHandler = Box<
),
>;

/// A function taking a URL and returning whether the webview should navigate to it or open it in
/// the browser. If missing in the config, all URLs will be allowed.
type NavigationHandler = Box<dyn Fn(&str) -> bool + 'static>;

/// The closing behaviour of specific application window.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[non_exhaustive]
Expand Down Expand Up @@ -70,6 +74,7 @@ pub struct Config {
pub(crate) disable_dma_buf_on_wayland: bool,
pub(crate) additional_windows_args: Option<String>,
pub(crate) tray_icon_show_window_on_click: bool,
pub(crate) navigation_handler: Option<NavigationHandler>,

#[allow(clippy::type_complexity)]
pub(crate) on_window: Option<Box<dyn FnMut(Arc<Window>, &mut VirtualDom) + 'static>>,
Expand Down Expand Up @@ -124,6 +129,7 @@ impl Config {
on_window: None,
additional_windows_args: None,
tray_icon_show_window_on_click: true,
navigation_handler: None,
}
}

Expand Down Expand Up @@ -350,6 +356,13 @@ impl Config {
self.tray_icon_show_window_on_click = show;
self
}

/// Set a custom navigation handler for non-dioxus URLs.
/// Return true to allow navigation inside the webview, false to block.
pub fn with_navigation_handler(mut self, f: impl Fn(&str) -> bool + 'static) -> Self {
self.navigation_handler = Some(Box::new(f));
self
}
}

impl Default for Config {
Expand Down
17 changes: 14 additions & 3 deletions packages/desktop/src/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ impl WebviewInstance {
}
};

let navigation_handler = cfg.navigation_handler.take();
let page_loaded = AtomicBool::new(false);

let mut webview = WebViewBuilder::new_with_web_context(&mut web_context)
Expand All @@ -363,15 +364,25 @@ impl WebviewInstance {
.with_url("dioxus://index.html/")
.with_ipc_handler(ipc_handler)
.with_navigation_handler(move |var| {
// We don't want to allow any navigation
// We only want to serve the index file and assets
// Serve the index and assets.
if var.starts_with("dioxus://")
|| var.starts_with("http://dioxus.")
|| var.starts_with("https://dioxus.")
{
// After the page has loaded once, don't allow any more navigation
let page_loaded = page_loaded.swap(true, std::sync::atomic::Ordering::SeqCst);
!page_loaded
return !page_loaded;
}

// By default, navigation is allowed. Users can have more granular control by
// providing a navigation handler. If not allowed, valid URLs will be opened in the
// browser.
let allow_nav = match navigation_handler.as_ref() {
Some(handler) => handler(&var),
None => true,
};
if allow_nav {
true
} else {
if var.starts_with("http://")
|| var.starts_with("https://")
Expand Down
Loading