From 0eb9b0e9f416328c10717573af356feed2878e9a Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 19 May 2026 22:52:39 +0100 Subject: [PATCH] Add Linux Firefox cookie path support Implements Phase 3 of xmaster-linux-patch design: - Add #[cfg(target_os = "linux")] firefox_profiles_dir() returning ~/.mozilla/firefox/Profiles/ - Add #[cfg(target_os = "macos")] firefox_profiles_dir() returning ~/Library/Application Support/Firefox/Profiles/ - Add find_firefox_profile() helper to search for cookies.sqlite - Simplify extract_firefox() to use platform-specific path functions Zero breaking changes to existing macOS functionality. Firefox-only approach (Chrome support deferred per design). Refs: xmaster-linux-patch-design.md --- src/browser_cookies.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/browser_cookies.rs b/src/browser_cookies.rs index d640b0c..ebe7090 100644 --- a/src/browser_cookies.rs +++ b/src/browser_cookies.rs @@ -311,17 +311,29 @@ fn decrypt_chrome_cookie( // Firefox — plain SQLite (no encryption!) // --------------------------------------------------------------------------- -fn extract_firefox() -> Result { +/// Returns the Firefox profiles directory on Linux: ~/.mozilla/firefox/Profiles/ +#[cfg(target_os = "linux")] +fn firefox_profiles_dir() -> Result { let home = std::env::var("HOME").map_err(|_| XmasterError::Config("HOME not set".into()))?; - let profiles_dir = PathBuf::from(&home).join("Library/Application Support/Firefox/Profiles"); + Ok(PathBuf::from(home).join(".mozilla/firefox/Profiles")) +} + +/// Returns the Firefox profiles directory on macOS: ~/Library/Application Support/Firefox/Profiles/ +#[cfg(target_os = "macos")] +fn firefox_profiles_dir() -> Result { + let home = std::env::var("HOME").map_err(|_| XmasterError::Config("HOME not set".into()))?; + Ok(PathBuf::from(home).join("Library/Application Support/Firefox/Profiles")) +} +/// Search for a Firefox profile with cookies.sqlite. +/// Tries profiles ending with .default-release first, then .default. +fn find_firefox_profile(profiles_dir: &PathBuf) -> Result { if !profiles_dir.exists() { return Err(XmasterError::Config("Firefox profiles directory not found".into())); } - // Find the default profile (usually ends with .default-release or .default) let mut cookie_db = None; - if let Ok(entries) = std::fs::read_dir(&profiles_dir) { + if let Ok(entries) = std::fs::read_dir(profiles_dir) { for entry in entries.flatten() { let name = entry.file_name().to_string_lossy().to_string(); if name.ends_with(".default-release") || name.ends_with(".default") { @@ -334,9 +346,14 @@ fn extract_firefox() -> Result { } } - let cookie_db = cookie_db.ok_or_else(|| { + cookie_db.ok_or_else(|| { XmasterError::Config("No Firefox profile with cookies.sqlite found".into()) - })?; + }) +} + +fn extract_firefox() -> Result { + let profiles_dir = firefox_profiles_dir()?; + let cookie_db = find_firefox_profile(&profiles_dir)?; // Copy to temp (Firefox also uses WAL) let tmp = std::env::temp_dir().join("xmaster_ff_cookies.sqlite");