refactor: handle missing mmdb

This commit is contained in:
zhom
2025-08-09 12:42:46 +04:00
parent ad2d9b73f2
commit 90d8e782de
4 changed files with 156 additions and 17 deletions
+48
View File
@@ -1044,6 +1044,27 @@ impl BrowserRunner {
Ok(missing_binaries)
}
/// Check if GeoIP database is missing for Camoufox profiles
pub fn check_missing_geoip_database(
&self,
) -> Result<bool, Box<dyn std::error::Error + Send + Sync>> {
// Get all profiles
let profiles = self
.list_profiles()
.map_err(|e| format!("Failed to list profiles: {e}"))?;
// Check if there are any Camoufox profiles
let has_camoufox_profiles = profiles.iter().any(|profile| profile.browser == "camoufox");
if has_camoufox_profiles {
// Check if GeoIP database is available
use crate::geoip_downloader::GeoIPDownloader;
return Ok(!GeoIPDownloader::is_geoip_database_available());
}
Ok(false)
}
/// Automatically download missing binaries for all profiles
pub async fn ensure_all_binaries_exist(
&self,
@@ -1082,6 +1103,25 @@ impl BrowserRunner {
}
}
// Check if GeoIP database is missing for Camoufox profiles
if self.check_missing_geoip_database()? {
println!("GeoIP database is missing for Camoufox profiles, downloading...");
use crate::geoip_downloader::GeoIPDownloader;
let geoip_downloader = GeoIPDownloader::instance();
match geoip_downloader.download_geoip_database(app_handle).await {
Ok(_) => {
downloaded.push("GeoIP database for Camoufox".to_string());
println!("GeoIP database downloaded successfully");
}
Err(e) => {
eprintln!("Failed to download GeoIP database: {e}");
// Don't fail the entire operation if GeoIP download fails
}
}
}
Ok(downloaded)
}
@@ -1794,6 +1834,14 @@ pub async fn check_missing_binaries() -> Result<Vec<(String, String, String)>, S
.map_err(|e| format!("Failed to check missing binaries: {e}"))
}
#[tauri::command]
pub async fn check_missing_geoip_database() -> Result<bool, String> {
let browser_runner = BrowserRunner::instance();
browser_runner
.check_missing_geoip_database()
.map_err(|e| format!("Failed to check missing GeoIP database: {e}"))
}
#[tauri::command]
pub async fn ensure_all_binaries_exist(
app_handle: tauri::AppHandle,
+55 -7
View File
@@ -31,13 +31,13 @@ mod version_updater;
extern crate lazy_static;
use browser_runner::{
check_browser_exists, check_browser_status, check_missing_binaries, create_browser_profile_new,
delete_profile, download_browser, ensure_all_binaries_exist, fetch_browser_versions_cached_first,
fetch_browser_versions_with_count, fetch_browser_versions_with_count_cached_first,
get_browser_release_types, get_downloaded_browser_versions, get_supported_browsers,
is_browser_supported_on_platform, kill_browser_profile, launch_browser_profile,
list_browser_profiles, rename_profile, update_camoufox_config, update_profile_proxy,
update_profile_version,
check_browser_exists, check_browser_status, check_missing_binaries, check_missing_geoip_database,
create_browser_profile_new, delete_profile, download_browser, ensure_all_binaries_exist,
fetch_browser_versions_cached_first, fetch_browser_versions_with_count,
fetch_browser_versions_with_count_cached_first, get_browser_release_types,
get_downloaded_browser_versions, get_supported_browsers, is_browser_supported_on_platform,
kill_browser_profile, launch_browser_profile, list_browser_profiles, rename_profile,
update_camoufox_config, update_profile_proxy, update_profile_version,
};
use settings_manager::{
@@ -69,6 +69,8 @@ use group_manager::{
get_groups_with_profile_counts, get_profile_groups, update_profile_group,
};
use geoip_downloader::GeoIPDownloader;
// Trait to extend WebviewWindow with transparent titlebar functionality
pub trait WindowExt {
#[cfg(target_os = "macos")]
@@ -173,6 +175,20 @@ async fn delete_stored_proxy(proxy_id: String) -> Result<(), String> {
.map_err(|e| format!("Failed to delete stored proxy: {e}"))
}
#[tauri::command]
async fn is_geoip_database_available() -> Result<bool, String> {
Ok(GeoIPDownloader::is_geoip_database_available())
}
#[tauri::command]
async fn download_geoip_database(app_handle: tauri::AppHandle) -> Result<(), String> {
let downloader = GeoIPDownloader::instance();
downloader
.download_geoip_database(&app_handle)
.await
.map_err(|e| format!("Failed to download GeoIP database: {e}"))
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
let args: Vec<String> = env::args().collect();
@@ -386,6 +402,35 @@ pub fn run() {
}
});
// Check and download GeoIP database at startup if needed
let app_handle_geoip = app.handle().clone();
tauri::async_runtime::spawn(async move {
// Wait a bit for the app to fully initialize
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
let browser_runner = crate::browser_runner::BrowserRunner::instance();
match browser_runner.check_missing_geoip_database() {
Ok(true) => {
println!("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}");
} else {
println!("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}");
}
}
});
// Start proxy cleanup task for dead browser processes
let app_handle_proxy_cleanup = app.handle().clone();
tauri::async_runtime::spawn(async move {
@@ -487,6 +532,7 @@ pub fn run() {
detect_existing_profiles,
import_browser_profile,
check_missing_binaries,
check_missing_geoip_database,
ensure_all_binaries_exist,
create_stored_proxy,
get_stored_proxies,
@@ -500,6 +546,8 @@ pub fn run() {
delete_profile_group,
assign_profiles_to_group,
delete_selected_profiles,
is_geoip_database_available,
download_geoip_database,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
+30 -9
View File
@@ -93,8 +93,18 @@ export default function Home() {
"check_missing_binaries",
);
if (missingBinaries.length > 0) {
console.log("Found missing binaries:", missingBinaries);
// Also check for missing GeoIP database
const missingGeoIP = await invoke<boolean>(
"check_missing_geoip_database",
);
if (missingBinaries.length > 0 || missingGeoIP) {
if (missingBinaries.length > 0) {
console.log("Found missing binaries:", missingBinaries);
}
if (missingGeoIP) {
console.log("Found missing GeoIP database for Camoufox");
}
// Group missing binaries by browser type to avoid concurrent downloads
const browserMap = new Map<string, string[]>();
@@ -109,34 +119,45 @@ export default function Home() {
}
// Show a toast notification about missing binaries and auto-download them
const missingList = Array.from(browserMap.entries())
let missingList = Array.from(browserMap.entries())
.map(([browser, versions]) => `${browser}: ${versions.join(", ")}`)
.join(", ");
console.log(`Downloading missing binaries: ${missingList}`);
if (missingGeoIP) {
if (missingList) {
missingList += ", GeoIP database for Camoufox";
} else {
missingList = "GeoIP database for Camoufox";
}
}
console.log(`Downloading missing components: ${missingList}`);
try {
// Download missing binaries sequentially by browser type to prevent conflicts
// Download missing binaries and GeoIP database sequentially to prevent conflicts
const downloaded = await invoke<string[]>(
"ensure_all_binaries_exist",
);
if (downloaded.length > 0) {
console.log(
"Successfully downloaded missing binaries:",
"Successfully downloaded missing components:",
downloaded,
);
}
} catch (downloadError) {
console.error("Failed to download missing binaries:", downloadError);
console.error(
"Failed to download missing components:",
downloadError,
);
setError(
`Failed to download missing binaries: ${JSON.stringify(
`Failed to download missing components: ${JSON.stringify(
downloadError,
)}`,
);
}
}
} catch (err: unknown) {
console.error("Failed to check missing binaries:", err);
console.error("Failed to check missing components:", err);
}
}, []);
+23 -1
View File
@@ -164,6 +164,20 @@ export function CreateProfileDialog({
}
}, []);
const checkAndDownloadGeoIPDatabase = useCallback(async () => {
try {
const isAvailable = await invoke<boolean>("is_geoip_database_available");
if (!isAvailable) {
console.log("GeoIP database not available, downloading...");
await invoke("download_geoip_database");
console.log("GeoIP database downloaded successfully");
}
} catch (error) {
console.error("Failed to check/download GeoIP database:", error);
// Don't show error to user as this is not critical for profile creation
}
}, []);
const loadReleaseTypes = useCallback(
async (browser: string) => {
// Set loading state
@@ -205,8 +219,16 @@ export function CreateProfileDialog({
void loadStoredProxies();
// Load camoufox release types when dialog opens
void loadReleaseTypes("camoufox");
// Check and download GeoIP database if needed for Camoufox
void checkAndDownloadGeoIPDatabase();
}
}, [isOpen, loadSupportedBrowsers, loadStoredProxies, loadReleaseTypes]);
}, [
isOpen,
loadSupportedBrowsers,
loadStoredProxies,
loadReleaseTypes,
checkAndDownloadGeoIPDatabase,
]);
// Load release types when browser selection changes
useEffect(() => {