chore: clippy

This commit is contained in:
zhom
2025-05-30 01:25:04 +04:00
parent 210924e36f
commit e3e6fd98c8
14 changed files with 297 additions and 385 deletions
+1 -1
View File
@@ -13,7 +13,7 @@
"shadcn:add": "pnpm dlx shadcn@latest add",
"prepare": "husky",
"format:js": "biome check src/ --fix",
"format:rust": "cd src-tauri && cargo fmt --all",
"format:rust": "cd src-tauri && cargo clippy --fix --allow-dirty --all-targets --all-features -- -D warnings -D clippy::all && cargo fmt --all",
"format:biome": "biome check src/ --fix",
"format": "pnpm format:js && pnpm format:rust"
},
+35 -46
View File
@@ -267,7 +267,7 @@ impl ApiClient {
pub fn load_cached_versions(&self, browser: &str) -> Option<Vec<String>> {
let cache_dir = Self::get_cache_dir().ok()?;
let cache_file = cache_dir.join(format!("{}_versions.json", browser));
let cache_file = cache_dir.join(format!("{browser}_versions.json"));
if !cache_file.exists() {
return None;
@@ -277,7 +277,7 @@ impl ApiClient {
let cached_data: CachedVersionData = serde_json::from_str(&content).ok()?;
// Always return cached versions regardless of age - they're always valid
println!("Using cached versions for {}", browser);
println!("Using cached versions for {browser}");
Some(cached_data.versions)
}
@@ -286,7 +286,7 @@ impl ApiClient {
Ok(dir) => dir,
Err(_) => return true, // If we can't get cache dir, consider expired
};
let cache_file = cache_dir.join(format!("{}_versions.json", browser));
let cache_file = cache_dir.join(format!("{browser}_versions.json"));
if !cache_file.exists() {
return true; // No cache file means expired
@@ -312,7 +312,7 @@ impl ApiClient {
versions: &[String],
) -> Result<(), Box<dyn std::error::Error>> {
let cache_dir = Self::get_cache_dir()?;
let cache_file = cache_dir.join(format!("{}_versions.json", browser));
let cache_file = cache_dir.join(format!("{browser}_versions.json"));
let cached_data = CachedVersionData {
versions: versions.to_vec(),
@@ -327,7 +327,7 @@ impl ApiClient {
fn load_cached_github_releases(&self, browser: &str) -> Option<Vec<GithubRelease>> {
let cache_dir = Self::get_cache_dir().ok()?;
let cache_file = cache_dir.join(format!("{}_github.json", browser));
let cache_file = cache_dir.join(format!("{browser}_github.json"));
if !cache_file.exists() {
return None;
@@ -337,7 +337,7 @@ impl ApiClient {
let cached_data: CachedGithubData = serde_json::from_str(&content).ok()?;
// Always use cached GitHub releases - cache never expires, only gets updated with new versions
println!("Using cached GitHub releases for {}", browser);
println!("Using cached GitHub releases for {browser}");
Some(cached_data.releases)
}
@@ -347,7 +347,7 @@ impl ApiClient {
releases: &[GithubRelease],
) -> Result<(), Box<dyn std::error::Error>> {
let cache_dir = Self::get_cache_dir()?;
let cache_file = cache_dir.join(format!("{}_github.json", browser));
let cache_file = cache_dir.join(format!("{browser}_github.json"));
let cached_data = CachedGithubData {
releases: releases.to_vec(),
@@ -376,8 +376,7 @@ impl ApiClient {
date: "".to_string(), // Cache doesn't store dates
is_prerelease: is_alpha_version(&version),
download_url: Some(format!(
"https://download.mozilla.org/?product=firefox-{}&os=osx&lang=en-US",
version
"https://download.mozilla.org/?product=firefox-{version}&os=osx&lang=en-US"
)),
}
})
@@ -438,7 +437,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_versions("firefox", &versions) {
eprintln!("Failed to cache Firefox versions: {}", e);
eprintln!("Failed to cache Firefox versions: {e}");
}
}
@@ -461,8 +460,7 @@ impl ApiClient {
date: "".to_string(), // Cache doesn't store dates
is_prerelease: is_alpha_version(&version),
download_url: Some(format!(
"https://download.mozilla.org/?product=devedition-{}&os=osx&lang=en-US",
version
"https://download.mozilla.org/?product=devedition-{version}&os=osx&lang=en-US"
)),
}
})
@@ -529,7 +527,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_versions("firefox-developer", &versions) {
eprintln!("Failed to cache Firefox Developer versions: {}", e);
eprintln!("Failed to cache Firefox Developer versions: {e}");
}
}
@@ -578,7 +576,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_github_releases("mullvad", &releases) {
eprintln!("Failed to cache Mullvad releases: {}", e);
eprintln!("Failed to cache Mullvad releases: {e}");
}
}
@@ -619,7 +617,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_github_releases("zen", &releases) {
eprintln!("Failed to cache Zen releases: {}", e);
eprintln!("Failed to cache Zen releases: {e}");
}
}
@@ -681,7 +679,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_github_releases("brave", &filtered_releases) {
eprintln!("Failed to cache Brave releases: {}", e);
eprintln!("Failed to cache Brave releases: {e}");
}
}
@@ -698,8 +696,7 @@ impl ApiClient {
"Mac"
};
let url = format!(
"https://commondatastorage.googleapis.com/chromium-browser-snapshots/{}/LAST_CHANGE",
arch
"https://commondatastorage.googleapis.com/chromium-browser-snapshots/{arch}/LAST_CHANGE"
);
let version = self
.client
@@ -756,7 +753,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_versions("chromium", &versions) {
eprintln!("Failed to cache Chromium versions: {}", e);
eprintln!("Failed to cache Chromium versions: {e}");
}
}
@@ -786,8 +783,7 @@ impl ApiClient {
date: "".to_string(), // Cache doesn't store dates
is_prerelease: false, // Assume all archived versions are stable
download_url: Some(format!(
"https://archive.torproject.org/tor-package-archive/torbrowser/{}/tor-browser-macos-{}.dmg",
version, version
"https://archive.torproject.org/tor-package-archive/torbrowser/{version}/tor-browser-macos-{version}.dmg"
)),
}
}).collect());
@@ -849,7 +845,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_versions("tor-browser", &version_strings) {
eprintln!("Failed to cache TOR versions: {}", e);
eprintln!("Failed to cache TOR versions: {e}");
}
}
@@ -859,8 +855,7 @@ impl ApiClient {
date: "".to_string(), // TOR archive doesn't provide structured dates
is_prerelease: false, // Assume all archived versions are stable
download_url: Some(format!(
"https://archive.torproject.org/tor-package-archive/torbrowser/{}/tor-browser-macos-{}.dmg",
version, version
"https://archive.torproject.org/tor-package-archive/torbrowser/{version}/tor-browser-macos-{version}.dmg"
)),
}
}).collect())
@@ -870,10 +865,7 @@ impl ApiClient {
&self,
version: &str,
) -> Result<bool, Box<dyn std::error::Error + Send + Sync>> {
let url = format!(
"https://archive.torproject.org/tor-package-archive/torbrowser/{}/",
version
);
let url = format!("https://archive.torproject.org/tor-package-archive/torbrowser/{version}/");
let html = self
.client
.get(&url)
@@ -1008,10 +1000,10 @@ mod tests {
);
println!("Firefox API test passed. Found {} releases", releases.len());
println!("Latest version: {}", first_release.version);
println!("Latest version: {}", releases[0].version);
}
Err(e) => {
println!("Firefox API test failed: {}", e);
println!("Firefox API test failed: {e}");
panic!("Firefox API should work");
}
}
@@ -1047,10 +1039,10 @@ mod tests {
"Firefox Developer API test passed. Found {} releases",
releases.len()
);
println!("Latest version: {}", first_release.version);
println!("Latest version: {}", releases[0].version);
}
Err(e) => {
println!("Firefox Developer API test failed: {}", e);
println!("Firefox Developer API test failed: {e}");
panic!("Firefox Developer API should work");
}
}
@@ -1074,10 +1066,10 @@ mod tests {
);
println!("Mullvad API test passed. Found {} releases", releases.len());
println!("Latest version: {}", first_release.tag_name);
println!("Latest version: {}", releases[0].tag_name);
}
Err(e) => {
println!("Mullvad API test failed: {}", e);
println!("Mullvad API test failed: {e}");
panic!("Mullvad API should work");
}
}
@@ -1101,10 +1093,10 @@ mod tests {
);
println!("Zen API test passed. Found {} releases", releases.len());
println!("Latest version: {}", first_release.tag_name);
println!("Latest version: {}", releases[0].tag_name);
}
Err(e) => {
println!("Zen API test failed: {}", e);
println!("Zen API test failed: {e}");
panic!("Zen API should work");
}
}
@@ -1129,7 +1121,7 @@ mod tests {
}
}
Err(e) => {
println!("Brave API test failed: {}", e);
println!("Brave API test failed: {e}");
panic!("Brave API should work");
}
}
@@ -1150,10 +1142,10 @@ mod tests {
"Version should be numeric"
);
println!("Chromium API test passed. Latest version: {}", version);
println!("Chromium API test passed. Latest version: {version}");
}
Err(e) => {
println!("Chromium API test failed: {}", e);
println!("Chromium API test failed: {e}");
panic!("Chromium API should work");
}
}
@@ -1188,10 +1180,10 @@ mod tests {
);
println!("TOR API test passed. Found {} releases", releases.len());
println!("Latest version: {}", first_release.version);
println!("Latest version: {}", releases[0].version);
}
Ok(Err(e)) => {
println!("TOR API test failed: {}", e);
println!("TOR API test failed: {e}");
// Don't panic for TOR API since it can be unreliable
println!("TOR API test skipped due to network issues");
}
@@ -1213,13 +1205,10 @@ mod tests {
match result {
Ok(has_macos) => {
assert!(has_macos, "Version 14.0.4 should have macOS support");
println!(
"TOR version check test passed. Version 14.0.4 has macOS: {}",
has_macos
);
println!("TOR version check test passed. Version 14.0.4 has macOS: {has_macos}");
}
Err(e) => {
println!("TOR version check test failed: {}", e);
println!("TOR version check test failed: {e}");
panic!("TOR version check should work");
}
}
+18 -18
View File
@@ -49,7 +49,7 @@ impl AutoUpdater {
let settings = self
.settings_manager
.load_settings()
.map_err(|e| format!("Failed to load settings: {}", e))?;
.map_err(|e| format!("Failed to load settings: {e}"))?;
if !settings.auto_updates_enabled {
return Ok(Vec::new());
}
@@ -57,7 +57,7 @@ impl AutoUpdater {
let profiles = self
.browser_runner
.list_profiles()
.map_err(|e| format!("Failed to list profiles: {}", e))?;
.map_err(|e| format!("Failed to list profiles: {e}"))?;
let mut notifications = Vec::new();
let mut browser_versions: HashMap<String, Vec<BrowserVersionInfo>> = HashMap::new();
@@ -188,7 +188,7 @@ impl AutoUpdater {
version: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let mut state = self.load_auto_update_state()?;
let download_key = format!("{}-{}", browser, version);
let download_key = format!("{browser}-{version}");
state.auto_update_downloads.insert(download_key);
self.save_auto_update_state(&state)?;
Ok(())
@@ -201,7 +201,7 @@ impl AutoUpdater {
version: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let mut state = self.load_auto_update_state()?;
let download_key = format!("{}-{}", browser, version);
let download_key = format!("{browser}-{version}");
state.auto_update_downloads.remove(&download_key);
self.save_auto_update_state(&state)?;
Ok(())
@@ -214,7 +214,7 @@ impl AutoUpdater {
version: &str,
) -> Result<bool, Box<dyn std::error::Error + Send + Sync>> {
let state = self.load_auto_update_state()?;
let download_key = format!("{}-{}", browser, version);
let download_key = format!("{browser}-{version}");
Ok(state.auto_update_downloads.contains(&download_key))
}
@@ -229,7 +229,7 @@ impl AutoUpdater {
state.disabled_browsers.insert(browser.to_string());
// Mark this download as auto-update for toast suppression
let download_key = format!("{}-{}", browser, new_version);
let download_key = format!("{browser}-{new_version}");
state.auto_update_downloads.insert(download_key);
self.save_auto_update_state(&state)?;
@@ -261,7 +261,7 @@ impl AutoUpdater {
let profiles = self
.browser_runner
.list_profiles()
.map_err(|e| format!("Failed to list profiles: {}", e))?;
.map_err(|e| format!("Failed to list profiles: {e}"))?;
let mut updated_profiles = Vec::new();
@@ -308,7 +308,7 @@ impl AutoUpdater {
// Remove browser from disabled list and clean up auto-update tracking
let mut state = self.load_auto_update_state()?;
state.disabled_browsers.remove(browser);
let download_key = format!("{}-{}", browser, new_version);
let download_key = format!("{browser}-{new_version}");
state.auto_update_downloads.remove(&download_key);
self.save_auto_update_state(&state)?;
@@ -409,7 +409,7 @@ pub async fn check_for_browser_updates() -> Result<Vec<UpdateNotification>, Stri
let notifications = updater
.check_for_updates()
.await
.map_err(|e| format!("Failed to check for updates: {}", e))?;
.map_err(|e| format!("Failed to check for updates: {e}"))?;
let grouped = updater.group_update_notifications(notifications);
Ok(grouped)
}
@@ -420,7 +420,7 @@ pub async fn start_browser_update(browser: String, new_version: String) -> Resul
updater
.start_browser_update(&browser, &new_version)
.await
.map_err(|e| format!("Failed to start browser update: {}", e))
.map_err(|e| format!("Failed to start browser update: {e}"))
}
#[tauri::command]
@@ -429,7 +429,7 @@ pub async fn complete_browser_update(browser: String) -> Result<(), String> {
updater
.complete_browser_update(&browser)
.await
.map_err(|e| format!("Failed to complete browser update: {}", e))
.map_err(|e| format!("Failed to complete browser update: {e}"))
}
#[tauri::command]
@@ -437,7 +437,7 @@ pub async fn is_browser_disabled_for_update(browser: String) -> Result<bool, Str
let updater = AutoUpdater::new();
updater
.is_browser_disabled(&browser)
.map_err(|e| format!("Failed to check browser status: {}", e))
.map_err(|e| format!("Failed to check browser status: {e}"))
}
#[tauri::command]
@@ -445,7 +445,7 @@ pub async fn dismiss_update_notification(notification_id: String) -> Result<(),
let updater = AutoUpdater::new();
updater
.dismiss_update_notification(&notification_id)
.map_err(|e| format!("Failed to dismiss notification: {}", e))
.map_err(|e| format!("Failed to dismiss notification: {e}"))
}
#[tauri::command]
@@ -457,7 +457,7 @@ pub async fn complete_browser_update_with_auto_update(
updater
.complete_browser_update_with_auto_update(&browser, &new_version)
.await
.map_err(|e| format!("Failed to complete browser update: {}", e))
.map_err(|e| format!("Failed to complete browser update: {e}"))
}
#[tauri::command]
@@ -465,7 +465,7 @@ pub async fn mark_auto_update_download(browser: String, version: String) -> Resu
let updater = AutoUpdater::new();
updater
.mark_auto_update_download(&browser, &version)
.map_err(|e| format!("Failed to mark auto-update download: {}", e))
.map_err(|e| format!("Failed to mark auto-update download: {e}"))
}
#[tauri::command]
@@ -473,7 +473,7 @@ pub async fn remove_auto_update_download(browser: String, version: String) -> Re
let updater = AutoUpdater::new();
updater
.remove_auto_update_download(&browser, &version)
.map_err(|e| format!("Failed to remove auto-update download: {}", e))
.map_err(|e| format!("Failed to remove auto-update download: {e}"))
}
#[tauri::command]
@@ -481,7 +481,7 @@ pub async fn is_auto_update_download(browser: String, version: String) -> Result
let updater = AutoUpdater::new();
updater
.is_auto_update_download(&browser, &version)
.map_err(|e| format!("Failed to check auto-update download: {}", e))
.map_err(|e| format!("Failed to check auto-update download: {e}"))
}
#[cfg(test)]
@@ -493,7 +493,7 @@ mod tests {
name: name.to_string(),
browser: browser.to_string(),
version: version.to_string(),
profile_path: format!("/tmp/{}", name),
profile_path: format!("/tmp/{name}"),
process_id: None,
proxy: None,
last_launch: None,
+7 -14
View File
@@ -44,7 +44,7 @@ impl BrowserType {
"brave" => Ok(BrowserType::Brave),
"zen" => Ok(BrowserType::Zen),
"tor-browser" => Ok(BrowserType::TorBrowser),
_ => Err(format!("Unknown browser type: {}", s)),
_ => Err(format!("Unknown browser type: {s}")),
}
}
}
@@ -139,10 +139,7 @@ impl Browser for FirefoxBrowser {
.join(self.browser_type().as_str())
.join(version);
println!(
"Firefox browser checking version {} in directory: {:?}",
version, browser_dir
);
println!("Firefox browser checking version {version} in directory: {browser_dir:?}");
// Only check if directory exists and contains a .app file
if browser_dir.exists() {
@@ -158,7 +155,7 @@ impl Browser for FirefoxBrowser {
}
println!("No .app files found in directory");
} else {
println!("Directory does not exist: {:?}", browser_dir);
println!("Directory does not exist: {browser_dir:?}");
}
false
}
@@ -229,8 +226,7 @@ impl Browser for ChromiumBrowser {
let pac_content = fs::read(&pac_path)?;
let pac_base64 = general_purpose::STANDARD.encode(&pac_content);
args.push(format!(
"--proxy-pac-url=data:application/x-javascript-config;base64,{}",
pac_base64
"--proxy-pac-url=data:application/x-javascript-config;base64,{pac_base64}"
));
}
}
@@ -248,10 +244,7 @@ impl Browser for ChromiumBrowser {
.join(self.browser_type().as_str())
.join(version);
println!(
"Chromium browser checking version {} in directory: {:?}",
version, browser_dir
);
println!("Chromium browser checking version {version} in directory: {browser_dir:?}");
// Check if directory exists and contains at least one .app file
if browser_dir.exists() {
@@ -273,7 +266,7 @@ impl Browser for ChromiumBrowser {
}
println!("No valid .app files found in directory");
} else {
println!("Directory does not exist: {:?}", browser_dir);
println!("Directory does not exist: {browser_dir:?}");
}
false
}
@@ -567,7 +560,7 @@ mod tests {
assert_eq!(browser_type, cloned);
// Test Debug trait
let debug_str = format!("{:?}", browser_type);
let debug_str = format!("{browser_type:?}");
assert!(debug_str.contains("Firefox"));
}
+135 -165
View File
@@ -130,7 +130,7 @@ impl BrowserRunner {
);
true
} else {
println!("PID {} does not exist", pid);
println!("PID {pid} does not exist");
false
}
}
@@ -169,7 +169,7 @@ impl BrowserRunner {
.iter()
.any(|p| p.name.to_lowercase() == name.to_lowercase())
{
return Err(format!("Profile with name '{}' already exists", name).into());
return Err(format!("Profile with name '{name}' already exists").into());
}
let snake_case_name = name.to_lowercase().replace(" ", "_");
@@ -216,7 +216,7 @@ impl BrowserRunner {
let profile_path = profiles_dir.join(profile_name.to_lowercase().replace(" ", "_"));
if !profile_file.exists() {
return Err(format!("Profile {} not found", profile_name).into());
return Err(format!("Profile {profile_name} not found").into());
}
// Read the profile
@@ -262,7 +262,7 @@ impl BrowserRunner {
));
if !profile_file.exists() {
return Err(format!("Profile {} not found", profile_name).into());
return Err(format!("Profile {profile_name} not found").into());
}
// Read the profile
@@ -283,7 +283,7 @@ impl BrowserRunner {
let binaries_dir = self.get_binaries_dir();
if !browser.is_version_downloaded(version, &binaries_dir) {
return Err(format!("Browser version {} is not downloaded", version).into());
return Err(format!("Browser version {version} is not downloaded").into());
}
// Update version
@@ -496,7 +496,7 @@ impl BrowserRunner {
// Try multiple times to find the process as it might take time to start
for attempt in 1..=5 {
println!("Attempt {} to find actual browser process...", attempt);
println!("Attempt {attempt} to find actual browser process...");
for (pid, process) in system.processes() {
let cmd = process.cmd();
@@ -605,7 +605,7 @@ impl BrowserRunner {
let pid = updated_profile.process_id.unwrap();
// First try: Use Firefox remote command (most reliable for these browsers)
println!("Trying Firefox remote command for PID: {}", pid);
println!("Trying Firefox remote command for PID: {pid}");
let mut browser_dir = self.get_binaries_dir();
browser_dir.push(&updated_profile.browser);
browser_dir.push(&updated_profile.version);
@@ -629,15 +629,11 @@ impl BrowserRunner {
Ok(output) => {
let stderr = String::from_utf8_lossy(&output.stderr);
println!(
"Firefox remote command failed with stderr: {}, trying AppleScript fallback",
stderr
"Firefox remote command failed with stderr: {stderr}, trying AppleScript fallback"
);
}
Err(e) => {
println!(
"Firefox remote command error: {}, trying AppleScript fallback",
e
);
println!("Firefox remote command error: {e}, trying AppleScript fallback");
}
}
}
@@ -653,11 +649,11 @@ impl BrowserRunner {
try
tell application "System Events"
-- Find the exact process by PID
set targetProcess to (first application process whose unix id is {})
set targetProcess to (first application process whose unix id is {pid})
-- Verify the process exists
if not (exists targetProcess) then
error "No process found with PID {}"
error "No process found with PID {pid}"
end if
-- Get the process name for verification
@@ -700,35 +696,30 @@ try
delay 0.5
-- Type the URL
keystroke "{}"
keystroke "{escaped_url}"
delay 0.5
-- Press Enter to navigate
keystroke return
end tell
return "Successfully opened URL in " & processName & " (PID: {})"
return "Successfully opened URL in " & processName & " (PID: {pid})"
end tell
on error errMsg number errNum
return "AppleScript failed: " & errMsg & " (Error " & errNum & ")"
end try
"#,
pid, pid, escaped_url, pid
"#
);
println!(
"Executing AppleScript fallback for Firefox-based browser (PID: {})...",
pid
);
println!("Executing AppleScript fallback for Firefox-based browser (PID: {pid})...");
let output = Command::new("osascript").args(["-e", &script]).output()?;
if !output.status.success() {
let error_msg = String::from_utf8_lossy(&output.stderr);
println!("AppleScript failed: {}", error_msg);
println!("AppleScript failed: {error_msg}");
return Err(
format!(
"Both Firefox remote command and AppleScript failed. AppleScript error: {}",
error_msg
"Both Firefox remote command and AppleScript failed. AppleScript error: {error_msg}"
)
.into(),
);
@@ -770,10 +761,7 @@ end try
{
let pid = updated_profile.process_id.unwrap();
println!(
"Opening URL in TOR/Mullvad browser using file-based approach (PID: {})",
pid
);
println!("Opening URL in TOR/Mullvad browser using file-based approach (PID: {pid})");
// Validate that we have the correct PID for this TOR/Mullvad browser
if !self.validate_tor_mullvad_pid(&updated_profile, pid) {
@@ -799,23 +787,22 @@ end try
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url={}">
<meta http-equiv="refresh" content="0; url={url}">
<title>Redirecting...</title>
<script>
window.location.href = "{}";
window.location.href = "{url}";
</script>
</head>
<body>
<p>Redirecting to <a href="{}">{}</a>...</p>
<p>Redirecting to <a href="{url}">{url}</a>...</p>
</body>
</html>"#,
url, url, url, url
</html>"#
);
// Write the HTML file
match std::fs::write(&temp_file_path, html_content) {
Ok(()) => {
println!("Created temporary HTML file: {:?}", temp_file_path);
println!("Created temporary HTML file: {temp_file_path:?}");
// Get the browser executable path to use with 'open'
let mut browser_dir = self.get_binaries_dir();
@@ -848,10 +835,10 @@ end try
}
Ok(output) => {
let stderr = String::from_utf8_lossy(&output.stderr);
println!("File-based approach failed: {}", stderr);
println!("File-based approach failed: {stderr}");
}
Err(e) => {
println!("File-based approach error: {}", e);
println!("File-based approach error: {e}");
}
}
}
@@ -860,7 +847,7 @@ end try
let _ = std::fs::remove_file(&temp_file_path);
}
Err(e) => {
println!("Failed to create temporary HTML file: {}", e);
println!("Failed to create temporary HTML file: {e}");
}
}
@@ -886,10 +873,10 @@ end try
}
Ok(output) => {
let stderr = String::from_utf8_lossy(&output.stderr);
println!("Direct 'open' command failed: {}", stderr);
println!("Direct 'open' command failed: {stderr}");
}
Err(e) => {
println!("Direct 'open' command error: {}", e);
println!("Direct 'open' command error: {e}");
}
}
}
@@ -901,9 +888,9 @@ end try
r#"
try
tell application "System Events"
set targetProcess to (first application process whose unix id is {})
set targetProcess to (first application process whose unix id is {pid})
if not (exists targetProcess) then
error "No process found with PID {}"
error "No process found with PID {pid}"
end if
-- Just bring the process to front without trying to control it
@@ -914,8 +901,7 @@ try
on error errMsg
return "Minimal AppleScript failed: " & errMsg
end try
"#,
pid, pid
"#
);
let minimal_output = Command::new("osascript")
@@ -926,7 +912,7 @@ end try
Ok(output) => {
let result = String::from_utf8_lossy(&output.stdout).trim().to_string();
if output.status.success() && result.contains("successfully") {
println!("Successfully brought browser to front: {}", result);
println!("Successfully brought browser to front: {result}");
// Now try to use the system's default URL opening mechanism
let system_open_result = Command::new("open").args([url]).output();
@@ -938,31 +924,30 @@ end try
}
Ok(output) => {
let stderr = String::from_utf8_lossy(&output.stderr);
println!("System default URL opening failed: {}", stderr);
println!("System default URL opening failed: {stderr}");
}
Err(e) => {
println!("System default URL opening error: {}", e);
println!("System default URL opening error: {e}");
}
}
} else {
println!("Minimal AppleScript failed: {}", result);
println!("Minimal AppleScript failed: {result}");
}
}
Err(e) => {
println!("Minimal AppleScript execution error: {}", e);
println!("Minimal AppleScript execution error: {e}");
}
}
// If all methods fail, return a more helpful error message
return Err(format!(
"Failed to open URL in existing TOR/Mullvad browser (PID: {}). All methods failed:\n\
"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\
3. Minimal AppleScript approach 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: {}",
pid, url
Try closing and reopening the browser, or manually paste the URL: {url}"
).into());
}
@@ -980,7 +965,7 @@ end try
let pid = updated_profile.process_id.unwrap();
// First, try using the browser's built-in URL opening capability
println!("Trying Chromium URL opening for PID: {}", pid);
println!("Trying Chromium URL opening for PID: {pid}");
let mut browser_dir = self.get_binaries_dir();
browser_dir.push(&updated_profile.browser);
browser_dir.push(&updated_profile.version);
@@ -1002,13 +987,10 @@ end try
}
Ok(output) => {
let stderr = String::from_utf8_lossy(&output.stderr);
println!(
"Chromium URL opening failed: {}, trying AppleScript",
stderr
);
println!("Chromium URL opening failed: {stderr}, trying AppleScript");
}
Err(e) => {
println!("Chromium URL opening error: {}, trying AppleScript", e);
println!("Chromium URL opening error: {e}, trying AppleScript");
}
}
}
@@ -1024,11 +1006,11 @@ end try
try
tell application "System Events"
-- Find the exact process by PID
set targetProcess to (first application process whose unix id is {})
set targetProcess to (first application process whose unix id is {pid})
-- Verify the process exists
if not (exists targetProcess) then
error "No process found with PID {}"
error "No process found with PID {pid}"
end if
-- Get the process name for verification
@@ -1071,37 +1053,29 @@ try
delay 0.5
-- Type the URL
keystroke "{}"
keystroke "{escaped_url}"
delay 0.5
-- Press Enter to navigate
keystroke return
end tell
return "Successfully opened URL in " & processName & " (PID: {})"
return "Successfully opened URL in " & processName & " (PID: {pid})"
end tell
on error errMsg number errNum
return "AppleScript failed: " & errMsg & " (Error " & errNum & ")"
end try
"#,
pid, pid, escaped_url, pid
"#
);
println!(
"Executing AppleScript for Chromium-based browser (PID: {})...",
pid
);
println!("Executing AppleScript for Chromium-based browser (PID: {pid})...");
let output = Command::new("osascript").args(["-e", &script]).output()?;
if !output.status.success() {
let error_msg = String::from_utf8_lossy(&output.stderr);
println!("AppleScript failed: {}", error_msg);
println!("AppleScript failed: {error_msg}");
return Err(
format!(
"Failed to open URL in existing Chromium-based browser: {}",
error_msg
)
.into(),
format!("Failed to open URL in existing Chromium-based browser: {error_msg}").into(),
);
} else {
println!("AppleScript succeeded");
@@ -1176,49 +1150,57 @@ end try
if is_running && url.is_some() {
// Browser is running and we have a URL to open
println!("Opening URL in existing browser: {}", url.as_ref().unwrap());
if let Some(url_ref) = url.as_ref() {
println!("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"
) {
println!("TOR/Mullvad browser detected - ensuring we have correct PID");
if final_profile.process_id.is_none() {
println!("ERROR: No PID found for running TOR/Mullvad browser - this should not happen");
return Err("No PID found for running browser".into());
// For TOR/Mullvad browsers, add extra verification
if matches!(
final_profile.browser.as_str(),
"tor-browser" | "mullvad-browser"
) {
println!("TOR/Mullvad browser detected - ensuring we have correct PID");
if final_profile.process_id.is_none() {
println!(
"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, &final_profile, url.as_ref().unwrap())
.await
{
Ok(()) => {
println!("Successfully opened URL in existing browser");
Ok(final_profile)
}
Err(e) => {
println!("Failed to open URL in existing browser: {}", e);
match self
.open_url_in_existing_browser(app_handle, &final_profile, url_ref)
.await
{
Ok(()) => {
println!("Successfully opened URL in existing browser");
Ok(final_profile)
}
Err(e) => {
println!("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
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())
}
_ => {
println!(
"Falling back to new instance for browser: {}",
final_profile.browser
);
// Fallback to launching a new instance for other browsers
self.launch_browser(&final_profile, url).await
// 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
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())
}
_ => {
println!(
"Falling back to new instance for browser: {}",
final_profile.browser
);
// Fallback to launching a new instance for other browsers
self.launch_browser(&final_profile, url).await
}
}
}
}
} else {
// This case shouldn't happen since we checked is_some() above, but handle it gracefully
println!("URL was unexpectedly None, launching new browser instance");
self.launch_browser(&final_profile, url).await
}
} else {
// Browser is not running or no URL provided, launch new instance
@@ -1249,7 +1231,7 @@ end try
.iter()
.any(|p| p.name.to_lowercase() == new_name.to_lowercase())
{
return Err(format!("Profile with name '{}' already exists", new_name).into());
return Err(format!("Profile with name '{new_name}' already exists").into());
}
// Read the profile
@@ -1400,13 +1382,10 @@ end try
pid, profile.name
);
} else {
println!("PID {} exists but doesn't match our profile path exactly, searching for correct process...", pid);
println!("PID {pid} exists but doesn't match our profile path exactly, searching for correct process...");
}
} else {
println!(
"Stored PID {} no longer exists, searching for browser process...",
pid
);
println!("Stored PID {pid} no longer exists, searching for browser process...");
}
}
@@ -1480,7 +1459,7 @@ end try
if inner_profile.process_id != Some(pid) {
inner_profile.process_id = Some(pid);
if let Err(e) = self.save_process_info(&inner_profile) {
println!("Warning: Failed to update process info: {}", e);
println!("Warning: Failed to update process info: {e}");
} else {
println!(
"Updated process ID for profile '{}' to: {}",
@@ -1495,7 +1474,7 @@ end try
if inner_profile.process_id.is_some() {
inner_profile.process_id = None;
if let Err(e) = self.save_process_info(&inner_profile) {
println!("Warning: Failed to clear process info: {}", e);
println!("Warning: Failed to clear process info: {e}");
} else {
println!("Cleared process ID for profile '{}'", inner_profile.name);
}
@@ -1616,11 +1595,11 @@ end try
found_pid.ok_or("Browser process not found")?
};
println!("Attempting to kill browser process with PID: {}", pid);
println!("Attempting to kill browser process with PID: {pid}");
// Stop any associated proxy first
if let Err(e) = PROXY_MANAGER.stop_proxy(app_handle, pid).await {
println!("Warning: Failed to stop proxy for PID {}: {}", pid, e);
println!("Warning: Failed to stop proxy for PID {pid}: {e}");
}
// Kill the process
@@ -1632,7 +1611,7 @@ end try
let output = Command::new("kill")
.args(["-TERM", &pid.to_string()])
.output()
.map_err(|e| format!("Failed to execute kill command: {}", e))?;
.map_err(|e| format!("Failed to execute kill command: {e}"))?;
if !output.status.success() {
// If SIGTERM fails, try SIGKILL (force kill)
@@ -1671,9 +1650,9 @@ end try
updated_profile.process_id = None;
self
.save_process_info(&updated_profile)
.map_err(|e| format!("Failed to update profile: {}", e))?;
.map_err(|e| format!("Failed to update profile: {e}"))?;
println!("Successfully killed browser process with PID: {}", pid);
println!("Successfully killed browser process with PID: {pid}");
Ok(())
}
}
@@ -1688,7 +1667,7 @@ pub fn create_browser_profile(
let browser_runner = BrowserRunner::new();
browser_runner
.create_profile(&name, &browser, &version, proxy)
.map_err(|e| format!("Failed to create profile: {}", e))
.map_err(|e| format!("Failed to create profile: {e}"))
}
#[tauri::command]
@@ -1696,7 +1675,7 @@ pub fn list_browser_profiles() -> Result<Vec<BrowserProfile>, String> {
let browser_runner = BrowserRunner::new();
browser_runner
.list_profiles()
.map_err(|e| format!("Failed to list profiles: {}", e))
.map_err(|e| format!("Failed to list profiles: {e}"))
}
#[tauri::command]
@@ -1734,10 +1713,10 @@ pub async fn launch_browser_profile(
// Apply the proxy settings with the internal proxy
browser_runner
.apply_proxy_settings_to_profile(&profile_path, proxy, Some(&internal_proxy_settings))
.map_err(|e| format!("Failed to update profile proxy: {}", e))?;
.map_err(|e| format!("Failed to update profile proxy: {e}"))?;
}
Err(e) => {
eprintln!("Failed to start proxy: {}", e);
eprintln!("Failed to start proxy: {e}");
// Continue without proxy
}
}
@@ -1765,7 +1744,7 @@ pub fn update_profile_proxy(
let browser_runner = BrowserRunner::new();
browser_runner
.update_profile_proxy(&profile_name, proxy)
.map_err(|e| format!("Failed to update profile: {}", e))
.map_err(|e| format!("Failed to update profile: {e}"))
}
#[tauri::command]
@@ -1776,7 +1755,7 @@ pub fn update_profile_version(
let browser_runner = BrowserRunner::new();
browser_runner
.update_profile_version(&profile_name, &version)
.map_err(|e| format!("Failed to update profile version: {}", e))
.map_err(|e| format!("Failed to update profile version: {e}"))
}
#[tauri::command]
@@ -1788,7 +1767,7 @@ pub async fn check_browser_status(
browser_runner
.check_browser_status(app_handle, &profile)
.await
.map_err(|e| format!("Failed to check browser status: {}", e))
.map_err(|e| format!("Failed to check browser status: {e}"))
}
#[tauri::command]
@@ -1800,7 +1779,7 @@ pub fn rename_profile(
let browser_runner = BrowserRunner::new();
browser_runner
.rename_profile(old_name, new_name)
.map_err(|e| format!("Failed to delete profile: {}", e))
.map_err(|e| format!("Failed to delete profile: {e}"))
}
#[tauri::command]
@@ -1808,7 +1787,7 @@ pub fn delete_profile(_app_handle: tauri::AppHandle, profile_name: String) -> Re
let browser_runner = BrowserRunner::new();
browser_runner
.delete_profile(profile_name.as_str())
.map_err(|e| format!("Failed to delete profile: {}", e))
.map_err(|e| format!("Failed to delete profile: {e}"))
}
#[tauri::command]
@@ -1832,7 +1811,7 @@ pub async fn fetch_browser_versions_detailed(
service
.fetch_browser_versions_detailed(&browser_str, false)
.await
.map_err(|e| format!("Failed to fetch detailed browser versions: {}", e))
.map_err(|e| format!("Failed to fetch detailed browser versions: {e}"))
}
#[tauri::command]
@@ -1853,10 +1832,7 @@ pub async fn fetch_browser_versions_cached_first(
.fetch_browser_versions_detailed(&browser_str_clone, false)
.await
{
eprintln!(
"Background version update failed for {}: {}",
browser_str_clone, e
);
eprintln!("Background version update failed for {browser_str_clone}: {e}");
}
});
}
@@ -1866,7 +1842,7 @@ pub async fn fetch_browser_versions_cached_first(
service
.fetch_browser_versions_detailed(&browser_str, false)
.await
.map_err(|e| format!("Failed to fetch detailed browser versions: {}", e))
.map_err(|e| format!("Failed to fetch detailed browser versions: {e}"))
}
}
@@ -1888,10 +1864,7 @@ pub async fn fetch_browser_versions_with_count_cached_first(
.fetch_browser_versions_with_count(&browser_str_clone, false)
.await
{
eprintln!(
"Background version update failed for {}: {}",
browser_str_clone, e
);
eprintln!("Background version update failed for {browser_str_clone}: {e}");
}
});
}
@@ -1907,7 +1880,7 @@ pub async fn fetch_browser_versions_with_count_cached_first(
service
.fetch_browser_versions_with_count(&browser_str, false)
.await
.map_err(|e| format!("Failed to fetch browser versions: {}", e))
.map_err(|e| format!("Failed to fetch browser versions: {e}"))
}
}
@@ -1933,12 +1906,12 @@ pub async fn download_browser(
) -> Result<String, String> {
let browser_runner = BrowserRunner::new();
let browser_type =
BrowserType::from_str(&browser_str).map_err(|e| format!("Invalid browser type: {}", e))?;
BrowserType::from_str(&browser_str).map_err(|e| format!("Invalid browser type: {e}"))?;
let browser = create_browser(browser_type.clone());
// Load registry and check if already downloaded
let mut registry = DownloadedBrowsersRegistry::load()
.map_err(|e| format!("Failed to load browser registry: {}", e))?;
.map_err(|e| format!("Failed to load browser registry: {e}"))?;
if registry.is_browser_downloaded(&browser_str, &version) {
return Ok(version);
@@ -1948,7 +1921,7 @@ pub async fn download_browser(
let version_service = BrowserVersionService::new();
let download_info = version_service
.get_download_info(&browser_str, &version)
.map_err(|e| format!("Failed to get download info: {}", e))?;
.map_err(|e| format!("Failed to get download info: {e}"))?;
// Create browser directory
let mut browser_dir = browser_runner.get_binaries_dir();
@@ -1957,16 +1930,16 @@ pub async fn download_browser(
// Clean up any failed previous download
if let Err(e) = registry.cleanup_failed_download(&browser_str, &version) {
println!("Warning: Failed to cleanup previous download: {}", e);
println!("Warning: Failed to cleanup previous download: {e}");
}
create_dir_all(&browser_dir).map_err(|e| format!("Failed to create browser directory: {}", e))?;
create_dir_all(&browser_dir).map_err(|e| format!("Failed to create browser directory: {e}"))?;
// Mark download as started in registry
registry.mark_download_started(&browser_str, &version, browser_dir.clone());
registry
.save()
.map_err(|e| format!("Failed to save registry: {}", e))?;
.map_err(|e| format!("Failed to save registry: {e}"))?;
// Use the new download module
let downloader = Downloader::new();
@@ -1985,7 +1958,7 @@ pub async fn download_browser(
// Clean up failed download
let _ = registry.cleanup_failed_download(&browser_str, &version);
let _ = registry.save();
return Err(format!("Failed to download browser: {}", e));
return Err(format!("Failed to download browser: {e}"));
}
};
@@ -2005,14 +1978,14 @@ pub async fn download_browser(
Ok(_) => {
// Clean up the downloaded archive
if let Err(e) = std::fs::remove_file(&download_path) {
println!("Warning: Could not delete archive file: {}", e);
println!("Warning: Could not delete archive file: {e}");
}
}
Err(e) => {
// Clean up failed download
let _ = registry.cleanup_failed_download(&browser_str, &version);
let _ = registry.save();
return Err(format!("Failed to extract browser: {}", e));
return Err(format!("Failed to extract browser: {e}"));
}
}
@@ -2034,10 +2007,7 @@ pub async fn download_browser(
let _ = app_handle.emit("download-progress", &progress);
// Verify the browser was downloaded correctly
println!(
"Verifying download for browser: {}, version: {}",
browser_str, version
);
println!("Verifying download for browser: {browser_str}, version: {version}");
// Use the browser's own verification method
let binaries_dir = browser_runner.get_binaries_dir();
@@ -2056,10 +2026,10 @@ pub async fn download_browser(
registry
.mark_download_completed_with_actual_version(&browser_str, &version, actual_version)
.map_err(|e| format!("Failed to mark download as completed: {}", e))?;
.map_err(|e| format!("Failed to mark download as completed: {e}"))?;
registry
.save()
.map_err(|e| format!("Failed to save registry: {}", e))?;
.map_err(|e| format!("Failed to save registry: {e}"))?;
// Emit completion
let progress = DownloadProgress {
@@ -2106,7 +2076,7 @@ pub async fn kill_browser_profile(
browser_runner
.kill_browser_process(app_handle, &profile)
.await
.map_err(|e| format!("Failed to kill browser: {}", e))
.map_err(|e| format!("Failed to kill browser: {e}"))
}
#[tauri::command]
@@ -2117,7 +2087,7 @@ pub fn create_browser_profile_new(
proxy: Option<ProxySettings>,
) -> Result<BrowserProfile, String> {
let browser_type =
BrowserType::from_str(&browser_str).map_err(|e| format!("Invalid browser type: {}", e))?;
BrowserType::from_str(&browser_str).map_err(|e| format!("Invalid browser type: {e}"))?;
create_browser_profile(name, browser_type.as_str().to_string(), version, proxy)
}
@@ -2127,7 +2097,7 @@ pub async fn fetch_browser_versions(browser_str: String) -> Result<Vec<String>,
service
.fetch_browser_versions(&browser_str, false)
.await
.map_err(|e| format!("Failed to fetch browser versions: {}", e))
.map_err(|e| format!("Failed to fetch browser versions: {e}"))
}
#[tauri::command]
@@ -2138,13 +2108,13 @@ pub async fn fetch_browser_versions_with_count(
service
.fetch_browser_versions_with_count(&browser_str, false)
.await
.map_err(|e| format!("Failed to fetch browser versions: {}", e))
.map_err(|e| format!("Failed to fetch browser versions: {e}"))
}
#[tauri::command]
pub fn get_downloaded_browser_versions(browser_str: String) -> Result<Vec<String>, String> {
let registry = DownloadedBrowsersRegistry::load()
.map_err(|e| format!("Failed to load browser registry: {}", e))?;
.map_err(|e| format!("Failed to load browser registry: {e}"))?;
Ok(registry.get_downloaded_versions(&browser_str))
}
+35 -43
View File
@@ -101,7 +101,7 @@ impl BrowserVersionService {
"brave" => self.fetch_brave_versions(true).await?,
"chromium" => self.fetch_chromium_versions(true).await?,
"tor-browser" => self.fetch_tor_versions(true).await?,
_ => return Err(format!("Unsupported browser: {}", browser).into()),
_ => return Err(format!("Unsupported browser: {browser}").into()),
};
let fresh_set: HashSet<String> = fresh_versions.into_iter().collect();
@@ -126,7 +126,7 @@ impl BrowserVersionService {
.api_client
.save_cached_versions(browser, &merged_versions)
{
eprintln!("Failed to save merged cache for {}: {}", browser, e);
eprintln!("Failed to save merged cache for {browser}: {e}");
}
}
@@ -304,7 +304,7 @@ impl BrowserVersionService {
})
.collect()
}
_ => return Err(format!("Unsupported browser: {}", browser).into()),
_ => return Err(format!("Unsupported browser: {browser}").into()),
};
Ok(detailed_info)
@@ -338,7 +338,7 @@ impl BrowserVersionService {
// Save the updated cache
if let Err(e) = self.api_client.save_cached_versions(browser, &all_versions) {
eprintln!("Failed to save updated cache for {}: {}", browser, e);
eprintln!("Failed to save updated cache for {browser}: {e}");
}
Ok(new_versions_count)
@@ -352,29 +352,27 @@ impl BrowserVersionService {
) -> Result<DownloadInfo, Box<dyn std::error::Error + Send + Sync>> {
match browser {
"firefox" => Ok(DownloadInfo {
url: format!("https://download.mozilla.org/?product=firefox-{}&os=osx&lang=en-US", version),
filename: format!("firefox-{}.dmg", version),
url: format!("https://download.mozilla.org/?product=firefox-{version}&os=osx&lang=en-US"),
filename: format!("firefox-{version}.dmg"),
is_archive: true,
}),
"firefox-developer" => Ok(DownloadInfo {
url: format!("https://download.mozilla.org/?product=devedition-{}&os=osx&lang=en-US", version),
filename: format!("firefox-developer-{}.dmg", version),
url: format!("https://download.mozilla.org/?product=devedition-{version}&os=osx&lang=en-US"),
filename: format!("firefox-developer-{version}.dmg"),
is_archive: true,
}),
"mullvad-browser" => Ok(DownloadInfo {
url: format!(
"https://github.com/mullvad/mullvad-browser/releases/download/{}/mullvad-browser-macos-{}.dmg",
version, version
"https://github.com/mullvad/mullvad-browser/releases/download/{version}/mullvad-browser-macos-{version}.dmg"
),
filename: format!("mullvad-browser-{}.dmg", version),
filename: format!("mullvad-browser-{version}.dmg"),
is_archive: true,
}),
"zen" => Ok(DownloadInfo {
url: format!(
"https://github.com/zen-browser/desktop/releases/download/{}/zen.macos-universal.dmg",
version
"https://github.com/zen-browser/desktop/releases/download/{version}/zen.macos-universal.dmg"
),
filename: format!("zen-{}.dmg", version),
filename: format!("zen-{version}.dmg"),
is_archive: true,
}),
"brave" => {
@@ -382,10 +380,9 @@ impl BrowserVersionService {
// The actual URL will be resolved in the download service using the GitHub API
Ok(DownloadInfo {
url: format!(
"https://github.com/brave/brave-browser/releases/download/{}/Brave-Browser-universal.dmg",
version
"https://github.com/brave/brave-browser/releases/download/{version}/Brave-Browser-universal.dmg"
),
filename: format!("brave-{}.dmg", version),
filename: format!("brave-{version}.dmg"),
is_archive: true,
})
}
@@ -393,22 +390,20 @@ impl BrowserVersionService {
let arch = if cfg!(target_arch = "aarch64") { "Mac_Arm" } else { "Mac" };
Ok(DownloadInfo {
url: format!(
"https://commondatastorage.googleapis.com/chromium-browser-snapshots/{}/{}/chrome-mac.zip",
arch, version
"https://commondatastorage.googleapis.com/chromium-browser-snapshots/{arch}/{version}/chrome-mac.zip"
),
filename: format!("chromium-{}.zip", version),
filename: format!("chromium-{version}.zip"),
is_archive: true,
})
}
"tor-browser" => Ok(DownloadInfo {
url: format!(
"https://archive.torproject.org/tor-package-archive/torbrowser/{}/tor-browser-macos-{}.dmg",
version, version
"https://archive.torproject.org/tor-package-archive/torbrowser/{version}/tor-browser-macos-{version}.dmg"
),
filename: format!("tor-browser-{}.dmg", version),
filename: format!("tor-browser-{version}.dmg"),
is_archive: true,
}),
_ => Err(format!("Unsupported browser: {}", browser).into()),
_ => Err(format!("Unsupported browser: {browser}").into()),
}
}
@@ -567,8 +562,8 @@ mod tests {
if let Ok(versions) = result_cached {
assert!(!versions.is_empty(), "Should have Firefox versions");
println!(
"Firefox cached test passed. Found {} versions",
versions.len()
"Firefox cached test passed. Found {versions_count} versions",
versions_count = versions.len()
);
}
@@ -588,8 +583,8 @@ mod tests {
"Should have Firefox versions without caching"
);
println!(
"Firefox no-cache test passed. Found {} versions",
versions.len()
"Firefox no-cache test passed. Found {versions_count} versions",
versions_count = versions.len()
);
}
}
@@ -611,8 +606,9 @@ mod tests {
"Total count should match versions length"
);
println!(
"Firefox count test passed. Found {} versions, new: {:?}",
result.total_versions_count, result.new_versions_count
"Firefox count test passed. Found {} versions, new: {}",
result.total_versions_count,
result.new_versions_count.unwrap_or(0)
);
}
}
@@ -636,8 +632,8 @@ mod tests {
"Version should not be empty"
);
println!(
"Firefox detailed test passed. Found {} detailed versions",
versions.len()
"Firefox detailed test passed. Found {versions_count} detailed versions",
versions_count = versions.len()
);
}
}
@@ -672,17 +668,10 @@ mod tests {
// The test should complete without panicking
match result {
Ok(count) => {
println!(
"Incremental update test passed. Found {} new versions",
count
);
println!("Incremental update test passed. Found {count} new versions");
}
Err(e) => {
println!(
"Incremental update test failed (expected for first run): {}",
e
);
// Don't fail the test, as this is expected behavior for first run
println!("Incremental update test failed (expected for first run): {e}");
}
}
}
@@ -706,11 +695,14 @@ mod tests {
match result {
Ok(versions) => {
println!("{} test passed. Found {} versions", browser, versions.len());
println!(
"{browser} test passed. Found {versions_count} versions",
versions_count = versions.len()
);
}
Err(e) => {
// Some browsers might fail due to network issues, but shouldn't panic
println!("{} test failed (network issue): {}", browser, e);
println!("{browser} test failed (network issue): {e}");
}
}
+9 -14
View File
@@ -49,12 +49,10 @@ mod macos {
if status != 0 {
let error_msg = match status {
-54 => format!(
"Failed to set as default browser for scheme '{}'. The app is not properly registered as a browser. Please:\n1. Build and install the app properly\n2. Manually set Donut Browser as default in System Settings > General > Default web browser\n3. Make sure the app is in your Applications folder",
scheme
"Failed to set as default browser for scheme '{scheme}'. The app is not properly registered as a browser. Please:\n1. Build and install the app properly\n2. Manually set Donut Browser as default in System Settings > General > Default web browser\n3. Make sure the app is in your Applications folder"
),
_ => format!(
"Failed to set as default browser for scheme '{}'. Status code: {}. Please manually set Donut Browser as default in System Settings > General > Default web browser.",
scheme, status
"Failed to set as default browser for scheme '{scheme}'. Status code: {status}. Please manually set Donut Browser as default in System Settings > General > Default web browser."
)
};
return Err(error_msg);
@@ -132,27 +130,24 @@ pub async fn open_url_with_profile(
// Get the profile by name
let profiles = runner
.list_profiles()
.map_err(|e| format!("Failed to list profiles: {}", e))?;
.map_err(|e| format!("Failed to list profiles: {e}"))?;
let profile = profiles
.into_iter()
.find(|p| p.name == profile_name)
.ok_or_else(|| format!("Profile '{}' not found", profile_name))?;
.ok_or_else(|| format!("Profile '{profile_name}' not found"))?;
println!("Opening URL '{}' with profile '{}'", url, profile_name);
println!("Opening URL '{url}' with profile '{profile_name}'");
// Use launch_or_open_url which handles both launching new instances and opening in existing ones
runner
.launch_or_open_url(app_handle, &profile, Some(url.clone()))
.await
.map_err(|e| {
println!("Failed to open URL with profile '{}': {}", profile_name, e);
format!("Failed to open URL with profile: {}", e)
println!("Failed to open URL with profile '{profile_name}': {e}");
format!("Failed to open URL with profile: {e}")
})?;
println!(
"Successfully opened URL '{}' with profile '{}'",
url, profile_name
);
println!("Successfully opened URL '{url}' with profile '{profile_name}'");
Ok(())
}
@@ -169,7 +164,7 @@ pub async fn smart_open_url(
// Get all profiles
let profiles = runner
.list_profiles()
.map_err(|e| format!("Failed to list profiles: {}", e))?;
.map_err(|e| format!("Failed to list profiles: {e}"))?;
if profiles.is_empty() {
return Err("no_profiles".to_string());
+18 -30
View File
@@ -52,7 +52,7 @@ impl Downloader {
.find(|r| {
r.tag_name == version || r.tag_name == format!("v{}", version.trim_start_matches('v'))
})
.ok_or(format!("Brave version {} not found", version))?;
.ok_or(format!("Brave version {version} not found"))?;
// Find the universal macOS DMG asset
let asset = release
@@ -60,8 +60,7 @@ impl Downloader {
.iter()
.find(|asset| asset.name.contains(".dmg") && asset.name.contains("universal"))
.ok_or(format!(
"No universal macOS DMG asset found for Brave version {}",
version
"No universal macOS DMG asset found for Brave version {version}"
))?;
Ok(asset.browser_download_url.clone())
@@ -73,7 +72,7 @@ impl Downloader {
let release = releases
.iter()
.find(|r| r.tag_name == version)
.ok_or(format!("Zen version {} not found", version))?;
.ok_or(format!("Zen version {version} not found"))?;
// Find the macOS universal DMG asset
let asset = release
@@ -81,8 +80,7 @@ impl Downloader {
.iter()
.find(|asset| asset.name == "zen.macos-universal.dmg")
.ok_or(format!(
"No macOS universal asset found for Zen version {}",
version
"No macOS universal asset found for Zen version {version}"
))?;
Ok(asset.browser_download_url.clone())
@@ -94,7 +92,7 @@ impl Downloader {
let release = releases
.iter()
.find(|r| r.tag_name == version)
.ok_or(format!("Mullvad version {} not found", version))?;
.ok_or(format!("Mullvad version {version} not found"))?;
// Find the macOS DMG asset
let asset = release
@@ -102,8 +100,7 @@ impl Downloader {
.iter()
.find(|asset| asset.name.contains(".dmg") && asset.name.contains("mac"))
.ok_or(format!(
"No macOS asset found for Mullvad version {}",
version
"No macOS asset found for Mullvad version {version}"
))?;
Ok(asset.browser_download_url.clone())
@@ -230,13 +227,10 @@ mod tests {
assert!(url.contains("github.com/brave/brave-browser"));
assert!(url.contains(".dmg"));
assert!(url.contains("universal"));
println!("Brave download URL resolved: {}", url);
println!("Brave download URL resolved: {url}");
}
Err(e) => {
println!(
"Brave URL resolution failed (expected if version doesn't exist): {}",
e
);
println!("Brave URL resolution failed (expected if version doesn't exist): {e}");
// This might fail if the version doesn't exist, which is okay for testing
}
}
@@ -260,13 +254,10 @@ mod tests {
Ok(url) => {
assert!(url.contains("github.com/zen-browser/desktop"));
assert!(url.contains("zen.macos-universal.dmg"));
println!("Zen download URL resolved: {}", url);
println!("Zen download URL resolved: {url}");
}
Err(e) => {
println!(
"Zen URL resolution failed (expected if version doesn't exist): {}",
e
);
println!("Zen URL resolution failed (expected if version doesn't exist): {e}");
}
}
}
@@ -289,13 +280,10 @@ mod tests {
Ok(url) => {
assert!(url.contains("github.com/mullvad/mullvad-browser"));
assert!(url.contains(".dmg"));
println!("Mullvad download URL resolved: {}", url);
println!("Mullvad download URL resolved: {url}");
}
Err(e) => {
println!(
"Mullvad URL resolution failed (expected if version doesn't exist): {}",
e
);
println!("Mullvad URL resolution failed (expected if version doesn't exist): {e}");
}
}
}
@@ -317,10 +305,10 @@ mod tests {
match result {
Ok(url) => {
assert_eq!(url, download_info.url);
println!("Firefox download URL (passthrough): {}", url);
println!("Firefox download URL (passthrough): {url}");
}
Err(e) => {
panic!("Firefox URL resolution should not fail: {}", e);
panic!("Firefox URL resolution should not fail: {e}");
}
}
}
@@ -342,10 +330,10 @@ mod tests {
match result {
Ok(url) => {
assert_eq!(url, download_info.url);
println!("Chromium download URL (passthrough): {}", url);
println!("Chromium download URL (passthrough): {url}");
}
Err(e) => {
panic!("Chromium URL resolution should not fail: {}", e);
panic!("Chromium URL resolution should not fail: {e}");
}
}
}
@@ -367,10 +355,10 @@ mod tests {
match result {
Ok(url) => {
assert_eq!(url, download_info.url);
println!("TOR download URL (passthrough): {}", url);
println!("TOR download URL (passthrough): {url}");
}
Err(e) => {
panic!("TOR URL resolution should not fail: {}", e);
panic!("TOR URL resolution should not fail: {e}");
}
}
}
+1 -4
View File
@@ -127,10 +127,7 @@ impl DownloadedBrowsersRegistry {
info.actual_version = actual_version;
Ok(())
} else {
Err(format!(
"Browser {}:{} not found in registry",
browser, version
))
Err(format!("Browser {browser}:{version} not found in registry"))
}
}
+1 -1
View File
@@ -42,7 +42,7 @@ impl Extractor {
match extension {
"dmg" => self.extract_dmg(archive_path, dest_dir).await,
"zip" => self.extract_zip(archive_path, dest_dir).await,
_ => Err(format!("Unsupported archive format: {}", extension).into()),
_ => Err(format!("Unsupported archive format: {extension}").into()),
}
}
+8 -8
View File
@@ -56,12 +56,12 @@ use auto_updater::{
fn greet() -> String {
let now = SystemTime::now();
let epoch_ms = now.duration_since(UNIX_EPOCH).unwrap().as_millis();
format!("Hello world from Rust! Current epoch: {}", epoch_ms)
format!("Hello world from Rust! Current epoch: {epoch_ms}")
}
#[tauri::command]
async fn handle_url_open(app: tauri::AppHandle, url: String) -> Result<(), String> {
println!("handle_url_open called with URL: {}", url);
println!("handle_url_open called with URL: {url}");
// Check if the main window exists and is ready
if let Some(window) = app.get_webview_window("main") {
@@ -70,7 +70,7 @@ async fn handle_url_open(app: tauri::AppHandle, url: String) -> Result<(), Strin
println!("Main window is visible, emitting show-profile-selector event");
app
.emit("show-profile-selector", url.clone())
.map_err(|e| format!("Failed to emit URL open event: {}", e))?;
.map_err(|e| format!("Failed to emit URL open event: {e}"))?;
let _ = window.show();
let _ = window.set_focus();
} else {
@@ -105,10 +105,10 @@ async fn check_and_handle_startup_url(app_handle: tauri::AppHandle) -> Result<bo
);
for url in pending_urls {
println!("Emitting show-profile-selector event for URL: {}", url);
println!("Emitting show-profile-selector event for URL: {url}");
if let Err(e) = app_handle.emit("show-profile-selector", url.clone()) {
eprintln!("Failed to emit URL event: {}", e);
return Err(format!("Failed to emit URL event: {}", e));
eprintln!("Failed to emit URL event: {e}");
return Err(format!("Failed to emit URL event: {e}"));
}
}
@@ -144,7 +144,7 @@ pub fn run() {
let urls = event.urls();
for url in urls {
let url_string = url.to_string();
println!("Deep link received: {}", url_string);
println!("Deep link received: {url_string}");
// Clone the handle for each async task
let handle_clone = handle.clone();
@@ -152,7 +152,7 @@ pub fn run() {
// Handle the URL asynchronously
tauri::async_runtime::spawn(async move {
if let Err(e) = handle_url_open(handle_clone, url_string.clone()).await {
eprintln!("Failed to handle deep link URL: {}", e);
eprintln!("Failed to handle deep link URL: {e}");
}
});
}
+6 -6
View File
@@ -78,15 +78,15 @@ impl ProxyManager {
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(format!("Proxy start failed: {}", stderr));
return Err(format!("Proxy start failed: {stderr}"));
}
let json_string = String::from_utf8(output.stdout)
.map_err(|e| format!("Failed to parse proxy output: {}", e))?;
let json_string =
String::from_utf8(output.stdout).map_err(|e| format!("Failed to parse proxy output: {e}"))?;
// Parse the JSON output
let json: Value =
serde_json::from_str(&json_string).map_err(|e| format!("Failed to parse JSON: {}", e))?;
serde_json::from_str(&json_string).map_err(|e| format!("Failed to parse JSON: {e}"))?;
// Extract proxy information
let id = json["id"].as_str().ok_or("Missing proxy ID")?;
@@ -146,7 +146,7 @@ impl ProxyManager {
let nodecar = app_handle
.shell()
.sidecar("nodecar")
.map_err(|e| format!("Failed to create sidecar: {}", e))?
.map_err(|e| format!("Failed to create sidecar: {e}"))?
.arg("proxy")
.arg("stop")
.arg("--id")
@@ -156,7 +156,7 @@ impl ProxyManager {
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
eprintln!("Proxy stop error: {}", stderr);
eprintln!("Proxy stop error: {stderr}");
// We still return Ok since we've already removed the proxy from our tracking
}
+9 -15
View File
@@ -98,23 +98,17 @@ impl SettingsManager {
Ok(settings) => {
// Save the settings back to ensure any missing fields are written with defaults
if let Err(e) = self.save_settings(&settings) {
eprintln!(
"Warning: Failed to update settings file with defaults: {}",
e
);
eprintln!("Warning: Failed to update settings file with defaults: {e}");
}
Ok(settings)
}
Err(e) => {
eprintln!(
"Warning: Failed to parse settings file, using defaults: {}",
e
);
eprintln!("Warning: Failed to parse settings file, using defaults: {e}");
let default_settings = AppSettings::default();
// Try to save default settings to fix the corrupted file
if let Err(save_error) = self.save_settings(&default_settings) {
eprintln!("Warning: Failed to save default settings: {}", save_error);
eprintln!("Warning: Failed to save default settings: {save_error}");
}
Ok(default_settings)
@@ -183,7 +177,7 @@ pub async fn get_app_settings() -> Result<AppSettings, String> {
let manager = SettingsManager::new();
manager
.load_settings()
.map_err(|e| format!("Failed to load settings: {}", e))
.map_err(|e| format!("Failed to load settings: {e}"))
}
#[tauri::command]
@@ -191,7 +185,7 @@ pub async fn save_app_settings(settings: AppSettings) -> Result<(), String> {
let manager = SettingsManager::new();
manager
.save_settings(&settings)
.map_err(|e| format!("Failed to save settings: {}", e))
.map_err(|e| format!("Failed to save settings: {e}"))
}
#[tauri::command]
@@ -199,7 +193,7 @@ pub async fn should_show_settings_on_startup() -> Result<bool, String> {
let manager = SettingsManager::new();
manager
.should_show_settings_on_startup()
.map_err(|e| format!("Failed to check prompt setting: {}", e))
.map_err(|e| format!("Failed to check prompt setting: {e}"))
}
#[tauri::command]
@@ -207,7 +201,7 @@ pub async fn disable_default_browser_prompt() -> Result<(), String> {
let manager = SettingsManager::new();
manager
.disable_default_browser_prompt()
.map_err(|e| format!("Failed to disable prompt: {}", e))
.map_err(|e| format!("Failed to disable prompt: {e}"))
}
#[tauri::command]
@@ -215,7 +209,7 @@ pub async fn get_table_sorting_settings() -> Result<TableSortingSettings, String
let manager = SettingsManager::new();
manager
.load_table_sorting()
.map_err(|e| format!("Failed to load table sorting settings: {}", e))
.map_err(|e| format!("Failed to load table sorting settings: {e}"))
}
#[tauri::command]
@@ -223,5 +217,5 @@ pub async fn save_table_sorting_settings(sorting: TableSortingSettings) -> Resul
let manager = SettingsManager::new();
manager
.save_table_sorting(&sorting)
.map_err(|e| format!("Failed to save table sorting settings: {}", e))
.map_err(|e| format!("Failed to save table sorting settings: {e}"))
}
+14 -20
View File
@@ -174,13 +174,13 @@ impl VersionUpdater {
};
if let Err(e) = Self::save_background_update_state(&state) {
eprintln!("Failed to save background update state: {}", e);
eprintln!("Failed to save background update state: {e}");
} else {
println!("Startup version update completed successfully");
}
}
Err(e) => {
eprintln!("Startup version update failed: {}", e);
eprintln!("Startup version update failed: {e}");
return Err(e);
}
}
@@ -198,7 +198,7 @@ impl VersionUpdater {
// Run initial startup check
if let Err(e) = self.check_and_run_startup_update().await {
eprintln!("Startup version update failed: {}", e);
eprintln!("Startup version update failed: {e}");
}
loop {
@@ -227,13 +227,13 @@ impl VersionUpdater {
};
if let Err(e) = Self::save_background_update_state(&state) {
eprintln!("Failed to save background update state: {}", e);
eprintln!("Failed to save background update state: {e}");
} else {
println!("Background version update completed successfully");
}
}
Err(e) => {
eprintln!("Background version update failed: {}", e);
eprintln!("Background version update failed: {e}");
// Emit error event
let progress = VersionUpdateProgress {
@@ -287,7 +287,7 @@ impl VersionUpdater {
for (index, browser) in browsers.iter().enumerate() {
// Check if individual browser cache is expired before updating
if !self.version_service.should_update_cache(browser) {
println!("Skipping {} - cache is still fresh", browser);
println!("Skipping {browser} - cache is still fresh");
let browser_result = BackgroundUpdateResult {
browser: browser.to_string(),
@@ -300,7 +300,7 @@ impl VersionUpdater {
continue;
}
println!("Updating versions for browser: {}", browser);
println!("Updating versions for browser: {browser}");
// Emit progress for current browser
let progress = VersionUpdateProgress {
@@ -327,10 +327,10 @@ impl VersionUpdater {
};
results.push(browser_result);
println!("Found {} new versions for {}", new_count, browser);
println!("Found {new_count} new versions for {browser}");
}
Err(e) => {
eprintln!("Failed to update versions for {}: {}", browser, e);
eprintln!("Failed to update versions for {browser}: {e}");
let browser_result = BackgroundUpdateResult {
browser: browser.to_string(),
new_versions_count: 0,
@@ -357,10 +357,7 @@ impl VersionUpdater {
};
let _ = app_handle.emit("version-update-progress", &progress);
println!(
"Background version update completed. Found {} new versions total",
total_new_versions
);
println!("Background version update completed. Found {total_new_versions} new versions total");
Ok(results)
}
@@ -388,10 +385,7 @@ impl VersionUpdater {
};
if let Err(e) = Self::save_background_update_state(&state) {
eprintln!(
"Failed to save background update state after manual update: {}",
e
);
eprintln!("Failed to save background update state after manual update: {e}");
}
Ok(results)
@@ -440,7 +434,7 @@ pub async fn trigger_manual_version_update(
updater_guard
.trigger_manual_update(&app_handle)
.await
.map_err(|e| format!("Failed to trigger manual update: {}", e))
.map_err(|e| format!("Failed to trigger manual update: {e}"))
}
#[tauri::command]
@@ -466,7 +460,7 @@ pub async fn force_version_update_check(_app_handle: tauri::AppHandle) -> Result
match updater_guard.check_and_run_startup_update().await {
Ok(_) => Ok(true),
Err(e) => Err(format!("Failed to run version update check: {}", e)),
Err(e) => Err(format!("Failed to run version update check: {e}")),
}
}
@@ -477,7 +471,7 @@ mod tests {
// Helper function to create a unique test state file
fn get_test_state_file(test_name: &str) -> PathBuf {
let cache_dir = VersionUpdater::get_cache_dir().unwrap();
cache_dir.join(format!("test_{}_state.json", test_name))
cache_dir.join(format!("test_{test_name}_state.json"))
}
fn save_test_state(