diff --git a/apps/desktop-shell/scripts/check-config.mjs b/apps/desktop-shell/scripts/check-config.mjs index 320ec604f..70f049d73 100644 --- a/apps/desktop-shell/scripts/check-config.mjs +++ b/apps/desktop-shell/scripts/check-config.mjs @@ -2674,7 +2674,11 @@ const requiredRustHostSnippets = [ 'DownloadEvent', 'should_allow_desktop_webview_download', 'DownloadEvent::Requested { .. } => false', - '.on_download(|_webview, event| should_allow_desktop_webview_download(&event))', + 'handle_desktop_webview_download', + 'log_desktop_webview_download_blocked', + 'desktop host event blocked for webview.download', + 'desktop_webview_download_handler_logs_blocked_requests', + '.on_download(|_webview, event| handle_desktop_webview_download(&event))', 'NewWindowResponse::Deny', 'HOST_BRIDGE_METHODS', 'HOST_BRIDGE_REQUEST_ID_MAX_LENGTH', @@ -2712,7 +2716,7 @@ for (const snippet of [ 'prepare_host_bridge_request(&mut invalid).expect("invalid envelope")', 'assert_eq!(response.id, "request-1");', 'assert_eq!(response.error.expect("error").code, "invalid_request");', - 'match replay_state.reserve("request-1")', + '.reserve("request-1")', 'invalid request must not reserve replay slot', ]) { if (!rustHostSource.includes(snippet)) { diff --git a/apps/desktop-shell/src-tauri/src/app.rs b/apps/desktop-shell/src-tauri/src/app.rs index d0d6a94a1..1724e6310 100644 --- a/apps/desktop-shell/src-tauri/src/app.rs +++ b/apps/desktop-shell/src-tauri/src/app.rs @@ -8,13 +8,12 @@ use crate::shell::tray::{ resolve_desktop_single_instance_action, show_main_window, DesktopSingleInstanceAction, }; use crate::shell::webview::{ - desktop_window_config_with_runtime_platform, emit_current_desktop_lifecycle_event, - desktop_external_navigation_url, log_desktop_host_event_result, - open_desktop_external_navigation, + desktop_external_navigation_url, desktop_window_config_with_runtime_platform, + emit_current_desktop_lifecycle_event, handle_desktop_webview_download, + log_desktop_host_event_result, open_desktop_external_navigation, open_normalized_desktop_external_url, register_desktop_file_drop_events, register_desktop_lifecycle_events, register_desktop_navigation_events, - replay_desktop_webview_state, - should_allow_desktop_webview_download, should_allow_desktop_webview_navigation, + replay_desktop_webview_state, should_allow_desktop_webview_navigation, should_replay_desktop_webview_state_on_page_load, }; use crate::shell::window_state::desktop_window_state_plugin; @@ -102,7 +101,7 @@ pub(crate) fn run() { replay_desktop_webview_state(&window); } }) - .on_download(|_webview, event| should_allow_desktop_webview_download(&event)) + .on_download(|_webview, event| handle_desktop_webview_download(&event)) .build()?; register_desktop_window_close_events(&window, tray_registered); register_desktop_lifecycle_events(&window); diff --git a/apps/desktop-shell/src-tauri/src/shell/navigation.rs b/apps/desktop-shell/src-tauri/src/shell/navigation.rs index d02e7d306..8d0e4fee6 100644 --- a/apps/desktop-shell/src-tauri/src/shell/navigation.rs +++ b/apps/desktop-shell/src-tauri/src/shell/navigation.rs @@ -179,6 +179,19 @@ pub(crate) fn should_allow_desktop_webview_download(event: &DownloadEvent<'_>) - } } +fn log_desktop_webview_download_blocked(url: &Url) -> bool { + eprintln!("desktop host event blocked for webview.download: {url}"); + false +} + +pub(crate) fn handle_desktop_webview_download(event: &DownloadEvent<'_>) -> bool { + if let DownloadEvent::Requested { url, .. } = event { + log_desktop_webview_download_blocked(url); + } + + should_allow_desktop_webview_download(event) +} + pub(crate) fn normalize_native_page_url(raw_url: &str) -> Option { let url = raw_url.trim(); if url.is_empty() || url.chars().any(char::is_control) { @@ -283,6 +296,19 @@ mod tests { assert!(should_allow_desktop_webview_download(&finished)); } + #[test] + fn desktop_webview_download_handler_logs_blocked_requests() { + let mut destination = std::env::temp_dir().join("genarrative-webview-download.txt"); + let url = Url::parse("https://app.genarrative.world/download.txt").expect("download url"); + let requested = DownloadEvent::Requested { + url: url.clone(), + destination: &mut destination, + }; + + assert!(!log_desktop_webview_download_blocked(&url)); + assert!(!handle_desktop_webview_download(&requested)); + } + #[test] fn native_page_url_normalization_allows_same_origin_routes() { let route = diff --git a/apps/desktop-shell/src-tauri/src/shell/webview.rs b/apps/desktop-shell/src-tauri/src/shell/webview.rs index e92747041..369a1b3f7 100644 --- a/apps/desktop-shell/src-tauri/src/shell/webview.rs +++ b/apps/desktop-shell/src-tauri/src/shell/webview.rs @@ -5,9 +5,9 @@ pub(crate) use crate::shell::lifecycle::{ should_replay_desktop_webview_state_on_page_load, }; pub(crate) use crate::shell::navigation::{ - desktop_external_navigation_url, normalize_external_url, normalize_native_page_url, - open_desktop_external_navigation, open_normalized_desktop_external_url, - register_desktop_navigation_events, should_allow_desktop_webview_download, + desktop_external_navigation_url, handle_desktop_webview_download, normalize_external_url, + normalize_native_page_url, open_desktop_external_navigation, + open_normalized_desktop_external_url, register_desktop_navigation_events, should_allow_desktop_webview_navigation, }; pub(crate) use crate::shell::network::resolve_desktop_network_status;