e563ae0a81
桌面 HostBridge replay 内部锁失败返回稳定 host_error 桌面配置门禁反查 replay 失败日志和无 panic 边界 补充原生壳方案文档和共享决策记录
86 lines
2.5 KiB
Rust
86 lines
2.5 KiB
Rust
mod appearance;
|
|
pub(crate) mod capabilities;
|
|
mod badge;
|
|
mod clipboard;
|
|
mod dispatch;
|
|
pub(crate) mod file_payloads;
|
|
pub(crate) mod files;
|
|
mod navigation;
|
|
mod network;
|
|
mod notifications;
|
|
pub(crate) mod protocol;
|
|
mod runtime;
|
|
mod share;
|
|
mod title;
|
|
|
|
pub(crate) use protocol::HostBridgeReplayState;
|
|
pub(crate) use share::DesktopShareState;
|
|
|
|
use crate::host_bridge::dispatch::execute_host_bridge_request;
|
|
use crate::host_bridge::protocol::{
|
|
normalize_request_id, validate_request, HostBridgeReplayReservation, HostBridgeRequest,
|
|
HostBridgeResponse,
|
|
};
|
|
|
|
fn prepare_host_bridge_request(
|
|
request: &mut HostBridgeRequest,
|
|
) -> Option<HostBridgeResponse> {
|
|
if let Some(response) = validate_request(request) {
|
|
return Some(response);
|
|
}
|
|
request.id = normalize_request_id(&request.id).unwrap_or_else(|| request.id.clone());
|
|
None
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub(crate) async fn host_bridge_request(
|
|
app: tauri::AppHandle,
|
|
replay_state: tauri::State<'_, HostBridgeReplayState>,
|
|
mut request: HostBridgeRequest,
|
|
) -> Result<HostBridgeResponse, String> {
|
|
if let Some(response) = prepare_host_bridge_request(&mut request) {
|
|
return Ok(response);
|
|
}
|
|
|
|
let response = match replay_state.reserve(&request.id) {
|
|
Err(response) => response,
|
|
Ok(HostBridgeReplayReservation::Wait(slot)) => {
|
|
HostBridgeReplayState::wait_for_response(slot)
|
|
}
|
|
Ok(HostBridgeReplayReservation::Execute(slot)) => {
|
|
let response = execute_host_bridge_request(app, request).await;
|
|
replay_state.complete(slot, response)
|
|
}
|
|
};
|
|
|
|
Ok(response)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::host_bridge::protocol::request;
|
|
|
|
#[test]
|
|
fn host_bridge_request_rejects_invalid_requests_before_replay() {
|
|
let replay_state = HostBridgeReplayState::default();
|
|
let mut invalid = request("share.open");
|
|
invalid.id = " request-1 ".to_string();
|
|
invalid.bridge = "OtherBridge".to_string();
|
|
|
|
let response =
|
|
prepare_host_bridge_request(&mut invalid).expect("invalid envelope");
|
|
|
|
assert!(!response.ok);
|
|
assert_eq!(response.id, "request-1");
|
|
assert_eq!(response.error.expect("error").code, "invalid_request");
|
|
|
|
match replay_state.reserve("request-1").expect("replay reservation") {
|
|
HostBridgeReplayReservation::Execute(_) => {}
|
|
HostBridgeReplayReservation::Wait(_) => {
|
|
panic!("invalid request must not reserve replay slot")
|
|
}
|
|
}
|
|
}
|
|
}
|