Compare commits

...

15 Commits

Author SHA1 Message Date
zhom e0a1dd5a8a refactor: more robust zip extraction and handle invalid characters 2025-08-08 10:09:43 +04:00
zhom e48b681215 refactor: better error handling for browser download 2025-08-08 09:50:26 +04:00
zhom 6796912606 test: properly mock api requests 2025-08-08 07:54:11 +04:00
zhom 7105f6544f test: cross-platform binary check 2025-08-08 07:10:27 +04:00
zhom 3003f868e7 chore: formatting 2025-08-08 06:42:36 +04:00
zhom b733d26f10 chore: linting 2025-08-08 06:33:49 +04:00
zhom 675c2417d7 chore: linting 2025-08-08 06:23:49 +04:00
zhom e10a7bf089 refactor: migrate from external commands to rust crates for extraction 2025-08-08 05:48:42 +04:00
zhom c8e3cd39ff build: don't fail fast 2025-08-08 05:16:40 +04:00
zhom 0103150dc7 build: run rust linting on ubuntu 2025-08-08 05:14:08 +04:00
zhom be57ac3219 chore: don't format md files 2025-08-08 02:51:22 +04:00
zhom b4067b5e34 build: remove file_pattern property from changelog creator 2025-08-07 23:17:15 +04:00
zhom 3fa8822139 build: disable camoufox installation 2025-08-07 23:10:06 +04:00
zhom 1e0ef0b497 Merge pull request #61 from zhom/contributors-readme-action-eImXtNP1X9
docs(contributor): contributors readme action update
2025-08-07 09:36:05 +04:00
github-actions[bot] 2da832f100 docs(contributor): contrib-readme-action has updated readme 2025-08-07 04:10:57 +00:00
21 changed files with 1166 additions and 782 deletions
+4 -5
View File
@@ -30,9 +30,8 @@ permissions:
jobs:
build:
strategy:
fail-fast: true
matrix:
os: [macos-latest]
os: [macos-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
@@ -87,9 +86,9 @@ jobs:
fi
# TODO: replace with an integration test that fetches everything from rust
- name: Download Camoufox for testing
run: npx camoufox-js fetch
continue-on-error: true
# - name: Download Camoufox for testing
# run: npx camoufox-js fetch
# continue-on-error: true
- name: Copy nodecar binary to Tauri binaries
shell: bash
+3 -4
View File
@@ -154,9 +154,9 @@ jobs:
cp nodecar/nodecar-bin src-tauri/binaries/nodecar-${{ matrix.target }}
fi
- name: Download Camoufox for testing
run: npx camoufox-js fetch
continue-on-error: true
# - name: Download Camoufox for testing
# run: npx camoufox-js fetch
# continue-on-error: true
- name: Build frontend
run: pnpm build
@@ -179,4 +179,3 @@ jobs:
with:
branch: main
commit_message: "docs: update CHANGELOG.md for ${{ github.ref_name }} [skip ci]"
file_pattern: CHANGELOG.md
+3 -3
View File
@@ -153,9 +153,9 @@ jobs:
cp nodecar/nodecar-bin src-tauri/binaries/nodecar-${{ matrix.target }}
fi
- name: Download Camoufox for testing
run: npx camoufox-js fetch
continue-on-error: true
# - name: Download Camoufox for testing
# run: npx camoufox-js fetch
# continue-on-error: true
- name: Build frontend
run: pnpm build
+3
View File
@@ -26,6 +26,7 @@
"codegen",
"codesign",
"CTYPE",
"daijro",
"dataclasses",
"datareporting",
"datas",
@@ -44,6 +45,7 @@
"esac",
"esbuild",
"etree",
"flate",
"frontmost",
"geoip",
"getcwd",
@@ -78,6 +80,7 @@
"libxdo",
"localtime",
"lxml",
"lzma",
"mmdb",
"mountpoint",
"msiexec",
+4 -4
View File
@@ -84,8 +84,8 @@ Have questions or want to contribute? We'd love to hear from you!
<!-- readme: collaborators,contributors -start -->
<table>
<tbody>
<tr>
<tbody>
<tr>
<td align="center">
<a href="https://github.com/zhom">
<img src="https://avatars.githubusercontent.com/u/2717306?v=4" width="100;" alt="zhom"/>
@@ -93,8 +93,8 @@ Have questions or want to contribute? We'd love to hear from you!
<sub><b>zhom</b></sub>
</a>
</td>
</tr>
<tbody>
</tr>
<tbody>
</table>
<!-- readme: collaborators,contributors -end -->
+1 -1
View File
@@ -72,7 +72,7 @@
},
"packageManager": "pnpm@10.13.1",
"lint-staged": {
"**/*.{js,jsx,ts,tsx,json,css,md}": [
"**/*.{js,jsx,ts,tsx,json,css}": [
"biome check --fix"
],
"src-tauri/**/*.rs": [
+118 -1
View File
@@ -429,6 +429,18 @@ dependencies = [
"libbz2-rs-sys",
]
[[package]]
name = "cab"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "171228650e6721d5acc0868a462cd864f49ac5f64e4a42cde270406e64e404d2"
dependencies = [
"byteorder",
"flate2",
"lzxd",
"time",
]
[[package]]
name = "cairo-rs"
version = "0.18.5"
@@ -524,6 +536,17 @@ dependencies = [
"uuid",
]
[[package]]
name = "cfb"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a4f8e55be323b378facfcf1f06aa97f6ec17cf4ac84fb17325093aaf62da41"
dependencies = [
"byteorder",
"fnv",
"uuid",
]
[[package]]
name = "cfg-expr"
version = "0.15.8"
@@ -691,6 +714,21 @@ dependencies = [
"libc",
]
[[package]]
name = "crc"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
dependencies = [
"crc-catalog",
]
[[package]]
name = "crc-catalog"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
[[package]]
name = "crc32fast"
version = "1.5.0"
@@ -987,20 +1025,25 @@ version = "0.8.2"
dependencies = [
"async-trait",
"base64 0.22.1",
"bzip2",
"chrono",
"core-foundation 0.10.1",
"directories",
"flate2",
"futures-util",
"http-body-util",
"hyper",
"hyper-util",
"lazy_static",
"lzma-rs",
"msi-extract",
"objc2 0.6.1",
"objc2-app-kit 0.3.1",
"reqwest",
"serde",
"serde_json",
"sysinfo",
"tar",
"tauri",
"tauri-build",
"tauri-plugin-deep-link",
@@ -1192,6 +1235,18 @@ dependencies = [
"rustc_version",
]
[[package]]
name = "filetime"
version = "0.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586"
dependencies = [
"cfg-if",
"libc",
"libredox",
"windows-sys 0.59.0",
]
[[package]]
name = "flate2"
version = "1.1.2"
@@ -2066,7 +2121,7 @@ version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7"
dependencies = [
"cfb",
"cfb 0.7.3",
]
[[package]]
@@ -2330,6 +2385,7 @@ checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
dependencies = [
"bitflags 2.9.1",
"libc",
"redox_syscall",
]
[[package]]
@@ -2369,6 +2425,22 @@ version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "lzma-rs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
dependencies = [
"byteorder",
"crc",
]
[[package]]
name = "lzxd"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b29dffab797218e12e4df08ef5d15ab9efca2504038b1b32b9b32fc844b39c9"
[[package]]
name = "mac"
version = "0.1.1"
@@ -2468,6 +2540,30 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "msi"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a2332f87a064dea9cce571408c879e0da8dc193b3af06a2b3b2604ee4182a32"
dependencies = [
"byteorder",
"cfb 0.10.0",
"encoding_rs",
"uuid",
]
[[package]]
name = "msi-extract"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32047fe35aac08636833dcae558307dafc7679726b97f56449c3c126ed4be108"
dependencies = [
"cab",
"cfb 0.10.0",
"msi",
"thiserror 2.0.12",
]
[[package]]
name = "muda"
version = "0.17.1"
@@ -4361,6 +4457,17 @@ dependencies = [
"syn 2.0.104",
]
[[package]]
name = "tar"
version = "0.4.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]]
name = "target-lexicon"
version = "0.12.16"
@@ -6212,6 +6319,16 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "xattr"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af3a19837351dc82ba89f8a125e22a3c475f05aba604acc023d62b2739ae2909"
dependencies = [
"libc",
"rustix",
]
[[package]]
name = "xdg-home"
version = "1.3.0"
+6 -3
View File
@@ -36,6 +36,12 @@ lazy_static = "1.4"
base64 = "0.22"
async-trait = "0.1"
futures-util = "0.3"
zip = "4"
tar = "0"
bzip2 = "0"
flate2 = "1"
lzma-rs = "0"
msi-extract = "0"
uuid = { version = "1.0", features = ["v4", "serde"] }
url = "2.5"
@@ -44,9 +50,6 @@ chrono = { version = "0.4", features = ["serde"] }
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\"))".dependencies]
tauri-plugin-single-instance = { version = "2", features = ["deep-link"] }
[target.'cfg(windows)'.dependencies]
zip = "4"
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.10"
objc2 = "0.6.1"
+11
View File
@@ -1678,11 +1678,22 @@ mod tests {
"name": "Release v1.81.9 (Chromium 137.0.7151.104)",
"prerelease": false,
"published_at": "2024-01-15T10:00:00Z",
"draft": false,
"assets": [
{
"name": "brave-v1.81.9-universal.dmg",
"browser_download_url": "https://example.com/brave-1.81.9-universal.dmg",
"size": 200000000
},
{
"name": "brave-browser-1.81.9-linux-amd64.zip",
"browser_download_url": "https://example.com/brave-1.81.9-linux-amd64.zip",
"size": 180000000
},
{
"name": "BraveBrowserStandaloneSetup.exe",
"browser_download_url": "https://example.com/brave-1.81.9-setup.exe",
"size": 150000000
}
]
}
+1 -1
View File
@@ -536,7 +536,7 @@ impl AppAutoUpdater {
/// Install the update by replacing the current app
async fn install_update(
&self,
installer_path: &Path,
#[allow(unused_variables)] installer_path: &Path,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
#[cfg(target_os = "macos")]
{
+62 -13
View File
@@ -1037,9 +1037,34 @@ mod tests {
let browser_dir = binaries_dir.join("firefox").join("139.0");
fs::create_dir_all(&browser_dir).unwrap();
// Create a mock .app directory
let app_dir = browser_dir.join("Firefox.app");
fs::create_dir_all(&app_dir).unwrap();
#[cfg(target_os = "macos")]
{
// Create a mock .app directory for macOS
let app_dir = browser_dir.join("Firefox.app");
fs::create_dir_all(&app_dir).unwrap();
}
#[cfg(target_os = "linux")]
{
// Create a mock firefox subdirectory and executable for Linux
let firefox_subdir = browser_dir.join("firefox");
fs::create_dir_all(&firefox_subdir).unwrap();
let executable_path = firefox_subdir.join("firefox");
fs::write(&executable_path, "mock executable").unwrap();
// Set executable permissions on Linux
use std::os::unix::fs::PermissionsExt;
let mut permissions = executable_path.metadata().unwrap().permissions();
permissions.set_mode(0o755);
fs::set_permissions(&executable_path, permissions).unwrap();
}
#[cfg(target_os = "windows")]
{
// Create a mock firefox.exe for Windows
let executable_path = browser_dir.join("firefox.exe");
fs::write(&executable_path, "mock executable").unwrap();
}
let browser = FirefoxBrowser::new(BrowserType::Firefox);
assert!(browser.is_version_downloaded("139.0", binaries_dir));
@@ -1048,15 +1073,39 @@ mod tests {
// Test with Chromium browser with new path structure
let chromium_dir = binaries_dir.join("chromium").join("1465660");
fs::create_dir_all(&chromium_dir).unwrap();
let chromium_app_dir = chromium_dir.join("Chromium.app");
fs::create_dir_all(chromium_app_dir.join("Contents").join("MacOS")).unwrap();
// Create a mock executable
let executable_path = chromium_app_dir
.join("Contents")
.join("MacOS")
.join("Chromium");
fs::write(&executable_path, "mock executable").unwrap();
#[cfg(target_os = "macos")]
{
let chromium_app_dir = chromium_dir.join("Chromium.app");
fs::create_dir_all(chromium_app_dir.join("Contents").join("MacOS")).unwrap();
// Create a mock executable
let executable_path = chromium_app_dir
.join("Contents")
.join("MacOS")
.join("Chromium");
fs::write(&executable_path, "mock executable").unwrap();
}
#[cfg(target_os = "linux")]
{
// Create a mock chromium executable for Linux
let executable_path = chromium_dir.join("chromium");
fs::write(&executable_path, "mock executable").unwrap();
// Set executable permissions on Linux
use std::os::unix::fs::PermissionsExt;
let mut permissions = executable_path.metadata().unwrap().permissions();
permissions.set_mode(0o755);
fs::set_permissions(&executable_path, permissions).unwrap();
}
#[cfg(target_os = "windows")]
{
// Create a mock chromium.exe for Windows
let executable_path = chromium_dir.join("chromium.exe");
fs::write(&executable_path, "mock executable").unwrap();
}
let chromium_browser = ChromiumBrowser::new(BrowserType::Chromium);
assert!(chromium_browser.is_version_downloaded("1465660", binaries_dir));
@@ -1068,11 +1117,11 @@ mod tests {
let temp_dir = TempDir::new().unwrap();
let binaries_dir = temp_dir.path();
// Create browser directory but no .app directory with new path structure
// Create browser directory but no proper executable structure
let browser_dir = binaries_dir.join("firefox").join("139.0");
fs::create_dir_all(&browser_dir).unwrap();
// Create some other files but no .app
// Create some other files but no proper executable structure
fs::write(browser_dir.join("readme.txt"), "Some content").unwrap();
let browser = FirefoxBrowser::new(BrowserType::Firefox);
+54 -1
View File
@@ -1250,6 +1250,59 @@ impl BrowserRunner {
// Use the browser's own verification method
let binaries_dir = self.get_binaries_dir();
if !browser.is_version_downloaded(&version, &binaries_dir) {
// Provide detailed error information for debugging
let browser_dir = binaries_dir.join(&browser_str).join(&version);
let mut error_details = format!(
"Browser download completed but verification failed for {} {}. Expected directory: {}",
browser_str,
version,
browser_dir.display()
);
// List what files actually exist
if browser_dir.exists() {
error_details.push_str("\nFiles found in directory:");
if let Ok(entries) = std::fs::read_dir(&browser_dir) {
for entry in entries.flatten() {
let path = entry.path();
let file_type = if path.is_dir() { "DIR" } else { "FILE" };
error_details.push_str(&format!("\n {} {}", file_type, path.display()));
}
} else {
error_details.push_str("\n (Could not read directory contents)");
}
} else {
error_details.push_str("\nDirectory does not exist!");
}
// For Camoufox on Linux, provide specific expected files
if browser_str == "camoufox" && cfg!(target_os = "linux") {
let camoufox_subdir = browser_dir.join("camoufox");
error_details.push_str("\nExpected Camoufox executable locations:");
error_details.push_str(&format!("\n {}/camoufox-bin", camoufox_subdir.display()));
error_details.push_str(&format!("\n {}/camoufox", camoufox_subdir.display()));
if camoufox_subdir.exists() {
error_details.push_str(&format!(
"\nCamoufox subdirectory exists: {}",
camoufox_subdir.display()
));
if let Ok(entries) = std::fs::read_dir(&camoufox_subdir) {
error_details.push_str("\nFiles in camoufox subdirectory:");
for entry in entries.flatten() {
let path = entry.path();
let file_type = if path.is_dir() { "DIR" } else { "FILE" };
error_details.push_str(&format!("\n {} {}", file_type, path.display()));
}
}
} else {
error_details.push_str(&format!(
"\nCamoufox subdirectory does not exist: {}",
camoufox_subdir.display()
));
}
}
let _ = registry.cleanup_failed_download(&browser_str, &version);
let _ = registry.save();
// Remove browser-version pair from downloading set on verification failure
@@ -1257,7 +1310,7 @@ impl BrowserRunner {
let mut downloading = DOWNLOADING_BROWSERS.lock().unwrap();
downloading.remove(&download_key);
}
return Err("Browser download completed but verification failed".into());
return Err(error_details.into());
}
registry
+158 -19
View File
@@ -1016,59 +1016,198 @@ mod tests {
fn test_get_download_info() {
let service = BrowserVersionService::instance();
// Test Firefox
// Test Firefox - platform-specific expectations
let firefox_info = service.get_download_info("firefox", "139.0").unwrap();
assert_eq!(firefox_info.filename, "Firefox 139.0.dmg");
#[cfg(target_os = "macos")]
{
assert_eq!(firefox_info.filename, "Firefox 139.0.dmg");
assert!(firefox_info.is_archive);
}
#[cfg(target_os = "linux")]
{
assert_eq!(firefox_info.filename, "firefox-139.0.tar.xz");
assert!(firefox_info.is_archive);
}
#[cfg(target_os = "windows")]
{
assert_eq!(firefox_info.filename, "Firefox Setup 139.0.exe");
assert!(!firefox_info.is_archive);
}
assert!(firefox_info
.url
.contains("download-installer.cdn.mozilla.net"));
assert!(firefox_info.url.contains("/pub/firefox/releases/139.0/"));
assert!(firefox_info.is_archive);
// Test Firefox Developer
let firefox_dev_info = service
.get_download_info("firefox-developer", "139.0b1")
.unwrap();
assert_eq!(firefox_dev_info.filename, "Firefox 139.0b1.dmg");
#[cfg(target_os = "macos")]
{
assert_eq!(firefox_dev_info.filename, "Firefox 139.0b1.dmg");
assert!(firefox_dev_info.is_archive);
}
#[cfg(target_os = "linux")]
{
assert_eq!(firefox_dev_info.filename, "firefox-139.0b1.tar.xz");
assert!(firefox_dev_info.is_archive);
}
#[cfg(target_os = "windows")]
{
assert_eq!(firefox_dev_info.filename, "Firefox Setup 139.0b1.exe");
assert!(!firefox_dev_info.is_archive);
}
assert!(firefox_dev_info
.url
.contains("download-installer.cdn.mozilla.net"));
assert!(firefox_dev_info
.url
.contains("/pub/devedition/releases/139.0b1/"));
assert!(firefox_dev_info.is_archive);
// Test Mullvad Browser
let mullvad_info = service
.get_download_info("mullvad-browser", "14.5a6")
.unwrap();
assert_eq!(mullvad_info.filename, "mullvad-browser-macos-14.5a6.dmg");
assert!(mullvad_info.url.contains("mullvad-browser-macos-14.5a6"));
assert!(mullvad_info.is_archive);
#[cfg(target_os = "macos")]
{
assert_eq!(mullvad_info.filename, "mullvad-browser-macos-14.5a6.dmg");
assert!(mullvad_info.url.contains("mullvad-browser-macos-14.5a6"));
assert!(mullvad_info.is_archive);
}
#[cfg(target_os = "linux")]
{
assert_eq!(
mullvad_info.filename,
"mullvad-browser-x86_64-14.5a6.tar.xz"
);
assert!(mullvad_info.url.contains("mullvad-browser-x86_64-14.5a6"));
assert!(mullvad_info.is_archive);
}
#[cfg(target_os = "windows")]
{
assert_eq!(
mullvad_info.filename,
"mullvad-browser-windows-x86_64-14.5a6.exe"
);
assert!(mullvad_info
.url
.contains("mullvad-browser-windows-x86_64-14.5a6"));
assert!(!mullvad_info.is_archive);
}
// Test Zen Browser
let zen_info = service.get_download_info("zen", "1.11b").unwrap();
assert_eq!(zen_info.filename, "zen-1.11b.dmg");
assert!(zen_info.url.contains("zen.macos-universal.dmg"));
assert!(zen_info.is_archive);
#[cfg(target_os = "macos")]
{
assert_eq!(zen_info.filename, "zen-1.11b.dmg");
assert!(zen_info.url.contains("zen.macos-universal.dmg"));
assert!(zen_info.is_archive);
}
#[cfg(target_os = "linux")]
{
assert_eq!(zen_info.filename, "zen-1.11b-x86_64.tar.xz");
assert!(zen_info.url.contains("zen.linux-x86_64.tar.xz"));
assert!(zen_info.is_archive);
}
#[cfg(target_os = "windows")]
{
assert_eq!(zen_info.filename, "zen-1.11b.exe");
assert!(zen_info.url.contains("zen.installer.exe"));
assert!(!zen_info.is_archive);
}
// Test Tor Browser
let tor_info = service.get_download_info("tor-browser", "14.0.4").unwrap();
assert_eq!(tor_info.filename, "tor-browser-macos-14.0.4.dmg");
assert!(tor_info.url.contains("tor-browser-macos-14.0.4"));
assert!(tor_info.is_archive);
#[cfg(target_os = "macos")]
{
assert_eq!(tor_info.filename, "tor-browser-macos-14.0.4.dmg");
assert!(tor_info.url.contains("tor-browser-macos-14.0.4"));
assert!(tor_info.is_archive);
}
#[cfg(target_os = "linux")]
{
assert_eq!(tor_info.filename, "tor-browser-linux-x86_64-14.0.4.tar.xz");
assert!(tor_info.url.contains("tor-browser-linux-x86_64-14.0.4"));
assert!(tor_info.is_archive);
}
#[cfg(target_os = "windows")]
{
assert_eq!(
tor_info.filename,
"tor-browser-windows-x86_64-portable-14.0.4.exe"
);
assert!(tor_info
.url
.contains("tor-browser-windows-x86_64-portable-14.0.4"));
assert!(!tor_info.is_archive);
}
// Test Chromium
let chromium_info = service.get_download_info("chromium", "1465660").unwrap();
assert_eq!(chromium_info.filename, "chromium-1465660-mac.zip");
assert!(chromium_info.url.contains("chrome-mac.zip"));
#[cfg(target_os = "macos")]
{
assert_eq!(chromium_info.filename, "chromium-1465660-mac.zip");
assert!(chromium_info.url.contains("chrome-mac.zip"));
}
#[cfg(target_os = "linux")]
{
assert_eq!(chromium_info.filename, "chromium-1465660-linux.zip");
assert!(chromium_info.url.contains("chrome-linux.zip"));
}
#[cfg(target_os = "windows")]
{
assert_eq!(chromium_info.filename, "chromium-1465660-win.zip");
assert!(chromium_info.url.contains("chrome-win.zip"));
}
assert!(chromium_info.is_archive);
// Test Brave - Note: Brave uses dynamic URL resolution, so get_download_info provides a template URL
let brave_info = service.get_download_info("brave", "v1.81.9").unwrap();
assert_eq!(brave_info.filename, "Brave-Browser-universal.dmg");
assert_eq!(brave_info.url, "https://github.com/brave/brave-browser/releases/download/v1.81.9/Brave-Browser-universal.dmg");
assert!(brave_info.is_archive);
#[cfg(target_os = "macos")]
{
assert_eq!(brave_info.filename, "Brave-Browser-universal.dmg");
assert_eq!(brave_info.url, "https://github.com/brave/brave-browser/releases/download/v1.81.9/Brave-Browser-universal.dmg");
assert!(brave_info.is_archive);
}
#[cfg(target_os = "linux")]
{
assert_eq!(brave_info.filename, "brave-browser-v1.81.9-linux-amd64.zip");
assert_eq!(brave_info.url, "https://github.com/brave/brave-browser/releases/download/v1.81.9/brave-browser-v1.81.9-linux-amd64.zip");
assert!(brave_info.is_archive);
}
#[cfg(target_os = "windows")]
{
assert_eq!(brave_info.filename, "brave-v1.81.9.exe");
assert_eq!(
brave_info.url,
"https://github.com/brave/brave-browser/releases/download/v1.81.9/brave-v1.81.9.exe"
);
assert!(!brave_info.is_archive);
}
// Test unsupported browser
let unsupported_result = service.get_download_info("unsupported", "1.0.0");
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
Hello, World!
Binary file not shown.
+11 -2
View File
@@ -210,9 +210,18 @@ export function useBrowserDownload() {
if (!suppressNotifications) {
// Dismiss any existing download toast and show error
dismissToast(`download-${browserStr}-${version}`);
let errorMessage = "Unknown error occurred";
if (error instanceof Error) {
errorMessage = error.message;
} else if (typeof error === "string") {
errorMessage = error;
} else if (error && typeof error === "object" && "message" in error) {
errorMessage = String(error.message);
}
showErrorToast(`Failed to download ${browserName} ${version}`, {
description:
error instanceof Error ? error.message : "Unknown error occurred",
description: errorMessage,
});
}
throw error;
+25 -6
View File
@@ -245,11 +245,22 @@ export function useVersionUpdater() {
}
} catch (error) {
console.error("Failed to handle browser auto-update:", error);
let errorMessage = "Unknown error occurred";
if (error instanceof Error) {
errorMessage = error.message;
} else if (typeof error === "string") {
errorMessage = error;
} else if (
error &&
typeof error === "object" &&
"message" in error
) {
errorMessage = String(error.message);
}
showErrorToast(`Failed to auto-update ${browserDisplayName}`, {
description:
error instanceof Error
? error.message
: "Unknown error occurred",
description: errorMessage,
duration: 8000,
});
} finally {
@@ -336,9 +347,17 @@ export function useVersionUpdater() {
return results;
} catch (error) {
console.error("Failed to trigger manual update:", error);
let errorMessage = "Unknown error occurred";
if (error instanceof Error) {
errorMessage = error.message;
} else if (typeof error === "string") {
errorMessage = error;
} else if (error && typeof error === "object" && "message" in error) {
errorMessage = String(error.message);
}
showErrorToast("Failed to update browser versions", {
description:
error instanceof Error ? error.message : "Unknown error occurred",
description: errorMessage,
duration: 4000,
});
throw error;