mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-05-09 19:47:32 +02:00
refactor: add proper logging
This commit is contained in:
@@ -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",
|
||||
|
||||
Generated
+10
@@ -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
|
||||
|
||||
Generated
+303
@@ -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"
|
||||
|
||||
@@ -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"] }
|
||||
|
||||
@@ -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
@@ -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(¤t_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!(
|
||||
|
||||
@@ -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(¤t_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, ¤t_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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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}"))
|
||||
|
||||
@@ -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}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
@@ -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}");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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?;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(" ")}`);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user