refactor: add proper logging

This commit is contained in:
zhom
2025-11-26 20:21:17 +04:00
parent bab9301c31
commit 0b63ad6556
28 changed files with 1119 additions and 631 deletions
+1
View File
@@ -45,6 +45,7 @@
"@tauri-apps/plugin-deep-link": "^2.4.5",
"@tauri-apps/plugin-dialog": "^2.4.2",
"@tauri-apps/plugin-fs": "~2.4.4",
"@tauri-apps/plugin-log": "^2.7.1",
"@tauri-apps/plugin-opener": "^2.5.2",
"ahooks": "^3.9.6",
"class-variance-authority": "^0.7.1",
+10
View File
@@ -59,6 +59,9 @@ importers:
'@tauri-apps/plugin-fs':
specifier: ~2.4.4
version: 2.4.4
'@tauri-apps/plugin-log':
specifier: ^2.7.1
version: 2.7.1
'@tauri-apps/plugin-opener':
specifier: ^2.5.2
version: 2.5.2
@@ -1777,6 +1780,9 @@ packages:
'@tauri-apps/plugin-fs@2.4.4':
resolution: {integrity: sha512-MTorXxIRmOnOPT1jZ3w96vjSuScER38ryXY88vl5F0uiKdnvTKKTtaEjTEo8uPbl4e3gnUtfsDVwC7h77GQLvQ==}
'@tauri-apps/plugin-log@2.7.1':
resolution: {integrity: sha512-jdb+o0wxQc8PjnLktgGpOs9Dh1YupaOGDXzO+Y8peA1UZ1ep3eXv4E1oiJ7nIQVN0XUFDDhnn3aBszl8ijhR+A==}
'@tauri-apps/plugin-opener@2.5.2':
resolution: {integrity: sha512-ei/yRRoCklWHImwpCcDK3VhNXx+QXM9793aQ64YxpqVF0BDuuIlXhZgiAkc15wnPVav+IbkYhmDJIv5R326Mew==}
@@ -4398,6 +4404,10 @@ snapshots:
dependencies:
'@tauri-apps/api': 2.9.0
'@tauri-apps/plugin-log@2.7.1':
dependencies:
'@tauri-apps/api': 2.9.0
'@tauri-apps/plugin-opener@2.5.2':
dependencies:
'@tauri-apps/api': 2.9.0
+303
View File
@@ -43,6 +43,17 @@ dependencies = [
"subtle",
]
[[package]]
name = "ahash"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
dependencies = [
"getrandom 0.2.16",
"once_cell",
"version_check",
]
[[package]]
name = "aho-corasick"
version = "1.1.4"
@@ -67,6 +78,23 @@ dependencies = [
"alloc-no-stdlib",
]
[[package]]
name = "android_log-sys"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d"
[[package]]
name = "android_logger"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3"
dependencies = [
"android_log-sys",
"env_filter",
"log",
]
[[package]]
name = "android_system_properties"
version = "0.1.5"
@@ -153,6 +181,12 @@ dependencies = [
"password-hash",
]
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "ashpd"
version = "0.11.0"
@@ -445,6 +479,18 @@ dependencies = [
"serde_core",
]
[[package]]
name = "bitvec"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "blake2"
version = "0.10.6"
@@ -494,6 +540,29 @@ dependencies = [
"piper",
]
[[package]]
name = "borsh"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f"
dependencies = [
"borsh-derive",
"cfg_aliases",
]
[[package]]
name = "borsh-derive"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c"
dependencies = [
"once_cell",
"proc-macro-crate 3.4.0",
"proc-macro2",
"quote",
"syn 2.0.110",
]
[[package]]
name = "brotli"
version = "8.0.2"
@@ -521,6 +590,40 @@ version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
[[package]]
name = "byte-unit"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c6d47a4e2961fb8721bcfc54feae6455f2f64e7054f9bc67e875f0e77f4c58d"
dependencies = [
"rust_decimal",
"schemars 1.1.0",
"serde",
"utf8-width",
]
[[package]]
name = "bytecheck"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2"
dependencies = [
"bytecheck_derive",
"ptr_meta",
"simdutf8",
]
[[package]]
name = "bytecheck_derive"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "bytemuck"
version = "1.24.0"
@@ -1210,6 +1313,7 @@ dependencies = [
"hyper-util",
"lazy_static",
"libc",
"log",
"lzma-rs",
"msi-extract",
"objc2 0.6.3",
@@ -1225,6 +1329,7 @@ dependencies = [
"tauri-plugin-deep-link",
"tauri-plugin-dialog",
"tauri-plugin-fs",
"tauri-plugin-log",
"tauri-plugin-macos-permissions",
"tauri-plugin-opener",
"tauri-plugin-shell",
@@ -1340,6 +1445,16 @@ dependencies = [
"syn 2.0.110",
]
[[package]]
name = "env_filter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2"
dependencies = [
"log",
"regex",
]
[[package]]
name = "equivalent"
version = "1.0.2"
@@ -1403,6 +1518,15 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "fern"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29"
dependencies = [
"log",
]
[[package]]
name = "field-offset"
version = "0.3.6"
@@ -1499,6 +1623,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "futf"
version = "0.1.5"
@@ -1945,6 +2075,9 @@ name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
]
[[package]]
name = "hashbrown"
@@ -2584,6 +2717,9 @@ name = "log"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
dependencies = [
"value-bag",
]
[[package]]
name = "lzma-rs"
@@ -2889,6 +3025,15 @@ dependencies = [
"syn 2.0.110",
]
[[package]]
name = "num_threads"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
dependencies = [
"libc",
]
[[package]]
name = "objc-sys"
version = "0.3.5"
@@ -3679,6 +3824,26 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "ptr_meta"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "quick-xml"
version = "0.37.5"
@@ -3712,6 +3877,12 @@ version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "rand"
version = "0.7.3"
@@ -3897,6 +4068,15 @@ version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
[[package]]
name = "rend"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c"
dependencies = [
"bytecheck",
]
[[package]]
name = "reqwest"
version = "0.12.24"
@@ -3979,6 +4159,35 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "rkyv"
version = "0.7.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b"
dependencies = [
"bitvec",
"bytecheck",
"bytes",
"hashbrown 0.12.3",
"ptr_meta",
"rend",
"rkyv_derive",
"seahash",
"tinyvec",
"uuid",
]
[[package]]
name = "rkyv_derive"
version = "0.7.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "rust-ini"
version = "0.21.3"
@@ -3989,6 +4198,22 @@ dependencies = [
"ordered-multimap",
]
[[package]]
name = "rust_decimal"
version = "1.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282"
dependencies = [
"arrayvec",
"borsh",
"bytes",
"num-traits",
"rand 0.8.5",
"rkyv",
"serde",
"serde_json",
]
[[package]]
name = "rustc_version"
version = "0.4.1"
@@ -4137,6 +4362,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "seahash"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "security-framework"
version = "2.11.1"
@@ -4444,6 +4675,12 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "simdutf8"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "siphasher"
version = "0.3.11"
@@ -4727,6 +4964,12 @@ dependencies = [
"syn 2.0.110",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tar"
version = "0.4.44"
@@ -4936,6 +5179,28 @@ dependencies = [
"url",
]
[[package]]
name = "tauri-plugin-log"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5709c792b8630290b5d9811a1f8fe983dd925fc87c7fc7f4923616458cd00b6"
dependencies = [
"android_logger",
"byte-unit",
"fern",
"log",
"objc2 0.6.3",
"objc2-foundation 0.3.2",
"serde",
"serde_json",
"serde_repr",
"swift-rs",
"tauri",
"tauri-plugin",
"thiserror 2.0.17",
"time",
]
[[package]]
name = "tauri-plugin-macos-permissions"
version = "2.3.0"
@@ -5183,7 +5448,9 @@ checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
dependencies = [
"deranged",
"itoa",
"libc",
"num-conv",
"num_threads",
"powerfmt",
"serde",
"time-core",
@@ -5225,6 +5492,21 @@ dependencies = [
"zerovec",
]
[[package]]
name = "tinyvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.48.0"
@@ -5633,6 +5915,12 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf8-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091"
[[package]]
name = "utf8_iter"
version = "1.0.4"
@@ -5657,6 +5945,12 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "value-bag"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0"
[[package]]
name = "vcpkg"
version = "0.2.15"
@@ -6560,6 +6854,15 @@ dependencies = [
"x11-dl",
]
[[package]]
name = "wyz"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
dependencies = [
"tap",
]
[[package]]
name = "x11"
version = "2.21.0"
+2 -1
View File
@@ -33,7 +33,8 @@ tauri-plugin-shell = "2"
tauri-plugin-deep-link = "2"
tauri-plugin-dialog = "2"
tauri-plugin-macos-permissions = "2"
tauri-plugin-log = "2"
log = "0.4"
directories = "6"
reqwest = { version = "0.12", features = ["json", "stream", "socks"] }
+2 -1
View File
@@ -29,6 +29,7 @@
"macos-permissions:allow-request-microphone-permission",
"macos-permissions:allow-request-camera-permission",
"macos-permissions:allow-check-microphone-permission",
"macos-permissions:allow-check-camera-permission"
"macos-permissions:allow-check-camera-permission",
"log:default"
]
}
+53 -49
View File
@@ -407,8 +407,8 @@ impl ApiClient {
let text = response.text().await?;
let mut page_releases: Vec<GithubRelease> = serde_json::from_str(&text).map_err(|e| {
eprintln!("Failed to parse GitHub API response (page {page}): {e}");
eprintln!(
log::error!("Failed to parse GitHub API response (page {page}): {e}");
log::error!(
"Response text (first 500 chars): {}",
if text.len() > 500 {
&text[..500]
@@ -487,13 +487,13 @@ impl ApiClient {
let content = fs::read_to_string(&cache_file).ok()?;
if let Ok(cached) = serde_json::from_str::<CachedVersionData>(&content) {
// Always return cached releases regardless of age - they're always valid
println!("Using cached versions for {browser}");
log::info!("Using cached versions for {browser}");
return Some(cached.releases);
}
// Backward compatibility: legacy caches stored just an array of version strings
if let Ok(legacy_versions) = serde_json::from_str::<Vec<String>>(&content) {
println!("Using legacy cached versions for {browser}; upgrading in-memory");
log::info!("Using legacy cached versions for {browser}; upgrading in-memory");
let releases: Vec<BrowserRelease> = legacy_versions
.into_iter()
.map(|version| BrowserRelease {
@@ -548,7 +548,7 @@ impl ApiClient {
let content = serde_json::to_string_pretty(&cached_data)?;
fs::write(&cache_file, content)?;
println!("Cached {} versions for {}", releases.len(), browser);
log::info!("Cached {} versions for {}", releases.len(), browser);
Ok(())
}
@@ -564,7 +564,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}");
log::info!("Using cached GitHub releases for {browser}");
Some(cached_data.releases)
}
@@ -588,7 +588,7 @@ impl ApiClient {
let content = serde_json::to_string_pretty(&cached_data)?;
fs::write(&cache_file, content)?;
println!("Cached {} GitHub releases for {}", releases.len(), browser);
log::info!("Cached {} GitHub releases for {}", releases.len(), browser);
Ok(())
}
@@ -603,7 +603,7 @@ impl ApiClient {
}
}
println!("Fetching Firefox releases from Mozilla API...");
log::info!("Fetching Firefox releases from Mozilla API...");
let url = format!("{}/firefox.json", self.firefox_api_base);
let response = self
@@ -648,7 +648,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_versions("firefox", &releases) {
eprintln!("Failed to cache Firefox versions: {e}");
log::error!("Failed to cache Firefox versions: {e}");
}
}
@@ -666,7 +666,7 @@ impl ApiClient {
}
}
println!("Fetching Firefox Developer Edition releases from Mozilla API...");
log::info!("Fetching Firefox Developer Edition releases from Mozilla API...");
let url = format!("{}/devedition.json", self.firefox_dev_api_base);
let response = self
@@ -682,7 +682,7 @@ impl ApiClient {
response.status(),
url
);
eprintln!("{error_msg}");
log::error!("{error_msg}");
return Err(error_msg.into());
}
@@ -717,7 +717,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_versions("firefox-developer", &releases) {
eprintln!("Failed to cache Firefox Developer versions: {e}");
log::error!("Failed to cache Firefox Developer versions: {e}");
}
}
@@ -735,7 +735,7 @@ impl ApiClient {
}
}
println!("Fetching Mullvad releases from GitHub API");
log::info!("Fetching Mullvad releases from GitHub API");
let base_url = format!(
"{}/repos/mullvad/mullvad-browser/releases",
self.github_api_base
@@ -756,7 +756,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}");
log::error!("Failed to cache Mullvad releases: {e}");
}
}
@@ -774,7 +774,7 @@ impl ApiClient {
}
}
println!("Fetching Zen releases from GitHub API");
log::info!("Fetching Zen releases from GitHub API");
let base_url = format!(
"{}/repos/zen-browser/desktop/releases",
self.github_api_base
@@ -792,7 +792,7 @@ impl ApiClient {
if release.tag_name.to_lowercase() == "twilight" {
if let Ok(has_update) = self.check_twilight_update(release).await {
if has_update {
println!(
log::info!(
"Detected update for Zen twilight release: {}",
release.tag_name
);
@@ -807,7 +807,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}");
log::error!("Failed to cache Zen releases: {e}");
}
}
@@ -825,7 +825,7 @@ impl ApiClient {
}
}
println!("Fetching Brave releases from GitHub API");
log::info!("Fetching Brave releases from GitHub API");
let base_url = format!(
"{}/repos/brave/brave-browser/releases",
self.github_api_base
@@ -843,7 +843,7 @@ impl ApiClient {
let has_compatible_asset = Self::has_compatible_brave_asset(&release.assets, &os);
if has_compatible_asset {
println!("release.name: {:?}", release.name);
log::info!("release.name: {:?}", release.name);
// Use the centralized nightly detection function
release.is_nightly =
is_browser_version_nightly("brave", &release.tag_name, Some(&release.name));
@@ -858,7 +858,7 @@ impl ApiClient {
sort_github_releases(&mut filtered_releases);
if let Err(e) = self.save_cached_github_releases("brave", &filtered_releases) {
eprintln!("Failed to cache Brave releases: {e}");
log::error!("Failed to cache Brave releases: {e}");
}
Ok(filtered_releases)
@@ -978,7 +978,7 @@ impl ApiClient {
}
}
println!("Fetching Chromium releases...");
log::info!("Fetching Chromium releases...");
// Get the latest version first
let latest_version = self.fetch_chromium_latest_version().await?;
@@ -1006,7 +1006,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_versions("chromium", &releases) {
eprintln!("Failed to cache Chromium versions: {e}");
log::error!("Failed to cache Chromium versions: {e}");
}
}
@@ -1020,7 +1020,7 @@ impl ApiClient {
// Check cache first (unless bypassing)
if !no_caching {
if let Some(cached_releases) = self.load_cached_github_releases("camoufox") {
println!(
log::info!(
"Using cached Camoufox releases, count: {}",
cached_releases.len()
);
@@ -1028,18 +1028,18 @@ impl ApiClient {
}
}
println!("Fetching Camoufox releases from GitHub API");
log::info!("Fetching Camoufox releases from GitHub API");
let base_url = format!("{}/repos/daijro/camoufox/releases", self.github_api_base);
let releases: Vec<GithubRelease> = self.fetch_github_releases_multiple_pages(&base_url).await?;
println!(
log::info!(
"Fetched {} total Camoufox releases from GitHub",
releases.len()
);
// Get platform info to filter appropriate releases
let (os, arch) = Self::get_platform_info();
println!("Filtering for platform: {os}/{arch}");
log::info!("Filtering for platform: {os}/{arch}");
// Filter releases that have assets compatible with the current platform
let mut compatible_releases: Vec<GithubRelease> = releases
@@ -1048,11 +1048,14 @@ impl ApiClient {
.filter_map(|(i, release)| {
let has_compatible = self.has_compatible_camoufox_asset(&release.assets, &os, &arch);
if !has_compatible {
println!(
log::info!(
"Release {} ({}) has no compatible assets for {}/{}",
i, release.tag_name, os, arch
i,
release.tag_name,
os,
arch
);
println!(
log::info!(
" Available assets: {:?}",
release.assets.iter().map(|a| &a.name).collect::<Vec<_>>()
);
@@ -1065,13 +1068,13 @@ impl ApiClient {
})
.collect();
println!(
log::info!(
"After platform filtering: {} compatible releases",
compatible_releases.len()
);
// Sort by version (latest first) with debugging
println!(
log::info!(
"Before sorting: {:?}",
compatible_releases
.iter()
@@ -1080,7 +1083,7 @@ impl ApiClient {
.collect::<Vec<_>>()
);
sort_github_releases(&mut compatible_releases);
println!(
log::info!(
"After sorting: {:?}",
compatible_releases
.iter()
@@ -1092,9 +1095,9 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_github_releases("camoufox", &compatible_releases) {
eprintln!("Failed to cache Camoufox releases: {e}");
log::error!("Failed to cache Camoufox releases: {e}");
} else {
println!("Cached {} Camoufox releases", compatible_releases.len());
log::info!("Cached {} Camoufox releases", compatible_releases.len());
}
}
@@ -1112,7 +1115,7 @@ impl ApiClient {
}
}
println!("Fetching TOR releases from archive...");
log::info!("Fetching TOR releases from archive...");
let url = format!("{}/", self.tor_archive_base);
let html = self
.client
@@ -1177,7 +1180,7 @@ impl ApiClient {
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_versions("tor-browser", &releases) {
eprintln!("Failed to cache TOR versions: {e}");
log::error!("Failed to cache TOR versions: {e}");
}
}
@@ -1248,9 +1251,10 @@ impl ApiClient {
// File size changed, update cache and return true
let content = serde_json::to_string_pretty(&current_info)?;
fs::write(&twilight_cache_file, content)?;
println!(
log::info!(
"Zen twilight release updated: file size changed from {} to {}",
cached_info.file_size, current_info.file_size
cached_info.file_size,
current_info.file_size
);
return Ok(true);
}
@@ -1268,10 +1272,10 @@ impl ApiClient {
let path = entry.path();
if path.is_file() {
fs::remove_file(&path)?;
println!("Removed cache file: {path:?}");
log::info!("Removed cache file: {path:?}");
}
}
println!("All version cache cleared successfully");
log::info!("All version cache cleared successfully");
}
Ok(())
@@ -1474,7 +1478,7 @@ mod tests {
let result = client.fetch_firefox_releases_with_caching(true).await;
if let Err(e) = &result {
println!("Firefox API test error: {e}");
log::info!("Firefox API test error: {e}");
}
assert!(result.is_ok());
let releases = result.unwrap();
@@ -1516,7 +1520,7 @@ mod tests {
.await;
if let Err(e) = &result {
println!("Firefox Developer API test error: {e}");
log::info!("Firefox Developer API test error: {e}");
}
assert!(result.is_ok());
let releases = result.unwrap();
@@ -1651,7 +1655,7 @@ mod tests {
let result = client.fetch_brave_releases_with_caching(true).await;
if let Err(e) = &result {
println!("Brave API test error: {e}");
log::info!("Brave API test error: {e}");
}
assert!(result.is_ok());
let releases = result.unwrap();
@@ -1992,8 +1996,8 @@ mod tests {
let v22 = VersionComponent::parse("135.0.5beta22");
let v24 = VersionComponent::parse("135.0.5beta24");
println!("v22: {v22:?}");
println!("v24: {v24:?}");
log::info!("v22: {v22:?}");
log::info!("v24: {v24:?}");
// v24 should be greater than v22
assert!(
@@ -2016,7 +2020,7 @@ mod tests {
sort_versions(&mut versions);
println!("Sorted versions: {versions:?}");
log::info!("Sorted versions: {versions:?}");
// Should be sorted from newest to oldest
assert_eq!(versions[0], "135.0.5beta24");
@@ -2031,8 +2035,8 @@ mod tests {
let v22 = VersionComponent::parse("135.0beta22");
let v24 = VersionComponent::parse("135.0.1beta24");
println!("User reported v22: {v22:?}");
println!("User reported v24: {v24:?}");
log::info!("User reported v22: {v22:?}");
log::info!("User reported v24: {v24:?}");
// 135.0.1beta24 should be greater than 135.0beta22 (newer patch version)
assert!(
@@ -2045,7 +2049,7 @@ mod tests {
sort_versions(&mut versions);
println!("User reported sorted versions: {versions:?}");
log::info!("User reported sorted versions: {versions:?}");
// Should be sorted from newest to oldest
assert_eq!(
+76 -73
View File
@@ -166,13 +166,13 @@ impl AppAutoUpdater {
let current_version = Self::get_current_version();
let is_nightly = Self::is_nightly_build();
println!("=== App Update Check ===");
println!("Current version: {current_version}");
println!("Is nightly build: {is_nightly}");
println!("STABLE_RELEASE env: {:?}", option_env!("STABLE_RELEASE"));
log::info!("=== App Update Check ===");
log::info!("Current version: {current_version}");
log::info!("Is nightly build: {is_nightly}");
log::info!("STABLE_RELEASE env: {:?}", option_env!("STABLE_RELEASE"));
let releases = self.fetch_app_releases().await?;
println!("Fetched {} releases from GitHub", releases.len());
log::info!("Fetched {} releases from GitHub", releases.len());
// Filter releases based on build type
let filtered_releases: Vec<&AppRelease> = if is_nightly {
@@ -181,7 +181,7 @@ impl AppAutoUpdater {
.iter()
.filter(|release| release.tag_name.starts_with("nightly-"))
.collect();
println!("Found {} nightly releases", nightly_releases.len());
log::info!("Found {} nightly releases", nightly_releases.len());
nightly_releases
} else {
// For stable builds, look for stable releases (semver format)
@@ -189,25 +189,26 @@ impl AppAutoUpdater {
.iter()
.filter(|release| release.tag_name.starts_with('v'))
.collect();
println!("Found {} stable releases", stable_releases.len());
log::info!("Found {} stable releases", stable_releases.len());
stable_releases
};
if filtered_releases.is_empty() {
println!("No releases found for build type (nightly: {is_nightly})");
log::info!("No releases found for build type (nightly: {is_nightly})");
return Ok(None);
}
// Get the latest release
let latest_release = filtered_releases[0];
println!(
log::info!(
"Latest release: {} ({})",
latest_release.tag_name, latest_release.name
latest_release.tag_name,
latest_release.name
);
// Check if we need to update
if self.should_update(&current_version, &latest_release.tag_name, is_nightly) {
println!("Update available!");
log::info!("Update available!");
// Find the appropriate asset for current platform
if let Some(download_url) = self.get_download_url_for_platform(&latest_release.assets) {
@@ -220,16 +221,17 @@ impl AppAutoUpdater {
published_at: latest_release.published_at.clone(),
};
println!(
log::info!(
"Update info prepared: {} -> {}",
update_info.current_version, update_info.new_version
update_info.current_version,
update_info.new_version
);
return Ok(Some(update_info));
} else {
println!("No suitable download asset found for current platform");
log::info!("No suitable download asset found for current platform");
}
} else {
println!("No update needed");
log::info!("No update needed");
}
Ok(None)
@@ -261,7 +263,7 @@ impl AppAutoUpdater {
return false;
}
println!(
log::info!(
"Comparing versions: current={current_version}, new={new_version}, is_nightly={is_nightly}"
);
@@ -273,20 +275,20 @@ impl AppAutoUpdater {
) {
// Different commit hashes mean we should update
let should_update = new_hash != current_hash;
println!("Nightly comparison: current_hash={current_hash}, new_hash={new_hash}, should_update={should_update}");
log::info!("Nightly comparison: current_hash={current_hash}, new_hash={new_hash}, should_update={should_update}");
return should_update;
}
// If current version doesn't have nightly prefix but we're in nightly mode,
// this could be a dev build or stable build upgrading to nightly
if !current_version.starts_with("nightly-") {
println!("Upgrading from non-nightly to nightly: {new_version}");
log::info!("Upgrading from non-nightly to nightly: {new_version}");
return true;
}
} else {
// For stable builds, use semantic versioning comparison
let should_update = self.is_version_newer(new_version, current_version);
println!("Stable comparison: {new_version} > {current_version} = {should_update}");
log::info!("Stable comparison: {new_version} > {current_version} = {should_update}");
return should_update;
}
@@ -354,7 +356,7 @@ impl AppAutoUpdater {
};
let exe_path_str = exe_path.to_string_lossy();
println!("Detecting installation method for: {exe_path_str}");
log::info!("Detecting installation method for: {exe_path_str}");
// Check if installed via package manager by querying package databases
if let Some(exe_name) = exe_path.file_name().and_then(|n| n.to_str()) {
@@ -365,7 +367,7 @@ impl AppAutoUpdater {
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
if !stdout.trim().is_empty() && !stdout.contains("no path found") {
println!("Found DEB package owning the executable");
log::info!("Found DEB package owning the executable");
return LinuxInstallationMethod::Deb;
}
}
@@ -376,7 +378,7 @@ impl AppAutoUpdater {
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
if !stdout.trim().is_empty() && !stdout.contains("not owned") {
println!("Found RPM package owning the executable");
log::info!("Found RPM package owning the executable");
return LinuxInstallationMethod::Rpm;
}
}
@@ -391,7 +393,7 @@ impl AppAutoUpdater {
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
if !stdout.trim().is_empty() && stdout.contains(exe_name) {
println!("Found RPM package via {rpm_cmd}");
log::info!("Found RPM package via {rpm_cmd}");
return LinuxInstallationMethod::Rpm;
}
}
@@ -402,7 +404,7 @@ impl AppAutoUpdater {
// Check installation location to infer method
if exe_path_str.starts_with("/usr/bin/") || exe_path_str.starts_with("/usr/local/bin/") {
// Likely installed via package manager or system-wide installation
println!("Executable in system directory, assuming package installation");
log::info!("Executable in system directory, assuming package installation");
// Try to determine which package system is available
if Command::new("dpkg").arg("--version").output().is_ok() {
@@ -414,11 +416,11 @@ impl AppAutoUpdater {
return LinuxInstallationMethod::Manual;
} else if exe_path_str.contains("/.local/") || exe_path_str.starts_with("/home/") {
// User-local installation
println!("Executable in user directory, assuming manual installation");
log::info!("Executable in user directory, assuming manual installation");
return LinuxInstallationMethod::Manual;
}
println!("Could not determine installation method");
log::info!("Could not determine installation method");
LinuxInstallationMethod::Unknown
}
@@ -432,13 +434,13 @@ impl AppAutoUpdater {
"unknown"
};
println!("Looking for platform-specific asset for arch: {arch}");
log::info!("Looking for platform-specific asset for arch: {arch}");
#[cfg(target_os = "linux")]
{
// If we're running from an AppImage, disable auto-updates for safety
if self.is_running_from_appimage() {
println!("Running from AppImage - auto-updates disabled for safety");
log::info!("Running from AppImage - auto-updates disabled for safety");
return None;
}
}
@@ -460,7 +462,7 @@ impl AppAutoUpdater {
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
{
println!("Unsupported platform for auto-update");
log::info!("Unsupported platform for auto-update");
None
}
}
@@ -475,7 +477,7 @@ impl AppAutoUpdater {
|| asset.name.contains(&format!("_{arch}_"))
|| asset.name.contains(&format!("-{arch}-")))
{
println!("Found exact architecture match: {}", asset.name);
log::info!("Found exact architecture match: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -486,7 +488,7 @@ impl AppAutoUpdater {
if asset.name.contains(".dmg")
&& (asset.name.contains("x86_64") || asset.name.contains("x86-64"))
{
println!("Found x86_64 variant: {}", asset.name);
log::info!("Found x86_64 variant: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -498,7 +500,7 @@ impl AppAutoUpdater {
if asset.name.contains(".dmg")
&& (asset.name.contains("arm64") || asset.name.contains("aarch64"))
{
println!("Found arm64 variant: {}", asset.name);
log::info!("Found arm64 variant: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -511,7 +513,7 @@ impl AppAutoUpdater {
|| asset.name.to_lowercase().contains("darwin")
|| !asset.name.contains(".app.tar.gz"))
{
println!("Found fallback DMG: {}", asset.name);
log::info!("Found fallback DMG: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -533,7 +535,7 @@ impl AppAutoUpdater {
|| asset.name.contains(&format!("_{arch}_"))
|| asset.name.contains(&format!("-{arch}-")))
{
println!("Found Windows {ext} with exact arch match: {}", asset.name);
log::info!("Found Windows {ext} with exact arch match: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -544,7 +546,7 @@ impl AppAutoUpdater {
if asset.name.to_lowercase().ends_with(&format!(".{ext}"))
&& (asset.name.contains("x86_64") || asset.name.contains("x86-64"))
{
println!("Found Windows {ext} with x86_64 variant: {}", asset.name);
log::info!("Found Windows {ext} with x86_64 variant: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -557,7 +559,7 @@ impl AppAutoUpdater {
|| asset.name.to_lowercase().contains("win32")
|| asset.name.to_lowercase().contains("win64"))
{
println!("Found Windows {ext} fallback: {}", asset.name);
log::info!("Found Windows {ext} fallback: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -570,7 +572,7 @@ impl AppAutoUpdater {
fn get_linux_download_url(&self, assets: &[AppReleaseAsset], arch: &str) -> Option<String> {
// Detect installation method to prioritize appropriate formats
let installation_method = self.detect_linux_installation_method();
println!("Detected Linux installation method: {installation_method:?}");
log::info!("Detected Linux installation method: {installation_method:?}");
// Priority order based on installation method
let extensions = match installation_method {
@@ -578,7 +580,7 @@ impl AppAutoUpdater {
LinuxInstallationMethod::Rpm => vec!["rpm", "tar.gz"],
LinuxInstallationMethod::AppImage => {
// AppImages should not auto-update for safety
println!("AppImage installation detected - auto-updates disabled");
log::info!("AppImage installation detected - auto-updates disabled");
return None;
}
LinuxInstallationMethod::Manual | LinuxInstallationMethod::Unknown => {
@@ -596,7 +598,7 @@ impl AppAutoUpdater {
|| asset.name.contains(&format!("_{arch}_"))
|| asset.name.contains(&format!("-{arch}-")))
{
println!("Found Linux {ext} with exact arch match: {}", asset.name);
log::info!("Found Linux {ext} with exact arch match: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -610,7 +612,7 @@ impl AppAutoUpdater {
|| asset.name.contains("x86-64")
|| asset.name.contains("amd64"))
{
println!("Found Linux {ext} with x86_64 variant: {}", asset.name);
log::info!("Found Linux {ext} with x86_64 variant: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -623,7 +625,7 @@ impl AppAutoUpdater {
if asset_name_lower.ends_with(&format!(".{ext}"))
&& (asset.name.contains("arm64") || asset.name.contains("aarch64"))
{
println!("Found Linux {ext} with arm64 variant: {}", asset.name);
log::info!("Found Linux {ext} with arm64 variant: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -637,7 +639,7 @@ impl AppAutoUpdater {
|| asset_name_lower.contains("ubuntu")
|| asset_name_lower.contains("debian"))
{
println!("Found Linux {ext} fallback: {}", asset.name);
log::info!("Found Linux {ext} fallback: {}", asset.name);
return Some(asset.browser_download_url.clone());
}
}
@@ -967,12 +969,12 @@ impl AppAutoUpdater {
.and_then(|ext| ext.to_str())
.unwrap_or("");
println!("Installing Windows update with extension: {extension}");
log::info!("Installing Windows update with extension: {extension}");
match extension {
"msi" => {
// Install MSI silently with enhanced error handling
println!("Running MSI installer: {}", installer_path.display());
log::info!("Running MSI installer: {}", installer_path.display());
let mut cmd = Command::new("msiexec");
cmd.args([
@@ -995,10 +997,10 @@ impl AppAutoUpdater {
let log_path = format!("{}.log", installer_path.to_str().unwrap());
let log_content = fs::read_to_string(&log_path).unwrap_or_default();
println!("MSI installation failed with exit code: {exit_code}");
println!("Error output: {error_msg}");
log::info!("MSI installation failed with exit code: {exit_code}");
log::info!("Error output: {error_msg}");
if !log_content.is_empty() {
println!(
log::info!(
"Log file content (last 500 chars): {}",
&log_content
.chars()
@@ -1016,11 +1018,11 @@ impl AppAutoUpdater {
);
}
println!("MSI installation completed successfully");
log::info!("MSI installation completed successfully");
}
"exe" => {
// Run exe installer silently with multiple fallback options
println!("Running EXE installer: {}", installer_path.display());
log::info!("Running EXE installer: {}", installer_path.display());
// Try NSIS silent flag first (most common for Tauri)
let mut success = false;
@@ -1035,12 +1037,12 @@ impl AppAutoUpdater {
];
for args in nsis_args {
println!("Trying installer with args: {:?}", args);
log::info!("Trying installer with args: {:?}", args);
let output = Command::new(installer_path).args(&args).output();
match output {
Ok(output) if output.status.success() => {
println!(
log::info!(
"EXE installation completed successfully with args: {:?}",
args
);
@@ -1054,13 +1056,14 @@ impl AppAutoUpdater {
output.status.code().unwrap_or(-1),
error_msg
);
println!("Installer failed with args {:?}: {}", args, last_error);
log::info!("Installer failed with args {:?}: {}", args, last_error);
}
Err(e) => {
last_error = format!("Failed to execute installer: {e}");
println!(
log::info!(
"Failed to execute installer with args {:?}: {}",
args, last_error
args,
last_error
);
}
}
@@ -1077,7 +1080,7 @@ impl AppAutoUpdater {
}
"zip" => {
// Handle ZIP files by extracting and replacing the current executable
println!("Handling ZIP update: {}", installer_path.display());
log::info!("Handling ZIP update: {}", installer_path.display());
let temp_extract_dir = installer_path.parent().unwrap().join("extracted");
fs::create_dir_all(&temp_extract_dir)?;
@@ -1124,7 +1127,7 @@ impl AppAutoUpdater {
// Clean up
let _ = fs::remove_dir_all(&temp_extract_dir);
println!("ZIP update completed successfully");
log::info!("ZIP update completed successfully");
}
_ => {
return Err(format!("Unsupported installer format: {extension}").into());
@@ -1141,7 +1144,7 @@ impl AppAutoUpdater {
.and_then(|name| name.to_str())
.unwrap_or("");
println!("Installing Linux update: {}", installer_path.display());
log::info!("Installing Linux update: {}", installer_path.display());
// Handle compound extensions like .tar.gz
if file_name.ends_with(".tar.gz") {
@@ -1173,7 +1176,7 @@ impl AppAutoUpdater {
&self,
deb_path: &Path,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Installing DEB package: {}", deb_path.display());
log::info!("Installing DEB package: {}", deb_path.display());
// Try different package managers in order of preference
let package_managers = [
@@ -1186,23 +1189,23 @@ impl AppAutoUpdater {
for (manager, args) in &package_managers {
// Check if package manager exists
if Command::new("which").arg(manager).output().is_ok() {
println!("Trying to install with {manager}");
log::info!("Trying to install with {manager}");
let output = Command::new("pkexec").arg(manager).args(args).output();
match output {
Ok(output) if output.status.success() => {
println!("DEB installation completed successfully with {manager}");
log::info!("DEB installation completed successfully with {manager}");
return Ok(());
}
Ok(output) => {
let error_msg = String::from_utf8_lossy(&output.stderr);
last_error = format!("{manager} failed: {error_msg}");
println!("Installation failed with {manager}: {error_msg}");
log::info!("Installation failed with {manager}: {error_msg}");
}
Err(e) => {
last_error = format!("Failed to execute {manager}: {e}");
println!("Failed to execute {manager}: {e}");
log::info!("Failed to execute {manager}: {e}");
}
}
}
@@ -1217,7 +1220,7 @@ impl AppAutoUpdater {
&self,
rpm_path: &Path,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Installing RPM package: {}", rpm_path.display());
log::info!("Installing RPM package: {}", rpm_path.display());
// Try different package managers in order of preference
let package_managers = [
@@ -1232,23 +1235,23 @@ impl AppAutoUpdater {
for (manager, args) in &package_managers {
// Check if package manager exists
if Command::new("which").arg(manager).output().is_ok() {
println!("Trying to install with {manager}");
log::info!("Trying to install with {manager}");
let output = Command::new("pkexec").arg(manager).args(args).output();
match output {
Ok(output) if output.status.success() => {
println!("RPM installation completed successfully with {manager}");
log::info!("RPM installation completed successfully with {manager}");
return Ok(());
}
Ok(output) => {
let error_msg = String::from_utf8_lossy(&output.stderr);
last_error = format!("{manager} failed: {error_msg}");
println!("Installation failed with {manager}: {error_msg}");
log::info!("Installation failed with {manager}: {error_msg}");
}
Err(e) => {
last_error = format!("Failed to execute {manager}: {e}");
println!("Failed to execute {manager}: {e}");
log::info!("Failed to execute {manager}: {e}");
}
}
}
@@ -1263,7 +1266,7 @@ impl AppAutoUpdater {
&self,
appimage_path: &Path,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Installing AppImage: {}", appimage_path.display());
log::info!("Installing AppImage: {}", appimage_path.display());
// This function should not be called for AppImages since we disable auto-updates for them
// But if it somehow gets called, we'll handle it safely
@@ -1297,7 +1300,7 @@ impl AppAutoUpdater {
// Replace the AppImage
fs::copy(appimage_path, &current_appimage)?;
println!("AppImage replacement completed successfully");
log::info!("AppImage replacement completed successfully");
Ok(())
}
@@ -1307,7 +1310,7 @@ impl AppAutoUpdater {
&self,
tarball_path: &Path,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Installing tarball: {}", tarball_path.display());
log::info!("Installing tarball: {}", tarball_path.display());
let current_exe = self.get_current_app_path()?;
let temp_extract_dir = tarball_path.parent().unwrap().join("extracted");
@@ -1369,7 +1372,7 @@ impl AppAutoUpdater {
// Clean up
let _ = fs::remove_dir_all(&temp_extract_dir);
println!("Tarball installation completed successfully");
log::info!("Tarball installation completed successfully");
Ok(())
}
@@ -1606,7 +1609,7 @@ pub async fn download_and_install_app_update(
#[tauri::command]
pub async fn check_for_app_updates_manual() -> Result<Option<AppUpdateInfo>, String> {
println!("Manual app update check triggered");
log::info!("Manual app update check triggered");
let updater = AppAutoUpdater::instance();
updater
.check_for_updates()
@@ -1622,7 +1625,7 @@ mod tests {
fn test_is_nightly_build() {
// This will depend on whether STABLE_RELEASE is set during test compilation
let is_nightly = AppAutoUpdater::is_nightly_build();
println!("Is nightly build: {is_nightly}");
log::info!("Is nightly build: {is_nightly}");
// The result should be true for test builds since STABLE_RELEASE is not set
// unless the test is run in a stable release environment
+16 -15
View File
@@ -109,13 +109,13 @@ impl AutoUpdater {
let new_version = &update.new_version.parse::<u32>().unwrap();
let result = new_version - current_version;
println!(
log::info!(
"Current version: {current_version}, New version: {new_version}, Result: {result}"
);
if result > 400 {
notifications.push(update);
} else {
println!(
log::info!(
"Skipping chromium update notification: only {result} new versions (need 400+)"
);
}
@@ -130,22 +130,23 @@ impl AutoUpdater {
}
pub async fn check_for_updates_with_progress(&self, app_handle: &tauri::AppHandle) {
println!("Starting auto-update check with progress...");
log::info!("Starting auto-update check with progress...");
// Check for browser updates and trigger auto-downloads
match self.check_for_updates().await {
Ok(update_notifications) => {
if !update_notifications.is_empty() {
println!(
log::info!(
"Found {} browser updates to auto-download",
update_notifications.len()
);
// Trigger automatic downloads for each update
for notification in update_notifications {
println!(
log::info!(
"Auto-downloading {} version {}",
notification.browser, notification.new_version
notification.browser,
notification.new_version
);
// Clone app_handle for the async task
@@ -164,7 +165,7 @@ impl AutoUpdater {
new_version.clone(),
) {
true => {
println!("Browser {browser} {new_version} already downloaded, proceeding to auto-update profiles");
log::info!("Browser {browser} {new_version} already downloaded, proceeding to auto-update profiles");
// Browser already exists, go straight to profile update
match AutoUpdater::instance()
@@ -176,19 +177,19 @@ impl AutoUpdater {
.await
{
Ok(updated_profiles) => {
println!(
log::info!(
"Auto-update completed for {} profiles: {:?}",
updated_profiles.len(),
updated_profiles
);
}
Err(e) => {
eprintln!("Failed to complete auto-update for {browser}: {e}");
log::error!("Failed to complete auto-update for {browser}: {e}");
}
}
}
false => {
println!("Downloading browser {browser} version {new_version}...");
log::info!("Downloading browser {browser} version {new_version}...");
// Emit the auto-update event to trigger frontend handling
let auto_update_event = serde_json::json!({
@@ -201,20 +202,20 @@ impl AutoUpdater {
if let Err(e) =
app_handle_clone.emit("browser-auto-update-available", &auto_update_event)
{
eprintln!("Failed to emit auto-update event for {browser}: {e}");
log::error!("Failed to emit auto-update event for {browser}: {e}");
} else {
println!("Emitted auto-update event for {browser}");
log::info!("Emitted auto-update event for {browser}");
}
}
}
});
}
} else {
println!("No browser updates needed");
log::info!("No browser updates needed");
}
}
Err(e) => {
eprintln!("Failed to check for browser updates: {e}");
log::error!("Failed to check for browser updates: {e}");
}
}
}
@@ -330,7 +331,7 @@ impl AutoUpdater {
updated_profiles.push(profile.name);
}
Err(e) => {
eprintln!("Failed to update profile {}: {}", profile.name, e);
log::error!("Failed to update profile {}: {}", profile.name, e);
}
}
}
+22 -15
View File
@@ -35,9 +35,9 @@ fn build_proxy_url(
async fn main() {
// Set up panic handler to log panics before process exits
std::panic::set_hook(Box::new(|panic_info| {
eprintln!("PANIC in proxy worker: {:?}", panic_info);
log::error!("PANIC in proxy worker: {:?}", panic_info);
if let Some(location) = panic_info.location() {
eprintln!(
log::error!(
"Location: {}:{}:{}",
location.file(),
location.line(),
@@ -45,7 +45,7 @@ async fn main() {
);
}
if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
eprintln!("Message: {}", s);
log::error!("Message: {}", s);
}
}));
@@ -142,6 +142,7 @@ async fn main() {
match start_proxy_process(upstream_url, port).await {
Ok(config) => {
// Output the configuration as JSON for the Rust side to parse
// Use println! here because this needs to go to stdout for parsing
println!(
"{}",
serde_json::json!({
@@ -162,6 +163,7 @@ async fn main() {
if let Some(id) = stop_matches.get_one::<String>("id") {
match stop_proxy_process(id).await {
Ok(success) => {
// Use println! here because this needs to go to stdout for parsing
println!("{}", serde_json::json!({ "success": success }));
process::exit(0);
}
@@ -187,12 +189,14 @@ async fn main() {
let _ = stop_proxy_process(&config.id).await;
}
// Use println! here because this needs to go to stdout for parsing
println!("{}", serde_json::json!({ "success": true }));
process::exit(0);
} else {
// Stop all proxies
match stop_all_proxy_processes().await {
Ok(_) => {
// Use println! here because this needs to go to stdout for parsing
println!("{}", serde_json::json!({ "success": true }));
process::exit(0);
}
@@ -204,10 +208,11 @@ async fn main() {
}
} else if proxy_matches.subcommand_matches("list").is_some() {
let configs = donutbrowser::proxy_storage::list_proxy_configs();
// Use println! here because this needs to go to stdout for parsing
println!("{}", serde_json::to_string(&configs).unwrap());
process::exit(0);
} else {
eprintln!("Invalid action. Use 'start', 'stop', or 'list'");
log::error!("Invalid action. Use 'start', 'stop', or 'list'");
process::exit(1);
}
} else if let Some(worker_matches) = matches.subcommand_matches("proxy-worker") {
@@ -219,39 +224,41 @@ async fn main() {
.expect("action is required");
if action == "start" {
eprintln!("Proxy worker starting, looking for config id: {}", id);
eprintln!("Process PID: {}", std::process::id());
log::error!("Proxy worker starting, looking for config id: {}", id);
log::error!("Process PID: {}", std::process::id());
let config = match get_proxy_config(id) {
Some(config) => {
eprintln!(
log::error!(
"Found config: id={}, port={:?}, upstream={}",
config.id, config.local_port, config.upstream_url
config.id,
config.local_port,
config.upstream_url
);
config
}
None => {
eprintln!("Proxy configuration {} not found", id);
log::error!("Proxy configuration {} not found", id);
process::exit(1);
}
};
// Run the proxy server - this should never return (infinite loop)
eprintln!("Starting proxy server for config id: {}", id);
log::error!("Starting proxy server for config id: {}", id);
if let Err(e) = run_proxy_server(config).await {
eprintln!("Failed to run proxy server: {}", e);
eprintln!("Error details: {:?}", e);
log::error!("Failed to run proxy server: {}", e);
log::error!("Error details: {:?}", e);
process::exit(1);
}
// This should never be reached - run_proxy_server has an infinite loop
eprintln!("ERROR: Proxy server returned unexpectedly (this should never happen)");
log::error!("ERROR: Proxy server returned unexpectedly (this should never happen)");
process::exit(1);
} else {
eprintln!("Invalid action for proxy-worker. Use 'start'");
log::error!("Invalid action for proxy-worker. Use 'start'");
process::exit(1);
}
} else {
eprintln!("No command specified");
log::error!("No command specified");
process::exit(1);
}
}
+10 -10
View File
@@ -377,7 +377,7 @@ mod linux {
pub fn prepare_executable(executable_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
// On Linux, ensure the executable has proper permissions
println!("Setting execute permissions for: {:?}", executable_path);
log::info!("Setting execute permissions for: {:?}", executable_path);
let metadata = std::fs::metadata(executable_path)?;
let mut permissions = metadata.permissions();
@@ -388,7 +388,7 @@ mod linux {
std::fs::set_permissions(executable_path, permissions)?;
println!(
log::info!(
"Execute permissions set successfully for: {:?}",
executable_path
);
@@ -653,14 +653,14 @@ impl Browser for FirefoxBrowser {
// Expected structure: binaries/<browser>/<version>
let browser_dir = binaries_dir.join(self.browser_type.as_str()).join(version);
println!("Firefox browser checking version {version} in directory: {browser_dir:?}");
log::info!("Firefox browser checking version {version} in directory: {browser_dir:?}");
if !browser_dir.exists() {
println!("Directory does not exist: {browser_dir:?}");
log::info!("Directory does not exist: {browser_dir:?}");
return false;
}
println!("Directory exists, checking for browser files...");
log::info!("Directory exists, checking for browser files...");
#[cfg(target_os = "macos")]
return macos::is_firefox_version_downloaded(&browser_dir);
@@ -673,7 +673,7 @@ impl Browser for FirefoxBrowser {
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
{
println!("Unsupported platform for browser verification");
log::info!("Unsupported platform for browser verification");
false
}
}
@@ -768,14 +768,14 @@ impl Browser for ChromiumBrowser {
// Expected structure: binaries/<browser>/<version>
let browser_dir = binaries_dir.join(self.browser_type.as_str()).join(version);
println!("Chromium browser checking version {version} in directory: {browser_dir:?}");
log::info!("Chromium browser checking version {version} in directory: {browser_dir:?}");
if !browser_dir.exists() {
println!("Directory does not exist: {browser_dir:?}");
log::info!("Directory does not exist: {browser_dir:?}");
return false;
}
println!("Directory exists, checking for browser files...");
log::info!("Directory exists, checking for browser files...");
#[cfg(target_os = "macos")]
return macos::is_chromium_version_downloaded(&browser_dir);
@@ -788,7 +788,7 @@ impl Browser for ChromiumBrowser {
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
{
println!("Unsupported platform for browser verification");
log::info!("Unsupported platform for browser verification");
false
}
}
+171 -122
View File
@@ -125,7 +125,7 @@ impl BrowserRunner {
if profile.browser == "camoufox" {
// Get or create camoufox config
let mut camoufox_config = profile.camoufox_config.clone().unwrap_or_else(|| {
println!(
log::info!(
"No camoufox config found for profile {}, using default",
profile.name
);
@@ -138,7 +138,7 @@ impl BrowserRunner {
.as_ref()
.and_then(|id| PROXY_MANAGER.get_proxy_settings_by_id(id));
println!(
log::info!(
"Starting local proxy for Camoufox profile: {} (upstream: {})",
profile.name,
upstream_proxy
@@ -159,7 +159,7 @@ impl BrowserRunner {
.await
.map_err(|e| {
let error_msg = format!("Failed to start local proxy for Camoufox: {e}");
eprintln!("{}", error_msg);
log::error!("{}", error_msg);
error_msg
})?;
@@ -174,13 +174,14 @@ impl BrowserRunner {
camoufox_config.geoip = Some(serde_json::Value::Bool(true));
}
println!(
log::info!(
"Configured local proxy for Camoufox: {:?}, geoip: {:?}",
camoufox_config.proxy, camoufox_config.geoip
camoufox_config.proxy,
camoufox_config.geoip
);
// Use the nodecar camoufox launcher
println!(
log::info!(
"Launching Camoufox via nodecar for profile: {}",
profile.name
);
@@ -194,7 +195,7 @@ impl BrowserRunner {
// For server-based Camoufox, we use the process_id
let process_id = camoufox_result.processId.unwrap_or(0);
println!("Camoufox launched successfully with PID: {process_id}");
log::info!("Camoufox launched successfully with PID: {process_id}");
// Update profile with the process info from camoufox result
let mut updated_profile = profile.clone();
@@ -203,9 +204,9 @@ impl BrowserRunner {
// Update the proxy manager with the correct PID
if let Err(e) = PROXY_MANAGER.update_proxy_pid(0, process_id) {
println!("Warning: Failed to update proxy PID mapping: {e}");
log::warn!("Warning: Failed to update proxy PID mapping: {e}");
} else {
println!("Updated proxy PID mapping from temp (0) to actual PID: {process_id}");
log::info!("Updated proxy PID mapping from temp (0) to actual PID: {process_id}");
}
// Save the updated profile
@@ -214,19 +215,19 @@ impl BrowserRunner {
let _ = crate::tag_manager::TAG_MANAGER.lock().map(|tm| {
let _ = tm.rebuild_from_profiles(&self.profile_manager.list_profiles().unwrap_or_default());
});
println!(
log::info!(
"Updated profile with process info: {}",
updated_profile.name
);
println!(
log::info!(
"Emitting profile events for successful Camoufox launch: {}",
updated_profile.name
);
// Emit profile update event to frontend
if let Err(e) = app_handle.emit("profile-updated", &updated_profile) {
println!("Warning: Failed to emit profile update event: {e}");
log::warn!("Warning: Failed to emit profile update event: {e}");
}
// Emit minimal running changed event to frontend with a small delay
@@ -242,11 +243,12 @@ impl BrowserRunner {
};
if let Err(e) = app_handle.emit("profile-running-changed", &payload) {
println!("Warning: Failed to emit profile running changed event: {e}");
log::warn!("Warning: Failed to emit profile running changed event: {e}");
} else {
println!(
log::info!(
"Successfully emitted profile-running-changed event for Camoufox {}: running={}",
updated_profile.name, payload.is_running
updated_profile.name,
payload.is_running
);
}
@@ -263,11 +265,11 @@ impl BrowserRunner {
.get_browser_executable_path(profile)
.expect("Failed to get executable path");
println!("Executable path: {executable_path:?}");
log::info!("Executable path: {executable_path:?}");
// Prepare the executable (set permissions, etc.)
if let Err(e) = browser.prepare_executable(&executable_path) {
println!("Warning: Failed to prepare executable: {e}");
log::warn!("Warning: Failed to prepare executable: {e}");
// Continue anyway, the error might not be critical
}
@@ -318,9 +320,11 @@ impl BrowserRunner {
let launcher_pid = child.id();
println!(
log::info!(
"Launched browser with launcher PID: {} for profile: {} (ID: {})",
launcher_pid, profile.name, profile.id
launcher_pid,
profile.name,
profile.id
);
// For TOR and Mullvad browsers, we need to find the actual browser process
@@ -347,9 +351,11 @@ impl BrowserRunner {
}
if self.is_tor_or_mullvad_browser(process_name, process_cmd, &profile.browser) {
println!(
log::info!(
"Found actual {} browser process: PID {} ({})",
profile.browser, pid_u32, process_name
profile.browser,
pid_u32,
process_name
);
actual_pid = pid_u32;
break;
@@ -489,14 +495,15 @@ impl BrowserRunner {
// which is already handled in the profile creation process
}
println!(
log::info!(
"Emitting profile events for successful launch: {} (ID: {})",
updated_profile.name, updated_profile.id
updated_profile.name,
updated_profile.id
);
// Emit profile update event to frontend
if let Err(e) = app_handle.emit("profile-updated", &updated_profile) {
println!("Warning: Failed to emit profile update event: {e}");
log::warn!("Warning: Failed to emit profile update event: {e}");
}
// Emit minimal running changed event to frontend with a small delay to ensure UI consistency
@@ -511,11 +518,12 @@ impl BrowserRunner {
};
if let Err(e) = app_handle.emit("profile-running-changed", &payload) {
println!("Warning: Failed to emit profile running changed event: {e}");
log::warn!("Warning: Failed to emit profile running changed event: {e}");
} else {
println!(
log::info!(
"Successfully emitted profile-running-changed event for {}: running={}",
updated_profile.name, payload.is_running
updated_profile.name,
payload.is_running
);
}
@@ -543,9 +551,10 @@ impl BrowserRunner {
.await
{
Ok(Some(_camoufox_process)) => {
println!(
log::info!(
"Opening URL in existing Camoufox process for profile: {} (ID: {})",
profile.name, profile.id
profile.name,
profile.id
);
// For Camoufox, we need to launch a new instance with the URL since it doesn't support remote commands
@@ -759,7 +768,7 @@ impl BrowserRunner {
.await
.map_err(|e| {
let error_msg = format!("Failed to start local proxy: {e}");
eprintln!("{}", error_msg);
log::error!("{}", error_msg);
error_msg
})?;
@@ -819,9 +828,10 @@ impl BrowserRunner {
url: Option<String>,
internal_proxy_settings: Option<&ProxySettings>,
) -> Result<BrowserProfile, Box<dyn std::error::Error + Send + Sync>> {
println!(
log::info!(
"launch_or_open_url called for profile: {} (ID: {})",
profile.name, profile.id
profile.name,
profile.id
);
// Get the most up-to-date profile data
@@ -834,9 +844,10 @@ impl BrowserRunner {
.find(|p| p.id == profile.id)
.unwrap_or_else(|| profile.clone());
println!(
log::info!(
"Checking browser status for profile: {} (ID: {})",
updated_profile.name, updated_profile.id
updated_profile.name,
updated_profile.id
);
// Check if browser is already running
@@ -855,24 +866,28 @@ impl BrowserRunner {
.find(|p| p.id == profile.id)
.unwrap_or_else(|| updated_profile.clone());
println!(
log::info!(
"Browser status check - Profile: {} (ID: {}), Running: {}, URL: {:?}, PID: {:?}",
final_profile.name, final_profile.id, is_running, url, final_profile.process_id
final_profile.name,
final_profile.id,
is_running,
url,
final_profile.process_id
);
if is_running && url.is_some() {
// Browser is running and we have a URL to open
if let Some(url_ref) = url.as_ref() {
println!("Opening URL in existing browser: {url_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"
) {
println!("TOR/Mullvad browser detected - ensuring we have correct PID");
log::info!("TOR/Mullvad browser detected - ensuring we have correct PID");
if final_profile.process_id.is_none() {
println!(
log::info!(
"ERROR: No PID found for running TOR/Mullvad browser - this should not happen"
);
return Err("No PID found for running browser".into());
@@ -888,11 +903,11 @@ impl BrowserRunner {
.await
{
Ok(()) => {
println!("Successfully opened URL in existing browser");
log::info!("Successfully opened URL in existing browser");
Ok(final_profile)
}
Err(e) => {
println!("Failed to open URL in existing browser: {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
@@ -901,7 +916,7 @@ impl BrowserRunner {
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);
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
}
@@ -910,7 +925,7 @@ impl BrowserRunner {
}
} 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");
log::info!("URL was unexpectedly None, launching new browser instance");
self
.launch_browser(
app_handle.clone(),
@@ -923,9 +938,9 @@ impl BrowserRunner {
} else {
// Browser is not running or no URL provided, launch new instance
if !is_running {
println!("Launching new browser instance - browser not running");
log::info!("Launching new browser instance - browser not running");
} else {
println!("Launching new browser instance - no URL provided");
log::info!("Launching new browser instance - no URL provided");
}
self
.launch_browser_internal(
@@ -974,9 +989,10 @@ impl BrowserRunner {
let profile_data_path = profile.get_profile_data_path(&profiles_dir);
let profile_path_str = profile_data_path.to_string_lossy();
println!(
log::info!(
"Attempting to kill Camoufox process for profile: {} (ID: {})",
profile.name, profile.id
profile.name,
profile.id
);
match self
@@ -985,9 +1001,10 @@ impl BrowserRunner {
.await
{
Ok(Some(camoufox_process)) => {
println!(
log::info!(
"Found Camoufox process: {} (PID: {:?})",
camoufox_process.id, camoufox_process.processId
camoufox_process.id,
camoufox_process.processId
);
match self
@@ -997,35 +1014,40 @@ impl BrowserRunner {
{
Ok(stopped) => {
if stopped {
println!(
log::info!(
"Successfully stopped Camoufox process: {} (PID: {:?})",
camoufox_process.id, camoufox_process.processId
camoufox_process.id,
camoufox_process.processId
);
} else {
println!(
log::info!(
"Failed to stop Camoufox process: {} (PID: {:?})",
camoufox_process.id, camoufox_process.processId
camoufox_process.id,
camoufox_process.processId
);
}
}
Err(e) => {
println!(
log::info!(
"Error stopping Camoufox process {}: {}",
camoufox_process.id, e
camoufox_process.id,
e
);
}
}
}
Ok(None) => {
println!(
log::info!(
"No running Camoufox process found for profile: {} (ID: {})",
profile.name, profile.id
profile.name,
profile.id
);
}
Err(e) => {
println!(
log::info!(
"Error finding Camoufox process for profile {}: {}",
profile.name, e
profile.name,
e
);
}
}
@@ -1039,9 +1061,11 @@ impl BrowserRunner {
.auto_updater
.get_pending_update(&profile.browser, &profile.version)
{
println!(
log::info!(
"Found pending update for Camoufox profile {}: {} -> {}",
profile.name, profile.version, pending_update.new_version
profile.name,
profile.version,
pending_update.new_version
);
// Update the profile to the new version
@@ -1051,9 +1075,11 @@ impl BrowserRunner {
&pending_update.new_version,
) {
Ok(updated_profile_after_update) => {
println!(
log::info!(
"Successfully updated Camoufox profile {} from version {} to {}",
profile.name, profile.version, pending_update.new_version
profile.name,
profile.version,
pending_update.new_version
);
updated_profile = updated_profile_after_update;
@@ -1062,13 +1088,14 @@ impl BrowserRunner {
.auto_updater
.dismiss_update_notification(&pending_update.id)
{
eprintln!("Warning: Failed to dismiss pending update notification: {e}");
log::warn!("Warning: Failed to dismiss pending update notification: {e}");
}
}
Err(e) => {
eprintln!(
log::error!(
"Failed to apply pending update for Camoufox profile {}: {}",
profile.name, e
profile.name,
e
);
// Continue with the original profile update (just clearing process_id)
}
@@ -1079,14 +1106,14 @@ impl BrowserRunner {
.save_process_info(&updated_profile)
.map_err(|e| format!("Failed to update profile: {e}"))?;
println!(
log::info!(
"Emitting profile events for successful Camoufox kill: {}",
updated_profile.name
);
// Emit profile update event to frontend
if let Err(e) = app_handle.emit("profile-updated", &updated_profile) {
println!("Warning: Failed to emit profile update event: {e}");
log::warn!("Warning: Failed to emit profile update event: {e}");
}
// Emit minimal running changed event to frontend immediately
@@ -1101,17 +1128,19 @@ impl BrowserRunner {
};
if let Err(e) = app_handle.emit("profile-running-changed", &payload) {
println!("Warning: Failed to emit profile running changed event: {e}");
log::warn!("Warning: Failed to emit profile running changed event: {e}");
} else {
println!(
log::info!(
"Successfully emitted profile-running-changed event for Camoufox {}: running={}",
updated_profile.name, payload.is_running
updated_profile.name,
payload.is_running
);
}
println!(
log::info!(
"Camoufox process cleanup completed for profile: {} (ID: {})",
profile.name, profile.id
profile.name,
profile.id
);
// Consolidate browser versions after stopping a browser
@@ -1120,9 +1149,9 @@ impl BrowserRunner {
.consolidate_browser_versions(&app_handle)
{
if !consolidated.is_empty() {
println!("Post-stop version consolidation results:");
log::info!("Post-stop version consolidation results:");
for action in &consolidated {
println!(" {action}");
log::info!(" {action}");
}
}
}
@@ -1216,25 +1245,29 @@ impl BrowserRunner {
};
if profile_path_match {
println!(
log::info!(
"Verified stored PID {} is valid for profile {} (ID: {})",
pid, profile.name, profile.id
pid,
profile.name,
profile.id
);
pid
} else {
println!("Stored PID {} doesn't match profile path for {} (ID: {}), searching for correct process", pid, profile.name, profile.id);
log::info!("Stored PID {} doesn't match profile path for {} (ID: {}), searching for correct process", pid, profile.name, profile.id);
// Fall through to search for correct process
self.find_browser_process_by_profile(profile)?
}
} else {
println!("Stored PID {} doesn't match browser type for {} (ID: {}), searching for correct process", pid, profile.name, profile.id);
log::info!("Stored PID {} doesn't match browser type for {} (ID: {}), searching for correct process", pid, profile.name, profile.id);
// Fall through to search for correct process
self.find_browser_process_by_profile(profile)?
}
} else {
println!(
log::info!(
"Stored PID {} is no longer valid for profile {} (ID: {}), searching for correct process",
pid, profile.name, profile.id
pid,
profile.name,
profile.id
);
// Fall through to search for correct process
self.find_browser_process_by_profile(profile)?
@@ -1244,11 +1277,11 @@ impl BrowserRunner {
self.find_browser_process_by_profile(profile)?
};
println!("Attempting to kill browser process with PID: {pid}");
log::info!("Attempting to kill browser process with PID: {pid}");
// Stop any associated proxy first
if let Err(e) = PROXY_MANAGER.stop_proxy(app_handle.clone(), pid).await {
println!("Warning: Failed to stop proxy for PID {pid}: {e}");
log::warn!("Warning: Failed to stop proxy for PID {pid}: {e}");
}
// Kill the process using platform-specific implementation
@@ -1273,9 +1306,11 @@ impl BrowserRunner {
.auto_updater
.get_pending_update(&profile.browser, &profile.version)
{
println!(
log::info!(
"Found pending update for profile {}: {} -> {}",
profile.name, profile.version, pending_update.new_version
profile.name,
profile.version,
pending_update.new_version
);
// Update the profile to the new version
@@ -1285,9 +1320,11 @@ impl BrowserRunner {
&pending_update.new_version,
) {
Ok(updated_profile_after_update) => {
println!(
log::info!(
"Successfully updated profile {} from version {} to {}",
profile.name, profile.version, pending_update.new_version
profile.name,
profile.version,
pending_update.new_version
);
updated_profile = updated_profile_after_update;
@@ -1296,13 +1333,14 @@ impl BrowserRunner {
.auto_updater
.dismiss_update_notification(&pending_update.id)
{
eprintln!("Warning: Failed to dismiss pending update notification: {e}");
log::warn!("Warning: Failed to dismiss pending update notification: {e}");
}
}
Err(e) => {
eprintln!(
log::error!(
"Failed to apply pending update for profile {}: {}",
profile.name, e
profile.name,
e
);
// Continue with the original profile update (just clearing process_id)
}
@@ -1313,14 +1351,14 @@ impl BrowserRunner {
.save_process_info(&updated_profile)
.map_err(|e| format!("Failed to update profile: {e}"))?;
println!(
log::info!(
"Emitting profile events for successful kill: {}",
updated_profile.name
);
// Emit profile update event to frontend
if let Err(e) = app_handle.emit("profile-updated", &updated_profile) {
println!("Warning: Failed to emit profile update event: {e}");
log::warn!("Warning: Failed to emit profile update event: {e}");
}
// Emit minimal running changed event to frontend immediately
@@ -1335,11 +1373,12 @@ impl BrowserRunner {
};
if let Err(e) = app_handle.emit("profile-running-changed", &payload) {
println!("Warning: Failed to emit profile running changed event: {e}");
log::warn!("Warning: Failed to emit profile running changed event: {e}");
} else {
println!(
log::info!(
"Successfully emitted profile-running-changed event for {}: running={}",
updated_profile.name, payload.is_running
updated_profile.name,
payload.is_running
);
}
@@ -1349,9 +1388,9 @@ impl BrowserRunner {
.consolidate_browser_versions(&app_handle)
{
if !consolidated.is_empty() {
println!("Post-stop version consolidation results:");
log::info!("Post-stop version consolidation results:");
for action in &consolidated {
println!(" {action}");
log::info!(" {action}");
}
}
}
@@ -1369,9 +1408,10 @@ impl BrowserRunner {
let profile_data_path = profile.get_profile_data_path(&profiles_dir);
let profile_data_path_str = profile_data_path.to_string_lossy();
println!(
log::info!(
"Searching for {} browser process with profile path: {}",
profile.browser, profile_data_path_str
profile.browser,
profile_data_path_str
);
for (pid, process) in system.processes() {
@@ -1459,9 +1499,12 @@ impl BrowserRunner {
if profile_path_match {
let pid_u32 = pid.as_u32();
println!(
log::info!(
"Found matching {} browser process with PID: {} for profile: {} (ID: {})",
profile.browser, pid_u32, profile.name, profile.id
profile.browser,
pid_u32,
profile.name,
profile.id
);
return Ok(pid_u32);
}
@@ -1492,18 +1535,18 @@ impl BrowserRunner {
.find(|p| p.id.to_string() == profile_id)
.ok_or_else(|| format!("Profile '{profile_id}' not found"))?;
println!("Opening URL '{url}' with profile '{profile_id}'");
log::info!("Opening URL '{url}' with profile '{profile_id}'");
// Use launch_or_open_url which handles both launching new instances and opening in existing ones
self
.launch_or_open_url(app_handle, &profile, Some(url.clone()), None)
.await
.map_err(|e| {
println!("Failed to open URL with profile '{profile_id}': {e}");
log::info!("Failed to open URL with profile '{profile_id}': {e}");
format!("Failed to open URL with profile: {e}")
})?;
println!("Successfully opened URL '{url}' with profile '{profile_id}'");
log::info!("Successfully opened URL '{url}' with profile '{profile_id}'");
Ok(())
}
}
@@ -1514,9 +1557,10 @@ pub async fn launch_browser_profile(
profile: BrowserProfile,
url: Option<String>,
) -> Result<BrowserProfile, String> {
println!(
log::info!(
"Launch request received for profile: {} (ID: {})",
profile.name, profile.id
profile.name,
profile.id
);
let browser_runner = BrowserRunner::instance();
@@ -1539,9 +1583,10 @@ pub async fn launch_browser_profile(
}
};
println!(
log::info!(
"Resolved profile for launch: {} (ID: {})",
profile_for_launch.name, profile_for_launch.id
profile_for_launch.name,
profile_for_launch.id
);
// Always start a local proxy before launching (non-Camoufox handled here; Camoufox has its own flow)
@@ -1596,7 +1641,7 @@ pub async fn launch_browser_profile(
.map_err(|e| format!("Failed to update profile proxy: {e}"))?;
}
println!(
log::info!(
"Local proxy prepared for profile: {} on port: {} (upstream: {})",
profile_for_launch.name,
internal_proxy.port,
@@ -1608,21 +1653,22 @@ pub async fn launch_browser_profile(
}
Err(e) => {
let error_msg = format!("Failed to start local proxy: {e}");
eprintln!("{}", error_msg);
log::error!("{}", error_msg);
// DO NOT launch browser if proxy startup fails - all browsers must use local proxy
return Err(error_msg);
}
}
}
println!(
log::info!(
"Starting browser launch for profile: {} (ID: {})",
profile_for_launch.name, profile_for_launch.id
profile_for_launch.name,
profile_for_launch.id
);
// Launch browser or open URL in existing instance
let updated_profile = browser_runner.launch_or_open_url(app_handle.clone(), &profile_for_launch, url, internal_proxy_settings.as_ref()).await.map_err(|e| {
println!("Browser launch failed for profile: {}, error: {}", profile_for_launch.name, e);
log::info!("Browser launch failed for profile: {}, error: {}", profile_for_launch.name, e);
// Emit a failure event to clear loading states in the frontend
#[derive(serde::Serialize)]
@@ -1636,7 +1682,7 @@ pub async fn launch_browser_profile(
};
if let Err(e) = app_handle.emit("profile-running-changed", &payload) {
println!("Warning: Failed to emit profile running changed event: {e}");
log::warn!("Warning: Failed to emit profile running changed event: {e}");
}
// Check if this is an architecture compatibility issue
@@ -1648,9 +1694,10 @@ pub async fn launch_browser_profile(
format!("Failed to launch browser or open URL: {e}")
})?;
println!(
log::info!(
"Browser launch completed for profile: {} (ID: {})",
updated_profile.name, updated_profile.id
updated_profile.name,
updated_profile.id
);
// Now update the proxy with the correct PID if we have one
@@ -1676,9 +1723,10 @@ pub async fn kill_browser_profile(
app_handle: tauri::AppHandle,
profile: BrowserProfile,
) -> Result<(), String> {
println!(
log::info!(
"Kill request received for profile: {} (ID: {})",
profile.name, profile.id
profile.name,
profile.id
);
let browser_runner = BrowserRunner::instance();
@@ -1688,14 +1736,15 @@ pub async fn kill_browser_profile(
.await
{
Ok(()) => {
println!(
log::info!(
"Successfully killed browser profile: {} (ID: {})",
profile.name, profile.id
profile.name,
profile.id
);
Ok(())
}
Err(e) => {
println!("Failed to kill browser profile {}: {}", profile.name, e);
log::info!("Failed to kill browser profile {}: {}", profile.name, e);
// Emit a failure event to clear loading states in the frontend
#[derive(serde::Serialize)]
@@ -1710,7 +1759,7 @@ pub async fn kill_browser_profile(
};
if let Err(e) = app_handle.emit("profile-running-changed", &payload) {
println!("Warning: Failed to emit profile running changed event: {e}");
log::warn!("Warning: Failed to emit profile running changed event: {e}");
}
Err(format!("Failed to kill browser: {e}"))
+7 -7
View File
@@ -277,7 +277,7 @@ impl BrowserVersionManager {
.api_client
.save_cached_versions(browser, &merged_releases)
{
eprintln!("Failed to save merged cache for {browser}: {e}");
log::error!("Failed to save merged cache for {browser}: {e}");
}
}
@@ -534,7 +534,7 @@ impl BrowserVersionManager {
})
.collect();
if let Err(e) = self.api_client.save_cached_versions(browser, &releases) {
eprintln!("Failed to save updated cache for {browser}: {e}");
log::error!("Failed to save updated cache for {browser}: {e}");
}
Ok(new_versions_count)
@@ -922,7 +922,7 @@ impl BrowserVersionManager {
.collect();
// Always save so that other callers without release_name can classify correctly
if let Err(e) = self.api_client.save_cached_versions("brave", &converted) {
eprintln!("Failed to persist Brave versions cache: {e}");
log::error!("Failed to persist Brave versions cache: {e}");
}
Ok(releases.into_iter().map(|r| r.tag_name).collect())
@@ -947,7 +947,7 @@ impl BrowserVersionManager {
})
.collect();
if let Err(e) = self.api_client.save_cached_versions("brave", &converted) {
eprintln!("Failed to persist Brave versions cache: {e}");
log::error!("Failed to persist Brave versions cache: {e}");
}
Ok(releases)
@@ -1271,7 +1271,7 @@ mod tests {
let unsupported_result = service.get_download_info("unsupported", "1.0.0");
assert!(unsupported_result.is_err());
println!("Download info test passed for all browsers");
log::info!("Download info test passed for all browsers");
}
}
@@ -1307,7 +1307,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}");
log::error!("Background version update failed for {browser_str_clone}: {e}");
}
});
}
@@ -1339,7 +1339,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}");
log::error!("Background version update failed for {browser_str_clone}: {e}");
}
});
}
+4 -4
View File
@@ -206,7 +206,7 @@ impl CamoufoxManager {
url: Option<&str>,
) -> Result<CamoufoxLaunchResult, Box<dyn std::error::Error + Send + Sync>> {
let custom_config = if let Some(existing_fingerprint) = &config.fingerprint {
println!("Using existing fingerprint from profile metadata");
log::info!("Using existing fingerprint from profile metadata");
existing_fingerprint.clone()
} else {
return Err("No fingerprint provided".into());
@@ -266,18 +266,18 @@ impl CamoufoxManager {
}
// Execute nodecar sidecar command
println!("Executing nodecar command with args: {args:?}");
log::info!("Executing nodecar command with args: {args:?}");
let output = sidecar_command.output().await?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
println!("nodecar camoufox failed - stdout: {stdout}, stderr: {stderr}");
log::info!("nodecar camoufox failed - stdout: {stdout}, stderr: {stderr}");
return Err(format!("nodecar camoufox failed: {stderr}").into());
}
let stdout = String::from_utf8_lossy(&output.stdout);
println!("nodecar camoufox output: {stdout}");
log::info!("nodecar camoufox output: {stdout}");
// Parse the JSON output
let launch_result: CamoufoxLaunchResult = serde_json::from_str(&stdout)
+60 -55
View File
@@ -122,7 +122,7 @@ impl DownloadedBrowsersRegistry {
let browser_type = match BrowserType::from_str(browser) {
Ok(bt) => bt,
Err(_) => {
println!("Invalid browser type: {browser}");
log::info!("Invalid browser type: {browser}");
return false;
}
};
@@ -146,7 +146,7 @@ impl DownloadedBrowsersRegistry {
// If files don't exist but registry thinks they do, clean up the registry
if !files_exist {
println!("Cleaning up stale registry entry for {browser} {version}");
log::info!("Cleaning up stale registry entry for {browser} {version}");
self.remove_browser(browser, version);
let _ = self.save(); // Don't fail if save fails, just log
}
@@ -166,7 +166,7 @@ impl DownloadedBrowsersRegistry {
pub fn mark_download_started(&self, browser: &str, version: &str, file_path: PathBuf) {
// Only mark download started, don't add to registry yet
// The browser will be added to registry only after verification succeeds
println!(
log::info!(
"Marking download started for {}:{} at {}",
browser,
version,
@@ -187,7 +187,7 @@ impl DownloadedBrowsersRegistry {
file_path,
};
self.add_browser(info);
println!("Browser {browser}:{version} successfully added to registry after verification");
log::info!("Browser {browser}:{version} successfully added to registry after verification");
Ok(())
}
@@ -268,7 +268,7 @@ impl DownloadedBrowsersRegistry {
let pending_updates = match self.auto_updater.get_pending_update_versions() {
Ok(updates) => updates,
Err(e) => {
eprintln!("Warning: Failed to get pending updates for cleanup: {e}");
log::warn!("Warning: Failed to get pending updates for cleanup: {e}");
std::collections::HashSet::new()
}
};
@@ -283,13 +283,13 @@ impl DownloadedBrowsersRegistry {
// Don't remove if it's used by any active profile
if active_set.contains(&browser_version) {
println!("Keeping: {browser} {version} (in use by profile)");
log::info!("Keeping: {browser} {version} (in use by profile)");
continue;
}
// Don't remove if it's currently running (even if not in active profiles)
if running_set.contains(&browser_version) {
println!("Keeping: {browser} {version} (currently running)");
log::info!("Keeping: {browser} {version} (currently running)");
continue;
}
@@ -300,14 +300,14 @@ impl DownloadedBrowsersRegistry {
let has_running_profile_for_browser =
running_profiles.iter().any(|(b, _)| b == browser);
if has_running_profile_for_browser {
println!("Keeping: {browser} {version} (pending update for running profile)");
log::info!("Keeping: {browser} {version} (pending update for running profile)");
continue;
}
}
// Mark for removal
to_remove.push(browser_version);
println!("Marking for removal: {browser} {version} (not used by any profile)");
log::info!("Marking for removal: {browser} {version} (not used by any profile)");
}
}
}
@@ -315,21 +315,21 @@ impl DownloadedBrowsersRegistry {
// Remove unused binaries and their version folders
for (browser, version) in to_remove {
if let Err(e) = self.cleanup_failed_download(&browser, &version) {
eprintln!("Failed to cleanup unused binary {browser}:{version}: {e}");
log::error!("Failed to cleanup unused binary {browser}:{version}: {e}");
} else {
// After removing the binary, also remove the empty version folder
if let Err(e) = self.remove_empty_version_folder(&browser, &version) {
eprintln!("Failed to remove empty version folder for {browser}:{version}: {e}");
log::error!("Failed to remove empty version folder for {browser}:{version}: {e}");
}
cleaned_up.push(format!("{browser} {version}"));
println!("Successfully removed unused binary: {browser} {version}");
log::info!("Successfully removed unused binary: {browser} {version}");
}
}
if cleaned_up.is_empty() {
println!("No unused binaries found to clean up");
log::info!("No unused binaries found to clean up");
} else {
println!("Cleaned up {} unused binaries", cleaned_up.len());
log::info!("Cleaned up {} unused binaries", cleaned_up.len());
}
Ok(cleaned_up)
@@ -374,7 +374,7 @@ impl DownloadedBrowsersRegistry {
// Files don't exist, remove from registry
if let Some(_removed) = self.remove_browser(&browser_str, &version) {
cleaned_up.push(format!("{browser_str} {version}"));
println!("Removed stale registry entry for {browser_str} {version}");
log::info!("Removed stale registry entry for {browser_str} {version}");
}
}
}
@@ -529,7 +529,7 @@ impl DownloadedBrowsersRegistry {
if entries.next().is_none() {
// Directory is empty, remove it
fs::remove_dir(&version_dir)?;
println!("Removed empty version folder: {}", version_dir.display());
log::info!("Removed empty version folder: {}", version_dir.display());
// Also check if the browser folder is now empty and remove it too
let browser_dir = binaries_dir.join(browser);
@@ -537,7 +537,7 @@ impl DownloadedBrowsersRegistry {
if let Ok(mut browser_entries) = fs::read_dir(&browser_dir) {
if browser_entries.next().is_none() {
fs::remove_dir(&browser_dir)?;
println!("Removed empty browser folder: {}", browser_dir.display());
log::info!("Removed empty browser folder: {}", browser_dir.display());
}
}
}
@@ -618,7 +618,7 @@ impl DownloadedBrowsersRegistry {
// Remove empty version directories
for (version_path, version_name) in empty_version_dirs {
if let Err(e) = fs::remove_dir(&version_path) {
eprintln!(
log::error!(
"Failed to remove empty version folder {}: {e}",
version_path.display()
);
@@ -626,7 +626,7 @@ impl DownloadedBrowsersRegistry {
cleaned_up.push(format!(
"Removed empty version folder: {browser_name}/{version_name}"
));
println!("Removed empty version folder: {}", version_path.display());
log::info!("Removed empty version folder: {}", version_path.display());
}
}
@@ -635,13 +635,13 @@ impl DownloadedBrowsersRegistry {
if let Ok(mut entries) = fs::read_dir(&browser_path) {
if entries.next().is_none() {
if let Err(e) = fs::remove_dir(&browser_path) {
eprintln!(
log::error!(
"Failed to remove empty browser folder {}: {e}",
browser_path.display()
);
} else {
cleaned_up.push(format!("Removed empty browser folder: {browser_name}"));
println!("Removed empty browser folder: {}", browser_path.display());
log::info!("Removed empty browser folder: {}", browser_path.display());
}
}
}
@@ -656,7 +656,7 @@ impl DownloadedBrowsersRegistry {
&self,
app_handle: &tauri::AppHandle,
) -> Result<Vec<String>, Box<dyn std::error::Error + Send + Sync>> {
println!("Starting browser version consolidation...");
log::info!("Starting browser version consolidation...");
let profiles = self
.profile_manager
@@ -691,15 +691,16 @@ impl DownloadedBrowsersRegistry {
if browser.is_version_downloaded(&profile.version, &binaries_dir) {
available_versions.push(profile.version.clone());
} else {
println!(
log::info!(
"Profile '{}' references version {} that doesn't exist on disk",
profile.name, profile.version
profile.name,
profile.version
);
}
}
if available_versions.is_empty() {
println!("No available versions found for {browser_name}, skipping consolidation");
log::info!("No available versions found for {browser_name}, skipping consolidation");
continue;
}
@@ -710,7 +711,7 @@ impl DownloadedBrowsersRegistry {
});
let latest_version = &available_versions[0];
println!("Latest available version for {browser_name}: {latest_version}");
log::info!("Latest available version for {browser_name}: {latest_version}");
// Check which profiles need to be updated to the latest version
let mut profiles_to_update = Vec::new();
@@ -723,9 +724,10 @@ impl DownloadedBrowsersRegistry {
profiles_to_update.push(profile);
older_versions_to_remove.insert(profile.version.clone());
} else {
println!(
log::info!(
"Skipping version update for running profile: {} ({})",
profile.name, profile.version
profile.name,
profile.version
);
}
}
@@ -744,21 +746,21 @@ impl DownloadedBrowsersRegistry {
));
}
Err(e) => {
eprintln!("Failed to update profile '{}': {}", profile.name, e);
log::error!("Failed to update profile '{}': {}", profile.name, e);
}
}
}
// Remove older version binaries that are no longer needed
for old_version in &older_versions_to_remove {
println!("Consolidating: removing old version {browser_name} {old_version}");
log::info!("Consolidating: removing old version {browser_name} {old_version}");
match self.cleanup_failed_download(browser_name, old_version) {
Ok(_) => {
consolidated.push(format!("Removed old version: {browser_name} {old_version}"));
println!("Successfully removed old version: {browser_name} {old_version}");
log::info!("Successfully removed old version: {browser_name} {old_version}");
}
Err(e) => {
eprintln!("Failed to cleanup old version {browser_name} {old_version}: {e}");
log::error!("Failed to cleanup old version {browser_name} {old_version}: {e}");
}
}
}
@@ -770,7 +772,7 @@ impl DownloadedBrowsersRegistry {
.save()
.map_err(|e| format!("Failed to save registry after consolidation: {e}"))?;
println!(
log::info!(
"Browser version consolidation completed: {} actions taken",
consolidated.len()
);
@@ -793,9 +795,10 @@ impl DownloadedBrowsersRegistry {
let browser_type = match BrowserType::from_str(&profile.browser) {
Ok(bt) => bt,
Err(_) => {
println!(
log::info!(
"Warning: Invalid browser type '{}' for profile '{}'",
profile.browser, profile.name
profile.browser,
profile.name
);
continue;
}
@@ -817,7 +820,7 @@ impl DownloadedBrowsersRegistry {
return Err("Failed to get base directories".into());
};
println!(
log::info!(
"binaries_dir: {binaries_dir:?} for profile: {}",
profile.name
);
@@ -839,7 +842,7 @@ impl DownloadedBrowsersRegistry {
// First, clean up any stale registry entries
if let Ok(cleaned_up) = self.verify_and_cleanup_stale_entries() {
if !cleaned_up.is_empty() {
println!(
log::info!(
"Cleaned up {} stale registry entries: {}",
cleaned_up.len(),
cleaned_up.join(", ")
@@ -850,9 +853,9 @@ impl DownloadedBrowsersRegistry {
// Consolidate browser versions - keep only latest version per browser
if let Ok(consolidated) = self.consolidate_browser_versions(app_handle) {
if !consolidated.is_empty() {
println!("Version consolidation results:");
log::info!("Version consolidation results:");
for action in &consolidated {
println!(" {action}");
log::info!(" {action}");
}
}
}
@@ -861,7 +864,7 @@ impl DownloadedBrowsersRegistry {
let mut downloaded = Vec::new();
for (profile_name, browser, version) in missing_binaries {
println!("Downloading missing binary for profile '{profile_name}': {browser} {version}");
log::info!("Downloading missing binary for profile '{profile_name}': {browser} {version}");
match crate::downloader::download_browser(
app_handle.clone(),
@@ -882,31 +885,31 @@ impl DownloadedBrowsersRegistry {
{
Ok(updated_profiles) => {
if !updated_profiles.is_empty() {
println!(
log::info!(
"Successfully updated {} profiles to version {}:",
updated_profiles.len(),
version
);
for update_msg in updated_profiles {
println!(" {update_msg}");
log::info!(" {update_msg}");
}
}
}
Err(e) => {
eprintln!("CRITICAL: Failed to update profiles to version {version}: {e}");
eprintln!("This may cause profile version inconsistencies and cleanup issues");
log::error!("CRITICAL: Failed to update profiles to version {version}: {e}");
log::error!("This may cause profile version inconsistencies and cleanup issues");
}
}
}
Err(e) => {
eprintln!("Failed to download {browser} {version} for profile '{profile_name}': {e}");
log::error!("Failed to download {browser} {version} for profile '{profile_name}': {e}");
}
}
}
// Check if GeoIP database is missing for Camoufox profiles
if self.geoip_downloader.check_missing_geoip_database()? {
println!("GeoIP database is missing for Camoufox profiles, downloading...");
log::info!("GeoIP database is missing for Camoufox profiles, downloading...");
match self
.geoip_downloader
@@ -915,10 +918,10 @@ impl DownloadedBrowsersRegistry {
{
Ok(_) => {
downloaded.push("GeoIP database for Camoufox".to_string());
println!("GeoIP database downloaded successfully");
log::info!("GeoIP database downloaded successfully");
}
Err(e) => {
eprintln!("Failed to download GeoIP database: {e}");
log::error!("Failed to download GeoIP database: {e}");
// Don't fail the entire operation if GeoIP download fails
}
}
@@ -945,9 +948,10 @@ impl DownloadedBrowsersRegistry {
if profile.browser == browser && profile.version != version {
// Check if profile is currently running
if profile.process_id.is_some() {
println!(
log::info!(
"Skipping version update for running profile: {} ({})",
profile.name, profile.version
profile.name,
profile.version
);
continue;
}
@@ -963,18 +967,19 @@ impl DownloadedBrowsersRegistry {
"Updated profile '{}' from {} to {}",
profile.name, profile.version, version
));
println!(
log::info!(
"Successfully updated profile '{}' to version {}",
profile.name, version
profile.name,
version
);
// Save registry after each profile update to ensure consistency
if let Err(e) = self.save() {
eprintln!("Warning: Failed to save registry after profile update: {e}");
log::warn!("Warning: Failed to save registry after profile update: {e}");
}
}
Err(e) => {
eprintln!("Failed to update profile '{}': {}", profile.name, e);
log::error!("Failed to update profile '{}': {}", profile.name, e);
}
}
}
@@ -1016,7 +1021,7 @@ lazy_static::lazy_static! {
static ref DOWNLOADED_BROWSERS_REGISTRY: DownloadedBrowsersRegistry = {
let registry = DownloadedBrowsersRegistry::new();
if let Err(e) = registry.load() {
eprintln!("Warning: Failed to load downloaded browsers registry: {e}");
log::warn!("Warning: Failed to load downloaded browsers registry: {e}");
}
registry
};
+9 -9
View File
@@ -104,7 +104,7 @@ impl Downloader {
let releases = match self.api_client.fetch_zen_releases_with_caching(true).await {
Ok(releases) => releases,
Err(e) => {
eprintln!("Failed to fetch Zen releases: {e}");
log::error!("Failed to fetch Zen releases: {e}");
return Err(format!("Failed to fetch Zen releases from GitHub API: {e}. This might be due to GitHub API rate limiting or network issues. Please try again later.").into());
}
};
@@ -644,7 +644,7 @@ impl Downloader {
return Ok(version);
} else {
// Registry says it's downloaded but files don't exist - clean up registry
println!("Registry indicates {browser_str} {version} is downloaded, but files are missing. Cleaning up registry entry.");
log::info!("Registry indicates {browser_str} {version} is downloaded, but files are missing. Cleaning up registry entry.");
self.registry.remove_browser(&browser_str, &version);
self
.registry
@@ -764,7 +764,7 @@ impl Downloader {
let _ = app_handle.emit("download-progress", &progress);
// Verify the browser was downloaded correctly
println!("Verifying download for browser: {browser_str}, version: {version}");
log::info!("Verifying download for browser: {browser_str}, version: {version}");
// Use the browser's own verification method
if !browser.is_version_downloaded(&version, &binaries_dir) {
@@ -838,7 +838,7 @@ impl Downloader {
.registry
.mark_download_completed(&browser_str, &version, browser_dir.clone())
{
eprintln!("Warning: Could not mark {browser_str} {version} as completed in registry: {e}");
log::warn!("Warning: Could not mark {browser_str} {version} as completed in registry: {e}");
}
self
.registry
@@ -850,7 +850,7 @@ impl Downloader {
let archive_path = browser_dir.join(&download_info.filename);
if archive_path.exists() {
if let Err(e) = std::fs::remove_file(&archive_path) {
println!("Warning: Could not delete archive file after verification: {e}");
log::warn!("Warning: Could not delete archive file after verification: {e}");
}
}
}
@@ -859,7 +859,7 @@ impl Downloader {
if browser_str == "camoufox" {
// Check if GeoIP database is already available
if !crate::geoip_downloader::GeoIPDownloader::is_geoip_database_available() {
println!("Downloading GeoIP database for Camoufox...");
log::info!("Downloading GeoIP database for Camoufox...");
match self
.geoip_downloader
@@ -867,15 +867,15 @@ impl Downloader {
.await
{
Ok(_) => {
println!("GeoIP database downloaded successfully");
log::info!("GeoIP database downloaded successfully");
}
Err(e) => {
eprintln!("Failed to download GeoIP database: {e}");
log::error!("Failed to download GeoIP database: {e}");
// Don't fail the browser download if GeoIP download fails
}
}
} else {
println!("GeoIP database already available");
log::info!("GeoIP database already available");
}
}
+50 -50
View File
@@ -55,7 +55,7 @@ impl Extractor {
// If the executable is not in the expected subdirectory, create the structure
if !exe_path.starts_with(&expected_subdir) {
println!("Reorganizing directory structure for {}", browser_type);
log::info!("Reorganizing directory structure for {}", browser_type);
// Create the expected subdirectory
std::fs::create_dir_all(&expected_subdir)?;
@@ -78,19 +78,19 @@ impl Extractor {
// Move the file/directory
if let Err(e) = std::fs::rename(&path, &target_path) {
println!(
log::info!(
"Warning: Failed to move {} to {}: {}",
path.display(),
target_path.display(),
e
);
} else {
println!("Moved {} to {}", path.display(), target_path.display());
log::info!("Moved {} to {}", path.display(), target_path.display());
}
}
}
println!("Directory structure reorganized for {}", browser_type);
log::info!("Directory structure reorganized for {}", browser_type);
}
Ok(())
@@ -117,7 +117,7 @@ impl Extractor {
};
let _ = app_handle.emit("download-progress", &progress);
println!(
log::info!(
"Starting extraction of {} for browser {} version {}",
archive_path.display(),
browser_type.as_str(),
@@ -132,7 +132,7 @@ impl Extractor {
e
)
})?;
println!("Detected format: {actual_format}");
log::info!("Detected format: {actual_format}");
let extraction_result = match actual_format.as_str() {
"dmg" => {
@@ -210,7 +210,7 @@ impl Extractor {
match extraction_result {
Ok(path) => {
println!(
log::info!(
"Successfully extracted {} {} to: {}",
browser_type.as_str(),
version,
@@ -219,7 +219,7 @@ impl Extractor {
Ok(path)
}
Err(e) => {
eprintln!(
log::error!(
"Extraction failed for {} {}: {}",
browser_type.as_str(),
version,
@@ -337,7 +337,7 @@ impl Extractor {
dmg_path: &Path,
dest_dir: &Path,
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
println!(
log::info!(
"Extracting DMG: {} to {}",
dmg_path.display(),
dest_dir.display()
@@ -353,7 +353,7 @@ impl Extractor {
));
create_dir_all(&mount_point)?;
println!("Created mount point: {}", mount_point.display());
log::info!("Created mount point: {}", mount_point.display());
// Mount the DMG
let output = Command::new("hdiutil")
@@ -369,7 +369,7 @@ impl Extractor {
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
println!("Failed to mount DMG. stdout: {stdout}, stderr: {stderr}");
log::info!("Failed to mount DMG. stdout: {stdout}, stderr: {stderr}");
// Clean up mount point before returning error
let _ = fs::remove_dir_all(&mount_point);
@@ -377,7 +377,7 @@ impl Extractor {
return Err(format!("Failed to mount DMG: {stderr}").into());
}
println!("Successfully mounted DMG");
log::info!("Successfully mounted DMG");
// Find the .app directory in the mount point
let app_result = self.find_app_in_directory(&mount_point).await;
@@ -385,7 +385,7 @@ impl Extractor {
let app_entry = match app_result {
Ok(app_path) => app_path,
Err(e) => {
println!("Failed to find .app in mount point: {e}");
log::info!("Failed to find .app in mount point: {e}");
// Try to unmount before returning error
let _ = Command::new("hdiutil")
@@ -397,12 +397,12 @@ impl Extractor {
}
};
println!("Found .app bundle: {}", app_entry.display());
log::info!("Found .app bundle: {}", app_entry.display());
// Copy the .app to the destination
let app_path = dest_dir.join(app_entry.file_name().unwrap());
println!("Copying .app to: {}", app_path.display());
log::info!("Copying .app to: {}", app_path.display());
let output = Command::new("cp")
.args([
@@ -414,7 +414,7 @@ impl Extractor {
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
println!("Failed to copy app: {stderr}");
log::info!("Failed to copy app: {stderr}");
// Unmount before returning error
let _ = Command::new("hdiutil")
@@ -425,7 +425,7 @@ impl Extractor {
return Err(format!("Failed to copy app: {stderr}").into());
}
println!("Successfully copied .app bundle");
log::info!("Successfully copied .app bundle");
// Remove quarantine attributes
let _ = Command::new("xattr")
@@ -436,7 +436,7 @@ impl Extractor {
.args(["-cr", app_path.to_str().unwrap()])
.output();
println!("Removed quarantine attributes");
log::info!("Removed quarantine attributes");
// Unmount the DMG
let output = Command::new("hdiutil")
@@ -445,10 +445,10 @@ impl Extractor {
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
println!("Warning: Failed to unmount DMG: {stderr}");
log::warn!("Warning: Failed to unmount DMG: {stderr}");
// Don't fail if unmount fails - the extraction was successful
} else {
println!("Successfully unmounted DMG");
log::info!("Successfully unmounted DMG");
}
// Clean up mount point directory
@@ -486,7 +486,7 @@ impl Extractor {
if path.is_dir() {
if let Some(extension) = path.extension() {
if extension == "app" {
println!("Found .app bundle at depth {}: {}", depth, path.display());
log::info!("Found .app bundle at depth {}: {}", depth, path.display());
return Ok(path);
}
}
@@ -535,7 +535,7 @@ impl Extractor {
zip_path: &Path,
dest_dir: &Path,
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
println!("Extracting ZIP archive: {}", zip_path.display());
log::info!("Extracting ZIP archive: {}", zip_path.display());
std::fs::create_dir_all(dest_dir)?;
let file = File::open(zip_path)
@@ -544,7 +544,7 @@ impl Extractor {
let mut archive = zip::ZipArchive::new(BufReader::new(file))
.map_err(|e| format!("Failed to read ZIP archive {}: {}", zip_path.display(), e))?;
println!("ZIP archive contains {} files", archive.len());
log::info!("ZIP archive contains {} files", archive.len());
for i in 0..archive.len() {
let mut entry = archive
@@ -591,7 +591,7 @@ impl Extractor {
}
}
println!("ZIP extraction completed. Searching for executable...");
log::info!("ZIP extraction completed. Searching for executable...");
self
.find_extracted_executable(dest_dir)
.await
@@ -603,7 +603,7 @@ impl Extractor {
tar_path: &Path,
dest_dir: &Path,
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
println!("Extracting tar.gz archive: {}", tar_path.display());
log::info!("Extracting tar.gz archive: {}", tar_path.display());
std::fs::create_dir_all(dest_dir)?;
let file = File::open(tar_path)?;
@@ -615,7 +615,7 @@ impl Extractor {
// Set executable permissions for extracted files
self.set_executable_permissions_recursive(dest_dir).await?;
println!("tar.gz extraction completed. Searching for executable...");
log::info!("tar.gz extraction completed. Searching for executable...");
self.find_extracted_executable(dest_dir).await
}
@@ -624,7 +624,7 @@ impl Extractor {
tar_path: &Path,
dest_dir: &Path,
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
println!("Extracting tar.bz2 archive: {}", tar_path.display());
log::info!("Extracting tar.bz2 archive: {}", tar_path.display());
std::fs::create_dir_all(dest_dir)?;
let file = File::open(tar_path)?;
@@ -636,7 +636,7 @@ impl Extractor {
// Set executable permissions for extracted files
self.set_executable_permissions_recursive(dest_dir).await?;
println!("tar.bz2 extraction completed. Searching for executable...");
log::info!("tar.bz2 extraction completed. Searching for executable...");
self.find_extracted_executable(dest_dir).await
}
@@ -645,7 +645,7 @@ impl Extractor {
tar_path: &Path,
dest_dir: &Path,
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
println!("Extracting tar.xz archive: {}", tar_path.display());
log::info!("Extracting tar.xz archive: {}", tar_path.display());
std::fs::create_dir_all(dest_dir)?;
let file = File::open(tar_path)?;
@@ -671,7 +671,7 @@ impl Extractor {
// Set executable permissions for extracted files
self.set_executable_permissions_recursive(dest_dir).await?;
println!("tar.xz extraction completed. Searching for executable...");
log::info!("tar.xz extraction completed. Searching for executable...");
self.find_extracted_executable(dest_dir).await
}
@@ -680,7 +680,7 @@ impl Extractor {
msi_path: &Path,
dest_dir: &Path,
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
println!("Extracting MSI archive: {}", msi_path.display());
log::info!("Extracting MSI archive: {}", msi_path.display());
std::fs::create_dir_all(dest_dir)?;
// Extract MSI in a separate scope to avoid Send issues
@@ -689,7 +689,7 @@ impl Extractor {
extractor.to(dest_dir);
}
println!("MSI extraction completed. Searching for executable...");
log::info!("MSI extraction completed. Searching for executable...");
self.find_extracted_executable(dest_dir).await
}
@@ -812,7 +812,7 @@ impl Extractor {
&self,
dest_dir: &Path,
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
println!("Searching for .app bundle in: {}", dest_dir.display());
log::info!("Searching for .app bundle in: {}", dest_dir.display());
// Use the enhanced recursive search
match self.find_app_in_directory(dest_dir).await {
@@ -820,7 +820,7 @@ impl Extractor {
// Check if the app is in a subdirectory and move it to the root if needed
let app_parent = app_path.parent().unwrap();
if app_parent != dest_dir {
println!(
log::info!(
"Found .app in subdirectory, moving to root: {} -> {}",
app_path.display(),
dest_dir.display()
@@ -837,15 +837,15 @@ impl Extractor {
}
}
println!("Successfully moved .app to: {}", target_path.display());
log::info!("Successfully moved .app to: {}", target_path.display());
Ok(target_path)
} else {
println!("Found .app at root level: {}", app_path.display());
log::info!("Found .app at root level: {}", app_path.display());
Ok(app_path)
}
}
Err(e) => {
println!("Failed to find .app bundle: {e}");
log::info!("Failed to find .app bundle: {e}");
Err("No .app found after extraction".into())
}
}
@@ -856,7 +856,7 @@ impl Extractor {
&self,
dest_dir: &Path,
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
println!(
log::info!(
"Searching for Windows executable in: {}",
dest_dir.display()
);
@@ -877,7 +877,7 @@ impl Extractor {
for exe_name in &priority_exe_names {
let exe_path = dest_dir.join(exe_name);
if exe_path.exists() {
println!("Found priority executable: {}", exe_path.display());
log::info!("Found priority executable: {}", exe_path.display());
return Ok(exe_path);
}
}
@@ -885,7 +885,7 @@ impl Extractor {
// Recursively search for executables with depth limit
match self.find_windows_executable_recursive(dest_dir, 0, 3).await {
Ok(exe_path) => {
println!(
log::info!(
"Found executable via recursive search: {}",
exe_path.display()
);
@@ -983,7 +983,7 @@ impl Extractor {
&self,
dest_dir: &Path,
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
println!("Searching for Linux executable in: {}", dest_dir.display());
log::info!("Searching for Linux executable in: {}", dest_dir.display());
// Enhanced list of common browser executable names
let exe_names = [
@@ -1031,7 +1031,7 @@ impl Extractor {
for exe_name in &exe_names {
let exe_path = dest_dir.join(exe_name);
if exe_path.exists() && self.is_executable(&exe_path) {
println!("Found executable at root level: {}", exe_path.display());
log::info!("Found executable at root level: {}", exe_path.display());
return Ok(exe_path);
}
}
@@ -1078,7 +1078,7 @@ impl Extractor {
for exe_name in &exe_names {
let exe_path = subdir_path.join(exe_name);
if exe_path.exists() && self.is_executable(&exe_path) {
println!("Found executable in subdirectory: {}", exe_path.display());
log::info!("Found executable in subdirectory: {}", exe_path.display());
return Ok(exe_path);
}
}
@@ -1091,7 +1091,7 @@ impl Extractor {
let path = entry.path();
if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) {
if file_name.ends_with(".AppImage") && self.is_executable(&path) {
println!("Found AppImage: {}", path.display());
log::info!("Found AppImage: {}", path.display());
return Ok(path);
}
}
@@ -1099,15 +1099,15 @@ impl Extractor {
}
// Last resort: recursive search for any executable file
println!("Performing recursive search for executables...");
log::info!("Performing recursive search for executables...");
match self.find_any_executable_recursive(dest_dir, 0).await {
Ok(path) => {
println!("Found executable via recursive search: {}", path.display());
log::info!("Found executable via recursive search: {}", path.display());
Ok(path)
}
Err(e) => {
// List all files in the directory for debugging
println!("Failed to find executable. Directory contents:");
log::info!("Failed to find executable. Directory contents:");
if let Ok(entries) = fs::read_dir(dest_dir) {
for entry in entries.flatten() {
let path = entry.path();
@@ -1116,7 +1116,7 @@ impl Extractor {
} else {
false
};
println!(" {} (executable: {})", path.display(), is_exec);
log::info!(" {} (executable: {})", path.display(), is_exec);
}
}
Err(
@@ -1220,7 +1220,7 @@ impl Extractor {
|| name_lower.contains("camoufox")
|| file_name.ends_with(".AppImage")
{
println!(
log::info!(
"Found priority executable at depth {}: {}",
depth,
path.display()
@@ -1262,7 +1262,7 @@ impl Extractor {
a_name.len().cmp(&b_name.len())
});
println!(
log::info!(
"Found potential executable at depth {}: {}",
depth,
potential_executables[0].display()
+3 -3
View File
@@ -120,7 +120,7 @@ impl GroupManager {
// Emit event for reactive UI updates
if let Err(e) = app_handle.emit("groups-changed", ()) {
eprintln!("Failed to emit groups-changed event: {e}");
log::error!("Failed to emit groups-changed event: {e}");
}
Ok(group)
@@ -156,7 +156,7 @@ impl GroupManager {
// Emit event for reactive UI updates
if let Err(e) = app_handle.emit("groups-changed", ()) {
eprintln!("Failed to emit groups-changed event: {e}");
log::error!("Failed to emit groups-changed event: {e}");
}
Ok(updated_group)
@@ -180,7 +180,7 @@ impl GroupManager {
// Emit event for reactive UI updates
if let Err(e) = app_handle.emit("groups-changed", ()) {
eprintln!("Failed to emit groups-changed event: {e}");
log::error!("Failed to emit groups-changed event: {e}");
}
Ok(())
+88 -49
View File
@@ -3,6 +3,7 @@ use std::env;
use std::sync::Mutex;
use tauri::{Emitter, Manager, Runtime, WebviewUrl, WebviewWindow, WebviewWindowBuilder};
use tauri_plugin_deep_link::DeepLinkExt;
use tauri_plugin_log::{Target, TargetKind};
// Store pending URLs that need to be handled when the window is ready
static PENDING_URLS: Mutex<Vec<String>> = Mutex::new(Vec::new());
@@ -152,7 +153,7 @@ async fn warm_up_nodecar(app: tauri::AppHandle) -> Result<(), String> {
match timeout(Duration::from_secs(120), exec_future).await {
Ok(Ok(_output)) => {
let duration = start_time.elapsed();
println!(
log::info!(
"Nodecar warm-up (frontend-triggered) completed in {:.2}s",
duration.as_secs_f64()
);
@@ -165,11 +166,11 @@ async fn warm_up_nodecar(app: tauri::AppHandle) -> Result<(), String> {
#[tauri::command]
async fn handle_url_open(app: tauri::AppHandle, url: String) -> Result<(), String> {
println!("handle_url_open called with URL: {url}");
log::info!("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") {
println!("Main window exists");
log::debug!("Main window exists");
// Try to show and focus the window first
let _ = window.show();
@@ -181,7 +182,7 @@ async fn handle_url_open(app: tauri::AppHandle, url: String) -> Result<(), Strin
.map_err(|e| format!("Failed to emit URL open event: {e}"))?;
} else {
// Window doesn't exist yet - add to pending URLs
println!("Main window doesn't exist, adding URL to pending list");
log::debug!("Main window doesn't exist, adding URL to pending list");
let mut pending = PENDING_URLS.lock().unwrap();
pending.push(url);
}
@@ -259,14 +260,49 @@ pub fn run() {
let startup_url = args.iter().find(|arg| arg.starts_with("http")).cloned();
if let Some(url) = startup_url.clone() {
println!("Found startup URL in command line: {url}");
log::info!("Found startup URL in command line: {url}");
let mut pending = PENDING_URLS.lock().unwrap();
pending.push(url.clone());
}
// Configure logging plugin with separate logs for dev and production
let log_file_name = if cfg!(debug_assertions) {
"DonutBrowserDev"
} else {
"DonutBrowser"
};
tauri::Builder::default()
.plugin(
tauri_plugin_log::Builder::new()
.clear_targets() // Clear default targets to avoid duplicates
.target(Target::new(TargetKind::Stdout))
.target(Target::new(TargetKind::Webview))
.target(Target::new(TargetKind::LogDir {
file_name: Some(log_file_name.to_string()),
}))
.max_file_size(100_000) // 100KB
.level(log::LevelFilter::Info)
.format(|out, message, record| {
use chrono::Local;
let now = Local::now();
let timestamp = format!(
"{}.{:03}",
now.format("%Y-%m-%d %H:%M:%S"),
now.timestamp_subsec_millis()
);
out.finish(format_args!(
"[{}][{}][{}] {}",
timestamp,
record.target(),
record.level(),
message
))
})
.build(),
)
.plugin(tauri_plugin_single_instance::init(|_, args, _cwd| {
println!("Single instance triggered with args: {args:?}");
log::info!("Single instance triggered with args: {args:?}");
}))
.plugin(tauri_plugin_deep_link::init())
.plugin(tauri_plugin_fs::init())
@@ -293,7 +329,7 @@ pub fn run() {
#[cfg(target_os = "macos")]
{
if let Err(e) = window.set_transparent_titlebar(true) {
eprintln!("Failed to set transparent titlebar: {e}");
log::warn!("Failed to set transparent titlebar: {e}");
}
}
@@ -304,7 +340,7 @@ pub fn run() {
{
// For Windows, register all deep links at runtime
if let Err(e) = app.deep_link().register_all() {
eprintln!("Failed to register deep links: {e}");
log::warn!("Failed to register deep links: {e}");
}
}
@@ -312,7 +348,7 @@ pub fn run() {
{
// On macOS, try to register deep links for development builds
if let Err(e) = app.deep_link().register_all() {
eprintln!(
log::debug!(
"Note: Deep link registration failed on macOS (this is normal for production): {e}"
);
}
@@ -322,11 +358,11 @@ pub fn run() {
let handle = handle.clone();
move |event| {
let urls = event.urls();
println!("Deep link event received with {} URLs", urls.len());
log::info!("Deep link event received with {} URLs", urls.len());
for url in urls {
let url_string = url.to_string();
println!("Deep link received: {url_string}");
log::info!("Deep link received: {url_string}");
// Clone the handle for each async task
let handle_clone = handle.clone();
@@ -334,7 +370,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}");
log::error!("Failed to handle deep link URL: {e}");
}
});
}
@@ -344,9 +380,9 @@ pub fn run() {
if let Some(startup_url) = startup_url {
let handle_clone = handle.clone();
tauri::async_runtime::spawn(async move {
println!("Processing startup URL from command line: {startup_url}");
log::info!("Processing startup URL from command line: {startup_url}");
if let Err(e) = handle_url_open(handle_clone, startup_url.clone()).await {
eprintln!("Failed to handle startup URL: {e}");
log::error!("Failed to handle startup URL: {e}");
}
});
}
@@ -366,7 +402,7 @@ pub fn run() {
{
let updater_guard = version_updater.lock().await;
if let Err(e) = updater_guard.start_background_updates().await {
eprintln!("Failed to start background updates: {e}");
log::error!("Failed to start background updates: {e}");
}
}
});
@@ -397,9 +433,9 @@ pub fn run() {
};
for url in pending_urls {
println!("Processing pending URL: {url}");
log::info!("Processing pending URL: {url}");
if let Err(e) = handle_url_open(handle_pending.clone(), url).await {
eprintln!("Failed to handle pending URL: {e}");
log::error!("Failed to handle pending URL: {e}");
}
}
});
@@ -414,35 +450,36 @@ pub fn run() {
let registry =
crate::downloaded_browsers_registry::DownloadedBrowsersRegistry::instance();
if let Err(e) = registry.cleanup_unused_binaries() {
eprintln!("Periodic cleanup failed: {e}");
log::error!("Periodic cleanup failed: {e}");
} else {
println!("Periodic cleanup completed successfully");
log::debug!("Periodic cleanup completed successfully");
}
}
});
let app_handle_update = app.handle().clone();
tauri::async_runtime::spawn(async move {
println!("Starting app update check at startup...");
log::info!("Starting app update check at startup...");
let updater = app_auto_updater::AppAutoUpdater::instance();
match updater.check_for_updates().await {
Ok(Some(update_info)) => {
println!(
log::info!(
"App update available: {} -> {}",
update_info.current_version, update_info.new_version
update_info.current_version,
update_info.new_version
);
// Emit update available event to the frontend
if let Err(e) = app_handle_update.emit("app-update-available", &update_info) {
eprintln!("Failed to emit app update event: {e}");
log::error!("Failed to emit app update event: {e}");
} else {
println!("App update event emitted successfully");
log::debug!("App update event emitted successfully");
}
}
Ok(None) => {
println!("No app updates available");
log::debug!("No app updates available");
}
Err(e) => {
eprintln!("Failed to check for app updates: {e}");
log::error!("Failed to check for app updates: {e}");
}
}
});
@@ -461,7 +498,7 @@ pub fn run() {
// Cleanup completed silently
}
Err(e) => {
eprintln!("Error during Camoufox cleanup: {e}");
log::error!("Error during Camoufox cleanup: {e}");
}
}
}
@@ -476,22 +513,24 @@ pub fn run() {
let geoip_downloader = crate::geoip_downloader::GeoIPDownloader::instance();
match geoip_downloader.check_missing_geoip_database() {
Ok(true) => {
println!("GeoIP database is missing for Camoufox profiles, downloading at startup...");
log::info!(
"GeoIP database is missing for Camoufox profiles, downloading at startup..."
);
let geoip_downloader = GeoIPDownloader::instance();
if let Err(e) = geoip_downloader
.download_geoip_database(&app_handle_geoip)
.await
{
eprintln!("Failed to download GeoIP database at startup: {e}");
log::error!("Failed to download GeoIP database at startup: {e}");
} else {
println!("GeoIP database downloaded successfully at startup");
log::info!("GeoIP database downloaded successfully at startup");
}
}
Ok(false) => {
// No Camoufox profiles or GeoIP database already available
}
Err(e) => {
eprintln!("Failed to check GeoIP database status at startup: {e}");
log::error!("Failed to check GeoIP database status at startup: {e}");
}
}
});
@@ -510,14 +549,14 @@ pub fn run() {
{
Ok(dead_pids) => {
if !dead_pids.is_empty() {
println!(
log::info!(
"Cleaned up proxies for {} dead browser processes",
dead_pids.len()
);
}
}
Err(e) => {
eprintln!("Error during proxy cleanup: {e}");
log::error!("Error during proxy cleanup: {e}");
}
}
}
@@ -538,7 +577,7 @@ pub fn run() {
let profiles = match runner.profile_manager.list_profiles() {
Ok(p) => p,
Err(e) => {
println!("Warning: Failed to list profiles in status checker: {e}");
log::warn!("Failed to list profiles in status checker: {e}");
continue;
}
};
@@ -558,9 +597,11 @@ pub fn run() {
// Only emit event if state actually changed
if last_state != is_running {
println!(
log::debug!(
"Status checker detected change for profile {}: {} -> {}",
profile.name, last_state, is_running
profile.name,
last_state,
is_running
);
#[derive(serde::Serialize)]
@@ -575,11 +616,12 @@ pub fn run() {
};
if let Err(e) = app_handle_status.emit("profile-running-changed", &payload) {
println!("Warning: Failed to emit profile running changed event: {e}");
log::warn!("Failed to emit profile running changed event: {e}");
} else {
println!(
log::debug!(
"Status checker emitted profile-running-changed event for {}: running={}",
profile.name, is_running
profile.name,
is_running
);
}
@@ -590,10 +632,7 @@ pub fn run() {
}
}
Err(e) => {
println!(
"Warning: Status check failed for profile {}: {}",
profile.name, e
);
log::warn!("Status check failed for profile {}: {}", profile.name, e);
continue;
}
}
@@ -609,12 +648,12 @@ pub fn run() {
match crate::settings_manager::get_app_settings(app_handle_api.clone()).await {
Ok(settings) => {
if settings.api_enabled {
println!("API is enabled in settings, starting API server...");
log::info!("API is enabled in settings, starting API server...");
match crate::api_server::start_api_server_internal(settings.api_port, &app_handle_api)
.await
{
Ok(port) => {
println!("API server started successfully on port {port}");
log::info!("API server started successfully on port {port}");
// Emit success toast to frontend
if let Err(e) = app_handle_api.emit(
"show-toast",
@@ -625,11 +664,11 @@ pub fn run() {
description: Some(format!("API server running on port {port}")),
},
) {
eprintln!("Failed to emit API start toast: {e}");
log::error!("Failed to emit API start toast: {e}");
}
}
Err(e) => {
eprintln!("Failed to start API server at startup: {e}");
log::error!("Failed to start API server at startup: {e}");
// Emit error toast to frontend
if let Err(toast_err) = app_handle_api.emit(
"show-toast",
@@ -640,14 +679,14 @@ pub fn run() {
description: Some(format!("Error: {e}")),
},
) {
eprintln!("Failed to emit API error toast: {toast_err}");
log::error!("Failed to emit API error toast: {toast_err}");
}
}
}
}
}
Err(e) => {
eprintln!("Failed to load app settings for API startup: {e}");
log::error!("Failed to load app settings for API startup: {e}");
}
}
});
+48 -46
View File
@@ -47,7 +47,7 @@ pub mod macos {
executable_path: &std::path::Path,
args: &[String],
) -> Result<std::process::Child, Box<dyn std::error::Error + Send + Sync>> {
println!("Launching browser on macOS: {executable_path:?} with args: {args:?}");
log::info!("Launching browser on macOS: {executable_path:?} with args: {args:?}");
// If the executable is inside an app bundle, launch via Launch Services so
// macOS recognizes the real application for privacy permissions (e.g. Screen Recording).
// This ensures TCC prompts are attributed to the browser app, not our launcher.
@@ -93,7 +93,7 @@ pub mod macos {
let profile_data_path = profile.get_profile_data_path(profiles_dir);
// First try: Use Firefox remote command
println!("Trying Firefox remote command for PID: {pid}");
log::info!("Trying Firefox remote command for PID: {pid}");
let browser = create_browser(browser_type);
if let Ok(executable_path) = browser.get_executable_path(browser_dir) {
let remote_args = vec![
@@ -107,17 +107,17 @@ pub mod macos {
match remote_output {
Ok(output) if output.status.success() => {
println!("Firefox remote command succeeded");
log::info!("Firefox remote command succeeded");
return Ok(());
}
Ok(output) => {
let stderr = String::from_utf8_lossy(&output.stderr);
println!(
log::info!(
"Firefox remote command failed with stderr: {stderr}, trying AppleScript fallback"
);
}
Err(e) => {
println!("Firefox remote command error: {e}, trying AppleScript fallback");
log::info!("Firefox remote command error: {e}, trying AppleScript fallback");
}
}
}
@@ -195,12 +195,12 @@ end try
"#
);
println!("Executing AppleScript fallback for Firefox-based browser (PID: {pid})...");
log::info!("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}");
log::info!("AppleScript failed: {error_msg}");
return Err(
format!(
"Both Firefox remote command and AppleScript failed. AppleScript error: {error_msg}"
@@ -208,7 +208,7 @@ end try
.into(),
);
} else {
println!("AppleScript succeeded");
log::info!("AppleScript succeeded");
}
Ok(())
@@ -217,13 +217,13 @@ end try
pub async fn kill_browser_process_impl(
pid: u32,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Attempting to kill browser process with PID: {pid}");
log::info!("Attempting to kill browser process with PID: {pid}");
// For Chromium-based browsers, use immediate aggressive termination
// Chromium browsers are notoriously difficult to kill on macOS due to process spawning
// Step 1: Immediate SIGKILL on main process (no graceful shutdown for Chromium)
println!("Starting immediate SIGKILL for PID: {pid}");
log::info!("Starting immediate SIGKILL for PID: {pid}");
let _ = Command::new("kill")
.args(["-KILL", &pid.to_string()])
.output();
@@ -261,7 +261,7 @@ end try
// Check if main process still exists
if system.process(Pid::from(pid as usize)).is_some() {
println!("Main process {pid} still running, using pattern-based termination");
log::info!("Main process {pid} still running, using pattern-based termination");
// Kill by common Chromium process patterns
let chromium_patterns = [
@@ -302,7 +302,7 @@ end try
if system.process(Pid::from(pid as usize)).is_some() {
// Last resort: try system kill command with different signals
println!("Process {pid} extremely persistent, trying system-level termination");
log::info!("Process {pid} extremely persistent, trying system-level termination");
let _ = Command::new("/bin/kill").args(["-KILL", &pid_str]).output();
@@ -322,12 +322,12 @@ end try
let system = System::new_all();
if system.process(Pid::from(pid as usize)).is_some() {
println!("WARNING: Process {pid} could not be terminated despite aggressive attempts");
log::info!("WARNING: Process {pid} could not be terminated despite aggressive attempts");
// Don't return error - let the UI update anyway since we tried everything
}
}
println!("Aggressive browser termination completed for PID: {pid}");
log::info!("Aggressive browser termination completed for PID: {pid}");
Ok(())
}
@@ -335,11 +335,11 @@ end try
async fn kill_chromium_process_tree_aggressive(
pid: u32,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Killing comprehensive process tree for PID: {pid}");
log::info!("Killing comprehensive process tree for PID: {pid}");
// Get all descendant processes using recursive process tree discovery
let descendant_pids = get_all_descendant_pids(pid).await;
println!(
log::info!(
"Found {} descendant processes to terminate",
descendant_pids.len()
);
@@ -347,7 +347,7 @@ end try
// Kill all descendants first (reverse order - children before parents)
for &desc_pid in descendant_pids.iter().rev() {
if desc_pid != pid {
println!("Terminating descendant process: {desc_pid}");
log::info!("Terminating descendant process: {desc_pid}");
let _ = Command::new("kill")
.args(["-KILL", &desc_pid.to_string()])
.output();
@@ -381,7 +381,7 @@ end try
// Helper function to kill all Chromium-related processes by name patterns
async fn kill_all_chromium_processes_by_name(
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Killing all Chromium-related processes by name patterns");
log::info!("Killing all Chromium-related processes by name patterns");
let chromium_patterns = [
"Chrome",
@@ -444,10 +444,10 @@ end try
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let pid = profile.process_id.unwrap();
println!("Opening URL in TOR/Mullvad browser using file-based approach (PID: {pid})");
log::info!("Opening URL in TOR/Mullvad browser using file-based approach (PID: {pid})");
// Method 1: Try using a temporary HTML file approach
println!("Attempting file-based URL opening for TOR/Mullvad browser");
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());
@@ -472,7 +472,7 @@ end try
match std::fs::write(&temp_file_path, html_content) {
Ok(()) => {
println!("Created temporary HTML file: {temp_file_path:?}");
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) {
@@ -493,15 +493,15 @@ end try
match open_result {
Ok(output) if output.status.success() => {
println!("Successfully opened URL using file-based approach");
log::info!("Successfully opened URL using file-based approach");
return Ok(());
}
Ok(output) => {
let stderr = String::from_utf8_lossy(&output.stderr);
println!("File-based approach failed: {stderr}");
log::info!("File-based approach failed: {stderr}");
}
Err(e) => {
println!("File-based approach error: {e}");
log::info!("File-based approach error: {e}");
}
}
}
@@ -509,12 +509,12 @@ end try
let _ = std::fs::remove_file(&temp_file_path);
}
Err(e) => {
println!("Failed to create temporary HTML file: {e}");
log::info!("Failed to create temporary HTML file: {e}");
}
}
// Method 2: Try using the 'open' command directly with the URL
println!("Attempting direct URL opening with 'open' command");
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) {
@@ -524,15 +524,15 @@ end try
match direct_open_result {
Ok(output) if output.status.success() => {
println!("Successfully opened URL using direct 'open' command");
log::info!("Successfully opened URL using direct 'open' command");
return Ok(());
}
Ok(output) => {
let stderr = String::from_utf8_lossy(&output.stderr);
println!("Direct 'open' command failed: {stderr}");
log::info!("Direct 'open' command failed: {stderr}");
}
Err(e) => {
println!("Direct 'open' command error: {e}");
log::info!("Direct 'open' command error: {e}");
}
}
}
@@ -561,7 +561,7 @@ end try
let pid = profile.process_id.unwrap();
// First, try using the browser's built-in URL opening capability
println!("Trying Chromium URL opening for PID: {pid}");
log::info!("Trying Chromium URL opening for PID: {pid}");
let browser = create_browser(browser_type);
if let Ok(executable_path) = browser.get_executable_path(browser_dir) {
@@ -575,15 +575,15 @@ end try
match remote_output {
Ok(output) if output.status.success() => {
println!("Chromium URL opening succeeded");
log::info!("Chromium URL opening succeeded");
return Ok(());
}
Ok(output) => {
let stderr = String::from_utf8_lossy(&output.stderr);
println!("Chromium URL opening failed: {stderr}, trying AppleScript");
log::info!("Chromium URL opening failed: {stderr}, trying AppleScript");
}
Err(e) => {
println!("Chromium URL opening error: {e}, trying AppleScript");
log::info!("Chromium URL opening error: {e}, trying AppleScript");
}
}
}
@@ -661,17 +661,17 @@ end try
"#
);
println!("Executing AppleScript for Chromium-based browser (PID: {pid})...");
log::info!("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}");
log::info!("AppleScript failed: {error_msg}");
return Err(
format!("Failed to open URL in existing Chromium-based browser: {error_msg}").into(),
);
} else {
println!("AppleScript succeeded");
log::info!("AppleScript succeeded");
}
Ok(())
@@ -722,9 +722,10 @@ pub mod windows {
executable_path: &std::path::Path,
args: &[String],
) -> Result<std::process::Child, Box<dyn std::error::Error + Send + Sync>> {
println!(
log::info!(
"Launching browser on Windows: {:?} with args: {:?}",
executable_path, args
executable_path,
args
);
// Check if the executable exists
@@ -763,7 +764,7 @@ pub mod windows {
.spawn()
.map_err(|e| format!("Failed to launch browser process: {}", e))?;
println!(
log::info!(
"Successfully launched browser process with PID: {}",
child.id()
);
@@ -930,7 +931,7 @@ pub mod windows {
let system = System::new_all();
if let Some(process) = system.process(Pid::from(pid as usize)) {
if process.kill() {
println!("Successfully killed browser process with PID: {pid}");
log::info!("Successfully killed browser process with PID: {pid}");
return Ok(());
}
}
@@ -946,7 +947,7 @@ pub mod windows {
match output {
Ok(result) => {
if result.status.success() {
println!("Successfully killed browser process with PID: {pid} using taskkill");
log::info!("Successfully killed browser process with PID: {pid} using taskkill");
Ok(())
} else {
Err(
@@ -981,9 +982,10 @@ pub mod linux {
executable_path: &std::path::Path,
args: &[String],
) -> Result<std::process::Child, Box<dyn std::error::Error + Send + Sync>> {
println!(
log::info!(
"Launching browser on Linux: {:?} with args: {:?}",
executable_path, args
executable_path,
args
);
// Check if the executable exists and is executable
@@ -1047,7 +1049,7 @@ pub mod linux {
// Set the combined LD_LIBRARY_PATH
if !ld_library_path.is_empty() {
cmd.env("LD_LIBRARY_PATH", ld_library_path.join(":"));
println!("Set LD_LIBRARY_PATH to: {}", ld_library_path.join(":"));
log::info!("Set LD_LIBRARY_PATH to: {}", ld_library_path.join(":"));
}
}
@@ -1064,7 +1066,7 @@ pub mod linux {
// Disable GPU acceleration if running in headless environments
if std::env::var("DISPLAY").is_err() || std::env::var("WAYLAND_DISPLAY").is_err() {
println!("No display detected, browser may fail to start");
log::info!("No display detected, browser may fail to start");
}
// Attempt to spawn with better error handling for architecture issues
@@ -1188,7 +1190,7 @@ pub mod linux {
return Err(format!("Process {} not found", pid).into());
}
println!("Successfully killed browser process with PID: {pid}");
log::info!("Successfully killed browser process with PID: {pid}");
Ok(())
}
}
+63 -53
View File
@@ -61,7 +61,7 @@ impl ProfileManager {
camoufox_config: Option<CamoufoxConfig>,
group_id: Option<String>,
) -> Result<BrowserProfile, Box<dyn std::error::Error>> {
println!("Attempting to create profile: {name}");
log::info!("Attempting to create profile: {name}");
// Check if a profile with this name already exists (case insensitive)
let existing_profiles = self.list_profiles()?;
@@ -86,7 +86,7 @@ impl ProfileManager {
// For Camoufox profiles, generate fingerprint during creation
let final_camoufox_config = if browser == "camoufox" {
let mut config = camoufox_config.unwrap_or_else(|| {
println!("Creating default Camoufox config for profile: {name}");
log::info!("Creating default Camoufox config for profile: {name}");
crate::camoufox_manager::CamoufoxConfig::default()
});
@@ -110,7 +110,7 @@ impl ProfileManager {
let binary_path = browser_dir.join("camoufox");
config.executable_path = Some(binary_path.to_string_lossy().to_string());
println!("Set Camoufox executable path: {:?}", config.executable_path);
log::info!("Set Camoufox executable path: {:?}", config.executable_path);
}
// Pass upstream proxy information to config for fingerprint generation
@@ -137,7 +137,7 @@ impl ProfileManager {
)
};
config.proxy = Some(proxy_url);
println!(
log::info!(
"Using upstream proxy for Camoufox fingerprint generation: {}://{}:{}",
proxy_settings.proxy_type.to_lowercase(),
proxy_settings.host,
@@ -148,7 +148,7 @@ impl ProfileManager {
// Generate fingerprint if not already provided
if config.fingerprint.is_none() {
println!("Generating fingerprint for Camoufox profile: {name}");
log::info!("Generating fingerprint for Camoufox profile: {name}");
// Use the camoufox launcher to generate the config
@@ -174,7 +174,7 @@ impl ProfileManager {
{
Ok(generated_fingerprint) => {
config.fingerprint = Some(generated_fingerprint);
println!("Successfully generated fingerprint for profile: {name}");
log::info!("Successfully generated fingerprint for profile: {name}");
}
Err(e) => {
return Err(
@@ -183,7 +183,7 @@ impl ProfileManager {
}
}
} else {
println!("Using provided fingerprint for Camoufox profile: {name}");
log::info!("Using provided fingerprint for Camoufox profile: {name}");
}
// Clear the proxy from config after fingerprint generation
@@ -217,7 +217,7 @@ impl ProfileManager {
return Err(format!("Failed to create profile file for '{name}'").into());
}
println!("Profile '{name}' created successfully with ID: {profile_id}");
log::info!("Profile '{name}' created successfully with ID: {profile_id}");
// Create user.js with common Firefox preferences and apply proxy settings if provided
if let Some(proxy_id_ref) = &proxy_id {
@@ -234,7 +234,7 @@ impl ProfileManager {
// Emit profile creation event
if let Err(e) = app_handle.emit("profiles-changed", ()) {
println!("Warning: Failed to emit profiles-changed event: {e}");
log::warn!("Warning: Failed to emit profiles-changed event: {e}");
}
Ok(profile)
@@ -320,7 +320,7 @@ impl ProfileManager {
// Emit profile rename event
if let Err(e) = app_handle.emit("profiles-changed", ()) {
println!("Warning: Failed to emit profiles-changed event: {e}");
log::warn!("Warning: Failed to emit profiles-changed event: {e}");
}
Ok(profile)
@@ -331,7 +331,7 @@ impl ProfileManager {
app_handle: &tauri::AppHandle,
profile_id: &str,
) -> Result<(), Box<dyn std::error::Error>> {
println!("Attempting to delete profile with ID: {profile_id}");
log::info!("Attempting to delete profile with ID: {profile_id}");
// Find the profile by ID
let profile_uuid =
@@ -354,9 +354,9 @@ impl ProfileManager {
// Delete the entire UUID directory (contains both metadata.json and profile data)
if profile_uuid_dir.exists() {
println!("Deleting profile directory: {}", profile_uuid_dir.display());
log::info!("Deleting profile directory: {}", profile_uuid_dir.display());
fs::remove_dir_all(&profile_uuid_dir)?;
println!("Profile directory deleted successfully");
log::info!("Profile directory deleted successfully");
}
// Verify deletion was successful
@@ -364,9 +364,10 @@ impl ProfileManager {
return Err(format!("Failed to completely delete profile '{}'", profile.name).into());
}
println!(
log::info!(
"Profile '{}' (ID: {}) deleted successfully",
profile.name, profile_id
profile.name,
profile_id
);
// Rebuild tag suggestions after deletion
@@ -376,12 +377,12 @@ impl ProfileManager {
// Always perform cleanup after profile deletion to remove unused binaries
if let Err(e) = DownloadedBrowsersRegistry::instance().cleanup_unused_binaries() {
println!("Warning: Failed to cleanup unused binaries after profile deletion: {e}");
log::warn!("Warning: Failed to cleanup unused binaries after profile deletion: {e}");
}
// Emit profile deletion event
if let Err(e) = app_handle.emit("profiles-changed", ()) {
println!("Warning: Failed to emit profiles-changed event: {e}");
log::warn!("Warning: Failed to emit profiles-changed event: {e}");
}
Ok(())
@@ -434,7 +435,7 @@ impl ProfileManager {
// Emit profile update event
if let Err(e) = app_handle.emit("profiles-changed", ()) {
println!("Warning: Failed to emit profiles-changed event: {e}");
log::warn!("Warning: Failed to emit profiles-changed event: {e}");
}
Ok(profile)
@@ -475,7 +476,7 @@ impl ProfileManager {
// Emit profile group assignment event
if let Err(e) = app_handle.emit("profiles-changed", ()) {
println!("Warning: Failed to emit profiles-changed event: {e}");
log::warn!("Warning: Failed to emit profiles-changed event: {e}");
}
Ok(())
@@ -515,7 +516,7 @@ impl ProfileManager {
// Emit profile tags update event
if let Err(e) = app_handle.emit("profiles-changed", ()) {
println!("Warning: Failed to emit profiles-changed event: {e}");
log::warn!("Warning: Failed to emit profiles-changed event: {e}");
}
Ok(profile)
@@ -558,7 +559,7 @@ impl ProfileManager {
// Emit profile deletion event
if let Err(e) = app_handle.emit("profiles-changed", ()) {
println!("Warning: Failed to emit profiles-changed event: {e}");
log::warn!("Warning: Failed to emit profiles-changed event: {e}");
}
Ok(())
@@ -610,14 +611,15 @@ impl ProfileManager {
format!("Failed to save profile: {e}").into()
})?;
println!(
log::info!(
"Camoufox configuration updated for profile '{}' (ID: {}).",
profile.name, profile_id
profile.name,
profile_id
);
// Emit profile config update event
if let Err(e) = app_handle.emit("profiles-changed", ()) {
println!("Warning: Failed to emit profiles-changed event: {e}");
log::warn!("Warning: Failed to emit profiles-changed event: {e}");
}
Ok(())
@@ -692,12 +694,12 @@ impl ProfileManager {
// Emit profile update event so frontend UIs can refresh immediately (e.g. proxy manager)
if let Err(e) = app_handle.emit("profile-updated", &profile) {
println!("Warning: Failed to emit profile update event: {e}");
log::warn!("Warning: Failed to emit profile update event: {e}");
}
// Emit general profiles changed event for profile list updates
if let Err(e) = app_handle.emit("profiles-changed", ()) {
println!("Warning: Failed to emit profiles-changed event: {e}");
log::warn!("Warning: Failed to emit profiles-changed event: {e}");
}
Ok(profile)
@@ -822,7 +824,7 @@ impl ProfileManager {
// Found a matching process
found_pid = Some(pid.as_u32());
is_running = true;
println!(
log::info!(
"Found browser process with PID: {} for profile: {}",
pid.as_u32(),
profile.name
@@ -856,14 +858,14 @@ impl ProfileManager {
if merged.process_id != Some(pid) {
merged.process_id = Some(pid);
if let Err(e) = self.save_profile(&merged) {
println!("Warning: Failed to update profile with new PID: {e}");
log::warn!("Warning: Failed to update profile with new PID: {e}");
}
}
} else if merged.process_id.is_some() {
// Clear the PID if no process found
merged.process_id = None;
if let Err(e) = self.save_profile(&merged) {
println!("Warning: Failed to clear profile PID: {e}");
log::warn!("Warning: Failed to clear profile PID: {e}");
}
// Stop any associated proxy immediately when the browser stops
@@ -876,7 +878,7 @@ impl ProfileManager {
// Emit profile update event to frontend
if let Err(e) = app_handle.emit("profile-updated", &merged) {
println!("Warning: Failed to emit profile update event: {e}");
log::warn!("Warning: Failed to emit profile update event: {e}");
}
}
@@ -916,17 +918,18 @@ impl ProfileManager {
if latest.process_id != camoufox_process.processId {
latest.process_id = camoufox_process.processId;
if let Err(e) = self.save_profile(&latest) {
println!("Warning: Failed to update Camoufox profile with process info: {e}");
log::warn!("Warning: Failed to update Camoufox profile with process info: {e}");
}
// Emit profile update event to frontend
if let Err(e) = app_handle.emit("profile-updated", &latest) {
println!("Warning: Failed to emit profile update event: {e}");
log::warn!("Warning: Failed to emit profile update event: {e}");
}
println!(
log::info!(
"Camoufox process has started for profile '{}' with PID: {:?}",
profile.name, camoufox_process.processId
profile.name,
camoufox_process.processId
);
}
}
@@ -951,7 +954,7 @@ impl ProfileManager {
if let Some(old_pid) = latest.process_id {
latest.process_id = None;
if let Err(e) = self.save_profile(&latest) {
println!("Warning: Failed to clear Camoufox profile process info: {e}");
log::warn!("Warning: Failed to clear Camoufox profile process info: {e}");
}
// Stop any proxy tied to this old PID immediately
@@ -961,7 +964,7 @@ impl ProfileManager {
// Emit profile update event to frontend
if let Err(e) = app_handle.emit("profile-updated", &latest) {
println!("Warning: Failed to emit profile update event: {e}");
log::warn!("Warning: Failed to emit profile update event: {e}");
}
}
}
@@ -969,7 +972,7 @@ impl ProfileManager {
}
Err(e) => {
// Error checking status, assume not running and clear process ID
println!("Warning: Failed to check Camoufox status via nodecar: {e}");
log::warn!("Warning: Failed to check Camoufox status via nodecar: {e}");
let profiles_dir = self.get_profiles_dir();
let profile_uuid_dir = profiles_dir.join(profile.id.to_string());
let metadata_file = profile_uuid_dir.join("metadata.json");
@@ -987,7 +990,9 @@ impl ProfileManager {
if let Some(old_pid) = latest.process_id {
latest.process_id = None;
if let Err(e2) = self.save_profile(&latest) {
println!("Warning: Failed to clear Camoufox profile process info after error: {e2}");
log::warn!(
"Warning: Failed to clear Camoufox profile process info after error: {e2}"
);
}
// Best-effort stop of proxy tied to old PID
@@ -997,7 +1002,7 @@ impl ProfileManager {
// Emit profile update event to frontend
if let Err(e3) = app_handle.emit("profile-updated", &latest) {
println!("Warning: Failed to emit profile update event: {e3}");
log::warn!("Warning: Failed to emit profile update event: {e3}");
}
}
}
@@ -1086,7 +1091,7 @@ impl ProfileManager {
// Remove prefs.js if it exists to ensure Firefox reads user.js instead
// Firefox may cache proxy settings in prefs.js, so we need to clear it
if prefs_js_path.exists() {
println!("Removing prefs.js to ensure Firefox reads updated user.js settings");
log::info!("Removing prefs.js to ensure Firefox reads updated user.js settings");
let _ = fs::remove_file(&prefs_js_path);
}
@@ -1109,16 +1114,19 @@ impl ProfileManager {
let proxy_url = if let Some(internal) = internal_proxy {
// Use internal proxy (local proxy) as the primary proxy
// This is the local proxy that forwards to the upstream proxy
println!(
log::info!(
"Applying local proxy settings to Firefox profile: {}:{}",
internal.host, internal.port
internal.host,
internal.port
);
format!("HTTP {}:{}", internal.host, internal.port)
} else {
// Use user-configured proxy directly (upstream proxy)
println!(
log::info!(
"Applying upstream proxy settings to Firefox profile: {}:{} ({})",
proxy.host, proxy.port, proxy.proxy_type
proxy.host,
proxy.port,
proxy.proxy_type
);
match proxy.proxy_type.as_str() {
"http" => format!("HTTP {}:{}", proxy.host, proxy.port),
@@ -1136,13 +1144,13 @@ impl ProfileManager {
// Save PAC file in UUID directory
let pac_path = uuid_dir.join("proxy.pac");
println!(
log::info!(
"Creating PAC file at: {} with proxy: {}",
pac_path.display(),
proxy_url
);
fs::write(&pac_path, &pac_content)?;
println!(
log::info!(
"Created PAC file at: {} with content: {}",
pac_path.display(),
pac_content
@@ -1162,8 +1170,8 @@ impl ProfileManager {
format!("file://{}", pac_path_absolute.to_string_lossy())
};
println!("PAC file path (absolute): {}", pac_path_absolute.display());
println!("PAC file URL for Firefox: {}", pac_url);
log::info!("PAC file path (absolute): {}", pac_path_absolute.display());
log::info!("PAC file URL for Firefox: {}", pac_url);
preferences.extend([
"user_pref(\"network.proxy.type\", 2);".to_string(),
@@ -1183,16 +1191,18 @@ impl ProfileManager {
// Write settings to user.js file
let user_js_content = preferences.join("\n");
fs::write(user_js_path, &user_js_content)?;
println!("Updated user.js with proxy settings. PAC URL: {}", pac_url);
log::info!("Updated user.js with proxy settings. PAC URL: {}", pac_url);
if let Some(internal) = internal_proxy {
println!(
log::info!(
"Firefox will use LOCAL proxy: {}:{} (which forwards to upstream)",
internal.host, internal.port
internal.host,
internal.port
);
} else {
println!(
log::info!(
"Firefox will use UPSTREAM proxy directly: {}:{}",
proxy.host, proxy.port
proxy.host,
proxy.port
);
}
+1 -1
View File
@@ -566,7 +566,7 @@ impl ProfileImporter {
// Save the profile metadata
self.profile_manager.save_profile(&profile)?;
println!(
log::info!(
"Successfully imported profile '{}' from '{}'",
new_profile_name,
source_path.display()
+22 -20
View File
@@ -85,7 +85,7 @@ impl ProxyManager {
// Load stored proxies on initialization
if let Err(e) = manager.load_stored_proxies() {
eprintln!("Warning: Failed to load stored proxies: {e}");
log::warn!("Failed to load stored proxies: {e}");
}
manager
@@ -222,11 +222,11 @@ impl ProxyManager {
let proxies_dir = self.get_proxies_dir();
if !proxies_dir.exists() {
eprintln!("Proxies directory does not exist: {:?}", proxies_dir);
log::debug!("Proxies directory does not exist: {:?}", proxies_dir);
return Ok(()); // No proxies directory yet
}
eprintln!("Loading stored proxies from: {:?}", proxies_dir);
log::debug!("Loading stored proxies from: {:?}", proxies_dir);
let mut stored_proxies = self.stored_proxies.lock().unwrap();
let mut loaded_count = 0;
@@ -242,18 +242,19 @@ impl ProxyManager {
Ok(content) => {
match serde_json::from_str::<StoredProxy>(&content) {
Ok(proxy) => {
eprintln!("Loaded stored proxy: {} ({})", proxy.name, proxy.id);
log::debug!("Loaded stored proxy: {} ({})", proxy.name, proxy.id);
stored_proxies.insert(proxy.id.clone(), proxy);
loaded_count += 1;
}
Err(e) => {
// Check if this is a ProxyConfig file (from proxy_storage.rs) - skip it
if serde_json::from_str::<crate::proxy_storage::ProxyConfig>(&content).is_ok() {
eprintln!("Skipping ProxyConfig file (not a StoredProxy): {:?}", path);
log::debug!("Skipping ProxyConfig file (not a StoredProxy): {:?}", path);
} else {
eprintln!(
log::warn!(
"Failed to parse proxy file {:?} as StoredProxy: {}",
path, e
path,
e
);
error_count += 1;
}
@@ -261,16 +262,17 @@ impl ProxyManager {
}
}
Err(e) => {
eprintln!("Failed to read proxy file {:?}: {}", path, e);
log::warn!("Failed to read proxy file {:?}: {}", path, e);
error_count += 1;
}
}
}
}
eprintln!(
log::info!(
"Loaded {} stored proxies ({} errors)",
loaded_count, error_count
loaded_count,
error_count
);
Ok(())
}
@@ -321,12 +323,12 @@ impl ProxyManager {
}
if let Err(e) = self.save_proxy(&stored_proxy) {
eprintln!("Warning: Failed to save proxy: {e}");
log::warn!("Failed to save proxy: {e}");
}
// Emit event for reactive UI updates
if let Err(e) = app_handle.emit("proxies-changed", ()) {
eprintln!("Failed to emit proxies-changed event: {e}");
log::error!("Failed to emit proxies-changed event: {e}");
}
Ok(stored_proxy)
@@ -388,12 +390,12 @@ impl ProxyManager {
};
if let Err(e) = self.save_proxy(&updated_proxy) {
eprintln!("Warning: Failed to save proxy: {e}");
log::warn!("Failed to save proxy: {e}");
}
// Emit event for reactive UI updates
if let Err(e) = app_handle.emit("proxies-changed", ()) {
eprintln!("Failed to emit proxies-changed event: {e}");
log::error!("Failed to emit proxies-changed event: {e}");
}
Ok(updated_proxy)
@@ -413,12 +415,12 @@ impl ProxyManager {
}
if let Err(e) = self.delete_proxy_file(proxy_id) {
eprintln!("Warning: Failed to delete proxy file: {e}");
log::warn!("Failed to delete proxy file: {e}");
}
// Emit event for reactive UI updates
if let Err(e) = app_handle.emit("proxies-changed", ()) {
eprintln!("Failed to emit proxies-changed event: {e}");
log::error!("Failed to emit proxies-changed event: {e}");
}
Ok(())
@@ -835,7 +837,7 @@ impl ProxyManager {
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
eprintln!("Proxy stop error: {stderr}");
log::warn!("Proxy stop error: {stderr}");
// We still return Ok since we've already removed the proxy from our tracking
}
@@ -851,7 +853,7 @@ impl ProxyManager {
// Emit event for reactive UI updates
if let Err(e) = app_handle.emit("proxies-changed", ()) {
eprintln!("Failed to emit proxies-changed event: {e}");
log::error!("Failed to emit proxies-changed event: {e}");
}
Ok(())
@@ -890,13 +892,13 @@ impl ProxyManager {
};
for dead_pid in &dead_pids {
println!("Cleaning up proxy for dead browser process PID: {dead_pid}");
log::info!("Cleaning up proxy for dead browser process PID: {dead_pid}");
let _ = self.stop_proxy(app_handle.clone(), *dead_pid).await;
}
// Emit event for reactive UI updates
if let Err(e) = app_handle.emit("proxies-changed", ()) {
eprintln!("Failed to emit proxies-changed event: {e}");
log::error!("Failed to emit proxies-changed event: {e}");
}
Ok(dead_pids)
+1 -1
View File
@@ -47,7 +47,7 @@ pub async fn start_proxy_process(
{
let log_path = std::path::PathBuf::from("/tmp").join(format!("donut-proxy-{}.log", id));
if let Ok(file) = std::fs::File::create(&log_path) {
eprintln!("Proxy worker stderr will be logged to: {:?}", log_path);
log::error!("Proxy worker stderr will be logged to: {:?}", log_path);
cmd.stderr(Stdio::from(file));
} else {
cmd.stderr(Stdio::null());
+33 -31
View File
@@ -105,7 +105,7 @@ async fn handle_connect(
return Ok(response);
}
Err(e) => {
eprintln!("Failed to connect to {}: {}", target_addr, e);
log::error!("Failed to connect to {}: {}", target_addr, e);
let mut response =
Response::new(Full::new(Bytes::from(format!("Connection failed: {}", e))));
*response.status_mut() = StatusCode::BAD_GATEWAY;
@@ -135,7 +135,7 @@ async fn handle_connect(
Ok(response)
}
Err(e) => {
eprintln!("HTTP proxy CONNECT failed: {}", e);
log::error!("HTTP proxy CONNECT failed: {}", e);
let mut response = Response::new(Full::new(Bytes::from(format!(
"Proxy connection failed: {}",
e
@@ -173,7 +173,7 @@ async fn handle_connect(
Ok(response)
}
Err(e) => {
eprintln!("SOCKS connection failed: {}", e);
log::error!("SOCKS connection failed: {}", e);
let mut response = Response::new(Full::new(Bytes::from(format!(
"SOCKS connection failed: {}",
e
@@ -306,7 +306,7 @@ async fn handle_http(
match build_reqwest_client_with_proxy(upstream) {
Ok(c) => c,
Err(e) => {
eprintln!("Failed to create proxy client: {}", e);
log::error!("Failed to create proxy client: {}", e);
let mut response = Response::new(Full::new(Bytes::from(format!(
"Proxy configuration error: {}",
e
@@ -385,7 +385,7 @@ async fn handle_http(
Ok(hyper_response)
}
Err(e) => {
eprintln!("Request failed: {}", e);
log::error!("Request failed: {}", e);
let mut response = Response::new(Full::new(Bytes::from(format!("Request failed: {}", e))));
*response.status_mut() = StatusCode::BAD_GATEWAY;
Ok(response)
@@ -426,7 +426,7 @@ fn build_reqwest_client_with_proxy(
}
pub async fn run_proxy_server(config: ProxyConfig) -> Result<(), Box<dyn std::error::Error>> {
eprintln!(
log::error!(
"Proxy worker starting, looking for config id: {}",
config.id
);
@@ -435,28 +435,30 @@ pub async fn run_proxy_server(config: ProxyConfig) -> Result<(), Box<dyn std::er
let config = match crate::proxy_storage::get_proxy_config(&config.id) {
Some(c) => c,
None => {
eprintln!("Config not found for id: {}", config.id);
log::error!("Config not found for id: {}", config.id);
return Err("Config not found".into());
}
};
eprintln!(
log::error!(
"Found config: id={}, port={:?}, upstream={}",
config.id, config.local_port, config.upstream_url
config.id,
config.local_port,
config.upstream_url
);
eprintln!("Starting proxy server for config id: {}", config.id);
log::error!("Starting proxy server for config id: {}", config.id);
// Determine the bind address
let bind_addr = SocketAddr::from(([127, 0, 0, 1], config.local_port.unwrap_or(0)));
eprintln!("Attempting to bind proxy server to {}", bind_addr);
log::error!("Attempting to bind proxy server to {}", bind_addr);
// Bind to the port
let listener = TcpListener::bind(bind_addr).await?;
let actual_port = listener.local_addr()?.port();
eprintln!("Successfully bound to port {}", actual_port);
log::error!("Successfully bound to port {}", actual_port);
// Update config with actual port and local_url
let mut updated_config = config.clone();
@@ -464,12 +466,12 @@ pub async fn run_proxy_server(config: ProxyConfig) -> Result<(), Box<dyn std::er
updated_config.local_url = Some(format!("http://127.0.0.1:{}", actual_port));
// Save the updated config
eprintln!(
log::error!(
"Saving updated config with local_url={:?}",
updated_config.local_url
);
if !crate::proxy_storage::update_proxy_config(&updated_config) {
eprintln!("Failed to update proxy config");
log::error!("Failed to update proxy config");
return Err("Failed to update proxy config".into());
}
@@ -479,12 +481,12 @@ pub async fn run_proxy_server(config: ProxyConfig) -> Result<(), Box<dyn std::er
Some(updated_config.upstream_url.clone())
};
eprintln!("Proxy server bound to 127.0.0.1:{}", actual_port);
eprintln!(
log::error!("Proxy server bound to 127.0.0.1:{}", actual_port);
log::error!(
"Proxy server listening on 127.0.0.1:{} (ready to accept connections)",
actual_port
);
eprintln!("Proxy server entering accept loop - process should stay alive");
log::error!("Proxy server entering accept loop - process should stay alive");
// Keep the runtime alive with an infinite loop
// This ensures the process doesn't exit even if there are no active connections
@@ -521,14 +523,14 @@ pub async fn run_proxy_server(config: ProxyConfig) -> Result<(), Box<dyn std::er
}
// Handle CONNECT manually
eprintln!(
log::error!(
"DEBUG: Handling CONNECT manually for: {}",
String::from_utf8_lossy(&full_request[..full_request.len().min(100)])
);
if let Err(e) = handle_connect_from_buffer(stream, full_request, upstream).await {
eprintln!("Error handling CONNECT request: {:?}", e);
log::error!("Error handling CONNECT request: {:?}", e);
} else {
eprintln!("DEBUG: CONNECT handled successfully");
log::error!("DEBUG: CONNECT handled successfully");
}
return;
}
@@ -543,7 +545,7 @@ pub async fn run_proxy_server(config: ProxyConfig) -> Result<(), Box<dyn std::er
let service = service_fn(move |req| handle_request(req, upstream.clone()));
if let Err(err) = http1::Builder::new().serve_connection(io, service).await {
eprintln!("Error serving connection: {:?}", err);
log::error!("Error serving connection: {:?}", err);
}
return;
}
@@ -555,12 +557,12 @@ pub async fn run_proxy_server(config: ProxyConfig) -> Result<(), Box<dyn std::er
let service = service_fn(move |req| handle_request(req, upstream.clone()));
if let Err(err) = http1::Builder::new().serve_connection(io, service).await {
eprintln!("Error serving connection: {:?}", err);
log::error!("Error serving connection: {:?}", err);
}
});
}
Err(e) => {
eprintln!("Error accepting connection: {:?}", e);
log::error!("Error accepting connection: {:?}", e);
// Continue accepting connections even if one fails
// Add a small delay to avoid busy-waiting on errors
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
@@ -689,24 +691,24 @@ async fn handle_connect_from_buffer(
.await?;
client_stream.flush().await?;
eprintln!("DEBUG: Sent 200 Connection Established response, starting tunnel");
log::error!("DEBUG: Sent 200 Connection Established response, starting tunnel");
// Now tunnel data bidirectionally
// Split streams for bidirectional copying
let (mut client_read, mut client_write) = tokio::io::split(client_stream);
let (mut target_read, mut target_write) = tokio::io::split(target_stream);
eprintln!("DEBUG: Starting bidirectional tunnel");
log::error!("DEBUG: Starting bidirectional tunnel");
// Spawn two tasks to forward data in both directions
let client_to_target = tokio::spawn(async move {
let result = tokio::io::copy(&mut client_read, &mut target_write).await;
match result {
Ok(bytes) => {
eprintln!("DEBUG: Tunneled {} bytes from client->target", bytes);
log::error!("DEBUG: Tunneled {} bytes from client->target", bytes);
}
Err(e) => {
eprintln!("Error forwarding client->target: {:?}", e);
log::error!("Error forwarding client->target: {:?}", e);
}
}
});
@@ -715,10 +717,10 @@ async fn handle_connect_from_buffer(
let result = tokio::io::copy(&mut target_read, &mut client_write).await;
match result {
Ok(bytes) => {
eprintln!("DEBUG: Tunneled {} bytes from target->client", bytes);
log::error!("DEBUG: Tunneled {} bytes from target->client", bytes);
}
Err(e) => {
eprintln!("Error forwarding target->client: {:?}", e);
log::error!("Error forwarding target->client: {:?}", e);
}
}
});
@@ -726,10 +728,10 @@ async fn handle_connect_from_buffer(
// Wait for either direction to finish (connection closed)
tokio::select! {
_ = client_to_target => {
eprintln!("DEBUG: Client->target tunnel closed");
log::error!("DEBUG: Client->target tunnel closed");
}
_ = target_to_client => {
eprintln!("DEBUG: Target->client tunnel closed");
log::error!("DEBUG: Target->client tunnel closed");
}
}
+3 -3
View File
@@ -110,17 +110,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}");
log::warn!("Warning: Failed to update settings file with defaults: {e}");
}
Ok(settings)
}
Err(e) => {
eprintln!("Warning: Failed to parse settings file, using defaults: {e}");
log::warn!("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}");
log::warn!("Warning: Failed to save default settings: {save_error}");
}
Ok(default_settings)
+13 -13
View File
@@ -129,14 +129,14 @@ impl VersionUpdater {
let should_update = state.last_update_time == 0 || elapsed_secs >= update_interval_secs;
if should_update {
println!(
log::debug!(
"Background update needed: last_update={}, elapsed={}h, required={}h",
state.last_update_time,
elapsed_secs / 3600,
state.update_interval_hours
);
} else {
println!(
log::debug!(
"Background update not needed: last_update={}, elapsed={}h, required={}h",
state.last_update_time,
elapsed_secs / 3600,
@@ -152,12 +152,12 @@ impl VersionUpdater {
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Only run if an update is actually needed
if !Self::should_run_background_update() {
println!("No startup version update needed");
log::debug!("No startup version update needed");
return Ok(());
}
if let Some(ref app_handle) = self.app_handle {
println!("Running startup version update...");
log::info!("Running startup version update...");
match self.update_all_browser_versions(app_handle).await {
Ok(_) => {
@@ -168,13 +168,13 @@ impl VersionUpdater {
};
if let Err(e) = Self::save_background_update_state(&state) {
eprintln!("Failed to save background update state: {e}");
log::error!("Failed to save background update state: {e}");
} else {
println!("Startup version update completed successfully");
log::info!("Startup version update completed successfully");
}
}
Err(e) => {
eprintln!("Startup version update failed: {e}");
log::error!("Startup version update failed: {e}");
return Err(e);
}
}
@@ -280,11 +280,11 @@ impl VersionUpdater {
};
if let Err(e) = app_handle.emit("version-update-progress", &initial_progress) {
eprintln!("Failed to emit initial progress: {e}");
log::error!("Failed to emit initial progress: {e}");
}
for (index, browser) in supported_browsers.iter().enumerate() {
println!("Updating browser versions for: {browser}");
log::debug!("Updating browser versions for: {browser}");
// Emit progress update for current browser
let progress = VersionUpdateProgress {
@@ -297,7 +297,7 @@ impl VersionUpdater {
};
if let Err(e) = app_handle.emit("version-update-progress", &progress) {
eprintln!("Failed to emit progress for {browser}: {e}");
log::error!("Failed to emit progress for {browser}: {e}");
}
match self.update_browser_versions(browser).await {
@@ -323,7 +323,7 @@ impl VersionUpdater {
};
if let Err(e) = app_handle.emit("version-update-progress", &progress) {
eprintln!("Failed to emit progress with versions for {browser}: {e}");
log::error!("Failed to emit progress with versions for {browser}: {e}");
}
}
Err(e) => {
@@ -393,7 +393,7 @@ impl VersionUpdater {
};
if let Err(e) = Self::save_background_update_state(&state) {
eprintln!("Failed to save background update state after manual update: {e}");
log::error!("Failed to save background update state after manual update: {e}");
}
Ok(results)
@@ -506,7 +506,7 @@ pub async fn clear_all_version_cache_and_refetch(
.auto_updater
.save_auto_update_state(&final_state)
{
eprintln!("Warning: Failed to re-enable browsers after cache clear: {e}");
log::warn!("Failed to re-enable browsers after cache clear: {e}");
}
result?;
+6
View File
@@ -2,10 +2,12 @@
import { Geist, Geist_Mono } from "next/font/google";
import "@/styles/globals.css";
import "flag-icons/css/flag-icons.min.css";
import { useEffect } from "react";
import { CustomThemeProvider } from "@/components/theme-provider";
import { Toaster } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { WindowDragArea } from "@/components/window-drag-area";
import { setupLogging } from "@/lib/logger";
const geistSans = Geist({
variable: "--font-geist-sans",
@@ -22,6 +24,10 @@ export default function RootLayout({
}: Readonly<{
children: React.ReactNode;
}>) {
useEffect(() => {
void setupLogging();
}, []);
return (
<html lang="en" suppressHydrationWarning>
<body
+42
View File
@@ -0,0 +1,42 @@
import {
attachConsole,
debug,
error,
info,
trace,
warn,
} from "@tauri-apps/plugin-log";
let consoleAttached = false;
export async function setupLogging() {
if (consoleAttached) {
return;
}
try {
await attachConsole();
consoleAttached = true;
} catch (err) {
// If attachConsole fails, log to regular console as fallback
console.error("Failed to attach console to logging plugin:", err);
}
}
export const logger = {
error: (message: string, ...args: unknown[]) => {
error(`${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}`);
},
warn: (message: string, ...args: unknown[]) => {
warn(`${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}`);
},
info: (message: string, ...args: unknown[]) => {
info(`${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}`);
},
debug: (message: string, ...args: unknown[]) => {
debug(`${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}`);
},
log: (message: string, ...args: unknown[]) => {
trace(`${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}`);
},
};