Skip to main content

seher/browser/
types.rs

1use std::path::PathBuf;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum BrowserType {
5    Chrome,
6    Edge,
7    Brave,
8    Chromium,
9    Vivaldi,
10    Comet,
11    Dia,
12    Atlas,
13    Firefox,
14    Safari,
15}
16
17impl BrowserType {
18    pub fn name(&self) -> &str {
19        match self {
20            BrowserType::Chrome => "Chrome",
21            BrowserType::Edge => "Edge",
22            BrowserType::Brave => "Brave",
23            BrowserType::Chromium => "Chromium",
24            BrowserType::Vivaldi => "Vivaldi",
25            BrowserType::Comet => "Comet",
26            BrowserType::Dia => "Dia",
27            BrowserType::Atlas => "Atlas",
28            BrowserType::Firefox => "Firefox",
29            BrowserType::Safari => "Safari",
30        }
31    }
32
33    pub fn is_chromium_based(&self) -> bool {
34        matches!(
35            self,
36            BrowserType::Chrome
37                | BrowserType::Edge
38                | BrowserType::Brave
39                | BrowserType::Chromium
40                | BrowserType::Vivaldi
41                | BrowserType::Comet
42                | BrowserType::Dia
43                | BrowserType::Atlas
44        )
45    }
46}
47
48impl std::str::FromStr for BrowserType {
49    type Err = String;
50    fn from_str(s: &str) -> Result<Self, Self::Err> {
51        match s.to_lowercase().as_str() {
52            "chrome" => Ok(BrowserType::Chrome),
53            "edge" => Ok(BrowserType::Edge),
54            "brave" => Ok(BrowserType::Brave),
55            "chromium" => Ok(BrowserType::Chromium),
56            "vivaldi" => Ok(BrowserType::Vivaldi),
57            "comet" => Ok(BrowserType::Comet),
58            "dia" => Ok(BrowserType::Dia),
59            "atlas" => Ok(BrowserType::Atlas),
60            "firefox" => Ok(BrowserType::Firefox),
61            "safari" => Ok(BrowserType::Safari),
62            other => Err(format!("Unknown browser: {}", other)),
63        }
64    }
65}
66
67#[derive(Debug, Clone)]
68pub struct Profile {
69    pub name: String,
70    pub path: PathBuf,
71    pub browser_type: BrowserType,
72}
73
74impl Profile {
75    pub fn new(name: String, path: PathBuf, browser_type: BrowserType) -> Self {
76        Self {
77            name,
78            path,
79            browser_type,
80        }
81    }
82
83    pub fn cookies_path(&self) -> PathBuf {
84        match self.browser_type {
85            BrowserType::Firefox => self.path.join("cookies.sqlite"),
86            BrowserType::Safari => self.path.clone(),
87            _ => self.path.join("Cookies"),
88        }
89    }
90
91    pub fn local_state_path(&self) -> PathBuf {
92        self.path
93            .parent()
94            .map(|p| p.join("Local State"))
95            .unwrap_or_else(|| PathBuf::from("Local State"))
96    }
97}
98
99#[derive(Debug, Clone)]
100pub struct Cookie {
101    pub name: String,
102    pub value: String,
103    pub domain: String,
104    pub path: String,
105    pub expires_utc: i64,
106    pub is_secure: bool,
107    pub is_httponly: bool,
108    pub same_site: i32,
109}
110
111impl Cookie {
112    pub fn is_expired(&self) -> bool {
113        use std::time::{SystemTime, UNIX_EPOCH};
114        let now = SystemTime::now()
115            .duration_since(UNIX_EPOCH)
116            .unwrap()
117            .as_secs() as i64;
118
119        // Chrome uses microseconds since Windows epoch (1601-01-01)
120        // Convert to Unix timestamp
121        let unix_timestamp = (self.expires_utc / 1_000_000) - 11644473600;
122        unix_timestamp > 0 && unix_timestamp < now
123    }
124}