mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-09-22 17:30:52 +02:00
refactor: allow custom location
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
use directories::BaseDirs;
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -464,13 +463,7 @@ impl ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_cache_dir() -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
|
fn get_cache_dir() -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let base_dirs = BaseDirs::new().ok_or("Failed to get base directories")?;
|
let cache_dir = crate::app_dirs::cache_dir().join("version_cache");
|
||||||
let app_name = if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
};
|
|
||||||
let cache_dir = base_dirs.cache_dir().join(app_name).join("version_cache");
|
|
||||||
fs::create_dir_all(&cache_dir)?;
|
fs::create_dir_all(&cache_dir)?;
|
||||||
Ok(cache_dir)
|
Ok(cache_dir)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,185 @@
|
|||||||
|
use directories::BaseDirs;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
static BASE_DIRS: OnceLock<BaseDirs> = OnceLock::new();
|
||||||
|
|
||||||
|
fn base_dirs() -> &'static BaseDirs {
|
||||||
|
BASE_DIRS.get_or_init(|| BaseDirs::new().expect("Failed to get base directories"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn app_name() -> &'static str {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
"DonutBrowserDev"
|
||||||
|
} else {
|
||||||
|
"DonutBrowser"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data_dir() -> PathBuf {
|
||||||
|
#[cfg(test)]
|
||||||
|
{
|
||||||
|
if let Some(dir) = TEST_DATA_DIR.with(|cell| cell.borrow().clone()) {
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(dir) = std::env::var("DONUTBROWSER_DATA_DIR") {
|
||||||
|
return PathBuf::from(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
base_dirs().data_local_dir().join(app_name())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cache_dir() -> PathBuf {
|
||||||
|
#[cfg(test)]
|
||||||
|
{
|
||||||
|
if let Some(dir) = TEST_CACHE_DIR.with(|cell| cell.borrow().clone()) {
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(dir) = std::env::var("DONUTBROWSER_CACHE_DIR") {
|
||||||
|
return PathBuf::from(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
base_dirs().cache_dir().join(app_name())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn profiles_dir() -> PathBuf {
|
||||||
|
data_dir().join("profiles")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn binaries_dir() -> PathBuf {
|
||||||
|
data_dir().join("binaries")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data_subdir() -> PathBuf {
|
||||||
|
data_dir().join("data")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn settings_dir() -> PathBuf {
|
||||||
|
data_dir().join("settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn proxies_dir() -> PathBuf {
|
||||||
|
data_dir().join("proxies")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
thread_local! {
|
||||||
|
static TEST_DATA_DIR: std::cell::RefCell<Option<PathBuf>> = const { std::cell::RefCell::new(None) };
|
||||||
|
static TEST_CACHE_DIR: std::cell::RefCell<Option<PathBuf>> = const { std::cell::RefCell::new(None) };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub struct TestDirGuard {
|
||||||
|
kind: TestDirKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
enum TestDirKind {
|
||||||
|
Data,
|
||||||
|
Cache,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl Drop for TestDirGuard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
match self.kind {
|
||||||
|
TestDirKind::Data => TEST_DATA_DIR.with(|cell| *cell.borrow_mut() = None),
|
||||||
|
TestDirKind::Cache => TEST_CACHE_DIR.with(|cell| *cell.borrow_mut() = None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub fn set_test_data_dir(dir: PathBuf) -> TestDirGuard {
|
||||||
|
TEST_DATA_DIR.with(|cell| *cell.borrow_mut() = Some(dir));
|
||||||
|
TestDirGuard {
|
||||||
|
kind: TestDirKind::Data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub fn set_test_cache_dir(dir: PathBuf) -> TestDirGuard {
|
||||||
|
TEST_CACHE_DIR.with(|cell| *cell.borrow_mut() = Some(dir));
|
||||||
|
TestDirGuard {
|
||||||
|
kind: TestDirKind::Cache,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_app_name() {
|
||||||
|
let name = app_name();
|
||||||
|
assert!(
|
||||||
|
name == "DonutBrowser" || name == "DonutBrowserDev",
|
||||||
|
"app_name should be DonutBrowser or DonutBrowserDev, got: {name}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_data_dir_returns_path() {
|
||||||
|
let dir = data_dir();
|
||||||
|
assert!(
|
||||||
|
dir.to_string_lossy().contains(app_name()),
|
||||||
|
"data_dir should contain app_name"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_dir_returns_path() {
|
||||||
|
let dir = cache_dir();
|
||||||
|
assert!(
|
||||||
|
dir.to_string_lossy().contains(app_name()),
|
||||||
|
"cache_dir should contain app_name"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_subdirectory_helpers() {
|
||||||
|
assert!(profiles_dir().ends_with("profiles"));
|
||||||
|
assert!(binaries_dir().ends_with("binaries"));
|
||||||
|
assert!(data_subdir().ends_with("data"));
|
||||||
|
assert!(settings_dir().ends_with("settings"));
|
||||||
|
assert!(proxies_dir().ends_with("proxies"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_test_data_dir() {
|
||||||
|
let tmp = PathBuf::from("/tmp/test-donut-data");
|
||||||
|
let _guard = set_test_data_dir(tmp.clone());
|
||||||
|
assert_eq!(data_dir(), tmp);
|
||||||
|
assert_eq!(profiles_dir(), tmp.join("profiles"));
|
||||||
|
assert_eq!(binaries_dir(), tmp.join("binaries"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_test_cache_dir() {
|
||||||
|
let tmp = PathBuf::from("/tmp/test-donut-cache");
|
||||||
|
let _guard = set_test_cache_dir(tmp.clone());
|
||||||
|
assert_eq!(cache_dir(), tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_guard_cleanup() {
|
||||||
|
let original_data = data_dir();
|
||||||
|
let original_cache = cache_dir();
|
||||||
|
|
||||||
|
{
|
||||||
|
let _guard = set_test_data_dir(PathBuf::from("/tmp/test-cleanup-data"));
|
||||||
|
assert_eq!(data_dir(), PathBuf::from("/tmp/test-cleanup-data"));
|
||||||
|
}
|
||||||
|
assert_eq!(data_dir(), original_data);
|
||||||
|
|
||||||
|
{
|
||||||
|
let _guard = set_test_cache_dir(PathBuf::from("/tmp/test-cleanup-cache"));
|
||||||
|
assert_eq!(cache_dir(), PathBuf::from("/tmp/test-cleanup-cache"));
|
||||||
|
}
|
||||||
|
assert_eq!(cache_dir(), original_cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,13 +6,11 @@ use crate::platform_browser;
|
|||||||
use crate::profile::{BrowserProfile, ProfileManager};
|
use crate::profile::{BrowserProfile, ProfileManager};
|
||||||
use crate::proxy_manager::PROXY_MANAGER;
|
use crate::proxy_manager::PROXY_MANAGER;
|
||||||
use crate::wayfern_manager::{WayfernConfig, WayfernManager};
|
use crate::wayfern_manager::{WayfernConfig, WayfernManager};
|
||||||
use directories::BaseDirs;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
use sysinfo::System;
|
use sysinfo::System;
|
||||||
pub struct BrowserRunner {
|
pub struct BrowserRunner {
|
||||||
base_dirs: BaseDirs,
|
|
||||||
pub profile_manager: &'static ProfileManager,
|
pub profile_manager: &'static ProfileManager,
|
||||||
pub downloaded_browsers_registry: &'static DownloadedBrowsersRegistry,
|
pub downloaded_browsers_registry: &'static DownloadedBrowsersRegistry,
|
||||||
auto_updater: &'static crate::auto_updater::AutoUpdater,
|
auto_updater: &'static crate::auto_updater::AutoUpdater,
|
||||||
@@ -23,7 +21,6 @@ pub struct BrowserRunner {
|
|||||||
impl BrowserRunner {
|
impl BrowserRunner {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
||||||
profile_manager: ProfileManager::instance(),
|
profile_manager: ProfileManager::instance(),
|
||||||
downloaded_browsers_registry: DownloadedBrowsersRegistry::instance(),
|
downloaded_browsers_registry: DownloadedBrowsersRegistry::instance(),
|
||||||
auto_updater: crate::auto_updater::AutoUpdater::instance(),
|
auto_updater: crate::auto_updater::AutoUpdater::instance(),
|
||||||
@@ -37,14 +34,7 @@ impl BrowserRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_binaries_dir(&self) -> PathBuf {
|
pub fn get_binaries_dir(&self) -> PathBuf {
|
||||||
let mut path = self.base_dirs.data_local_dir().to_path_buf();
|
crate::app_dirs::binaries_dir()
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("binaries");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the executable path for a browser profile
|
/// Get the executable path for a browser profile
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use crate::browser_runner::BrowserRunner;
|
use crate::browser_runner::BrowserRunner;
|
||||||
use crate::camoufox::{CamoufoxConfigBuilder, GeoIPOption, ScreenConstraints};
|
use crate::camoufox::{CamoufoxConfigBuilder, GeoIPOption, ScreenConstraints};
|
||||||
use crate::profile::BrowserProfile;
|
use crate::profile::BrowserProfile;
|
||||||
use directories::BaseDirs;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -74,7 +73,6 @@ struct CamoufoxManagerInner {
|
|||||||
|
|
||||||
pub struct CamoufoxManager {
|
pub struct CamoufoxManager {
|
||||||
inner: Arc<AsyncMutex<CamoufoxManagerInner>>,
|
inner: Arc<AsyncMutex<CamoufoxManagerInner>>,
|
||||||
base_dirs: BaseDirs,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CamoufoxManager {
|
impl CamoufoxManager {
|
||||||
@@ -83,7 +81,6 @@ impl CamoufoxManager {
|
|||||||
inner: Arc::new(AsyncMutex::new(CamoufoxManagerInner {
|
inner: Arc::new(AsyncMutex::new(CamoufoxManagerInner {
|
||||||
instances: HashMap::new(),
|
instances: HashMap::new(),
|
||||||
})),
|
})),
|
||||||
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,14 +89,7 @@ impl CamoufoxManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_profiles_dir(&self) -> PathBuf {
|
pub fn get_profiles_dir(&self) -> PathBuf {
|
||||||
let mut path = self.base_dirs.data_local_dir().to_path_buf();
|
crate::app_dirs::profiles_dir()
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("profiles");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate Camoufox fingerprint configuration during profile creation
|
/// Generate Camoufox fingerprint configuration during profile creation
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use directories::BaseDirs;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@@ -71,16 +70,7 @@ impl DownloadedBrowsersRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_registry_path() -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
|
fn get_registry_path() -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let base_dirs = BaseDirs::new().ok_or("Failed to get base directories")?;
|
Ok(crate::app_dirs::data_subdir().join("downloaded_browsers.json"))
|
||||||
let mut path = base_dirs.data_local_dir().to_path_buf();
|
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("data");
|
|
||||||
path.push("downloaded_browsers.json");
|
|
||||||
Ok(path)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_browser(&self, info: DownloadedBrowserInfo) {
|
pub fn add_browser(&self, info: DownloadedBrowserInfo) {
|
||||||
@@ -128,19 +118,7 @@ impl DownloadedBrowsersRegistry {
|
|||||||
};
|
};
|
||||||
let browser_instance = create_browser(browser_type.clone());
|
let browser_instance = create_browser(browser_type.clone());
|
||||||
|
|
||||||
// Get binaries directory
|
let binaries_dir = crate::app_dirs::binaries_dir();
|
||||||
let binaries_dir = if let Some(base_dirs) = directories::BaseDirs::new() {
|
|
||||||
let mut path = base_dirs.data_local_dir().to_path_buf();
|
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("binaries");
|
|
||||||
path
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
let files_exist = browser_instance.is_version_downloaded(version, &binaries_dir);
|
let files_exist = browser_instance.is_version_downloaded(version, &binaries_dir);
|
||||||
|
|
||||||
@@ -535,15 +513,7 @@ impl DownloadedBrowsersRegistry {
|
|||||||
browser: &str,
|
browser: &str,
|
||||||
version: &str,
|
version: &str,
|
||||||
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
// Get binaries directory path
|
let binaries_dir = crate::app_dirs::binaries_dir();
|
||||||
let base_dirs = directories::BaseDirs::new().ok_or("Failed to get base directories")?;
|
|
||||||
let mut binaries_dir = base_dirs.data_local_dir().to_path_buf();
|
|
||||||
binaries_dir.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
binaries_dir.push("binaries");
|
|
||||||
|
|
||||||
let version_dir = binaries_dir.join(browser).join(version);
|
let version_dir = binaries_dir.join(browser).join(version);
|
||||||
|
|
||||||
@@ -830,19 +800,7 @@ impl DownloadedBrowsersRegistry {
|
|||||||
|
|
||||||
let browser = create_browser(browser_type.clone());
|
let browser = create_browser(browser_type.clone());
|
||||||
|
|
||||||
// Get binaries directory
|
let binaries_dir = crate::app_dirs::binaries_dir();
|
||||||
let binaries_dir = if let Some(base_dirs) = directories::BaseDirs::new() {
|
|
||||||
let mut path = base_dirs.data_local_dir().to_path_buf();
|
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("binaries");
|
|
||||||
path
|
|
||||||
} else {
|
|
||||||
return Err("Failed to get base directories".into());
|
|
||||||
};
|
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"binaries_dir: {binaries_dir:?} for profile: {}",
|
"binaries_dir: {binaries_dir:?} for profile: {}",
|
||||||
|
|||||||
@@ -681,21 +681,7 @@ impl Downloader {
|
|||||||
|
|
||||||
// Use injected registry instance
|
// Use injected registry instance
|
||||||
|
|
||||||
// Get binaries directory - we need to get it from somewhere
|
let binaries_dir = crate::app_dirs::binaries_dir();
|
||||||
// This is a bit tricky since we don't have access to BrowserRunner's get_binaries_dir
|
|
||||||
// We'll need to replicate this logic
|
|
||||||
let binaries_dir = if let Some(base_dirs) = directories::BaseDirs::new() {
|
|
||||||
let mut path = base_dirs.data_local_dir().to_path_buf();
|
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("binaries");
|
|
||||||
path
|
|
||||||
} else {
|
|
||||||
return Err("Failed to get base directories".into());
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if registry thinks it's downloaded, but also verify files actually exist
|
// Check if registry thinks it's downloaded, but also verify files actually exist
|
||||||
if self.registry.is_browser_downloaded(&browser_str, &version) {
|
if self.registry.is_browser_downloaded(&browser_str, &version) {
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use directories::BaseDirs;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use crate::events;
|
use crate::events;
|
||||||
@@ -33,48 +31,15 @@ struct GroupsData {
|
|||||||
groups: Vec<ProfileGroup>,
|
groups: Vec<ProfileGroup>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GroupManager {
|
pub struct GroupManager;
|
||||||
base_dirs: BaseDirs,
|
|
||||||
data_dir_override: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GroupManager {
|
impl GroupManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self
|
||||||
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
||||||
data_dir_override: std::env::var("DONUTBROWSER_DATA_DIR")
|
|
||||||
.ok()
|
|
||||||
.map(PathBuf::from),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for tests to override data directory without global env var
|
fn get_groups_file_path(&self) -> std::path::PathBuf {
|
||||||
#[allow(dead_code)]
|
crate::app_dirs::data_subdir().join("groups.json")
|
||||||
pub fn with_data_dir_override(dir: &Path) -> Self {
|
|
||||||
Self {
|
|
||||||
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
||||||
data_dir_override: Some(dir.to_path_buf()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_groups_file_path(&self) -> PathBuf {
|
|
||||||
if let Some(dir) = &self.data_dir_override {
|
|
||||||
let mut override_path = dir.clone();
|
|
||||||
// Ensure the directory exists before returning the path
|
|
||||||
let _ = fs::create_dir_all(&override_path);
|
|
||||||
override_path.push("groups.json");
|
|
||||||
return override_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut path = self.base_dirs.data_local_dir().to_path_buf();
|
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("data");
|
|
||||||
path.push("groups.json");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_groups_data(&self) -> Result<GroupsData, Box<dyn std::error::Error>> {
|
fn load_groups_data(&self) -> Result<GroupsData, Box<dyn std::error::Error>> {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ static PENDING_URLS: Mutex<Vec<String>> = Mutex::new(Vec::new());
|
|||||||
mod api_client;
|
mod api_client;
|
||||||
mod api_server;
|
mod api_server;
|
||||||
mod app_auto_updater;
|
mod app_auto_updater;
|
||||||
|
pub mod app_dirs;
|
||||||
mod auto_updater;
|
mod auto_updater;
|
||||||
mod browser;
|
mod browser;
|
||||||
mod browser_runner;
|
mod browser_runner;
|
||||||
@@ -706,12 +707,7 @@ pub fn run() {
|
|||||||
pending.push(url.clone());
|
pending.push(url.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure logging plugin with separate logs for dev and production
|
let log_file_name = app_dirs::app_name();
|
||||||
let log_file_name = if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
};
|
|
||||||
|
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(
|
.plugin(
|
||||||
|
|||||||
@@ -6,13 +6,11 @@ use crate::events;
|
|||||||
use crate::profile::types::{get_host_os, BrowserProfile};
|
use crate::profile::types::{get_host_os, BrowserProfile};
|
||||||
use crate::proxy_manager::PROXY_MANAGER;
|
use crate::proxy_manager::PROXY_MANAGER;
|
||||||
use crate::wayfern_manager::WayfernConfig;
|
use crate::wayfern_manager::WayfernConfig;
|
||||||
use directories::BaseDirs;
|
|
||||||
use std::fs::{self, create_dir_all};
|
use std::fs::{self, create_dir_all};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use sysinfo::{Pid, System};
|
use sysinfo::{Pid, System};
|
||||||
|
|
||||||
pub struct ProfileManager {
|
pub struct ProfileManager {
|
||||||
base_dirs: BaseDirs,
|
|
||||||
camoufox_manager: &'static crate::camoufox_manager::CamoufoxManager,
|
camoufox_manager: &'static crate::camoufox_manager::CamoufoxManager,
|
||||||
wayfern_manager: &'static crate::wayfern_manager::WayfernManager,
|
wayfern_manager: &'static crate::wayfern_manager::WayfernManager,
|
||||||
}
|
}
|
||||||
@@ -20,7 +18,6 @@ pub struct ProfileManager {
|
|||||||
impl ProfileManager {
|
impl ProfileManager {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
||||||
camoufox_manager: crate::camoufox_manager::CamoufoxManager::instance(),
|
camoufox_manager: crate::camoufox_manager::CamoufoxManager::instance(),
|
||||||
wayfern_manager: crate::wayfern_manager::WayfernManager::instance(),
|
wayfern_manager: crate::wayfern_manager::WayfernManager::instance(),
|
||||||
}
|
}
|
||||||
@@ -31,25 +28,11 @@ impl ProfileManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_profiles_dir(&self) -> PathBuf {
|
pub fn get_profiles_dir(&self) -> PathBuf {
|
||||||
let mut path = self.base_dirs.data_local_dir().to_path_buf();
|
crate::app_dirs::profiles_dir()
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("profiles");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_binaries_dir(&self) -> PathBuf {
|
pub fn get_binaries_dir(&self) -> PathBuf {
|
||||||
let mut path = self.base_dirs.data_local_dir().to_path_buf();
|
crate::app_dirs::binaries_dir()
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("binaries");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use directories::BaseDirs;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -149,18 +148,15 @@ pub struct ProxyManager {
|
|||||||
// Track active proxy IDs by profile name for targeted cleanup
|
// Track active proxy IDs by profile name for targeted cleanup
|
||||||
profile_active_proxy_ids: Mutex<HashMap<String, String>>, // Maps profile name to proxy id
|
profile_active_proxy_ids: Mutex<HashMap<String, String>>, // Maps profile name to proxy id
|
||||||
stored_proxies: Mutex<HashMap<String, StoredProxy>>, // Maps proxy ID to stored proxy
|
stored_proxies: Mutex<HashMap<String, StoredProxy>>, // Maps proxy ID to stored proxy
|
||||||
base_dirs: BaseDirs,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProxyManager {
|
impl ProxyManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let base_dirs = BaseDirs::new().expect("Failed to get base directories");
|
|
||||||
let manager = Self {
|
let manager = Self {
|
||||||
active_proxies: Mutex::new(HashMap::new()),
|
active_proxies: Mutex::new(HashMap::new()),
|
||||||
profile_proxies: Mutex::new(HashMap::new()),
|
profile_proxies: Mutex::new(HashMap::new()),
|
||||||
profile_active_proxy_ids: Mutex::new(HashMap::new()),
|
profile_active_proxy_ids: Mutex::new(HashMap::new()),
|
||||||
stored_proxies: Mutex::new(HashMap::new()),
|
stored_proxies: Mutex::new(HashMap::new()),
|
||||||
base_dirs,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Load stored proxies on initialization
|
// Load stored proxies on initialization
|
||||||
@@ -171,27 +167,12 @@ impl ProxyManager {
|
|||||||
manager
|
manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the path to the proxies directory
|
|
||||||
fn get_proxies_dir(&self) -> PathBuf {
|
fn get_proxies_dir(&self) -> PathBuf {
|
||||||
let mut path = self.base_dirs.data_local_dir().to_path_buf();
|
crate::app_dirs::proxies_dir()
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("proxies");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the path to the proxy check cache directory
|
|
||||||
fn get_proxy_check_cache_dir(&self) -> Result<PathBuf, Box<dyn std::error::Error>> {
|
fn get_proxy_check_cache_dir(&self) -> Result<PathBuf, Box<dyn std::error::Error>> {
|
||||||
let mut path = self.base_dirs.cache_dir().to_path_buf();
|
let path = crate::app_dirs::cache_dir().join("proxy_checks");
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("proxy_checks");
|
|
||||||
fs::create_dir_all(&path)?;
|
fs::create_dir_all(&path)?;
|
||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use directories::BaseDirs;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -35,15 +34,7 @@ impl ProxyConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_storage_dir() -> PathBuf {
|
pub fn get_storage_dir() -> PathBuf {
|
||||||
let base_dirs = BaseDirs::new().expect("Failed to get base directories");
|
crate::app_dirs::proxies_dir()
|
||||||
let mut path = base_dirs.data_local_dir().to_path_buf();
|
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("proxies");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_proxy_config(config: &ProxyConfig) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn save_proxy_config(config: &ProxyConfig) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use directories::BaseDirs;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fs::{self, create_dir_all};
|
use std::fs::{self, create_dir_all};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -91,27 +90,11 @@ impl Default for AppSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SettingsManager {
|
pub struct SettingsManager;
|
||||||
base_dirs: BaseDirs,
|
|
||||||
data_dir_override: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SettingsManager {
|
impl SettingsManager {
|
||||||
fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
Self {
|
Self
|
||||||
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
||||||
data_dir_override: std::env::var("DONUTBROWSER_DATA_DIR")
|
|
||||||
.ok()
|
|
||||||
.map(PathBuf::from),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
fn with_data_dir_override(dir: &std::path::Path) -> Self {
|
|
||||||
Self {
|
|
||||||
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
||||||
data_dir_override: Some(dir.to_path_buf()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn instance() -> &'static SettingsManager {
|
pub fn instance() -> &'static SettingsManager {
|
||||||
@@ -119,18 +102,7 @@ impl SettingsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_settings_dir(&self) -> PathBuf {
|
pub fn get_settings_dir(&self) -> PathBuf {
|
||||||
if let Some(dir) = &self.data_dir_override {
|
crate::app_dirs::settings_dir()
|
||||||
return dir.join("settings");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut path = self.base_dirs.data_local_dir().to_path_buf();
|
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("settings");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_settings_file(&self) -> PathBuf {
|
pub fn get_settings_file(&self) -> PathBuf {
|
||||||
@@ -950,16 +922,16 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
fn create_test_settings_manager() -> (SettingsManager, TempDir) {
|
fn create_test_settings_manager() -> (SettingsManager, TempDir, crate::app_dirs::TestDirGuard) {
|
||||||
let temp_dir = TempDir::new().expect("Failed to create temp directory");
|
let temp_dir = TempDir::new().expect("Failed to create temp directory");
|
||||||
let manager = SettingsManager::with_data_dir_override(temp_dir.path());
|
let guard = crate::app_dirs::set_test_data_dir(temp_dir.path().to_path_buf());
|
||||||
(manager, temp_dir)
|
let manager = SettingsManager::new();
|
||||||
|
(manager, temp_dir, guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_settings_manager_creation() {
|
fn test_settings_manager_creation() {
|
||||||
let (_manager, _temp_dir) = create_test_settings_manager();
|
let (_manager, _temp_dir, _guard) = create_test_settings_manager();
|
||||||
// Test passes if no panic occurs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -992,7 +964,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load_settings_nonexistent_file() {
|
fn test_load_settings_nonexistent_file() {
|
||||||
let (manager, _temp_dir) = create_test_settings_manager();
|
let (manager, _temp_dir, _guard) = create_test_settings_manager();
|
||||||
|
|
||||||
let result = manager.load_settings();
|
let result = manager.load_settings();
|
||||||
assert!(
|
assert!(
|
||||||
@@ -1010,7 +982,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_save_and_load_settings() {
|
fn test_save_and_load_settings() {
|
||||||
let (manager, _temp_dir) = create_test_settings_manager();
|
let (manager, _temp_dir, _guard) = create_test_settings_manager();
|
||||||
|
|
||||||
let test_settings = AppSettings {
|
let test_settings = AppSettings {
|
||||||
set_as_default_browser: true,
|
set_as_default_browser: true,
|
||||||
@@ -1029,11 +1001,9 @@ mod tests {
|
|||||||
language: None,
|
language: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save settings
|
|
||||||
let save_result = manager.save_settings(&test_settings);
|
let save_result = manager.save_settings(&test_settings);
|
||||||
assert!(save_result.is_ok(), "Should save settings successfully");
|
assert!(save_result.is_ok(), "Should save settings successfully");
|
||||||
|
|
||||||
// Load settings back
|
|
||||||
let load_result = manager.load_settings();
|
let load_result = manager.load_settings();
|
||||||
assert!(load_result.is_ok(), "Should load settings successfully");
|
assert!(load_result.is_ok(), "Should load settings successfully");
|
||||||
|
|
||||||
@@ -1050,7 +1020,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load_table_sorting_nonexistent_file() {
|
fn test_load_table_sorting_nonexistent_file() {
|
||||||
let (manager, _temp_dir) = create_test_settings_manager();
|
let (manager, _temp_dir, _guard) = create_test_settings_manager();
|
||||||
|
|
||||||
let result = manager.load_table_sorting();
|
let result = manager.load_table_sorting();
|
||||||
assert!(
|
assert!(
|
||||||
@@ -1065,18 +1035,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_save_and_load_table_sorting() {
|
fn test_save_and_load_table_sorting() {
|
||||||
let (manager, _temp_dir) = create_test_settings_manager();
|
let (manager, _temp_dir, _guard) = create_test_settings_manager();
|
||||||
|
|
||||||
let test_sorting = TableSortingSettings {
|
let test_sorting = TableSortingSettings {
|
||||||
column: "browser".to_string(),
|
column: "browser".to_string(),
|
||||||
direction: "desc".to_string(),
|
direction: "desc".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save sorting
|
|
||||||
let save_result = manager.save_table_sorting(&test_sorting);
|
let save_result = manager.save_table_sorting(&test_sorting);
|
||||||
assert!(save_result.is_ok(), "Should save sorting successfully");
|
assert!(save_result.is_ok(), "Should save sorting successfully");
|
||||||
|
|
||||||
// Load sorting back
|
|
||||||
let load_result = manager.load_table_sorting();
|
let load_result = manager.load_table_sorting();
|
||||||
assert!(load_result.is_ok(), "Should load sorting successfully");
|
assert!(load_result.is_ok(), "Should load sorting successfully");
|
||||||
|
|
||||||
@@ -1093,45 +1061,37 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_should_show_launch_on_login_prompt() {
|
fn test_should_show_launch_on_login_prompt() {
|
||||||
let (manager, _temp_dir) = create_test_settings_manager();
|
let (manager, _temp_dir, _guard) = create_test_settings_manager();
|
||||||
|
|
||||||
let result = manager.should_show_launch_on_login_prompt();
|
let result = manager.should_show_launch_on_login_prompt();
|
||||||
assert!(result.is_ok(), "Should not fail");
|
assert!(result.is_ok(), "Should not fail");
|
||||||
|
|
||||||
// By default, should show prompt (not declined, autostart not enabled)
|
|
||||||
let _should_show = result.unwrap();
|
let _should_show = result.unwrap();
|
||||||
// Note: The actual value depends on system autostart state, so we just test it doesn't fail
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decline_launch_on_login() {
|
fn test_decline_launch_on_login() {
|
||||||
let (manager, _temp_dir) = create_test_settings_manager();
|
let (manager, _temp_dir, _guard) = create_test_settings_manager();
|
||||||
|
|
||||||
// Initially not declined
|
|
||||||
let settings = manager.load_settings().unwrap();
|
let settings = manager.load_settings().unwrap();
|
||||||
assert!(!settings.launch_on_login_declined);
|
assert!(!settings.launch_on_login_declined);
|
||||||
|
|
||||||
// Decline
|
|
||||||
manager.decline_launch_on_login().unwrap();
|
manager.decline_launch_on_login().unwrap();
|
||||||
|
|
||||||
// Should be declined now
|
|
||||||
let settings = manager.load_settings().unwrap();
|
let settings = manager.load_settings().unwrap();
|
||||||
assert!(settings.launch_on_login_declined);
|
assert!(settings.launch_on_login_declined);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load_corrupted_settings_file() {
|
fn test_load_corrupted_settings_file() {
|
||||||
let (manager, _temp_dir) = create_test_settings_manager();
|
let (manager, _temp_dir, _guard) = create_test_settings_manager();
|
||||||
|
|
||||||
// Create settings directory
|
|
||||||
let settings_dir = manager.get_settings_dir();
|
let settings_dir = manager.get_settings_dir();
|
||||||
fs::create_dir_all(&settings_dir).expect("Should create settings directory");
|
fs::create_dir_all(&settings_dir).expect("Should create settings directory");
|
||||||
|
|
||||||
// Write corrupted JSON
|
|
||||||
let settings_file = manager.get_settings_file();
|
let settings_file = manager.get_settings_file();
|
||||||
fs::write(&settings_file, "{ invalid json }").expect("Should write corrupted file");
|
fs::write(&settings_file, "{ invalid json }").expect("Should write corrupted file");
|
||||||
|
|
||||||
// Should handle corrupted file gracefully
|
|
||||||
let result = manager.load_settings();
|
let result = manager.load_settings();
|
||||||
assert!(
|
assert!(
|
||||||
result.is_ok(),
|
result.is_ok(),
|
||||||
@@ -1151,7 +1111,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_settings_file_paths() {
|
fn test_settings_file_paths() {
|
||||||
let (manager, _temp_dir) = create_test_settings_manager();
|
let (manager, _temp_dir, _guard) = create_test_settings_manager();
|
||||||
|
|
||||||
let settings_dir = manager.get_settings_dir();
|
let settings_dir = manager.get_settings_dir();
|
||||||
let settings_file = manager.get_settings_file();
|
let settings_file = manager.get_settings_file();
|
||||||
|
|||||||
@@ -1,56 +1,22 @@
|
|||||||
use crate::profile::BrowserProfile;
|
use crate::profile::BrowserProfile;
|
||||||
use directories::BaseDirs;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
|
||||||
struct TagsData {
|
struct TagsData {
|
||||||
tags: Vec<String>,
|
tags: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TagManager {
|
pub struct TagManager;
|
||||||
base_dirs: BaseDirs,
|
|
||||||
data_dir_override: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TagManager {
|
impl TagManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self
|
||||||
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
||||||
data_dir_override: std::env::var("DONUTBROWSER_DATA_DIR")
|
|
||||||
.ok()
|
|
||||||
.map(PathBuf::from),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for tests to override data directory without global env var
|
fn get_tags_file_path(&self) -> std::path::PathBuf {
|
||||||
#[allow(dead_code)]
|
crate::app_dirs::data_subdir().join("tags.json")
|
||||||
pub fn with_data_dir_override(dir: &Path) -> Self {
|
|
||||||
Self {
|
|
||||||
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
||||||
data_dir_override: Some(dir.to_path_buf()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_tags_file_path(&self) -> PathBuf {
|
|
||||||
if let Some(dir) = &self.data_dir_override {
|
|
||||||
let mut override_path = dir.clone();
|
|
||||||
let _ = fs::create_dir_all(&override_path);
|
|
||||||
override_path.push("tags.json");
|
|
||||||
return override_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut path = self.base_dirs.data_local_dir().to_path_buf();
|
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("data");
|
|
||||||
path.push("tags.json");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_tags_data(&self) -> Result<TagsData, Box<dyn std::error::Error>> {
|
fn load_tags_data(&self) -> Result<TagsData, Box<dyn std::error::Error>> {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use directories::BaseDirs;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@@ -328,17 +327,8 @@ fn acquire_file_lock(lock_path: &PathBuf) -> Result<FileLockGuard, Box<dyn std::
|
|||||||
Ok(FileLockGuard { _file: file })
|
Ok(FileLockGuard { _file: file })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the traffic stats storage directory
|
|
||||||
pub fn get_traffic_stats_dir() -> PathBuf {
|
pub fn get_traffic_stats_dir() -> PathBuf {
|
||||||
let base_dirs = BaseDirs::new().expect("Failed to get base directories");
|
crate::app_dirs::cache_dir().join("traffic_stats")
|
||||||
let mut path = base_dirs.cache_dir().to_path_buf();
|
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("traffic_stats");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the storage key for traffic stats (profile_id if available, otherwise proxy_id)
|
/// Get the storage key for traffic stats (profile_id if available, otherwise proxy_id)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use directories::BaseDirs;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -67,13 +66,7 @@ impl VersionUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_cache_dir() -> Result<PathBuf, Box<dyn std::error::Error>> {
|
fn get_cache_dir() -> Result<PathBuf, Box<dyn std::error::Error>> {
|
||||||
let base_dirs = BaseDirs::new().ok_or("Failed to get base directories")?;
|
let cache_dir = crate::app_dirs::cache_dir().join("version_cache");
|
||||||
let app_name = if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
};
|
|
||||||
let cache_dir = base_dirs.cache_dir().join(app_name).join("version_cache");
|
|
||||||
fs::create_dir_all(&cache_dir)?;
|
fs::create_dir_all(&cache_dir)?;
|
||||||
Ok(cache_dir)
|
Ok(cache_dir)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::browser_runner::BrowserRunner;
|
use crate::browser_runner::BrowserRunner;
|
||||||
use crate::profile::BrowserProfile;
|
use crate::profile::BrowserProfile;
|
||||||
use directories::BaseDirs;
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
@@ -72,8 +71,6 @@ struct WayfernManagerInner {
|
|||||||
|
|
||||||
pub struct WayfernManager {
|
pub struct WayfernManager {
|
||||||
inner: Arc<AsyncMutex<WayfernManagerInner>>,
|
inner: Arc<AsyncMutex<WayfernManagerInner>>,
|
||||||
#[allow(dead_code)]
|
|
||||||
base_dirs: BaseDirs,
|
|
||||||
http_client: Client,
|
http_client: Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +88,6 @@ impl WayfernManager {
|
|||||||
inner: Arc::new(AsyncMutex::new(WayfernManagerInner {
|
inner: Arc::new(AsyncMutex::new(WayfernManagerInner {
|
||||||
instances: HashMap::new(),
|
instances: HashMap::new(),
|
||||||
})),
|
})),
|
||||||
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
||||||
http_client: Client::new(),
|
http_client: Client::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,26 +98,12 @@ impl WayfernManager {
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn get_profiles_dir(&self) -> PathBuf {
|
pub fn get_profiles_dir(&self) -> PathBuf {
|
||||||
let mut path = self.base_dirs.data_local_dir().to_path_buf();
|
crate::app_dirs::profiles_dir()
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("profiles");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn get_binaries_dir(&self) -> PathBuf {
|
fn get_binaries_dir(&self) -> PathBuf {
|
||||||
let mut path = self.base_dirs.data_local_dir().to_path_buf();
|
crate::app_dirs::binaries_dir()
|
||||||
path.push(if cfg!(debug_assertions) {
|
|
||||||
"DonutBrowserDev"
|
|
||||||
} else {
|
|
||||||
"DonutBrowser"
|
|
||||||
});
|
|
||||||
path.push("binaries");
|
|
||||||
path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn find_free_port() -> Result<u16, Box<dyn std::error::Error + Send + Sync>> {
|
async fn find_free_port() -> Result<u16, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
|
|||||||
@@ -516,13 +516,7 @@ async fn test_traffic_tracking() -> Result<(), Box<dyn std::error::Error + Send
|
|||||||
// Wait for traffic stats to be flushed (happens every second)
|
// Wait for traffic stats to be flushed (happens every second)
|
||||||
sleep(Duration::from_secs(2)).await;
|
sleep(Duration::from_secs(2)).await;
|
||||||
|
|
||||||
// Verify traffic was tracked by checking traffic stats file exists
|
let traffic_stats_dir = donutbrowser_lib::app_dirs::cache_dir().join("traffic_stats");
|
||||||
// Note: Traffic stats are stored in the cache directory
|
|
||||||
let cache_dir = directories::BaseDirs::new()
|
|
||||||
.expect("Failed to get base directories")
|
|
||||||
.cache_dir()
|
|
||||||
.to_path_buf();
|
|
||||||
let traffic_stats_dir = cache_dir.join("DonutBrowserDev").join("traffic_stats");
|
|
||||||
let stats_file = traffic_stats_dir.join(format!("{}.json", proxy_id));
|
let stats_file = traffic_stats_dir.join(format!("{}.json", proxy_id));
|
||||||
|
|
||||||
if stats_file.exists() {
|
if stats_file.exists() {
|
||||||
|
|||||||
Reference in New Issue
Block a user