Files
Genarrative/apps/desktop-shell/src-tauri/src/host_bridge/dispatch.rs
T
kdletters 838bd86ea0 收口桌面壳未声明方法测试派生
桌面壳 Rust 测试从 method 白名单和 capability 差集派生 unsupported 覆盖

桌面壳配置检查反查 unsupported 测试派生路径

架构文档记录桌面壳未声明方法派生规则
2026-06-20 04:01:09 +08:00

111 lines
4.7 KiB
Rust

use crate::host_bridge::appearance::desktop_appearance_color_scheme;
use crate::host_bridge::badge::set_desktop_app_badge_count;
use crate::host_bridge::clipboard::{
read_desktop_host_bridge_clipboard_text, write_desktop_host_bridge_clipboard_text,
};
use crate::host_bridge::files::{
export_desktop_host_bridge_audio_file, export_desktop_host_bridge_image_file,
export_desktop_host_bridge_text_file, import_desktop_host_bridge_audio_file,
import_desktop_host_bridge_document_file, import_desktop_host_bridge_image_file,
import_desktop_host_bridge_text_file,
};
use crate::host_bridge::navigation::{
open_desktop_host_bridge_external_url, open_desktop_host_bridge_native_page,
reload_desktop_host_bridge_webview,
};
use crate::host_bridge::network::resolve_desktop_host_bridge_network_status;
use crate::host_bridge::notifications::show_desktop_local_notification;
use crate::host_bridge::protocol::{
failed, validate_request, HostBridgeRequest, HostBridgeResponse,
};
use crate::host_bridge::runtime::desktop_host_bridge_runtime_response;
use crate::host_bridge::share::{
open_desktop_host_bridge_share, set_desktop_host_bridge_share_target,
};
use crate::host_bridge::title::set_desktop_host_bridge_window_title;
pub(crate) fn resolve_host_bridge_request(request: HostBridgeRequest) -> HostBridgeResponse {
if let Some(response) = validate_request(&request) {
return response;
}
match request.method.as_str() {
"host.getRuntime" => desktop_host_bridge_runtime_response(&request),
_ => failed(
request.id,
"unsupported_method",
format!("{} unsupported in desktop shell", request.method),
),
}
}
pub(super) async fn execute_host_bridge_request(
app: tauri::AppHandle,
request: HostBridgeRequest,
) -> HostBridgeResponse {
if let Some(response) = validate_request(&request) {
return response;
}
match request.method.as_str() {
"app.openExternalUrl" => open_desktop_host_bridge_external_url(&app, &request),
"appearance.getColorScheme" => desktop_appearance_color_scheme(&app, &request),
"navigation.openNativePage" => open_desktop_host_bridge_native_page(&app, &request),
"app.reloadWebView" => reload_desktop_host_bridge_webview(&app, &request),
"clipboard.writeText" => write_desktop_host_bridge_clipboard_text(&app, &request),
"clipboard.readText" => read_desktop_host_bridge_clipboard_text(&app, &request),
"file.exportText" => export_desktop_host_bridge_text_file(&app, &request).await,
"file.importText" => import_desktop_host_bridge_text_file(&app, &request).await,
"file.importDocument" => import_desktop_host_bridge_document_file(&app, &request).await,
"file.exportImage" => export_desktop_host_bridge_image_file(&app, &request).await,
"file.importImage" => import_desktop_host_bridge_image_file(&app, &request).await,
"file.importAudio" => import_desktop_host_bridge_audio_file(&app, &request).await,
"file.exportAudio" => export_desktop_host_bridge_audio_file(&app, &request).await,
"app.setTitle" => set_desktop_host_bridge_window_title(&app, &request),
"app.setBadgeCount" => set_desktop_app_badge_count(&app, &request),
"network.status" => resolve_desktop_host_bridge_network_status(&request).await,
"notification.showLocal" => show_desktop_local_notification(&app, &request),
"share.setTarget" => set_desktop_host_bridge_share_target(&app, &request),
"share.open" => open_desktop_host_bridge_share(&app, &request),
_ => resolve_host_bridge_request(request),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::host_bridge::capabilities::capabilities;
use crate::host_bridge::protocol::HOST_BRIDGE_METHODS;
use crate::host_bridge::protocol::request;
#[test]
fn unsupported_method_is_explicit() {
let desktop_capabilities = capabilities();
let unsupported_methods = HOST_BRIDGE_METHODS
.iter()
.copied()
.filter(|method| !desktop_capabilities.contains(method))
.collect::<Vec<_>>();
assert_eq!(
unsupported_methods,
vec![
"auth.requestLogin",
"payment.request",
"file.captureImage",
"scanner.scanQrCode",
"haptics.impact",
],
);
for method in unsupported_methods {
let response = resolve_host_bridge_request(request(method));
assert!(!response.ok);
let error = response.error.expect("error");
assert_eq!(error.code, "unsupported_method");
assert!(error.message.contains(method));
}
}
}