mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-05-11 04:24:57 +02:00
235 lines
6.6 KiB
Rust
235 lines
6.6 KiB
Rust
use directories::BaseDirs;
|
|
use std::path::PathBuf;
|
|
use std::process::Stdio;
|
|
use tokio::process::Command as TokioCommand;
|
|
|
|
use crate::browser::{create_browser, BrowserType};
|
|
use crate::downloaded_browsers_registry::DownloadedBrowsersRegistry;
|
|
use crate::profile::ProfileManager;
|
|
|
|
const ACCEPT_TERMS_FLAG: &str = "--accept-terms-and-conditions";
|
|
const MIN_VALID_TIMESTAMP: i64 = 1577836800; // 2020-01-01 00:00:00 UTC
|
|
|
|
pub struct WayfernTermsManager {
|
|
base_dirs: BaseDirs,
|
|
}
|
|
|
|
impl WayfernTermsManager {
|
|
fn new() -> Self {
|
|
Self {
|
|
base_dirs: BaseDirs::new().expect("Failed to get base directories"),
|
|
}
|
|
}
|
|
|
|
pub fn instance() -> &'static WayfernTermsManager {
|
|
&WAYFERN_TERMS_MANAGER
|
|
}
|
|
|
|
fn get_license_file_path(&self) -> PathBuf {
|
|
#[cfg(target_os = "windows")]
|
|
{
|
|
// Windows: %APPDATA%\Wayfern\license-accepted
|
|
if let Some(app_data) = std::env::var_os("APPDATA") {
|
|
return PathBuf::from(app_data)
|
|
.join("Wayfern")
|
|
.join("license-accepted");
|
|
}
|
|
// Fallback to home directory
|
|
self
|
|
.base_dirs
|
|
.home_dir()
|
|
.join("AppData")
|
|
.join("Roaming")
|
|
.join("Wayfern")
|
|
.join("license-accepted")
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
{
|
|
// macOS: ~/Library/Application Support/Wayfern/license-accepted
|
|
self
|
|
.base_dirs
|
|
.home_dir()
|
|
.join("Library")
|
|
.join("Application Support")
|
|
.join("Wayfern")
|
|
.join("license-accepted")
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
|
{
|
|
// Linux: ~/.config/Wayfern/license-accepted or $XDG_CONFIG_HOME/Wayfern/license-accepted
|
|
if let Some(xdg_config) = std::env::var_os("XDG_CONFIG_HOME") {
|
|
let xdg_path = PathBuf::from(xdg_config);
|
|
if !xdg_path.as_os_str().is_empty() {
|
|
return xdg_path.join("Wayfern").join("license-accepted");
|
|
}
|
|
}
|
|
self
|
|
.base_dirs
|
|
.home_dir()
|
|
.join(".config")
|
|
.join("Wayfern")
|
|
.join("license-accepted")
|
|
}
|
|
}
|
|
|
|
pub fn is_terms_accepted(&self) -> bool {
|
|
let license_file = self.get_license_file_path();
|
|
|
|
if !license_file.exists() {
|
|
return false;
|
|
}
|
|
|
|
// Read the timestamp from the file
|
|
let contents = match std::fs::read_to_string(&license_file) {
|
|
Ok(c) => c,
|
|
Err(_) => return false,
|
|
};
|
|
|
|
// Parse timestamp (Wayfern stores Unix timestamp as text)
|
|
let timestamp: i64 = match contents.trim().parse() {
|
|
Ok(t) => t,
|
|
Err(_) => return false,
|
|
};
|
|
|
|
// Check that timestamp is positive and after 2020-01-01
|
|
timestamp >= MIN_VALID_TIMESTAMP
|
|
}
|
|
|
|
pub fn is_wayfern_downloaded(&self) -> bool {
|
|
let registry = DownloadedBrowsersRegistry::instance();
|
|
let versions = registry.get_downloaded_versions("wayfern");
|
|
!versions.is_empty()
|
|
}
|
|
|
|
fn get_any_wayfern_executable(&self) -> Option<PathBuf> {
|
|
// First try to get executable from any downloaded Wayfern version
|
|
let registry = DownloadedBrowsersRegistry::instance();
|
|
let versions = registry.get_downloaded_versions("wayfern");
|
|
|
|
if versions.is_empty() {
|
|
return None;
|
|
}
|
|
|
|
// Get first available version
|
|
let version = versions.first()?;
|
|
|
|
// Get binaries directory
|
|
let binaries_dir = ProfileManager::instance().get_binaries_dir();
|
|
let mut browser_dir = binaries_dir;
|
|
browser_dir.push("wayfern");
|
|
browser_dir.push(version);
|
|
|
|
let browser = create_browser(BrowserType::Wayfern);
|
|
browser.get_executable_path(&browser_dir).ok()
|
|
}
|
|
|
|
pub async fn accept_terms(&self) -> Result<(), String> {
|
|
let executable_path = self.get_any_wayfern_executable().ok_or_else(|| {
|
|
"No Wayfern browser downloaded. Please download a Wayfern browser version first.".to_string()
|
|
})?;
|
|
|
|
log::info!(
|
|
"Running Wayfern with {} flag: {:?}",
|
|
ACCEPT_TERMS_FLAG,
|
|
executable_path
|
|
);
|
|
|
|
#[cfg(target_os = "macos")]
|
|
{
|
|
// On macOS, if it's an app bundle, we need to find the actual executable
|
|
let executable_str = executable_path.to_string_lossy();
|
|
if executable_str.ends_with(".app") {
|
|
// Navigate to Contents/MacOS and find the executable
|
|
let macos_dir = executable_path.join("Contents").join("MacOS");
|
|
if let Ok(entries) = std::fs::read_dir(&macos_dir) {
|
|
for entry in entries.flatten() {
|
|
let path = entry.path();
|
|
if path.is_file() {
|
|
return self.run_accept_command(&path).await;
|
|
}
|
|
}
|
|
}
|
|
return Err("Could not find executable in Wayfern app bundle".to_string());
|
|
}
|
|
}
|
|
|
|
self.run_accept_command(&executable_path).await
|
|
}
|
|
|
|
async fn run_accept_command(&self, executable_path: &PathBuf) -> Result<(), String> {
|
|
let output = TokioCommand::new(executable_path)
|
|
.arg(ACCEPT_TERMS_FLAG)
|
|
.stdout(Stdio::piped())
|
|
.stderr(Stdio::piped())
|
|
.output()
|
|
.await
|
|
.map_err(|e| format!("Failed to run Wayfern: {e}"))?;
|
|
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
log::error!("Wayfern terms acceptance failed: {stderr}");
|
|
return Err(format!(
|
|
"Wayfern terms acceptance failed with exit code: {:?}",
|
|
output.status.code()
|
|
));
|
|
}
|
|
|
|
// Verify the license file was created
|
|
if !self.is_terms_accepted() {
|
|
return Err(
|
|
"Terms acceptance command succeeded but license file was not created".to_string(),
|
|
);
|
|
}
|
|
|
|
log::info!("Wayfern terms and conditions accepted successfully");
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
lazy_static::lazy_static! {
|
|
static ref WAYFERN_TERMS_MANAGER: WayfernTermsManager = WayfernTermsManager::new();
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_license_file_path() {
|
|
let manager = WayfernTermsManager::new();
|
|
let path = manager.get_license_file_path();
|
|
let path_str = path.to_string_lossy();
|
|
|
|
assert!(
|
|
path_str.contains("Wayfern"),
|
|
"License file path should contain Wayfern"
|
|
);
|
|
assert!(
|
|
path_str.ends_with("license-accepted"),
|
|
"License file should be named license-accepted"
|
|
);
|
|
|
|
#[cfg(target_os = "macos")]
|
|
assert!(
|
|
path_str.contains("Application Support"),
|
|
"macOS path should contain Application Support"
|
|
);
|
|
|
|
#[cfg(target_os = "linux")]
|
|
assert!(
|
|
path_str.contains(".config") || std::env::var_os("XDG_CONFIG_HOME").is_some(),
|
|
"Linux path should be in .config or XDG_CONFIG_HOME"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_is_terms_accepted_no_file() {
|
|
let manager = WayfernTermsManager::new();
|
|
// This test will pass if no license file exists (which is typically the case in test env)
|
|
// The actual behavior depends on whether the file exists
|
|
let _ = manager.is_terms_accepted();
|
|
}
|
|
}
|