mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-04-25 05:16:18 +02:00
refactor: better process handling on macos
This commit is contained in:
@@ -368,6 +368,82 @@ impl BrowserRunner {
|
||||
}
|
||||
}
|
||||
|
||||
// On macOS, when launching via `open -a`, the child PID is the `open` helper.
|
||||
// Resolve and store the actual browser PID for all browser types.
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
// Give the browser a moment to start
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(1500)).await;
|
||||
|
||||
let system = System::new_all();
|
||||
let profiles_dir = self.get_profiles_dir();
|
||||
let profile_data_path = profile.get_profile_data_path(&profiles_dir);
|
||||
let profile_data_path_str = profile_data_path.to_string_lossy();
|
||||
|
||||
for (pid, process) in system.processes() {
|
||||
let cmd = process.cmd();
|
||||
if cmd.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine if this process matches the intended browser type
|
||||
let exe_name_lower = process.name().to_string_lossy().to_lowercase();
|
||||
let is_correct_browser = match profile.browser.as_str() {
|
||||
"firefox" => {
|
||||
exe_name_lower.contains("firefox")
|
||||
&& !exe_name_lower.contains("developer")
|
||||
&& !exe_name_lower.contains("tor")
|
||||
&& !exe_name_lower.contains("mullvad")
|
||||
&& !exe_name_lower.contains("camoufox")
|
||||
}
|
||||
"firefox-developer" => {
|
||||
exe_name_lower.contains("firefox") && exe_name_lower.contains("developer")
|
||||
}
|
||||
"mullvad-browser" => {
|
||||
self.is_tor_or_mullvad_browser(&exe_name_lower, cmd, "mullvad-browser")
|
||||
}
|
||||
"tor-browser" => self.is_tor_or_mullvad_browser(&exe_name_lower, cmd, "tor-browser"),
|
||||
"zen" => exe_name_lower.contains("zen"),
|
||||
"chromium" => exe_name_lower.contains("chromium"),
|
||||
"brave" => exe_name_lower.contains("brave"),
|
||||
// Camoufox uses nodecar, not PID-based here
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !is_correct_browser {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for profile path match in command line args
|
||||
let profile_path_match = cmd.iter().any(|s| {
|
||||
let arg = s.to_str().unwrap_or("");
|
||||
if profile.browser == "tor-browser"
|
||||
|| profile.browser == "firefox"
|
||||
|| profile.browser == "firefox-developer"
|
||||
|| profile.browser == "mullvad-browser"
|
||||
|| profile.browser == "zen"
|
||||
{
|
||||
arg == profile_data_path_str || arg == format!("-profile={profile_data_path_str}")
|
||||
} else {
|
||||
// For Chromium-based browsers, look for user-data-dir flag or raw path
|
||||
arg.contains(&format!("--user-data-dir={profile_data_path_str}"))
|
||||
|| arg == profile_data_path_str
|
||||
}
|
||||
});
|
||||
|
||||
if profile_path_match {
|
||||
let pid_u32 = pid.as_u32();
|
||||
if pid_u32 != launcher_pid {
|
||||
actual_pid = pid_u32;
|
||||
println!(
|
||||
"Resolved actual macOS browser PID: {actual_pid} (launcher PID: {launcher_pid})"
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update profile with process info and save
|
||||
let mut updated_profile = profile.clone();
|
||||
updated_profile.process_id = Some(actual_pid);
|
||||
|
||||
@@ -48,7 +48,38 @@ pub mod macos {
|
||||
args: &[String],
|
||||
) -> Result<std::process::Child, Box<dyn std::error::Error + Send + Sync>> {
|
||||
println!("Launching browser on macOS: {executable_path:?} with args: {args:?}");
|
||||
Ok(Command::new(executable_path).args(args).spawn()?)
|
||||
// If the executable is inside an app bundle, launch via Launch Services so
|
||||
// macOS recognizes the real application for privacy permissions (e.g. Screen Recording).
|
||||
// This ensures TCC prompts are attributed to the browser app, not our launcher.
|
||||
let mut current = Some(executable_path);
|
||||
let mut app_bundle: Option<std::path::PathBuf> = None;
|
||||
while let Some(path) = current {
|
||||
if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) {
|
||||
if file_name.ends_with(".app") {
|
||||
app_bundle = Some(path.to_path_buf());
|
||||
break;
|
||||
}
|
||||
}
|
||||
current = path.parent();
|
||||
}
|
||||
|
||||
if let Some(app_path) = app_bundle {
|
||||
// Use `open -n -a <App>.app --args ...` to launch the app bundle.
|
||||
// Note: The returned child PID will belong to `open`, not the browser.
|
||||
// The caller should resolve the actual browser PID after launch.
|
||||
let mut cmd = Command::new("open");
|
||||
cmd.arg("-n");
|
||||
cmd.arg("-a");
|
||||
cmd.arg(app_path);
|
||||
cmd.arg("--args");
|
||||
for a in args {
|
||||
cmd.arg(a);
|
||||
}
|
||||
Ok(cmd.spawn()?)
|
||||
} else {
|
||||
// Fallback: direct spawn if this is not an app bundle
|
||||
Ok(Command::new(executable_path).args(args).spawn()?)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn open_url_in_existing_browser_firefox_like(
|
||||
|
||||
Reference in New Issue
Block a user