rightkit_tauri_shell/
opener.rs1use std::process::{Command, Stdio};
5
6use crate::nav::external_scheme_allowed;
7
8pub trait ExternalOpener: Send + Sync + 'static {
9 fn open(&self, target: &str) -> Result<(), String>;
11}
12
13pub struct SystemOpener;
16
17impl ExternalOpener for SystemOpener {
18 fn open(&self, target: &str) -> Result<(), String> {
19 let mut cmd;
20 #[cfg(target_os = "macos")]
21 {
22 cmd = Command::new("/usr/bin/open");
23 cmd.arg(target);
24 }
25 #[cfg(windows)]
26 {
27 use std::os::windows::process::CommandExt;
28 cmd = Command::new("rundll32.exe");
29 cmd.arg("url.dll,FileProtocolHandler").arg(target);
30 cmd.creation_flags(0x0800_0000);
32 }
33 #[cfg(not(any(target_os = "macos", windows)))]
34 {
35 cmd = Command::new("xdg-open");
36 cmd.arg(target);
37 }
38 cmd.stdin(Stdio::null())
39 .stdout(Stdio::null())
40 .stderr(Stdio::null());
41 cmd.spawn()
42 .map(|mut child| {
43 std::thread::spawn(move || {
45 let _ = child.wait();
46 });
47 })
48 .map_err(|e| format!("open {target}: {e}"))
49 }
50}
51
52pub fn open_checked(opener: &dyn ExternalOpener, target: &str) -> Result<(), String> {
54 if !external_scheme_allowed(target) {
55 return Err("blocked: only http(s)/mailto links open externally".into());
56 }
57 opener.open(target.trim())
58}