锁定桌面文件不可用响应

桌面文件导出把系统写入和线程失败转为稳定 host_error

桌面文件导入把后台读取线程失败转为稳定 host_error

桌面文件单测覆盖不可用响应 code 和 message

桌面壳配置检查反查文件不可用响应边界
This commit is contained in:
2026-06-20 12:21:34 +08:00
parent a1ff692912
commit d777ad6633
2 changed files with 45 additions and 10 deletions
@@ -2235,9 +2235,14 @@ const requiredRustHostSnippets = [
'"copied_to_clipboard"',
'file_export_cancelled_response',
'file_import_cancelled_response',
'file_export_unavailable_response',
'file_import_unavailable_response',
'desktop_file_cancelled_responses_are_stable',
'desktop_file_unavailable_responses_are_stable',
'"file export cancelled"',
'"file import cancelled"',
'"file export unavailable"',
'"file import unavailable"',
'BASE64_STANDARD.decode',
'blocking_pick_file',
'import_text_file_payload',
@@ -15,6 +15,22 @@ fn file_import_cancelled_response(request: &HostBridgeRequest) -> HostBridgeResp
failed(request.id.clone(), "cancelled", "file import cancelled")
}
fn file_export_unavailable_response(request: &HostBridgeRequest) -> HostBridgeResponse {
failed(
request.id.clone(),
"host_error",
"file export unavailable",
)
}
fn file_import_unavailable_response(request: &HostBridgeRequest) -> HostBridgeResponse {
failed(
request.id.clone(),
"host_error",
"file import unavailable",
)
}
pub(crate) async fn export_desktop_host_bridge_text_file(
app: &tauri::AppHandle,
request: &HostBridgeRequest,
@@ -40,8 +56,7 @@ pub(crate) async fn export_desktop_host_bridge_text_file(
tauri::async_runtime::spawn_blocking(move || write_export_text_file(path, content)).await;
let bytes = match export_result {
Ok(Ok(bytes)) => bytes,
Ok(Err(error)) => return failed(request.id.clone(), "host_error", error),
Err(error) => return failed(request.id.clone(), "host_error", error.to_string()),
Ok(Err(_)) | Err(_) => return file_export_unavailable_response(request),
};
ok(
@@ -75,7 +90,7 @@ pub(crate) async fn import_desktop_host_bridge_text_file(
match import_result {
Ok(Ok(payload)) => ok(request.id.clone(), payload),
Ok(Err(error)) => failed(request.id.clone(), "invalid_request", error),
Err(error) => failed(request.id.clone(), "host_error", error.to_string()),
Err(_) => file_import_unavailable_response(request),
}
}
@@ -103,7 +118,7 @@ pub(crate) async fn import_desktop_host_bridge_document_file(
match import_result {
Ok(Ok(payload)) => ok(request.id.clone(), payload),
Ok(Err(error)) => failed(request.id.clone(), "invalid_request", error),
Err(error) => failed(request.id.clone(), "host_error", error.to_string()),
Err(_) => file_import_unavailable_response(request),
}
}
@@ -132,8 +147,7 @@ pub(crate) async fn export_desktop_host_bridge_image_file(
tauri::async_runtime::spawn_blocking(move || write_export_bytes_file(path, bytes)).await;
let byte_count = match export_result {
Ok(Ok(byte_count)) => byte_count,
Ok(Err(error)) => return failed(request.id.clone(), "host_error", error),
Err(error) => return failed(request.id.clone(), "host_error", error.to_string()),
Ok(Err(_)) | Err(_) => return file_export_unavailable_response(request),
};
ok(
request.id.clone(),
@@ -168,7 +182,7 @@ pub(crate) async fn import_desktop_host_bridge_image_file(
match import_result {
Ok(Ok(payload)) => ok(request.id.clone(), payload),
Ok(Err(error)) => failed(request.id.clone(), "invalid_request", error),
Err(error) => failed(request.id.clone(), "host_error", error.to_string()),
Err(_) => file_import_unavailable_response(request),
}
}
@@ -193,7 +207,7 @@ pub(crate) async fn import_desktop_host_bridge_audio_file(
match import_result {
Ok(Ok(payload)) => ok(request.id.clone(), payload),
Ok(Err(error)) => failed(request.id.clone(), "invalid_request", error),
Err(error) => failed(request.id.clone(), "host_error", error.to_string()),
Err(_) => file_import_unavailable_response(request),
}
}
@@ -222,8 +236,7 @@ pub(crate) async fn export_desktop_host_bridge_audio_file(
tauri::async_runtime::spawn_blocking(move || write_export_bytes_file(path, bytes)).await;
let byte_count = match export_result {
Ok(Ok(byte_count)) => byte_count,
Ok(Err(error)) => return failed(request.id.clone(), "host_error", error),
Err(error) => return failed(request.id.clone(), "host_error", error.to_string()),
Ok(Err(_)) | Err(_) => return file_export_unavailable_response(request),
};
ok(
request.id.clone(),
@@ -256,4 +269,21 @@ mod tests {
assert_eq!(import_error.code, "cancelled");
assert_eq!(import_error.message, "file import cancelled");
}
#[test]
fn desktop_file_unavailable_responses_are_stable() {
let request = request("file.importText");
let export_error = file_export_unavailable_response(&request)
.error
.expect("export error");
assert_eq!(export_error.code, "host_error");
assert_eq!(export_error.message, "file export unavailable");
let import_error = file_import_unavailable_response(&request)
.error
.expect("import error");
assert_eq!(import_error.code, "host_error");
assert_eq!(import_error.message, "file import unavailable");
}
}