补齐桌面壳导航失败观测
桌面外链导航和刷新记录系统异常日志 Rust 单测覆盖稳定错误和日志边界 配置门禁和文档同步导航观测约束
This commit is contained in:
@@ -2000,9 +2000,12 @@ if (
|
||||
for (const snippet of [
|
||||
'open_desktop_host_bridge_external_url',
|
||||
'external_url_unavailable_response',
|
||||
'log_desktop_navigation_failure',
|
||||
'desktop navigation failed for {label}: {error}',
|
||||
'desktop_external_url_from_request',
|
||||
'normalize_external_url',
|
||||
'open_normalized_desktop_external_url(app, url)',
|
||||
'log_desktop_navigation_failure("external.open", &error.to_string())',
|
||||
'desktop_external_url_request_accepts_only_safe_system_protocols',
|
||||
'"external URL cannot be opened"',
|
||||
'external_url_unavailable_response_is_stable',
|
||||
@@ -2011,12 +2014,18 @@ for (const snippet of [
|
||||
'desktop_native_page_url_from_request',
|
||||
'normalize_native_page_url',
|
||||
'window.navigate(url)',
|
||||
'log_desktop_navigation_failure("native.navigate", &error.to_string())',
|
||||
'log_desktop_navigation_failure("native.window", "main window unavailable")',
|
||||
'desktop_native_page_request_accepts_only_same_origin_h5_routes',
|
||||
'navigation_failures_are_logged_without_exposing_native_detail',
|
||||
'"native page unavailable"',
|
||||
'native_page_unavailable_response_is_stable',
|
||||
'reload_desktop_host_bridge_webview',
|
||||
'webview_reload_unavailable_response',
|
||||
'window.reload()',
|
||||
'log_desktop_navigation_failure("webview.reload", &error.to_string())',
|
||||
'log_desktop_navigation_failure("webview.window", "main window unavailable")',
|
||||
'webview_reload_failures_are_logged_without_exposing_native_detail',
|
||||
'"webview reload unavailable"',
|
||||
'webview_reload_unavailable_response_is_stable',
|
||||
]) {
|
||||
@@ -2024,6 +2033,12 @@ for (const snippet of [
|
||||
throw new Error(`desktop shell navigation module is missing ${snippet}`);
|
||||
}
|
||||
}
|
||||
if (
|
||||
desktopHostBridgeNavigationSource.includes('failed(request.id.clone(), "host_error", error.to_string())') ||
|
||||
desktopHostBridgeNavigationSource.includes('"main window not found"')
|
||||
) {
|
||||
throw new Error('desktop shell navigation module must hide native navigation errors');
|
||||
}
|
||||
|
||||
if (
|
||||
!desktopHostBridgeDispatchSource.includes(
|
||||
|
||||
@@ -48,7 +48,10 @@ pub(crate) fn open_desktop_host_bridge_external_url(
|
||||
|
||||
match open_normalized_desktop_external_url(app, url) {
|
||||
Ok(()) => ok(request.id.clone(), json!(true)),
|
||||
Err(_) => external_url_unavailable_response(request),
|
||||
Err(error) => {
|
||||
log_desktop_navigation_failure("external.open", &error.to_string());
|
||||
external_url_unavailable_response(request)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,9 +75,15 @@ pub(crate) fn open_desktop_host_bridge_native_page(
|
||||
match app.get_webview_window("main") {
|
||||
Some(window) => match window.navigate(url) {
|
||||
Ok(()) => ok(request.id.clone(), json!(true)),
|
||||
Err(_) => native_page_unavailable_response(request),
|
||||
Err(error) => {
|
||||
log_desktop_navigation_failure("native.navigate", &error.to_string());
|
||||
native_page_unavailable_response(request)
|
||||
}
|
||||
},
|
||||
None => native_page_unavailable_response(request),
|
||||
None => {
|
||||
log_desktop_navigation_failure("native.window", "main window unavailable");
|
||||
native_page_unavailable_response(request)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +91,14 @@ fn native_page_unavailable_response(request: &HostBridgeRequest) -> HostBridgeRe
|
||||
failed(request.id.clone(), "host_error", "native page unavailable")
|
||||
}
|
||||
|
||||
fn log_desktop_navigation_failure(label: &str, error: &str) -> bool {
|
||||
if !error.is_empty() {
|
||||
eprintln!("desktop navigation failed for {label}: {error}");
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -182,6 +199,22 @@ mod tests {
|
||||
assert_eq!(error.code, "host_error");
|
||||
assert_eq!(error.message, "native page unavailable");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn navigation_failures_are_logged_without_exposing_native_detail() {
|
||||
assert!(!log_desktop_navigation_failure(
|
||||
"external.open",
|
||||
"private external detail"
|
||||
));
|
||||
assert!(!log_desktop_navigation_failure(
|
||||
"native.navigate",
|
||||
"private navigation detail"
|
||||
));
|
||||
assert!(!log_desktop_navigation_failure(
|
||||
"native.window",
|
||||
"main window unavailable"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn reload_desktop_host_bridge_webview(
|
||||
@@ -191,9 +224,15 @@ pub(crate) fn reload_desktop_host_bridge_webview(
|
||||
match app.get_webview_window("main") {
|
||||
Some(window) => match window.reload() {
|
||||
Ok(()) => ok(request.id.clone(), json!(true)),
|
||||
Err(_) => webview_reload_unavailable_response(request),
|
||||
Err(error) => {
|
||||
log_desktop_navigation_failure("webview.reload", &error.to_string());
|
||||
webview_reload_unavailable_response(request)
|
||||
}
|
||||
},
|
||||
None => webview_reload_unavailable_response(request),
|
||||
None => {
|
||||
log_desktop_navigation_failure("webview.window", "main window unavailable");
|
||||
webview_reload_unavailable_response(request)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,4 +258,16 @@ mod reload_tests {
|
||||
assert_eq!(error.code, "host_error");
|
||||
assert_eq!(error.message, "webview reload unavailable");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn webview_reload_failures_are_logged_without_exposing_native_detail() {
|
||||
assert!(!log_desktop_navigation_failure(
|
||||
"webview.reload",
|
||||
"private reload detail"
|
||||
));
|
||||
assert!(!log_desktop_navigation_failure(
|
||||
"webview.window",
|
||||
"main window unavailable"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user