From effe22906761749c717bc7ee2647bde392ac8eb1 Mon Sep 17 00:00:00 2001 From: zhom <2717306+zhom@users.noreply.github.com> Date: Mon, 1 Dec 2025 12:25:21 +0400 Subject: [PATCH] refactor: remove mullvad and tor browser artifacts --- .vscode/settings.json | 3 - src-tauri/src/api_client.rs | 383 --------------------- src-tauri/src/browser.rs | 77 +---- src-tauri/src/browser_runner.rs | 171 ++------- src-tauri/src/browser_version_manager.rs | 249 -------------- src-tauri/src/downloader.rs | 86 ----- src-tauri/src/extraction.rs | 24 +- src-tauri/src/platform_browser.rs | 248 ------------- src-tauri/src/profile/manager.rs | 41 +-- src-tauri/src/profile_importer.rs | 17 - src/app/page.tsx | 8 +- src/components/create-profile-dialog.tsx | 19 +- src/components/import-profile-dialog.tsx | 5 +- src/components/profile-data-table.tsx | 32 +- src/components/profile-selector-dialog.tsx | 6 +- src/components/proxy-assignment-dialog.tsx | 9 +- src/hooks/use-browser-state.ts | 16 +- src/lib/browser-utils.ts | 8 +- 18 files changed, 50 insertions(+), 1352 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index e29077a..0729c99 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -105,8 +105,6 @@ "mstone", "msvc", "msys", - "Mullvad", - "mullvadbrowser", "mypy", "noarchive", "nobrowse", @@ -188,7 +186,6 @@ "timedatectl", "titlebar", "tkinter", - "Torbrowser", "tqdm", "trackingprotection", "trailhead", diff --git a/src-tauri/src/api_client.rs b/src-tauri/src/api_client.rs index 67226e1..b9a7f3c 100644 --- a/src-tauri/src/api_client.rs +++ b/src-tauri/src/api_client.rs @@ -292,7 +292,6 @@ pub fn is_browser_version_nightly( // This will be handled in the API parsing, so this fallback is for cached versions is_nightly_version(version) } - "mullvad-browser" | "tor-browser" => is_nightly_version(version), "chromium" => { // Chromium builds are generally stable snapshots false @@ -349,7 +348,6 @@ pub struct ApiClient { firefox_dev_api_base: String, github_api_base: String, chromium_api_base: String, - tor_archive_base: String, } impl ApiClient { @@ -366,7 +364,6 @@ impl ApiClient { github_api_base: "https://api.github.com".to_string(), chromium_api_base: "https://commondatastorage.googleapis.com/chromium-browser-snapshots" .to_string(), - tor_archive_base: "https://archive.torproject.org/tor-package-archive/torbrowser".to_string(), } } @@ -439,7 +436,6 @@ impl ApiClient { firefox_dev_api_base: String, github_api_base: String, chromium_api_base: String, - tor_archive_base: String, ) -> Self { Self { client: Client::new(), @@ -723,45 +719,6 @@ impl ApiClient { Ok(releases) } - pub async fn fetch_mullvad_releases_with_caching( - &self, - no_caching: bool, - ) -> Result, Box> { - // Check cache first (unless bypassing) - if !no_caching { - if let Some(cached_releases) = self.load_cached_github_releases("mullvad") { - return Ok(cached_releases); - } - } - - log::info!("Fetching Mullvad releases from GitHub API"); - let base_url = format!( - "{}/repos/mullvad/mullvad-browser/releases", - self.github_api_base - ); - let releases = self.fetch_github_releases_multiple_pages(&base_url).await?; - - let mut releases: Vec = releases - .into_iter() - .map(|mut release| { - release.is_nightly = release.prerelease; - release - }) - .collect(); - - // Sort releases using the new version sorting system - sort_github_releases(&mut releases); - - // Cache the results (unless bypassing cache) - if !no_caching { - if let Err(e) = self.save_cached_github_releases("mullvad", &releases) { - log::error!("Failed to cache Mullvad releases: {e}"); - } - } - - Ok(releases) - } - pub async fn fetch_zen_releases_with_caching( &self, no_caching: bool, @@ -1102,107 +1059,6 @@ impl ApiClient { Ok(compatible_releases) } - pub async fn fetch_tor_releases_with_caching( - &self, - no_caching: bool, - ) -> Result, Box> { - // Check cache first (unless bypassing) - if !no_caching { - if let Some(cached_releases) = self.load_cached_versions("tor-browser") { - return Ok(cached_releases); - } - } - - log::info!("Fetching TOR releases from archive..."); - let url = format!("{}/", self.tor_archive_base); - let html = self - .client - .get(url) - .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36") - .send() - .await? - .text() - .await?; - - // Parse HTML to extract version directories - let mut version_candidates = Vec::new(); - - // Look for directory links in the HTML - for line in html.lines() { - if line.contains("") { - // Extract the directory name from the href attribute - if let Some(start) = line.find("") { - let version = &line[start..start + end]; - - // Skip parent directory and non-version entries - if version != ".." - && !version.is_empty() - && version.chars().next().unwrap_or('a').is_ascii_digit() - { - version_candidates.push(version.to_string()); - } - } - } - } - } - - // Sort version candidates using the new version sorting system - sort_versions(&mut version_candidates); - - // Only check the first 10 versions to avoid being too slow - let mut version_strings = Vec::new(); - for version in version_candidates.into_iter().take(10) { - // Check if this version has a macOS DMG file - if let Ok(has_macos) = self.check_tor_version_has_macos(&version).await { - if has_macos { - version_strings.push(version); - } - } - - // Add a small delay to avoid overwhelming the server - tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; - } - - // Convert to BrowserRelease objects - let releases: Vec = version_strings - .into_iter() - .map(|version| BrowserRelease { - version: version.clone(), - date: "".to_string(), // TOR archive doesn't provide structured dates - is_prerelease: false, // Assume all archived versions are stable - }) - .collect(); - - // Cache the results (unless bypassing cache) - if !no_caching { - if let Err(e) = self.save_cached_versions("tor-browser", &releases) { - log::error!("Failed to cache TOR versions: {e}"); - } - } - - Ok(releases) - } - - async fn check_tor_version_has_macos( - &self, - version: &str, - ) -> Result> { - let url = format!("{}/{version}/", self.tor_archive_base); - let html = self - .client - .get(&url) - .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36") - .send() - .await? - .text() - .await?; - - // Check if there's a macOS DMG file in this version directory - Ok(html.contains("tor-browser-macos-") && html.contains(".dmg")) - } - /// Check if a Zen twilight release has been updated by comparing file size pub async fn check_twilight_update( &self, @@ -1302,7 +1158,6 @@ mod tests { base_url.clone(), // firefox_dev_api_base base_url.clone(), // github_api_base base_url.clone(), // chromium_api_base - base_url.clone(), // tor_archive_base ) } @@ -1526,47 +1381,6 @@ mod tests { assert_eq!(releases[0].version, "140.0b1"); } - #[tokio::test] - async fn test_mullvad_api() { - let server = setup_mock_server().await; - let client = create_test_client(&server); - - let mock_response = r#"[ - { - "tag_name": "14.5a6", - "name": "Mullvad Browser 14.5a6", - "prerelease": true, - "published_at": "2024-01-15T10:00:00Z", - "assets": [ - { - "name": "mullvad-browser-macos-14.5a6.dmg", - "browser_download_url": "https://example.com/mullvad-14.5a6.dmg", - "size": 100000000 - } - ] - } - ]"#; - - Mock::given(method("GET")) - .and(path("/repos/mullvad/mullvad-browser/releases")) - .and(query_param("per_page", "100")) - .respond_with( - ResponseTemplate::new(200) - .set_body_string(mock_response) - .insert_header("content-type", "application/json"), - ) - .mount(&server) - .await; - - let result = client.fetch_mullvad_releases_with_caching(true).await; - - assert!(result.is_ok()); - let releases = result.unwrap(); - assert!(!releases.is_empty()); - assert_eq!(releases[0].tag_name, "14.5a6"); - assert!(releases[0].is_nightly); - } - #[tokio::test] async fn test_zen_api() { let server = setup_mock_server().await; @@ -1720,125 +1534,6 @@ mod tests { assert!(!releases[0].is_prerelease); } - #[tokio::test] - async fn test_tor_api() { - let server = setup_mock_server().await; - let client = create_test_client(&server); - - let mock_html = r#" - - - ../ - 14.0.4/ - 14.0.3/ - - - "#; - - let version_html = r#" - - - tor-browser-macos-14.0.4.dmg - - - "#; - - Mock::given(method("GET")) - .and(path("/")) - .respond_with( - ResponseTemplate::new(200) - .set_body_string(mock_html) - .insert_header("content-type", "text/html"), - ) - .mount(&server) - .await; - - Mock::given(method("GET")) - .and(path("/14.0.4/")) - .respond_with( - ResponseTemplate::new(200) - .set_body_string(version_html) - .insert_header("content-type", "text/html"), - ) - .mount(&server) - .await; - - Mock::given(method("GET")) - .and(path("/14.0.3/")) - .respond_with( - ResponseTemplate::new(200) - .set_body_string(version_html.replace("14.0.4", "14.0.3")) - .insert_header("content-type", "text/html"), - ) - .mount(&server) - .await; - - let result = client.fetch_tor_releases_with_caching(true).await; - - assert!(result.is_ok()); - let releases = result.unwrap(); - assert!(!releases.is_empty()); - assert_eq!(releases[0].version, "14.0.4"); - } - - #[tokio::test] - async fn test_tor_version_check() { - let server = setup_mock_server().await; - let client = create_test_client(&server); - - let version_html = r#" - - - tor-browser-macos-14.0.4.dmg - - - "#; - - Mock::given(method("GET")) - .and(path("/14.0.4/")) - .respond_with( - ResponseTemplate::new(200) - .set_body_string(version_html) - .insert_header("content-type", "text/html"), - ) - .mount(&server) - .await; - - let result = client.check_tor_version_has_macos("14.0.4").await; - - assert!(result.is_ok()); - assert!(result.unwrap()); - } - - #[tokio::test] - async fn test_tor_version_check_no_macos() { - let server = setup_mock_server().await; - let client = create_test_client(&server); - - let version_html = r#" - - - tor-browser-linux-14.0.4.tar.xz - - - "#; - - Mock::given(method("GET")) - .and(path("/14.0.5/")) - .respond_with( - ResponseTemplate::new(200) - .set_body_string(version_html) - .insert_header("content-type", "text/html"), - ) - .mount(&server) - .await; - - let result = client.check_tor_version_has_macos("14.0.5").await; - - assert!(result.is_ok()); - assert!(!result.unwrap()); - } - #[test] fn test_is_nightly_version() { assert!(is_nightly_version("1.2.3a1")); @@ -1910,84 +1605,6 @@ mod tests { assert!(result.is_err()); } - #[tokio::test] - async fn test_mullvad_pagination_two_pages() { - let server = setup_mock_server().await; - let client = create_test_client(&server); - - // Page 1 response with Link: rel="next" header - let mock_page1 = r#"[ - { - "tag_name": "100.0", - "name": "Mullvad Browser 100.0", - "prerelease": false, - "published_at": "2024-07-01T00:00:00Z", - "assets": [ - { "name": "mullvad-browser-macos-100.0.dmg", "browser_download_url": "https://example.com/100.0.dmg", "size": 1 } - ] - } - ]"#; - - // Page 2 response - let mock_page2 = r#"[ - { - "tag_name": "99.0", - "name": "Mullvad Browser 99.0", - "prerelease": false, - "published_at": "2024-06-01T00:00:00Z", - "assets": [ - { "name": "mullvad-browser-macos-99.0.dmg", "browser_download_url": "https://example.com/99.0.dmg", "size": 1 } - ] - } - ]"#; - - // Mock page 1 - Mock::given(method("GET")) - .and(path("/repos/mullvad/mullvad-browser/releases")) - .and(query_param("per_page", "100")) - .and(query_param("page", "1")) - .respond_with( - ResponseTemplate::new(200) - .set_body_string(mock_page1) - .insert_header("content-type", "application/json") - .insert_header( - "link", - format!( - "<{}?per_page=100&page=2>; rel=\"next\", <{}?per_page=100&page=2>; rel=\"last\"", - server.uri().to_string() + "/repos/mullvad/mullvad-browser/releases", - server.uri().to_string() + "/repos/mullvad/mullvad-browser/releases" - ), - ), - ) - .mount(&server) - .await; - - // Mock page 2 - Mock::given(method("GET")) - .and(path("/repos/mullvad/mullvad-browser/releases")) - .and(query_param("per_page", "100")) - .and(query_param("page", "2")) - .respond_with( - ResponseTemplate::new(200) - .set_body_string(mock_page2) - .insert_header("content-type", "application/json"), - ) - .mount(&server) - .await; - - let result = client.fetch_mullvad_releases_with_caching(true).await; - - assert!(result.is_ok()); - let releases = result.unwrap(); - // We currently only fetch 1 page intentionally; ensure we at least got page 1 - assert_eq!( - releases.len(), - 1, - "Should fetch only the first page of results" - ); - assert_eq!(releases[0].tag_name, "100.0"); - } - #[test] fn test_camoufox_beta_version_parsing() { // Test specific Camoufox beta versions that are causing issues diff --git a/src-tauri/src/browser.rs b/src-tauri/src/browser.rs index df7e669..506154e 100644 --- a/src-tauri/src/browser.rs +++ b/src-tauri/src/browser.rs @@ -13,39 +13,33 @@ pub struct ProxySettings { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum BrowserType { - MullvadBrowser, Chromium, Firefox, FirefoxDeveloper, Brave, Zen, - TorBrowser, Camoufox, } impl BrowserType { pub fn as_str(&self) -> &'static str { match self { - BrowserType::MullvadBrowser => "mullvad-browser", BrowserType::Chromium => "chromium", BrowserType::Firefox => "firefox", BrowserType::FirefoxDeveloper => "firefox-developer", BrowserType::Brave => "brave", BrowserType::Zen => "zen", - BrowserType::TorBrowser => "tor-browser", BrowserType::Camoufox => "camoufox", } } pub fn from_str(s: &str) -> Result { match s { - "mullvad-browser" => Ok(BrowserType::MullvadBrowser), "chromium" => Ok(BrowserType::Chromium), "firefox" => Ok(BrowserType::Firefox), "firefox-developer" => Ok(BrowserType::FirefoxDeveloper), "brave" => Ok(BrowserType::Brave), "zen" => Ok(BrowserType::Zen), - "tor-browser" => Ok(BrowserType::TorBrowser), "camoufox" => Ok(BrowserType::Camoufox), _ => Err(format!("Unknown browser type: {s}")), } @@ -92,9 +86,7 @@ mod macos { let binding = entry.file_name(); let name = binding.to_string_lossy(); name.starts_with("firefox") - || name.starts_with("mullvad") || name.starts_with("zen") - || name.starts_with("tor") || name.starts_with("camoufox") || name.contains("Browser") }) @@ -190,28 +182,9 @@ mod linux { browser_subdir.join("firefox"), browser_subdir.join("firefox-bin"), ], - BrowserType::MullvadBrowser => { - vec![ - browser_subdir.join("firefox"), - browser_subdir.join("mullvad-browser"), - browser_subdir.join("firefox-bin"), - ] - } BrowserType::Zen => { vec![browser_subdir.join("zen"), browser_subdir.join("zen-bin")] } - BrowserType::TorBrowser => { - vec![ - // Common Tor Browser launchers - browser_subdir.join("tor-browser"), - // Firefox-based binaries - browser_subdir.join("firefox"), - browser_subdir.join("firefox-bin"), - // Sometimes packaged similarly to Firefox - install_dir.join("firefox").join("firefox"), - install_dir.join("firefox").join("firefox-bin"), - ] - } BrowserType::Camoufox => { vec![ install_dir.join("camoufox-bin"), @@ -303,23 +276,9 @@ mod linux { install_dir.join("firefox").join("firefox"), ] } - BrowserType::MullvadBrowser => { - vec![ - browser_subdir.join("mullvad-browser"), - browser_subdir.join("firefox-bin"), - browser_subdir.join("firefox"), - ] - } BrowserType::Zen => { vec![browser_subdir.join("zen"), browser_subdir.join("zen-bin")] } - BrowserType::TorBrowser => { - vec![ - browser_subdir.join("tor-browser"), - browser_subdir.join("firefox-bin"), - browser_subdir.join("firefox"), - ] - } BrowserType::Camoufox => { vec![ install_dir.join("camoufox-bin"), @@ -424,9 +383,7 @@ mod windows { if path.extension().is_some_and(|ext| ext == "exe") { let name = path.file_stem().unwrap_or_default().to_string_lossy(); if name.starts_with("firefox") - || name.starts_with("mullvad") || name.starts_with("zen") - || name.starts_with("tor") || name.starts_with("camoufox") || name.contains("browser") { @@ -510,9 +467,7 @@ mod windows { if path.extension().is_some_and(|ext| ext == "exe") { let name = path.file_stem().unwrap_or_default().to_string_lossy(); if name.starts_with("firefox") - || name.starts_with("mullvad") || name.starts_with("zen") - || name.starts_with("tor") || name.starts_with("camoufox") || name.contains("browser") { @@ -903,11 +858,9 @@ impl BrowserFactory { pub fn create_browser(&self, browser_type: BrowserType) -> Box { match browser_type { - BrowserType::MullvadBrowser - | BrowserType::Firefox - | BrowserType::FirefoxDeveloper - | BrowserType::Zen - | BrowserType::TorBrowser => Box::new(FirefoxBrowser::new(browser_type)), + BrowserType::Firefox | BrowserType::FirefoxDeveloper | BrowserType::Zen => { + Box::new(FirefoxBrowser::new(browser_type)) + } BrowserType::Chromium | BrowserType::Brave => Box::new(ChromiumBrowser::new(browser_type)), BrowserType::Camoufox => Box::new(CamoufoxBrowser::new()), } @@ -985,20 +938,14 @@ mod tests { #[test] fn test_browser_type_conversions() { // Test as_str - assert_eq!(BrowserType::MullvadBrowser.as_str(), "mullvad-browser"); assert_eq!(BrowserType::Firefox.as_str(), "firefox"); assert_eq!(BrowserType::FirefoxDeveloper.as_str(), "firefox-developer"); assert_eq!(BrowserType::Chromium.as_str(), "chromium"); assert_eq!(BrowserType::Brave.as_str(), "brave"); assert_eq!(BrowserType::Zen.as_str(), "zen"); - assert_eq!(BrowserType::TorBrowser.as_str(), "tor-browser"); assert_eq!(BrowserType::Camoufox.as_str(), "camoufox"); // Test from_str - use expect with descriptive messages instead of unwrap - assert_eq!( - BrowserType::from_str("mullvad-browser").expect("mullvad-browser should be valid"), - BrowserType::MullvadBrowser - ); assert_eq!( BrowserType::from_str("firefox").expect("firefox should be valid"), BrowserType::Firefox @@ -1019,10 +966,6 @@ mod tests { BrowserType::from_str("zen").expect("zen should be valid"), BrowserType::Zen ); - assert_eq!( - BrowserType::from_str("tor-browser").expect("tor-browser should be valid"), - BrowserType::TorBrowser - ); assert_eq!( BrowserType::from_str("camoufox").expect("camoufox should be valid"), BrowserType::Camoufox @@ -1089,20 +1032,6 @@ mod tests { "Firefox should include debugging port" ); - // Test Mullvad Browser (no special flags without remote debugging) - let browser = FirefoxBrowser::new(BrowserType::MullvadBrowser); - let args = browser - .create_launch_args("/path/to/profile", None, None, None, false) - .expect("Failed to create launch args for Mullvad Browser"); - assert_eq!(args, vec!["-profile", "/path/to/profile"]); - - // Test Tor Browser (no special flags without remote debugging) - let browser = FirefoxBrowser::new(BrowserType::TorBrowser); - let args = browser - .create_launch_args("/path/to/profile", None, None, None, false) - .expect("Failed to create launch args for Tor Browser"); - assert_eq!(args, vec!["-profile", "/path/to/profile"]); - // Test Zen Browser (no special flags without remote debugging) let browser = FirefoxBrowser::new(BrowserType::Zen); let args = browser diff --git a/src-tauri/src/browser_runner.rs b/src-tauri/src/browser_runner.rs index 2c7123a..daeeefb 100644 --- a/src-tauri/src/browser_runner.rs +++ b/src-tauri/src/browser_runner.rs @@ -33,29 +33,6 @@ impl BrowserRunner { &BROWSER_RUNNER } - // Helper function to check if a process matches TOR/Mullvad browser - fn is_tor_or_mullvad_browser( - &self, - exe_name: &str, - cmd: &[std::ffi::OsString], - browser_type: &str, - ) -> bool { - #[cfg(target_os = "macos")] - return platform_browser::macos::is_tor_or_mullvad_browser(exe_name, cmd, browser_type); - - #[cfg(target_os = "windows")] - return platform_browser::windows::is_tor_or_mullvad_browser(exe_name, cmd, browser_type); - - #[cfg(target_os = "linux")] - return platform_browser::linux::is_tor_or_mullvad_browser(exe_name, cmd, browser_type); - - #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] - { - let _ = (exe_name, cmd, browser_type); - false - } - } - pub fn get_binaries_dir(&self) -> PathBuf { let mut path = self.base_dirs.data_local_dir().to_path_buf(); path.push(if cfg!(debug_assertions) { @@ -395,42 +372,8 @@ impl BrowserRunner { profile.id ); - // For TOR and Mullvad browsers, we need to find the actual browser process - // because they use launcher scripts that spawn the real browser process let mut actual_pid = launcher_pid; - if matches!( - browser_type, - BrowserType::TorBrowser | BrowserType::MullvadBrowser - ) { - // Wait a moment for the actual browser process to start - tokio::time::sleep(tokio::time::Duration::from_millis(3000)).await; - - // Find the actual browser process - let system = System::new_all(); - for (pid, process) in system.processes() { - let process_name = process.name().to_str().unwrap_or(""); - let process_cmd = process.cmd(); - let pid_u32 = pid.as_u32(); - - // Skip if this is the launcher process itself - if pid_u32 == launcher_pid { - continue; - } - - if self.is_tor_or_mullvad_browser(process_name, process_cmd, &profile.browser) { - log::info!( - "Found actual {} browser process: PID {} ({})", - profile.browser, - pid_u32, - process_name - ); - actual_pid = pid_u32; - break; - } - } - } - // 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")] @@ -455,8 +398,6 @@ impl BrowserRunner { "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" => { @@ -472,10 +413,6 @@ impl BrowserRunner { })) || exe_name_lower == "firefox" // Firefox Developer might just show as "firefox" } - "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") || exe_name_lower.contains("chrome"), "brave" => exe_name_lower.contains("brave") || exe_name_lower.contains("Brave"), @@ -489,7 +426,7 @@ impl BrowserRunner { // Check for profile path match let profile_path_match = if matches!( profile.browser.as_str(), - "firefox" | "firefox-developer" | "tor-browser" | "mullvad-browser" | "zen" + "firefox" | "firefox-developer" | "zen" ) { // Firefox-based browsers: look for -profile argument followed by path let mut found_profile_arg = false; @@ -552,11 +489,7 @@ impl BrowserRunner { if profile.proxy_id.is_some() && matches!( browser_type, - BrowserType::Firefox - | BrowserType::FirefoxDeveloper - | BrowserType::Zen - | BrowserType::TorBrowser - | BrowserType::MullvadBrowser + BrowserType::Firefox | BrowserType::FirefoxDeveloper | BrowserType::Zen ) { // Proxy settings for Firefox-based browsers are applied via user.js file @@ -714,48 +647,9 @@ impl BrowserRunner { #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] return Err("Unsupported platform".into()); } - BrowserType::MullvadBrowser | BrowserType::TorBrowser => { - #[cfg(target_os = "macos")] - { - let profiles_dir = self.profile_manager.get_profiles_dir(); - return platform_browser::macos::open_url_in_existing_browser_tor_mullvad( - &updated_profile, - url, - browser_type, - &browser_dir, - &profiles_dir, - ) - .await; - } - - #[cfg(target_os = "windows")] - { - let profiles_dir = self.profile_manager.get_profiles_dir(); - return platform_browser::windows::open_url_in_existing_browser_tor_mullvad( - &updated_profile, - url, - browser_type, - &browser_dir, - &profiles_dir, - ) - .await; - } - - #[cfg(target_os = "linux")] - { - let profiles_dir = self.profile_manager.get_profiles_dir(); - return platform_browser::linux::open_url_in_existing_browser_tor_mullvad( - &updated_profile, - url, - browser_type, - &browser_dir, - &profiles_dir, - ) - .await; - } - - #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] - return Err("Unsupported platform".into()); + BrowserType::Camoufox => { + // Camoufox uses nodecar for launching, URL opening is handled differently + return Err("URL opening in existing Camoufox instance is not supported".into()); } BrowserType::Chromium | BrowserType::Brave => { #[cfg(target_os = "macos")] @@ -800,10 +694,6 @@ impl BrowserRunner { #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] return Err("Unsupported platform".into()); } - BrowserType::Camoufox => { - // This should never be reached due to the early return above, but handle it just in case - Err("Camoufox URL opening should be handled in the early return above".into()) - } } } @@ -848,7 +738,7 @@ impl BrowserRunner { // For Firefox-based browsers, apply PAC/user.js to point to the local proxy if matches!( profile.browser.as_str(), - "firefox" | "firefox-developer" | "zen" | "tor-browser" | "mullvad-browser" + "firefox" | "firefox-developer" | "zen" ) { let profiles_dir = self.profile_manager.get_profiles_dir(); let profile_path = profiles_dir.join(profile.id.to_string()).join("profile"); @@ -949,19 +839,6 @@ impl BrowserRunner { if let Some(url_ref) = url.as_ref() { log::info!("Opening URL in existing browser: {url_ref}"); - // For TOR/Mullvad browsers, add extra verification - if matches!( - final_profile.browser.as_str(), - "tor-browser" | "mullvad-browser" - ) { - log::info!("TOR/Mullvad browser detected - ensuring we have correct PID"); - if final_profile.process_id.is_none() { - log::info!( - "ERROR: No PID found for running TOR/Mullvad browser - this should not happen" - ); - return Err("No PID found for running browser".into()); - } - } match self .open_url_in_existing_browser( app_handle.clone(), @@ -978,16 +855,24 @@ impl BrowserRunner { Err(e) => { log::info!("Failed to open URL in existing browser: {e}"); - // For Mullvad and Tor browsers, don't fall back to new instance since they use -no-remote - // and can't have multiple instances with the same profile + // Fall back to launching a new instance match final_profile.browser.as_str() { - "mullvad-browser" | "tor-browser" => { - Err(format!("Failed to open URL in existing {} browser. Cannot launch new instance due to profile conflict: {}", final_profile.browser, e).into()) - } _ => { - log::info!("Falling back to new instance for browser: {}", final_profile.browser); + log::info!( + "Falling back to new instance for browser: {}", + final_profile.browser + ); // Fallback to launching a new instance for other browsers - self.launch_browser_internal(app_handle.clone(), &final_profile, url, internal_proxy_settings, None, false).await + self + .launch_browser_internal( + app_handle.clone(), + &final_profile, + url, + internal_proxy_settings, + None, + false, + ) + .await } } } @@ -1316,8 +1201,6 @@ impl BrowserRunner { "firefox" => { exe_name.contains("firefox") && !exe_name.contains("developer") - && !exe_name.contains("tor") - && !exe_name.contains("mullvad") && !exe_name.contains("camoufox") } "firefox-developer" => { @@ -1333,8 +1216,6 @@ impl BrowserRunner { })) || exe_name == "firefox" // Firefox Developer might just show as "firefox" } - "mullvad-browser" => self.is_tor_or_mullvad_browser(&exe_name, cmd, "mullvad-browser"), - "tor-browser" => self.is_tor_or_mullvad_browser(&exe_name, cmd, "tor-browser"), "zen" => exe_name.contains("zen"), "chromium" => exe_name.contains("chromium") || exe_name.contains("chrome"), "brave" => exe_name.contains("brave") || exe_name.contains("Brave"), @@ -1349,7 +1230,7 @@ impl BrowserRunner { let profile_path_match = if matches!( profile.browser.as_str(), - "firefox" | "firefox-developer" | "tor-browser" | "mullvad-browser" | "zen" + "firefox" | "firefox-developer" | "zen" ) { // Firefox-based browsers: look for -profile argument followed by path let mut found_profile_arg = false; @@ -1598,8 +1479,6 @@ impl BrowserRunner { "firefox" => { exe_name.contains("firefox") && !exe_name.contains("developer") - && !exe_name.contains("tor") - && !exe_name.contains("mullvad") && !exe_name.contains("camoufox") } "firefox-developer" => { @@ -1615,8 +1494,6 @@ impl BrowserRunner { })) || exe_name == "firefox" // Firefox Developer might just show as "firefox" } - "mullvad-browser" => self.is_tor_or_mullvad_browser(&exe_name, cmd, "mullvad-browser"), - "tor-browser" => self.is_tor_or_mullvad_browser(&exe_name, cmd, "tor-browser"), "zen" => exe_name.contains("zen"), "chromium" => exe_name.contains("chromium") || exe_name.contains("chrome"), "brave" => exe_name.contains("brave") || exe_name.contains("Brave"), @@ -1630,7 +1507,7 @@ impl BrowserRunner { // Check for profile path match with improved logic let profile_path_match = if matches!( profile.browser.as_str(), - "firefox" | "firefox-developer" | "tor-browser" | "mullvad-browser" | "zen" + "firefox" | "firefox-developer" | "zen" ) { // Firefox-based browsers: look for -profile argument followed by path let mut found_profile_arg = false; @@ -1792,7 +1669,7 @@ pub async fn launch_browser_profile( // For Firefox-based browsers, always apply PAC/user.js to point to the local proxy if matches!( profile_for_launch.browser.as_str(), - "firefox" | "firefox-developer" | "zen" | "tor-browser" | "mullvad-browser" + "firefox" | "firefox-developer" | "zen" ) { let profiles_dir = browser_runner.profile_manager.get_profiles_dir(); let profile_path = profiles_dir diff --git a/src-tauri/src/browser_version_manager.rs b/src-tauri/src/browser_version_manager.rs index cd17ebf..85a0b31 100644 --- a/src-tauri/src/browser_version_manager.rs +++ b/src-tauri/src/browser_version_manager.rs @@ -54,14 +54,6 @@ impl BrowserVersionManager { match browser { "firefox" | "firefox-developer" => Ok(true), - "mullvad-browser" => { - // Mullvad doesn't support ARM64 on Windows and Linux - if arch == "arm64" && (os == "windows" || os == "linux") { - Ok(false) - } else { - Ok(true) - } - } "zen" => { // Zen supports all platforms and architectures Ok(true) @@ -78,14 +70,6 @@ impl BrowserVersionManager { Ok(true) } } - "tor-browser" => { - // TOR Browser doesn't support ARM64 on Windows and Linux - if arch == "arm64" && (os == "windows" || os == "linux") { - Ok(false) - } else { - Ok(true) - } - } "camoufox" => { // Camoufox supports all platforms and architectures according to the JS code Ok(true) @@ -99,11 +83,9 @@ impl BrowserVersionManager { let all_browsers = vec![ "firefox", "firefox-developer", - "mullvad-browser", "zen", "brave", "chromium", - "tor-browser", "camoufox", ]; @@ -238,11 +220,9 @@ impl BrowserVersionManager { let fresh_versions = match browser { "firefox" => self.fetch_firefox_versions(true).await?, // Always fetch fresh for merging "firefox-developer" => self.fetch_firefox_developer_versions(true).await?, - "mullvad-browser" => self.fetch_mullvad_versions(true).await?, "zen" => self.fetch_zen_versions(true).await?, "brave" => self.fetch_brave_versions(true).await?, "chromium" => self.fetch_chromium_versions(true).await?, - "tor-browser" => self.fetch_tor_versions(true).await?, "camoufox" => self.fetch_camoufox_versions(true).await?, _ => return Err(format!("Unsupported browser: {browser}").into()), }; @@ -356,27 +336,6 @@ impl BrowserVersionManager { }) .collect() } - "mullvad-browser" => { - let releases = self.fetch_mullvad_releases_detailed(true).await?; - merged_versions - .into_iter() - .map(|version| { - if let Some(release) = releases.iter().find(|r| r.tag_name == version) { - BrowserVersionInfo { - version: release.tag_name.clone(), - is_prerelease: release.is_nightly, - date: release.published_at.clone(), - } - } else { - BrowserVersionInfo { - version: version.clone(), - is_prerelease: false, // Mullvad usually stable releases - date: "".to_string(), - } - } - }) - .collect() - } "zen" => { let releases = self.fetch_zen_releases_detailed(true).await?; merged_versions @@ -444,31 +403,6 @@ impl BrowserVersionManager { }) .collect() } - "tor-browser" => { - let releases = self.fetch_tor_releases_detailed(true).await?; - merged_versions - .into_iter() - .map(|version| { - if let Some(release) = releases.iter().find(|r| r.version == version) { - BrowserVersionInfo { - version: release.version.clone(), - is_prerelease: crate::api_client::is_browser_version_nightly( - "tor-browser", - &release.version, - None, - ), - date: release.date.clone(), - } - } else { - BrowserVersionInfo { - version: version.clone(), - is_prerelease: false, // TOR Browser usually stable releases - date: "".to_string(), - } - } - }) - .collect() - } "camoufox" => { let releases = self.fetch_camoufox_releases_detailed(true).await?; merged_versions @@ -602,50 +536,6 @@ impl BrowserVersionManager { is_archive, }) } - "mullvad-browser" => { - // Mullvad Browser doesn't support ARM64 on Windows and Linux - if arch == "arm64" && (os == "windows" || os == "linux") { - return Err(format!("Mullvad Browser doesn't support ARM64 on {os}").into()); - } - - let (platform_str, filename, is_archive) = match os.as_str() { - "windows" => { - if arch == "arm64" { - return Err("Mullvad Browser doesn't support ARM64 on Windows".into()); - } - ( - "windows-x86_64", - format!("mullvad-browser-windows-x86_64-{version}.exe"), - false, - ) - } - "linux" => { - if arch == "arm64" { - return Err("Mullvad Browser doesn't support ARM64 on Linux".into()); - } - ( - "x86_64", - format!("mullvad-browser-x86_64-{version}.tar.xz"), - true, - ) - } - "macos" => ( - "macos", - format!("mullvad-browser-macos-{version}.dmg"), - true, - ), - _ => return Err(format!("Unsupported platform for Mullvad Browser: {os}").into()), - }; - - Ok(DownloadInfo { - url: format!( - "https://github.com/mullvad/mullvad-browser/releases/download/{version}/mullvad-browser-{platform_str}-{version}{}", - if os == "windows" { ".exe" } else if os == "linux" { ".tar.xz" } else { ".dmg" } - ), - filename, - is_archive, - }) - } "zen" => { let (asset_name, filename, is_archive) = match (&os[..], &arch[..]) { ("windows", "x64") => ("zen.installer.exe", format!("zen-{version}.exe"), false), @@ -731,46 +621,6 @@ impl BrowserVersionManager { is_archive: true, }) } - "tor-browser" => { - // TOR Browser doesn't support ARM64 on Windows and Linux - if arch == "arm64" && (os == "windows" || os == "linux") { - return Err(format!("TOR Browser doesn't support ARM64 on {os}").into()); - } - - let (platform_str, filename, is_archive) = match os.as_str() { - "windows" => { - if arch == "arm64" { - return Err("TOR Browser doesn't support ARM64 on Windows".into()); - } - ( - "windows-x86_64-portable", - format!("tor-browser-windows-x86_64-portable-{version}.exe"), - false, - ) - } - "linux" => { - if arch == "arm64" { - return Err("TOR Browser doesn't support ARM64 on Linux".into()); - } - ( - "linux-x86_64", - format!("tor-browser-linux-x86_64-{version}.tar.xz"), - true, - ) - } - "macos" => ("macos", format!("tor-browser-macos-{version}.dmg"), true), - _ => return Err(format!("Unsupported platform for TOR Browser: {os}").into()), - }; - - Ok(DownloadInfo { - url: format!( - "https://archive.torproject.org/tor-package-archive/torbrowser/{version}/tor-browser-{platform_str}-{version}{}", - if os == "windows" { ".exe" } else if os == "linux" { ".tar.xz" } else { ".dmg" } - ), - filename, - is_archive, - }) - } "camoufox" => { // Camoufox downloads from GitHub releases with pattern: camoufox-{version}-{release}-{os}.{arch}.zip let (os_name, arch_name) = match (&os[..], &arch[..]) { @@ -864,24 +714,6 @@ impl BrowserVersionManager { .await } - async fn fetch_mullvad_versions( - &self, - no_caching: bool, - ) -> Result, Box> { - let releases = self.fetch_mullvad_releases_detailed(no_caching).await?; - Ok(releases.into_iter().map(|r| r.tag_name).collect()) - } - - async fn fetch_mullvad_releases_detailed( - &self, - no_caching: bool, - ) -> Result, Box> { - self - .api_client - .fetch_mullvad_releases_with_caching(no_caching) - .await - } - async fn fetch_zen_versions( &self, no_caching: bool, @@ -971,24 +803,6 @@ impl BrowserVersionManager { .await } - async fn fetch_tor_versions( - &self, - no_caching: bool, - ) -> Result, Box> { - let releases = self.fetch_tor_releases_detailed(no_caching).await?; - Ok(releases.into_iter().map(|r| r.version).collect()) - } - - async fn fetch_tor_releases_detailed( - &self, - no_caching: bool, - ) -> Result, Box> { - self - .api_client - .fetch_tor_releases_with_caching(no_caching) - .await - } - async fn fetch_camoufox_versions( &self, no_caching: bool, @@ -1130,40 +944,6 @@ mod tests { .url .contains("/pub/devedition/releases/139.0b1/")); - // Test Mullvad Browser - let mullvad_info = service - .get_download_info("mullvad-browser", "14.5a6") - .unwrap(); - - #[cfg(target_os = "macos")] - { - assert_eq!(mullvad_info.filename, "mullvad-browser-macos-14.5a6.dmg"); - assert!(mullvad_info.url.contains("mullvad-browser-macos-14.5a6")); - assert!(mullvad_info.is_archive); - } - - #[cfg(target_os = "linux")] - { - assert_eq!( - mullvad_info.filename, - "mullvad-browser-x86_64-14.5a6.tar.xz" - ); - assert!(mullvad_info.url.contains("mullvad-browser-x86_64-14.5a6")); - assert!(mullvad_info.is_archive); - } - - #[cfg(target_os = "windows")] - { - assert_eq!( - mullvad_info.filename, - "mullvad-browser-windows-x86_64-14.5a6.exe" - ); - assert!(mullvad_info - .url - .contains("mullvad-browser-windows-x86_64-14.5a6")); - assert!(!mullvad_info.is_archive); - } - // Test Zen Browser let zen_info = service.get_download_info("zen", "1.11b").unwrap(); @@ -1188,35 +968,6 @@ mod tests { assert!(!zen_info.is_archive); } - // Test Tor Browser - let tor_info = service.get_download_info("tor-browser", "14.0.4").unwrap(); - - #[cfg(target_os = "macos")] - { - assert_eq!(tor_info.filename, "tor-browser-macos-14.0.4.dmg"); - assert!(tor_info.url.contains("tor-browser-macos-14.0.4")); - assert!(tor_info.is_archive); - } - - #[cfg(target_os = "linux")] - { - assert_eq!(tor_info.filename, "tor-browser-linux-x86_64-14.0.4.tar.xz"); - assert!(tor_info.url.contains("tor-browser-linux-x86_64-14.0.4")); - assert!(tor_info.is_archive); - } - - #[cfg(target_os = "windows")] - { - assert_eq!( - tor_info.filename, - "tor-browser-windows-x86_64-portable-14.0.4.exe" - ); - assert!(tor_info - .url - .contains("tor-browser-windows-x86_64-portable-14.0.4")); - assert!(!tor_info.is_archive); - } - // Test Chromium let chromium_info = service.get_download_info("chromium", "1465660").unwrap(); diff --git a/src-tauri/src/downloader.rs b/src-tauri/src/downloader.rs index 3efaf63..d139c43 100644 --- a/src-tauri/src/downloader.rs +++ b/src-tauri/src/downloader.rs @@ -145,30 +145,6 @@ impl Downloader { Ok(asset_url) } - BrowserType::MullvadBrowser => { - // For Mullvad, verify the asset exists - let releases = self - .api_client - .fetch_mullvad_releases_with_caching(true) - .await?; - - let release = releases - .iter() - .find(|r| r.tag_name == version) - .ok_or(format!("Mullvad version {version} not found"))?; - - // Get platform and architecture info - let (os, arch) = Self::get_platform_info(); - - // Find the appropriate asset - let asset_url = self - .find_mullvad_asset(&release.assets, &os, &arch) - .ok_or(format!( - "No compatible asset found for Mullvad version {version} on {os}/{arch}" - ))?; - - Ok(asset_url) - } BrowserType::Camoufox => { // For Camoufox, verify the asset exists and find the correct download URL let releases = self @@ -327,46 +303,6 @@ impl Downloader { asset.map(|a| a.browser_download_url.clone()) } - /// Find the appropriate Mullvad asset for the current platform and architecture - fn find_mullvad_asset( - &self, - assets: &[crate::browser::GithubAsset], - os: &str, - arch: &str, - ) -> Option { - // Mullvad asset naming patterns: - // Windows: mullvad-browser-windows-x86_64-VERSION.exe - // macOS: mullvad-browser-macos-VERSION.dmg - // Linux: mullvad-browser-x86_64-VERSION.tar.xz - - let asset = match (os, arch) { - ("windows", "x64") => assets.iter().find(|asset| { - asset.name.contains("windows") - && asset.name.contains("x86_64") - && asset.name.ends_with(".exe") - }), - ("windows", "arm64") => { - // Mullvad doesn't support ARM64 on Windows - None - } - ("macos", _) => assets - .iter() - .find(|asset| asset.name.contains("macos") && asset.name.ends_with(".dmg")), - ("linux", "x64") => assets.iter().find(|asset| { - asset.name.contains("x86_64") - && asset.name.ends_with(".tar.xz") - && !asset.name.contains("windows") - }), - ("linux", "arm64") => { - // Mullvad doesn't support ARM64 on Linux - None - } - _ => None, - }; - - asset.map(|a| a.browser_download_url.clone()) - } - /// Find the appropriate Camoufox asset for the current platform and architecture fn find_camoufox_asset( &self, @@ -937,7 +873,6 @@ mod tests { base_url.clone(), // firefox_dev_api_base base_url.clone(), // github_api_base base_url.clone(), // chromium_api_base - base_url.clone(), // tor_archive_base ) } @@ -984,27 +919,6 @@ mod tests { assert_eq!(url, download_info.url); } - #[tokio::test] - async fn test_resolve_tor_download_url() { - let server = setup_mock_server().await; - let api_client = create_test_api_client(&server); - let downloader = Downloader::new_with_api_client(api_client); - - let download_info = DownloadInfo { - url: "https://archive.torproject.org/tor-package-archive/torbrowser/14.0.4/tor-browser-macos-14.0.4.dmg".to_string(), - filename: "tor-test.dmg".to_string(), - is_archive: true, - }; - - let result = downloader - .resolve_download_url(BrowserType::TorBrowser, "14.0.4", &download_info) - .await; - - assert!(result.is_ok()); - let url = result.unwrap(); - assert_eq!(url, download_info.url); - } - #[tokio::test] async fn test_download_browser_with_progress() { let server = setup_mock_server().await; diff --git a/src-tauri/src/extraction.rs b/src-tauri/src/extraction.rs index b9ed33c..3a6c61c 100644 --- a/src-tauri/src/extraction.rs +++ b/src-tauri/src/extraction.rs @@ -868,9 +868,6 @@ impl Extractor { "chromium.exe", "zen.exe", "brave.exe", - "tor-browser.exe", - "tor.exe", - "mullvad-browser.exe", ]; // First try priority executable names @@ -937,8 +934,6 @@ impl Extractor { || file_name.contains("chromium") || file_name.contains("zen") || file_name.contains("brave") - || file_name.contains("tor") - || file_name.contains("mullvad") || file_name.contains("browser") { return Ok(path); @@ -1012,15 +1007,6 @@ impl Extractor { "brave-browser-beta", "brave-browser-dev", "brave-bin", - // Tor Browser variants - "tor-browser", - "torbrowser-launcher", - "tor-browser_en-US", - "start-tor-browser", - "Browser/start-tor-browser", - // Mullvad Browser - "mullvad-browser", - "mullvad-browser-bin", // Camoufox variants "camoufox", "camoufox-bin", @@ -1049,19 +1035,14 @@ impl Extractor { "chromium", "brave", "zen", - "tor-browser", - "mullvad-browser", "camoufox", ".", "./", "firefox", - "mullvad-browser", - "tor-browser_en-US", "Browser", "browser", "opt/google/chrome", "opt/brave.com/brave", - "opt/mullvad-browser", "opt/camoufox", "usr/lib/firefox", "usr/lib/chromium", @@ -1159,8 +1140,7 @@ impl Extractor { || name_lower.contains("chrome") || name_lower.contains("brave") || name_lower.contains("zen") - || name_lower.contains("tor") - || name_lower.contains("mullvad") + || name_lower.contains("camoufox") || name_lower.ends_with(".appimage") || !name_lower.contains('.') { @@ -1215,8 +1195,6 @@ impl Extractor { || name_lower.contains("chrome") || name_lower.contains("brave") || name_lower.contains("zen") - || name_lower.contains("tor") - || name_lower.contains("mullvad") || name_lower.contains("camoufox") || file_name.ends_with(".AppImage") { diff --git a/src-tauri/src/platform_browser.rs b/src-tauri/src/platform_browser.rs index 137dcfa..fcda02e 100644 --- a/src-tauri/src/platform_browser.rs +++ b/src-tauri/src/platform_browser.rs @@ -1,6 +1,5 @@ use crate::browser::{create_browser, BrowserType}; use crate::profile::BrowserProfile; -use std::ffi::OsString; use std::path::Path; use std::process::Command; @@ -10,40 +9,6 @@ pub mod macos { use super::*; use sysinfo::{Pid, System}; - pub fn is_tor_or_mullvad_browser(exe_name: &str, cmd: &[OsString], browser_type: &str) -> bool { - match browser_type { - "mullvad-browser" => { - let has_mullvad_in_exe = exe_name.contains("mullvad"); - let has_firefox_exe = exe_name == "firefox" || exe_name.contains("firefox-bin"); - let has_mullvad_in_cmd = cmd.iter().any(|arg| { - let arg_str = arg.to_str().unwrap_or(""); - arg_str.contains("Mullvad Browser.app") - || arg_str.contains("mullvad") - || arg_str.contains("Mullvad") - || arg_str.contains("/Applications/Mullvad Browser.app/") - || arg_str.contains("MullvadBrowser") - }); - - has_mullvad_in_exe || (has_firefox_exe && has_mullvad_in_cmd) - } - "tor-browser" => { - let has_tor_in_exe = exe_name.contains("tor"); - let has_firefox_exe = exe_name == "firefox" || exe_name.contains("firefox-bin"); - let has_tor_in_cmd = cmd.iter().any(|arg| { - let arg_str = arg.to_str().unwrap_or(""); - arg_str.contains("Tor Browser.app") - || arg_str.contains("tor-browser") - || arg_str.contains("TorBrowser") - || arg_str.contains("/Applications/Tor Browser.app/") - || arg_str.contains("TorBrowser-Data") - }); - - has_tor_in_exe || (has_firefox_exe && has_tor_in_cmd) - } - _ => false, - } - } - pub async fn launch_browser_process( executable_path: &std::path::Path, args: &[String], @@ -375,122 +340,6 @@ end try descendants } - pub async fn open_url_in_existing_browser_tor_mullvad( - profile: &BrowserProfile, - url: &str, - browser_type: BrowserType, - browser_dir: &Path, - _profiles_dir: &Path, - ) -> Result<(), Box> { - let pid = profile.process_id.unwrap(); - - log::info!("Opening URL in TOR/Mullvad browser using file-based approach (PID: {pid})"); - - // Method 1: Try using a temporary HTML file approach - log::info!("Attempting file-based URL opening for TOR/Mullvad browser"); - - let temp_dir = std::env::temp_dir(); - let temp_file_name = format!("donut_browser_url_{}.html", std::process::id()); - let temp_file_path = temp_dir.join(&temp_file_name); - - let html_content = format!( - r#" - - - - - Redirecting... - - - -

Redirecting to {url}...

- -"# - ); - - match std::fs::write(&temp_file_path, html_content) { - Ok(()) => { - log::info!("Created temporary HTML file: {temp_file_path:?}"); - - let browser = create_browser(browser_type.clone()); - if let Ok(executable_path) = browser.get_executable_path(browser_dir) { - let open_result = Command::new("open") - .args([ - "-a", - executable_path.to_str().unwrap(), - temp_file_path.to_str().unwrap(), - ]) - .output(); - - // Clean up the temporary file after a short delay - let temp_file_path_clone = temp_file_path.clone(); - tokio::spawn(async move { - tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; - let _ = std::fs::remove_file(temp_file_path_clone); - }); - - match open_result { - Ok(output) if output.status.success() => { - log::info!("Successfully opened URL using file-based approach"); - return Ok(()); - } - Ok(output) => { - let stderr = String::from_utf8_lossy(&output.stderr); - log::info!("File-based approach failed: {stderr}"); - } - Err(e) => { - log::info!("File-based approach error: {e}"); - } - } - } - - let _ = std::fs::remove_file(&temp_file_path); - } - Err(e) => { - log::info!("Failed to create temporary HTML file: {e}"); - } - } - - // Method 2: Try using the 'open' command directly with the URL - log::info!("Attempting direct URL opening with 'open' command"); - - let browser = create_browser(browser_type.clone()); - if let Ok(executable_path) = browser.get_executable_path(browser_dir) { - let direct_open_result = Command::new("open") - .args(["-a", executable_path.to_str().unwrap(), url]) - .output(); - - match direct_open_result { - Ok(output) if output.status.success() => { - log::info!("Successfully opened URL using direct 'open' command"); - return Ok(()); - } - Ok(output) => { - let stderr = String::from_utf8_lossy(&output.stderr); - log::info!("Direct 'open' command failed: {stderr}"); - } - Err(e) => { - log::info!("Direct 'open' command error: {e}"); - } - } - } - - // If all methods fail, return a helpful error message - Err( - format!( - "Failed to open URL in existing TOR/Mullvad browser (PID: {pid}). All methods failed:\n\ - 1. File-based approach failed\n\ - 2. Direct 'open' command failed\n\ - \n\ - This may be due to browser security restrictions or the browser process may have changed.\n\ - Try closing and reopening the browser, or manually paste the URL: {url}" - ) - .into(), - ) - } - pub async fn open_url_in_existing_browser_chromium( profile: &BrowserProfile, url: &str, @@ -622,42 +471,6 @@ end try pub mod windows { use super::*; - pub fn is_tor_or_mullvad_browser(exe_name: &str, cmd: &[OsString], browser_type: &str) -> bool { - let exe_lower = exe_name.to_lowercase(); - - // Check for Firefox-based browsers first by executable name - let is_firefox_family = exe_lower.contains("firefox") || exe_lower.contains(".exe"); - - if !is_firefox_family { - return false; - } - - // Check command arguments for profile paths and browser-specific indicators - let cmd_line = cmd - .iter() - .map(|s| s.to_string_lossy().to_lowercase()) - .collect::>() - .join(" "); - - match browser_type { - "tor-browser" => { - // Check for TOR browser specific paths and arguments - cmd_line.contains("tor") - || cmd_line.contains("browser\\torbrowser") - || cmd_line.contains("tor-browser") - || cmd_line.contains("profile") && (cmd_line.contains("tor") || cmd_line.contains("tbb")) - } - "mullvad-browser" => { - // Check for Mullvad browser specific paths and arguments - cmd_line.contains("mullvad") - || cmd_line.contains("browser\\mullvadbrowser") - || cmd_line.contains("mullvad-browser") - || cmd_line.contains("profile") && cmd_line.contains("mullvad") - } - _ => false, - } - } - pub async fn launch_browser_process( executable_path: &std::path::Path, args: &[String], @@ -782,48 +595,6 @@ pub mod windows { Ok(()) } - pub async fn open_url_in_existing_browser_tor_mullvad( - profile: &BrowserProfile, - url: &str, - browser_type: BrowserType, - browser_dir: &Path, - profiles_dir: &Path, - ) -> Result<(), Box> { - // On Windows, TOR and Mullvad browsers can sometimes accept URLs via command line - // even with -no-remote, by launching a new instance that hands off to existing one - let browser = create_browser(browser_type.clone()); - let executable_path = browser - .get_executable_path(browser_dir) - .map_err(|e| format!("Failed to get executable path: {}", e))?; - - let mut cmd = Command::new(&executable_path); - let profile_data_path = profile.get_profile_data_path(profiles_dir); - cmd.args(["-profile", &profile_data_path.to_string_lossy(), url]); - - // Set working directory - if let Some(parent_dir) = browser_dir - .parent() - .or_else(|| browser_dir.ancestors().nth(1)) - { - cmd.current_dir(parent_dir); - } - - let output = cmd.output()?; - - if !output.status.success() { - return Err( - format!( - "Failed to open URL in existing {}: {}. Note: TOR and Mullvad browsers may require manual URL opening for security reasons.", - browser_type.as_str(), - String::from_utf8_lossy(&output.stderr) - ) - .into(), - ); - } - - Ok(()) - } - pub async fn open_url_in_existing_browser_chromium( profile: &BrowserProfile, url: &str, @@ -909,15 +680,6 @@ pub mod windows { pub mod linux { use super::*; - pub fn is_tor_or_mullvad_browser( - _exe_name: &str, - _cmd: &[OsString], - _browser_type: &str, - ) -> bool { - // Linux implementation would go here - false - } - pub async fn launch_browser_process( executable_path: &std::path::Path, args: &[String], @@ -1074,16 +836,6 @@ pub mod linux { Ok(()) } - pub async fn open_url_in_existing_browser_tor_mullvad( - _profile: &BrowserProfile, - _url: &str, - _browser_type: BrowserType, - _browser_dir: &Path, - _profiles_dir: &Path, - ) -> Result<(), Box> { - Err("Opening URLs in existing Firefox-based browsers is not supported on Linux when using -no-remote".into()) - } - pub async fn open_url_in_existing_browser_chromium( profile: &BrowserProfile, url: &str, diff --git a/src-tauri/src/profile/manager.rs b/src-tauri/src/profile/manager.rs index ea51965..4d18cca 100644 --- a/src-tauri/src/profile/manager.rs +++ b/src-tauri/src/profile/manager.rs @@ -765,10 +765,8 @@ impl ProfileManager { let profile_path_match = cmd.iter().any(|s| { let arg = s.to_str().unwrap_or(""); // For Firefox-based browsers, check for exact profile path match - if profile.browser == "tor-browser" - || profile.browser == "firefox" + if profile.browser == "firefox" || profile.browser == "firefox-developer" - || profile.browser == "mullvad-browser" || profile.browser == "zen" { arg == profile_data_path_str @@ -803,13 +801,9 @@ impl ProfileManager { "firefox" => { exe_name.contains("firefox") && !exe_name.contains("developer") - && !exe_name.contains("tor") - && !exe_name.contains("mullvad") && !exe_name.contains("camoufox") } "firefox-developer" => exe_name.contains("firefox") && exe_name.contains("developer"), - "mullvad-browser" => self.is_tor_or_mullvad_browser(&exe_name, cmd, "mullvad-browser"), - "tor-browser" => self.is_tor_or_mullvad_browser(&exe_name, cmd, "tor-browser"), "zen" => exe_name.contains("zen"), "chromium" => exe_name.contains("chromium"), "brave" => exe_name.contains("brave"), @@ -832,10 +826,8 @@ impl ProfileManager { // Camoufox uses user_data_dir like Chromium browsers arg.contains(&format!("--user-data-dir={profile_data_path_str}")) || arg == profile_data_path_str - } else if profile.browser == "tor-browser" - || profile.browser == "firefox" + } else if profile.browser == "firefox" || profile.browser == "firefox-developer" - || profile.browser == "mullvad-browser" || profile.browser == "zen" { arg == profile_data_path_str @@ -1042,33 +1034,6 @@ impl ProfileManager { } } - // Helper function to check if a process matches TOR/Mullvad browser - fn is_tor_or_mullvad_browser( - &self, - exe_name: &str, - cmd: &[std::ffi::OsString], - browser_type: &str, - ) -> bool { - #[cfg(target_os = "macos")] - return crate::platform_browser::macos::is_tor_or_mullvad_browser(exe_name, cmd, browser_type); - - #[cfg(target_os = "windows")] - return crate::platform_browser::windows::is_tor_or_mullvad_browser( - exe_name, - cmd, - browser_type, - ); - - #[cfg(target_os = "linux")] - return crate::platform_browser::linux::is_tor_or_mullvad_browser(exe_name, cmd, browser_type); - - #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] - { - let _ = (exe_name, cmd, browser_type); - false - } - } - fn get_common_firefox_preferences(&self) -> Vec { vec![ // Disable default browser check @@ -1180,7 +1145,7 @@ impl ProfileManager { ); // Use MANUAL proxy configuration (type 1) instead of PAC file (type 2) - // PAC files with file:// URLs are blocked by privacy-focused browsers like Zen and Mullvad + // PAC files with file:// URLs are blocked by privacy-focused browsers like Zen // Manual proxy configuration works reliably across all Firefox variants preferences.push("user_pref(\"network.proxy.type\", 1);".to_string()); diff --git a/src-tauri/src/profile_importer.rs b/src-tauri/src/profile_importer.rs index 21024c9..19e72ae 100644 --- a/src-tauri/src/profile_importer.rs +++ b/src-tauri/src/profile_importer.rs @@ -59,8 +59,6 @@ impl ProfileImporter { // Detect Zen Browser profiles detected_profiles.extend(self.detect_zen_browser_profiles()?); - // NOTE: Mullvad and Tor Browser profile imports are no longer supported. - // We intentionally do not detect these profiles to avoid offering them in the UI. // Remove duplicates based on path let mut seen_paths = HashSet::new(); @@ -495,9 +493,7 @@ impl ProfileImporter { "firefox-developer" => "Firefox Developer", "chromium" => "Chrome/Chromium", "brave" => "Brave", - "mullvad-browser" => "Mullvad Browser", "zen" => "Zen Browser", - "tor-browser" => "Tor Browser", _ => "Unknown Browser", } } @@ -509,11 +505,6 @@ impl ProfileImporter { browser_type: &str, new_profile_name: &str, ) -> Result<(), Box> { - // Disable imports for Mullvad and Tor browsers - if browser_type == "mullvad-browser" || browser_type == "tor-browser" { - return Err("Importing Mullvad Browser or Tor Browser profiles is not supported".into()); - } - // Validate that source path exists let source_path = Path::new(source_path); if !source_path.exists() { @@ -685,15 +676,7 @@ mod tests { "Chrome/Chromium" ); assert_eq!(importer.get_browser_display_name("brave"), "Brave"); - assert_eq!( - importer.get_browser_display_name("mullvad-browser"), - "Mullvad Browser" - ); assert_eq!(importer.get_browser_display_name("zen"), "Zen Browser"); - assert_eq!( - importer.get_browser_display_name("tor-browser"), - "Tor Browser" - ); assert_eq!( importer.get_browser_display_name("unknown"), "Unknown Browser" diff --git a/src/app/page.tsx b/src/app/page.tsx index 94988cf..24ae25a 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -30,13 +30,11 @@ import { showErrorToast, showToast } from "@/lib/toast-utils"; import type { BrowserProfile, CamoufoxConfig } from "@/types"; type BrowserTypeString = - | "mullvad-browser" | "firefox" | "firefox-developer" | "chromium" | "brave" | "zen" - | "tor-browser" | "camoufox"; interface PendingUrl { @@ -648,9 +646,7 @@ export default function Home() { if (profiles.length === 0) return; const deprecatedProfiles = profiles.filter( - (p) => - ["tor-browser", "mullvad-browser"].includes(p.browser) || - (p.release_type === "nightly" && p.browser !== "firefox-developer"), + (p) => p.release_type === "nightly" && p.browser !== "firefox-developer", ); if (deprecatedProfiles.length > 0) { @@ -661,7 +657,7 @@ export default function Home() { id: "deprecated-profiles-warning", type: "error", title: "Some profiles will be deprecated soon", - description: `The following profiles will be deprecated soon: ${deprecatedNames}. Tor Browser, Mullvad Browser, and nightly profiles (except Firefox Developers Edition) will be removed in upcoming versions. Please check GitHub for migration instructions.`, + description: `The following profiles will be deprecated soon: ${deprecatedNames}. Nightly profiles (except Firefox Developers Edition) will be removed in upcoming versions. Please check GitHub for migration instructions.`, duration: 15000, action: { label: "Learn more", diff --git a/src/components/create-profile-dialog.tsx b/src/components/create-profile-dialog.tsx index cd9afe5..5965e14 100644 --- a/src/components/create-profile-dialog.tsx +++ b/src/components/create-profile-dialog.tsx @@ -42,13 +42,11 @@ const getCurrentOS = (): CamoufoxOS => { import { RippleButton } from "./ui/ripple"; type BrowserTypeString = - | "mullvad-browser" | "firefox" | "firefox-developer" | "chromium" | "brave" | "zen" - | "tor-browser" | "camoufox"; interface CreateProfileDialogProps { @@ -92,14 +90,6 @@ const browserOptions: BrowserOption[] = [ value: "zen", label: "Zen Browser", }, - { - value: "mullvad-browser", - label: "Mullvad Browser", - }, - { - value: "tor-browser", - label: "Tor Browser", - }, ]; export function CreateProfileDialog({ @@ -429,12 +419,9 @@ export function CreateProfileDialog({ isBrowserVersionAvailable, ]); - // Filter supported browsers for regular browsers (excluding mullvad and tor) - const regularBrowsers = browserOptions.filter( - (browser) => - supportedBrowsers.includes(browser.value) && - browser.value !== "mullvad-browser" && - browser.value !== "tor-browser", + // Filter supported browsers for regular browsers + const regularBrowsers = browserOptions.filter((browser) => + supportedBrowsers.includes(browser.value), ); return ( diff --git a/src/components/import-profile-dialog.tsx b/src/components/import-profile-dialog.tsx index 3343b46..62c3810 100644 --- a/src/components/import-profile-dialog.tsx +++ b/src/components/import-profile-dialog.tsx @@ -62,10 +62,7 @@ export function ImportProfileDialog({ const { supportedBrowsers, isLoading: isLoadingSupport } = useBrowserSupport(); - // Exclude browsers that are no longer supported for import - const importableBrowsers = supportedBrowsers.filter( - (b) => b !== "mullvad-browser" && b !== "tor-browser", - ); + const importableBrowsers = supportedBrowsers; const loadDetectedProfiles = useCallback(async () => { setIsLoading(true); diff --git a/src/components/profile-data-table.tsx b/src/components/profile-data-table.tsx index e602d29..51b5615 100644 --- a/src/components/profile-data-table.tsx +++ b/src/components/profile-data-table.tsx @@ -1680,19 +1680,12 @@ export function ProfilesDataTable({ ? (meta.storedProxies.find((p) => p.id === effectiveProxyId) ?? null) : null; - const displayName = - profile.browser === "tor-browser" - ? "Not supported" - : effectiveProxy - ? effectiveProxy.name - : "Not Selected"; + const displayName = effectiveProxy + ? effectiveProxy.name + : "Not Selected"; const profileHasProxy = Boolean(effectiveProxy); const tooltipText = - profile.browser === "tor-browser" - ? "Proxies are not supported for TOR browser" - : profileHasProxy && effectiveProxy - ? effectiveProxy.name - : null; + profileHasProxy && effectiveProxy ? effectiveProxy.name : null; const isSelectorOpen = meta.openProxySelectorFor === profile.id; // When profile is running, show bandwidth chart instead of proxy selector @@ -1717,23 +1710,6 @@ export function ProfilesDataTable({ ); } - if (profile.browser === "tor-browser") { - return ( - - - - - Not supported - - - - {(tooltipText || displayName.length > 10) && ( - {tooltipText || displayName} - )} - - ); - } - return (
{ const isRunning = runningProfiles.has(profile.id); // Simple check without browserState dependency - return ( - isRunning && - profile.browser !== "tor-browser" && - profile.browser !== "mullvad-browser" - ); + return isRunning; }); if (runningAvailableProfile) { diff --git a/src/components/proxy-assignment-dialog.tsx b/src/components/proxy-assignment-dialog.tsx index ddccb53..66c2ffd 100644 --- a/src/components/proxy-assignment-dialog.tsx +++ b/src/components/proxy-assignment-dialog.tsx @@ -49,10 +49,9 @@ export function ProxyAssignmentDialog({ setIsAssigning(true); setError(null); try { - // Filter out TOR browser profiles as they don't support proxies const validProfiles = selectedProfiles.filter((profileId) => { const profile = profiles.find((p) => p.id === profileId); - return profile && profile.browser !== "tor-browser"; + return profile; }); if (validProfiles.length === 0) { @@ -119,15 +118,9 @@ export function ProxyAssignmentDialog({ (p: BrowserProfile) => p.id === profileId, ); const displayName = profile ? profile.name : profileId; - const isTorBrowser = profile?.browser === "tor-browser"; return (
  • • {displayName} - {isTorBrowser && ( - - (TOR - no proxy support) - - )}
  • ); })} diff --git a/src/hooks/use-browser-state.ts b/src/hooks/use-browser-state.ts index a29b40f..6f95e2a 100644 --- a/src/hooks/use-browser-state.ts +++ b/src/hooks/use-browser-state.ts @@ -3,7 +3,7 @@ import { getBrowserDisplayName } from "@/lib/browser-utils"; import type { BrowserProfile } from "@/types"; /** - * Hook for managing browser state and enforcing single-instance rules for Tor and Mullvad browsers + * Hook for managing browser state */ export function useBrowserState( profiles: BrowserProfile[], @@ -22,8 +22,8 @@ export function useBrowserState( * Check if a browser type allows only one instance to run at a time */ const isSingleInstanceBrowser = useCallback( - (browserType: string): boolean => { - return browserType === "tor-browser" || browserType === "mullvad-browser"; + (_browserType: string): boolean => { + return false; // No browsers currently require single instance }, [], ); @@ -102,7 +102,7 @@ export function useBrowserState( return false; } - // For single-instance browsers (Tor and Mullvad) + // For single-instance browsers if (isSingleInstanceBrowser(profile.browser)) { const runningInstancesOfType = profiles.filter( (p) => p.browser === profile.browser && runningProfiles.has(p.id), @@ -195,9 +195,7 @@ export function useBrowserState( isSingleInstanceBrowser(profile.browser) && !canLaunchProfile(profile) ) { - const browserDisplayName = - profile.browser === "tor-browser" ? "TOR" : "Mullvad"; - return `Only one ${browserDisplayName} browser instance can run at a time. Stop the running ${browserDisplayName} browser first.`; + return `Only one instance of this browser can run at a time. Stop the running browser first.`; } return ""; @@ -242,8 +240,6 @@ export function useBrowserState( } if (isSingleInstanceBrowser(profile.browser)) { - const browserDisplayName = - profile.browser === "tor-browser" ? "TOR" : "Mullvad"; const runningInstancesOfType = profiles.filter( (p) => p.browser === profile.browser && runningProfiles.has(p.id), ); @@ -252,7 +248,7 @@ export function useBrowserState( const runningProfileNames = runningInstancesOfType .map((p) => p.name) .join(", "); - return `${browserDisplayName} browser is already running (${runningProfileNames}). Only one instance can run at a time.`; + return `${getBrowserDisplayName(profile.browser)} browser is already running (${runningProfileNames}). Only one instance can run at a time.`; } } diff --git a/src/lib/browser-utils.ts b/src/lib/browser-utils.ts index c88980b..faa21b5 100644 --- a/src/lib/browser-utils.ts +++ b/src/lib/browser-utils.ts @@ -4,7 +4,7 @@ */ import { FaChrome, FaFirefox, FaShieldAlt } from "react-icons/fa"; -import { SiBrave, SiMullvad, SiTorbrowser } from "react-icons/si"; +import { SiBrave } from "react-icons/si"; import { ZenBrowser } from "@/components/icons/zen-browser"; /** @@ -14,11 +14,9 @@ export function getBrowserDisplayName(browserType: string): string { const browserNames: Record = { firefox: "Firefox", "firefox-developer": "Firefox Developer Edition", - "mullvad-browser": "Mullvad Browser", zen: "Zen Browser", brave: "Brave", chromium: "Chromium", - "tor-browser": "Tor Browser", camoufox: "Anti-Detect", }; @@ -30,8 +28,6 @@ export function getBrowserDisplayName(browserType: string): string { */ export function getBrowserIcon(browserType: string) { switch (browserType) { - case "mullvad-browser": - return SiMullvad; case "chromium": return FaChrome; case "brave": @@ -41,8 +37,6 @@ export function getBrowserIcon(browserType: string) { return FaFirefox; case "zen": return ZenBrowser; - case "tor-browser": - return SiTorbrowser; case "camoufox": return FaShieldAlt; default: