收紧桌面壳事件注册失败处理
桌面壳新窗口策略增加可测试决策函数 桌面壳 WebView 事件注册失败改为启动阻断或日志记录 桌面壳配置门禁禁止事件注册静默吞错 宿主壳协议和共享决策记录补充事件注册失败规则
This commit is contained in:
@@ -9,7 +9,9 @@ use crate::shell::tray::{
|
||||
};
|
||||
use crate::shell::webview::{
|
||||
desktop_window_config_with_runtime_platform, emit_current_desktop_lifecycle_event,
|
||||
open_desktop_external_navigation, register_desktop_file_drop_events,
|
||||
desktop_external_navigation_url,
|
||||
log_desktop_webview_state_replay_result, open_desktop_external_navigation,
|
||||
open_normalized_desktop_external_url, register_desktop_file_drop_events,
|
||||
register_desktop_lifecycle_events, register_desktop_navigation_events,
|
||||
register_desktop_network_events, replay_desktop_webview_state,
|
||||
should_allow_desktop_webview_download, should_allow_desktop_webview_navigation,
|
||||
@@ -37,6 +39,14 @@ fn desktop_main_window_config(
|
||||
desktop_main_window_config_from_windows(&app.config().app.windows)
|
||||
}
|
||||
|
||||
fn desktop_new_window_external_url(url: &tauri::Url) -> Option<String> {
|
||||
desktop_external_navigation_url(url)
|
||||
}
|
||||
|
||||
fn desktop_new_window_response<R: tauri::Runtime>() -> NewWindowResponse<R> {
|
||||
NewWindowResponse::Deny
|
||||
}
|
||||
|
||||
pub(crate) fn run() {
|
||||
tauri::Builder::default()
|
||||
.manage(DesktopShareState::default())
|
||||
@@ -76,8 +86,13 @@ pub(crate) fn run() {
|
||||
}
|
||||
})
|
||||
.on_new_window(move |url, _features| {
|
||||
open_desktop_external_navigation(&new_window_app_handle, &url);
|
||||
NewWindowResponse::Deny
|
||||
if let Some(external_url) = desktop_new_window_external_url(&url) {
|
||||
let _ = open_normalized_desktop_external_url(
|
||||
&new_window_app_handle,
|
||||
external_url,
|
||||
);
|
||||
}
|
||||
desktop_new_window_response::<tauri::Wry>()
|
||||
})
|
||||
.on_page_load(|window, payload| {
|
||||
if should_replay_desktop_webview_state_on_page_load(payload.event()) {
|
||||
@@ -88,9 +103,12 @@ pub(crate) fn run() {
|
||||
.build()?;
|
||||
register_desktop_window_close_events(&window, tray_registered);
|
||||
register_desktop_lifecycle_events(&window);
|
||||
let _ = emit_current_desktop_lifecycle_event(&window);
|
||||
let _ = register_desktop_network_events(&window);
|
||||
let _ = register_desktop_navigation_events(&window);
|
||||
log_desktop_webview_state_replay_result(
|
||||
"app.lifecycle",
|
||||
emit_current_desktop_lifecycle_event(&window),
|
||||
);
|
||||
register_desktop_network_events(&window)?;
|
||||
register_desktop_navigation_events(&window)?;
|
||||
register_desktop_file_drop_events(&window);
|
||||
register_desktop_deep_link_events(app)?;
|
||||
register_desktop_deep_link_schemes(app);
|
||||
@@ -143,4 +161,30 @@ mod tests {
|
||||
|
||||
assert!(matches!(error, tauri::Error::WindowNotFound));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_new_window_policy_denies_embedded_windows() {
|
||||
assert!(matches!(
|
||||
desktop_new_window_response::<tauri::Wry>(),
|
||||
NewWindowResponse::Deny
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_new_window_policy_opens_only_safe_external_urls() {
|
||||
let external_url = tauri::Url::parse("https://example.com/share")
|
||||
.expect("external desktop new window url");
|
||||
assert_eq!(
|
||||
desktop_new_window_external_url(&external_url),
|
||||
Some("https://example.com/share".to_string())
|
||||
);
|
||||
|
||||
let same_origin_url = tauri::Url::parse("https://app.genarrative.world/works/detail")
|
||||
.expect("same-origin desktop new window url");
|
||||
assert_eq!(desktop_new_window_external_url(&same_origin_url), None);
|
||||
|
||||
let unsafe_url =
|
||||
tauri::Url::parse("javascript:alert(1)").expect("unsafe desktop new window url");
|
||||
assert_eq!(desktop_new_window_external_url(&unsafe_url), None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,10 +97,32 @@ pub(crate) fn should_replay_desktop_webview_state_on_page_load(event: PageLoadEv
|
||||
event == PageLoadEvent::Finished
|
||||
}
|
||||
|
||||
pub(crate) fn log_desktop_webview_state_replay_result(
|
||||
label: &'static str,
|
||||
result: tauri::Result<()>,
|
||||
) -> bool {
|
||||
match result {
|
||||
Ok(()) => true,
|
||||
Err(error) => {
|
||||
eprintln!("desktop webview state replay failed for {label}: {error}");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn replay_desktop_webview_state(window: &WebviewWindow) {
|
||||
let _ = emit_current_desktop_lifecycle_event(window);
|
||||
let _ = register_desktop_network_events(window);
|
||||
let _ = register_desktop_navigation_events(window);
|
||||
log_desktop_webview_state_replay_result(
|
||||
"app.lifecycle",
|
||||
emit_current_desktop_lifecycle_event(window),
|
||||
);
|
||||
log_desktop_webview_state_replay_result(
|
||||
"network.statusChanged",
|
||||
register_desktop_network_events(window),
|
||||
);
|
||||
log_desktop_webview_state_replay_result(
|
||||
"navigation.canGoBack",
|
||||
register_desktop_navigation_events(window),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -117,6 +139,15 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_state_replay_result_reports_success_and_failure() {
|
||||
assert!(log_desktop_webview_state_replay_result("network", Ok(())));
|
||||
assert!(!log_desktop_webview_state_replay_result(
|
||||
"navigation",
|
||||
Err(tauri::Error::AssetNotFound("navigation".to_string()))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_lifecycle_payload_maps_hidden_and_minimized_to_background() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
pub(crate) use crate::shell::file_drop::register_desktop_file_drop_events;
|
||||
pub(crate) use crate::shell::lifecycle::{
|
||||
emit_current_desktop_lifecycle_event, register_desktop_lifecycle_events,
|
||||
replay_desktop_webview_state, should_replay_desktop_webview_state_on_page_load,
|
||||
emit_current_desktop_lifecycle_event, log_desktop_webview_state_replay_result,
|
||||
register_desktop_lifecycle_events, replay_desktop_webview_state,
|
||||
should_replay_desktop_webview_state_on_page_load,
|
||||
};
|
||||
pub(crate) use crate::shell::navigation::{
|
||||
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, should_allow_desktop_webview_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,
|
||||
should_allow_desktop_webview_navigation,
|
||||
};
|
||||
pub(crate) use crate::shell::network::{
|
||||
register_desktop_network_events, resolve_desktop_network_status,
|
||||
|
||||
Reference in New Issue
Block a user