Files
searchi/apps/desktop/src-tauri/src/instance.rs
T

79 lines
2.7 KiB
Rust

//! Official single-instance transport, scoped to an explicitly selected profile.
use sha2::{Digest, Sha256};
use std::{ffi::OsString, io, path::PathBuf};
use tauri::{Emitter, Manager};
pub fn profile_identifier(base: &str, profile: Option<OsString>) -> io::Result<String> {
let Some(profile) = profile else {
return Ok(base.to_owned());
};
let path = crate::data_directory::resolve(PathBuf::new(), Some(profile))?;
// Resolve the existing ancestor without creating a first-use profile.
let canonical = crate::data_directory::canonical_exclusion(&path)?;
let mut digest = Sha256::new();
#[cfg(windows)]
{
use std::os::windows::ffi::OsStrExt;
for unit in canonical.as_os_str().encode_wide() {
digest.update(unit.to_le_bytes());
}
}
#[cfg(not(windows))]
{
use std::os::unix::ffi::OsStrExt;
digest.update(canonical.as_os_str().as_bytes());
}
Ok(format!("{base}.profile{:x}", digest.finalize()))
}
pub fn focus_search(app: &tauri::AppHandle) {
if let Some(window) = app.get_webview_window("main") {
let result = window
.show()
.and_then(|_| window.unminimize())
.and_then(|_| window.set_focus());
if let Err(error) = result {
eprintln!("Could not focus searchi: {error}");
}
let _ = window.emit("focus-search", ());
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_identity_is_unchanged_and_invalid_profile_rejected() {
assert_eq!(
profile_identifier("dev.searchi.desktop", None).unwrap(),
"dev.searchi.desktop"
);
assert!(profile_identifier("dev.searchi.desktop", Some("relative".into())).is_err());
}
#[test]
fn canonical_profiles_are_stable_distinct_and_do_not_expose_paths() {
let root = tempfile::tempdir().unwrap();
let first = root.path().join("Gemäß_日本_😀");
let second = root.path().join("other");
let id = profile_identifier("dev.searchi.desktop", Some(first.clone().into_os_string()))
.unwrap();
assert!(!first.exists());
std::fs::create_dir(&first).unwrap();
assert_eq!(
id,
profile_identifier(
"dev.searchi.desktop",
Some(first.join(".").into_os_string())
)
.unwrap()
);
assert_ne!(
id,
profile_identifier("dev.searchi.desktop", Some(second.into_os_string())).unwrap()
);
assert!(!id.contains("Gemäß"));
assert_eq!(id.len(), "dev.searchi.desktop.profile".len() + 64);
assert!(!root.path().join("other").exists());
}
}