Skip to content

Commit f1a0124

Browse files
jkelleyrtpmartinmrnot-a-cowfr
authored
backport iframe fix to v0.7 (#5535)
* feat:Add opt‑in navigation handler for external URLs (#5531) * add navigation handler config option code from #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>
1 parent 003ec32 commit f1a0124

2 files changed

Lines changed: 30 additions & 12 deletions

File tree

packages/desktop/src/config.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ type CustomEventHandler = Box<
2020
),
2121
>;
2222

23+
/// A function taking a URL and returning whether the webview should navigate to it or open it in
24+
/// the browser. If missing in the config, all URLs will be allowed.
25+
type NavigationHandler = Box<dyn Fn(&str) -> bool + 'static>;
26+
2327
/// The closing behaviour of specific application window.
2428
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
2529
#[non_exhaustive]
@@ -70,6 +74,7 @@ pub struct Config {
7074
pub(crate) disable_dma_buf_on_wayland: bool,
7175
pub(crate) additional_windows_args: Option<String>,
7276
pub(crate) tray_icon_show_window_on_click: bool,
77+
pub(crate) navigation_handler: Option<NavigationHandler>,
7378

7479
#[allow(clippy::type_complexity)]
7580
pub(crate) on_window: Option<Box<dyn FnMut(Arc<Window>, &mut VirtualDom) + 'static>>,
@@ -124,6 +129,7 @@ impl Config {
124129
on_window: None,
125130
additional_windows_args: None,
126131
tray_icon_show_window_on_click: true,
132+
navigation_handler: None,
127133
}
128134
}
129135

@@ -350,6 +356,13 @@ impl Config {
350356
self.tray_icon_show_window_on_click = show;
351357
self
352358
}
359+
360+
/// Set a custom navigation handler for non-dioxus URLs.
361+
/// Return true to allow navigation inside the webview, false to block.
362+
pub fn with_navigation_handler(mut self, f: impl Fn(&str) -> bool + 'static) -> Self {
363+
self.navigation_handler = Some(Box::new(f));
364+
self
365+
}
353366
}
354367

355368
impl Default for Config {

packages/desktop/src/webview.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ impl WebviewInstance {
353353
}
354354
};
355355

356+
let navigation_handler = cfg.navigation_handler.take();
356357
let page_loaded = AtomicBool::new(false);
357358

358359
let mut webview = WebViewBuilder::new_with_web_context(&mut web_context)
@@ -367,25 +368,29 @@ impl WebviewInstance {
367368
.with_url("dioxus://index.html/")
368369
.with_ipc_handler(ipc_handler)
369370
.with_navigation_handler(move |var| {
370-
// We don't want to allow any navigation
371-
// We only want to serve the index file and assets
371+
// Serve the index and assets.
372372
if var.starts_with("dioxus://")
373373
|| var.starts_with("http://dioxus.")
374374
|| var.starts_with("https://dioxus.")
375375
{
376376
// After the page has loaded once, don't allow any more navigation
377377
let page_loaded = page_loaded.swap(true, std::sync::atomic::Ordering::SeqCst);
378-
!page_loaded
379-
} else {
380-
if var.starts_with("http://")
381-
|| var.starts_with("https://")
382-
|| var.starts_with("mailto:")
383-
{
384-
_ = webbrowser::open(&var);
385-
}
386-
false
378+
return !page_loaded;
387379
}
388-
}) // prevent all navigations
380+
381+
// External links always open somewhere else. Prevents the webview from navigating
382+
if var.starts_with("http://")
383+
|| var.starts_with("https://")
384+
|| var.starts_with("mailto:")
385+
{
386+
_ = webbrowser::open(&var);
387+
return false;
388+
}
389+
390+
// By default, external links are allowed. This keeps things like iframes working.
391+
// However, users can customize this to allow/disallow domains/routes/patterns.
392+
navigation_handler.as_ref().map(|f| f(&var)).unwrap_or(true)
393+
})
389394
.with_asynchronous_custom_protocol(String::from("dioxus"), request_handler);
390395

391396
// Enable https scheme on android, needed for secure context API, like the geolocation API

0 commit comments

Comments
 (0)