decrypt_cookies/browser/
firefox.rs

1use std::path::PathBuf;
2
3use super::CACHE_PATH;
4
5pub trait FirefoxPath {
6    /// Suffix for data path
7    const BASE: &'static str;
8    /// Name for [`std::fmt::Display`]
9    const NAME: &'static str;
10    /// Suffix for cookies data path (sqlite3 database)
11    const COOKIES: &str = "cookies.sqlite";
12    /// Suffix for login data path (json)
13    const LOGIN_DATA: &str = "logins.json";
14    /// Suffix for decryption key path (sqlite3 database)
15    const KEY: &str = "key4.db";
16
17    /// Decryption key path (sqlite3 database)
18    fn key(mut base: PathBuf) -> PathBuf {
19        push_exact!(base, Self::KEY);
20
21        base
22    }
23    /// Copy the decryption key file to a location to avoid conflicts with the browser over access to it.
24    fn key_temp() -> Option<PathBuf> {
25        push_temp!(cache, Self::KEY);
26
27        cache.into()
28    }
29
30    /// Cookies path (sqlite3 database)
31    fn cookies(mut base: PathBuf) -> PathBuf {
32        push_exact!(base, Self::COOKIES);
33
34        base
35    }
36    /// Copy the cookies file to a location to avoid conflicts with the browser over access to it.
37    fn cookies_temp() -> Option<PathBuf> {
38        push_temp!(cache, Self::COOKIES);
39
40        cache.into()
41    }
42
43    /// Login data path (json)
44    fn login_data(mut base: PathBuf) -> PathBuf {
45        push_exact!(base, Self::LOGIN_DATA);
46
47        base
48    }
49    /// Copy the login data file to a location to avoid conflicts with the browser over access to it.
50    fn login_data_temp() -> Option<PathBuf> {
51        push_temp!(cache, Self::LOGIN_DATA);
52
53        cache.into()
54    }
55}
56
57/// Register a Firefox based browser info
58///
59/// When linkme feature is enabled, the macro requires the `linkme` crate.
60///
61/// It accept
62/// - `platform`
63/// - `browser`: Generate a struct
64/// - `base: <path>`: A browser all data location relative to home dir.
65/// - `cookies: <path>`, `login_data: <path>`, `key: <path>`: Relative to profile dir. (optional)
66///
67/// # Example:
68///
69/// ```rust, no_run
70/// firefox!(
71///     "linux",
72///     Firefox,
73///     base: ".mozilla/firefox",
74///     cookies: "cookies.sqlite",
75///     login_data: "logins.json",
76///     key: "key4.db"
77/// );
78/// // or omit use default value
79/// firefox!("linux", Firefox, base: ".mozilla/firefox");
80/// firefox!("macos", Firefox, base: "Library/Application Support/Firefox");
81/// firefox!("windows", Firefox, base: r"AppData\Roaming\Mozilla\Firefox");
82/// ```
83#[macro_export]
84macro_rules! firefox {
85    (
86        $platform:literal,
87        $browser:ident,
88        base: $base:literal
89        $(, cookies: $cookies:literal)?
90        $(, login_data: $login_data:literal)?
91        $(, key = $key:literal)?
92    ) => {
93        #[cfg(feature = "linkme")]
94        $crate::pastey::paste! {
95            #[cfg(target_os = $platform)]
96            #[linkme::distributed_slice($crate::browser::BROWSERS)]
97            static [<$browser:upper _NAME>]: &str = stringify!($browser);
98        }
99
100        #[cfg(target_os = $platform)]
101        #[derive(Clone, Copy)]
102        #[derive(Debug)]
103        #[derive(Default)]
104        #[derive(PartialEq, Eq, PartialOrd, Ord)]
105        #[expect(clippy::exhaustive_structs, reason = "unit struct")]
106        pub struct $browser;
107
108        #[cfg(target_os = $platform)]
109        impl FirefoxPath for $browser {
110            const BASE: &'static str = $base;
111            const NAME: &'static str = stringify!($browser);
112            $(const COOKIES: &str = $cookies;)?
113            $(const LOGIN_DATA: &str = $login_data;)?
114            $(const KEY: &str = $key;)?
115        }
116
117        #[cfg(target_os = $platform)]
118        impl std::fmt::Display for $browser {
119            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120                f.write_str(Self::NAME)
121            }
122        }
123    };
124}
125
126firefox!("linux", Firefox  , base: ".mozilla/firefox");
127firefox!("linux", Librewolf, base: ".librewolf"      );
128firefox!("linux", Floorp   , base: ".floorp"         );
129firefox!("linux", Zen      , base: ".zen"            );
130
131firefox!("macos", Firefox  , base: "Library/Application Support/Firefox"  );
132firefox!("macos", Librewolf, base: "Library/Application Support/librewolf");
133firefox!("macos", Floorp   , base: "Library/Application Support/Floorp"   );
134firefox!("macos", Zen      , base: "Library/Application Support/zen"      );
135
136firefox!("windows", Firefox  , base: r"AppData\Roaming\Mozilla\Firefox");
137firefox!("windows", Librewolf, base: r"AppData\Roaming\librewolf"      );
138firefox!("windows", Floorp   , base: r"AppData\Roaming\Floorp"         );
139firefox!("windows", Zen      , base: r"AppData\Roaming\zen"            );