backport iframe fix to v0.7 (#5535)

* feat:Add opt‑in navigation handler for external URLs (#5531)

* add navigation handler config option

code from https://github.com/DioxusLabs/dioxus/pull/5231

* Re-order branches

The branches should be reorder so that the branch that checks for
the index and assets is always taken first. Otherwise, they will
fail to load for users who forget to allow them in their custom
handlers, which will be a crappy experience and hard to debug.

* remove return

* Change behavior when handler not set

---------

Co-authored-by: not a cow <agielow@proton.me>

* fix: allow navigations but disallow external nav

---------

Co-authored-by: Martin Martinez Rivera <mrtnz.rvr@gmail.com>
Co-authored-by: not a cow <agielow@proton.me>
This commit is contained in:
authored and GitHub committed 2026-05-07 15:11:47 -07:00
1 parent 003ec3270b
commit f1a0124227
2 files changed
+30 -12

No files matched your search

+13
View File
@@ -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]
@@ -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>>,
@@ -124,6 +129,7 @@ impl Config {
on_window: None,
additional_windows_args: None,
tray_icon_show_window_on_click: true,
navigation_handler: None,
}
}
@@ -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 {
+17 -12
View File
@@ -353,6 +353,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)
@@ -367,25 +368,29 @@ 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
} else {
if var.starts_with("http://")
|| var.starts_with("https://")
|| var.starts_with("mailto:")
{
_ = webbrowser::open(&var);
}
false
return !page_loaded;
}
}) // prevent all navigations
// External links always open somewhere else. Prevents the webview from navigating
if var.starts_with("http://")
|| var.starts_with("https://")
|| var.starts_with("mailto:")
{
_ = webbrowser::open(&var);
return false;
}
// By default, external links are allowed. This keeps things like iframes working.
// However, users can customize this to allow/disallow domains/routes/patterns.
navigation_handler.as_ref().map(|f| f(&var)).unwrap_or(true)
})
.with_asynchronous_custom_protocol(String::from("dioxus"), request_handler);
// Enable https scheme on android, needed for secure context API, like the geolocation API