be870c58df
桌面壳窗口标题失败只记录固定阶段标签 扩展桌面壳配置门禁禁止窗口标题日志输出 Tauri 错误细节 补充宿主壳方案和共享决策中的窗口标题诊断边界
138 lines
4.3 KiB
Rust
138 lines
4.3 KiB
Rust
use crate::host_bridge::protocol::{
|
|
failed, ok, required_string_payload, HostBridgeRequest, HostBridgeResponse,
|
|
};
|
|
use serde_json::json;
|
|
use tauri::Manager;
|
|
|
|
const WINDOW_TITLE_MAX_LENGTH: usize = 80;
|
|
|
|
fn normalize_window_title(raw_title: &str) -> Option<String> {
|
|
let title = raw_title.trim();
|
|
if title.is_empty() || title.chars().any(char::is_control) {
|
|
return None;
|
|
}
|
|
|
|
Some(title.chars().take(WINDOW_TITLE_MAX_LENGTH).collect())
|
|
}
|
|
|
|
fn window_title_from_request(
|
|
request: &HostBridgeRequest,
|
|
) -> Result<String, HostBridgeResponse> {
|
|
required_string_payload(request, "title")
|
|
.ok()
|
|
.and_then(normalize_window_title)
|
|
.ok_or_else(|| failed(request.id.clone(), "invalid_request", "title is required"))
|
|
}
|
|
|
|
pub(crate) fn set_desktop_host_bridge_window_title(
|
|
app: &tauri::AppHandle,
|
|
request: &HostBridgeRequest,
|
|
) -> HostBridgeResponse {
|
|
let title = match window_title_from_request(request) {
|
|
Ok(title) => title,
|
|
Err(response) => return response,
|
|
};
|
|
|
|
match app.get_webview_window("main") {
|
|
Some(window) => match window.set_title(&title) {
|
|
Ok(()) => ok(request.id.clone(), json!(true)),
|
|
Err(_error) => {
|
|
log_desktop_window_title_failure("set");
|
|
window_title_unavailable_response(request)
|
|
}
|
|
},
|
|
None => {
|
|
log_desktop_window_title_failure("window");
|
|
window_title_unavailable_response(request)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn window_title_unavailable_response(request: &HostBridgeRequest) -> HostBridgeResponse {
|
|
failed(request.id.clone(), "host_error", "window title unavailable")
|
|
}
|
|
|
|
fn log_desktop_window_title_failure(label: &str) -> bool {
|
|
eprintln!("desktop window title failed for {label}");
|
|
false
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::host_bridge::protocol::request;
|
|
use serde_json::json;
|
|
|
|
#[test]
|
|
fn window_title_normalization_requires_visible_text() {
|
|
assert_eq!(
|
|
normalize_window_title(" Genarrative "),
|
|
Some("Genarrative".to_string())
|
|
);
|
|
assert_eq!(normalize_window_title(""), None);
|
|
assert_eq!(normalize_window_title("Genarrative\nDev"), None);
|
|
|
|
let long_title = "甲".repeat(120);
|
|
assert_eq!(
|
|
normalize_window_title(&long_title)
|
|
.expect("truncated title")
|
|
.chars()
|
|
.count(),
|
|
80
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn window_title_request_rejects_missing_or_invalid_payload() {
|
|
for payload in [
|
|
None,
|
|
Some(json!({})),
|
|
Some(json!({ "title": 1 })),
|
|
Some(json!({ "title": " " })),
|
|
Some(json!({ "title": "Genarrative\nDev" })),
|
|
] {
|
|
let mut request = request("app.setTitle");
|
|
request.payload = payload;
|
|
|
|
let response = window_title_from_request(&request).expect_err("invalid title");
|
|
let error = response.error.expect("error");
|
|
assert_eq!(error.code, "invalid_request");
|
|
assert_eq!(error.message, "title is required");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn window_title_request_trims_and_truncates_shared_boundary() {
|
|
let mut request = request("app.setTitle");
|
|
request.payload = Some(json!({
|
|
"title": format!(" {} ", "甲".repeat(120))
|
|
}));
|
|
|
|
let title = window_title_from_request(&request).expect("window title");
|
|
|
|
assert_eq!(title.chars().count(), WINDOW_TITLE_MAX_LENGTH);
|
|
assert!(title.chars().all(|character| character == '甲'));
|
|
}
|
|
|
|
#[test]
|
|
fn window_title_unavailable_response_is_stable() {
|
|
let response = window_title_unavailable_response(&request("app.setTitle"));
|
|
|
|
assert!(!response.ok);
|
|
let error = response.error.expect("window title error");
|
|
assert_eq!(error.code, "host_error");
|
|
assert_eq!(error.message, "window title unavailable");
|
|
}
|
|
|
|
#[test]
|
|
fn window_title_failures_are_logged_without_exposing_native_detail() {
|
|
assert!(!log_desktop_window_title_failure("set"));
|
|
assert!(!log_desktop_window_title_failure("window"));
|
|
}
|
|
|
|
#[test]
|
|
fn window_title_failures_log_stable_label_only() {
|
|
assert!(!log_desktop_window_title_failure("set"));
|
|
}
|
|
}
|