Skip to main content

clawser_browser/
profile.rs

1use std::path::PathBuf;
2use std::sync::atomic::{AtomicU64, Ordering};
3
4const CHROME_MAJOR: &str = "134";
5const CHROME_FULL: &str = "134.0.6998.0";
6const GREASE_BRAND: &str = "Not:A-Brand";
7
8const NV: &str = "Google Inc. (NVIDIA)";
9const AMD: &str = "Google Inc. (AMD)";
10const INTEL: &str = "Google Inc. (Intel)";
11
12macro_rules! nv { ($n:expr) => { concat!("ANGLE (NVIDIA, NVIDIA GeForce ", $n, " Direct3D11 vs_5_0 ps_5_0, D3D11)") } }
13macro_rules! amd { ($n:expr) => { concat!("ANGLE (AMD, AMD Radeon ", $n, " Direct3D11 vs_5_0 ps_5_0, D3D11)") } }
14macro_rules! amd_i { ($n:expr) => { concat!("ANGLE (AMD, AMD Radeon(TM) ", $n, " Direct3D11 vs_5_0 ps_5_0, D3D11)") } }
15macro_rules! intel { ($n:expr) => { concat!("ANGLE (Intel, Intel(R) ", $n, " Direct3D11 vs_5_0 ps_5_0, D3D11)") } }
16
17#[derive(Debug, Clone, Copy)]
18pub struct HwProfile {
19    pub gpu_vendor: &'static str,
20    pub gpu_renderer: &'static str,
21    pub width: u32,
22    pub height: u32,
23    pub cores: u32,
24    pub memory: u32,
25    pub dpr: f64,
26    pub max_texture_size: u32,
27}
28
29// 100 realistic device profiles — Steam Hardware Survey + realistic CPU/RAM pairings
30#[rustfmt::skip]
31pub static PROFILES: [HwProfile; 100] = [
32    // ── NVIDIA Desktop (25) ──
33    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 5090"),           width: 3840, height: 2160, cores: 32, memory: 64, dpr: 2.0,  max_texture_size: 32768 },
34    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 5090"),           width: 2560, height: 1440, cores: 24, memory: 32, dpr: 1.0,  max_texture_size: 32768 },
35    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 5080"),           width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 32768 },
36    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 5080"),           width: 3840, height: 2160, cores: 24, memory: 64, dpr: 1.5,  max_texture_size: 32768 },
37    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 5070 Ti"),        width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
38    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 5070"),           width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
39    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4090"),           width: 3840, height: 2160, cores: 24, memory: 64, dpr: 1.5,  max_texture_size: 32768 },
40    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4090"),           width: 2560, height: 1440, cores: 32, memory: 32, dpr: 1.0,  max_texture_size: 32768 },
41    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4080 SUPER"),     width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
42    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4080"),           width: 2560, height: 1440, cores: 24, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
43    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4070 Ti SUPER"),  width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
44    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4070 Ti"),        width: 1920, height: 1080, cores: 12, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
45    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4070 SUPER"),     width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
46    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4070"),           width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
47    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4060 Ti"),        width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
48    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4060"),           width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
49    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3090 Ti"),        width: 3840, height: 2160, cores: 24, memory: 64, dpr: 1.5,  max_texture_size: 16384 },
50    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3090"),           width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
51    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3080 Ti"),        width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
52    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3080"),           width: 2560, height: 1440, cores: 12, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
53    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3070 Ti"),        width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
54    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3070"),           width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
55    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3060 Ti"),        width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
56    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3060"),           width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
57    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3050"),           width: 1920, height: 1080, cores:  6, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
58    // ── NVIDIA Older (5) ──
59    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("GTX 1660 SUPER"),     width: 1920, height: 1080, cores:  6, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
60    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("GTX 1660"),           width: 1920, height: 1080, cores:  6, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
61    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("GTX 1650 SUPER"),     width: 1920, height: 1080, cores:  6, memory:  8, dpr: 1.0,  max_texture_size: 16384 },
62    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("GTX 1650"),           width: 1920, height: 1080, cores:  4, memory:  8, dpr: 1.0,  max_texture_size: 16384 },
63    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("GTX 1050 Ti"),        width: 1920, height: 1080, cores:  4, memory:  8, dpr: 1.0,  max_texture_size: 16384 },
64    // ── AMD Desktop (20) ──
65    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 9070 XT"),       width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
66    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 9070"),          width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
67    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7900 XTX"),      width: 3840, height: 2160, cores: 24, memory: 64, dpr: 1.5,  max_texture_size: 16384 },
68    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7900 XT"),       width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
69    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7900 GRE"),      width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
70    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7800 XT"),       width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
71    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7700 XT"),       width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
72    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7600 XT"),       width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
73    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7600"),          width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
74    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6950 XT"),       width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
75    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6900 XT"),       width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
76    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6800 XT"),       width: 2560, height: 1440, cores: 12, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
77    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6800"),          width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
78    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6700 XT"),       width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
79    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6700"),          width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
80    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6650 XT"),       width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
81    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6600 XT"),       width: 1920, height: 1080, cores:  6, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
82    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6600"),          width: 1920, height: 1080, cores:  6, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
83    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6500 XT"),       width: 1920, height: 1080, cores:  6, memory:  8, dpr: 1.0,  max_texture_size: 16384 },
84    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 5700 XT"),       width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
85    // ── Intel Desktop (10) ──
86    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("Arc(TM) A770 Graphics"),  width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0, max_texture_size: 16384 },
87    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("Arc(TM) A750 Graphics"),  width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0, max_texture_size: 16384 },
88    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("Arc(TM) A580 Graphics"),  width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0, max_texture_size: 16384 },
89    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("UHD Graphics 770"),       width: 1920, height: 1080, cores: 24, memory: 32, dpr: 1.0, max_texture_size: 16384 },
90    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("UHD Graphics 770"),       width: 1920, height: 1080, cores: 16, memory: 16, dpr: 1.0, max_texture_size: 16384 },
91    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("UHD Graphics 730"),       width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0, max_texture_size: 16384 },
92    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("UHD Graphics 630"),       width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0, max_texture_size: 16384 },
93    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("UHD Graphics 630"),       width: 1920, height: 1080, cores:  6, memory: 16, dpr: 1.0, max_texture_size: 16384 },
94    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("UHD Graphics 610"),       width: 1920, height: 1080, cores:  4, memory:  8, dpr: 1.0, max_texture_size: 16384 },
95    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("HD Graphics 530"),        width: 1920, height: 1080, cores:  4, memory:  8, dpr: 1.0, max_texture_size: 16384 },
96    // ── NVIDIA Laptop (10) ──
97    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4090 Laptop GPU"),   width: 2560, height: 1600, cores: 16, memory: 32, dpr: 1.25, max_texture_size: 16384 },
98    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4080 Laptop GPU"),   width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
99    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4070 Laptop GPU"),   width: 1920, height: 1200, cores: 12, memory: 16, dpr: 1.25, max_texture_size: 16384 },
100    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4060 Laptop GPU"),   width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
101    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4050 Laptop GPU"),   width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.25, max_texture_size: 16384 },
102    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3080 Laptop GPU"),   width: 2560, height: 1440, cores: 12, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
103    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3070 Laptop GPU"),   width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
104    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3060 Laptop GPU"),   width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.25, max_texture_size: 16384 },
105    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3050 Laptop GPU"),   width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
106    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 2060"),              width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
107    // ── Intel Laptop (7) ──
108    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("Iris(R) Xe Graphics"),    width: 1920, height: 1200, cores: 12, memory: 16, dpr: 1.25, max_texture_size: 16384 },
109    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("Iris(R) Xe Graphics"),    width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
110    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("Iris(R) Xe Graphics"),    width: 2560, height: 1600, cores: 12, memory: 16, dpr: 1.5,  max_texture_size: 16384 },
111    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("UHD Graphics"),           width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.25, max_texture_size: 16384 },
112    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("UHD Graphics"),           width: 1920, height: 1080, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
113    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("Iris(R) Plus Graphics"),  width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
114    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("UHD Graphics"),           width: 1920, height: 1080, cores: 16, memory: 32, dpr: 1.25, max_texture_size: 16384 },
115    // ── AMD Laptop (8) ──
116    HwProfile { gpu_vendor: AMD, gpu_renderer: amd_i!("780M"),                  width: 1920, height: 1200, cores:  8, memory: 16, dpr: 1.25, max_texture_size: 16384 },
117    HwProfile { gpu_vendor: AMD, gpu_renderer: amd_i!("780M"),                  width: 2560, height: 1600, cores:  8, memory: 16, dpr: 1.5,  max_texture_size: 16384 },
118    HwProfile { gpu_vendor: AMD, gpu_renderer: amd_i!("680M"),                  width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
119    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7600M XT"),             width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
120    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6700M"),                width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
121    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6600M"),                width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.25, max_texture_size: 16384 },
122    HwProfile { gpu_vendor: AMD, gpu_renderer: amd_i!("Vega 8 Graphics"),       width: 1920, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
123    HwProfile { gpu_vendor: AMD, gpu_renderer: amd_i!("Vega 10 Graphics"),      width: 1920, height: 1080, cores:  4, memory:  8, dpr: 1.0,  max_texture_size: 16384 },
124    // ── Ultrawide & Alt Configs (15) ──
125    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4070 Ti"),          width: 3440, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
126    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3080"),             width: 3440, height: 1440, cores: 12, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
127    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7900 XTX"),       width: 3440, height: 1440, cores: 24, memory: 64, dpr: 1.0,  max_texture_size: 16384 },
128    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4090"),             width: 2560, height: 1440, cores: 24, memory: 128, dpr: 1.0, max_texture_size: 32768 },
129    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3060"),             width: 1366, height:  768, cores:  6, memory:  8, dpr: 1.0,  max_texture_size: 16384 },
130    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4060 Ti"),          width: 2560, height: 1440, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
131    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7800 XT"),        width: 2560, height: 1440, cores: 12, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
132    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3070 Ti"),          width: 2560, height: 1440, cores: 12, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
133    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 7600"),           width: 1920, height: 1080, cores:  6, memory: 16, dpr: 1.25, max_texture_size: 16384 },
134    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 4070 SUPER"),       width: 2560, height: 1440, cores: 16, memory: 32, dpr: 1.0,  max_texture_size: 16384 },
135    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 5070 Ti"),          width: 3840, height: 2160, cores: 16, memory: 32, dpr: 1.5,  max_texture_size: 16384 },
136    HwProfile { gpu_vendor: INTEL, gpu_renderer: intel!("Arc(TM) A770 Graphics"), width: 1920, height: 1080, cores: 16, memory: 32, dpr: 1.0, max_texture_size: 16384 },
137    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("RTX 3060"),             width: 2560, height: 1080, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
138    HwProfile { gpu_vendor: AMD, gpu_renderer: amd!("RX 6700 XT"),        width: 2560, height: 1440, cores:  8, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
139    HwProfile { gpu_vendor: NV, gpu_renderer: nv!("GTX 1660 Ti"),          width: 1920, height: 1080, cores:  6, memory: 16, dpr: 1.0,  max_texture_size: 16384 },
140];
141
142static TIMEZONES: &[(&str, &str)] = &[
143    ("America/New_York", "en-US"),
144    ("America/Chicago", "en-US"),
145    ("America/Denver", "en-US"),
146    ("America/Los_Angeles", "en-US"),
147    ("America/Phoenix", "en-US"),
148    ("Europe/London", "en-GB"),
149    ("Europe/Paris", "fr-FR"),
150    ("Europe/Berlin", "de-DE"),
151    ("Europe/Madrid", "es-ES"),
152    ("Europe/Rome", "it-IT"),
153    ("Europe/Amsterdam", "nl-NL"),
154    ("Europe/Warsaw", "pl-PL"),
155    ("Europe/Bucharest", "ro-RO"),
156    ("Europe/Istanbul", "tr-TR"),
157    ("Europe/Moscow", "ru-RU"),
158    ("Asia/Tokyo", "ja-JP"),
159    ("Asia/Seoul", "ko-KR"),
160    ("Asia/Shanghai", "zh-CN"),
161    ("Asia/Hong_Kong", "zh-HK"),
162    ("Asia/Taipei", "zh-TW"),
163    ("Asia/Singapore", "en-SG"),
164    ("Asia/Bangkok", "th-TH"),
165    ("Australia/Sydney", "en-AU"),
166    ("America/Toronto", "en-CA"),
167    ("America/Sao_Paulo", "pt-BR"),
168    ("Asia/Kolkata", "hi-IN"),
169];
170
171static FONTS: &[&str] = &[
172    "Arial", "Arial Black", "Calibri", "Cambria", "Candara",
173    "Comic Sans MS", "Consolas", "Constantia", "Corbel",
174    "Courier New", "Georgia", "Impact", "Lucida Console",
175    "Lucida Sans Unicode", "Microsoft Sans Serif", "Palatino Linotype",
176    "Segoe Print", "Segoe Script", "Segoe UI", "Segoe UI Symbol",
177    "Tahoma", "Times New Roman", "Trebuchet MS", "Verdana",
178    "Webdings", "Wingdings",
179];
180
181// ── PRNG ──
182
183struct Rng(u64);
184
185impl Rng {
186    fn new(seed: u64) -> Self {
187        Self(if seed == 0 { 1 } else { seed })
188    }
189
190    fn next(&mut self) -> u64 {
191        let mut x = self.0;
192        x ^= x << 13;
193        x ^= x >> 7;
194        x ^= x << 17;
195        self.0 = x;
196        x
197    }
198
199    fn range(&mut self, max: usize) -> usize {
200        (self.next() % max as u64) as usize
201    }
202}
203
204// ── Public API ──
205
206static COUNTER: AtomicU64 = AtomicU64::new(0);
207
208/// Pick a random profile index and seed using OS time + counter.
209pub fn random_profile() -> (usize, u64) {
210    let nanos = std::time::SystemTime::now()
211        .duration_since(std::time::UNIX_EPOCH)
212        .unwrap()
213        .as_nanos() as u64;
214    let count = COUNTER.fetch_add(1, Ordering::Relaxed);
215    let seed = nanos ^ count.wrapping_mul(6364136223846793005);
216    let idx = (seed as usize) % PROFILES.len();
217    (idx, seed)
218}
219
220/// Generate a complete clawser config JSON for the given profile and seed.
221pub fn generate_config_json(profile_index: usize, seed: u64) -> String {
222    let idx = profile_index % PROFILES.len();
223    let p = &PROFILES[idx];
224    let mut rng = Rng::new(seed);
225
226    // No timezone/locale spoofing — use system defaults.
227    // Spoofed timezone mismatches IP geolocation and is a detection signal.
228    let langs: Vec<String> = vec!["en-US".to_string(), "en".to_string()];
229
230    let config = serde_json::json!({
231        "profile_id": format!("clawser_{}_{}", idx, seed),
232        "navigator": {
233            "user_agent": format!(
234                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{}.0.0.0 Safari/537.36",
235                CHROME_MAJOR
236            ),
237            "app_version": format!(
238                "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{}.0.0.0 Safari/537.36",
239                CHROME_MAJOR
240            ),
241            "platform": "Win32",
242            "vendor": "Google Inc.",
243            "languages": langs,
244            "hardware_concurrency": p.cores,
245            "device_memory": p.memory,
246            "max_touch_points": 0,
247            "user_agent_data": {
248                "brands": [
249                    { "brand": "Chromium", "version": CHROME_MAJOR },
250                    { "brand": "Google Chrome", "version": CHROME_MAJOR },
251                    { "brand": GREASE_BRAND, "version": "24" }
252                ],
253                "mobile": false,
254                "platform": "Windows",
255                "platform_version": "15.0.0",
256                "architecture": "x86",
257                "bitness": "64",
258                "model": "",
259                "full_version_list": [
260                    { "brand": "Chromium", "version": CHROME_FULL },
261                    { "brand": "Google Chrome", "version": CHROME_FULL },
262                    { "brand": GREASE_BRAND, "version": "24.0.0.0" }
263                ]
264            }
265        },
266        "screen": {
267            "width": p.width,
268            "height": p.height,
269            "avail_width": p.width,
270            "avail_height": p.height.saturating_sub(40),
271            "color_depth": 24,
272            "pixel_depth": 24,
273            "device_pixel_ratio": p.dpr
274        },
275        "gpu": {
276            "vendor": p.gpu_vendor,
277            "renderer": p.gpu_renderer
278        },
279        "noise_seeds": {
280            "canvas": rng.next(),
281            "webgl": rng.next(),
282            "audio": rng.next(),
283            "client_rects": rng.next()
284        },
285        "locale": "en-US",
286        "fonts": FONTS,
287        "media_devices": {
288            "audio_inputs": 1 + rng.range(2),
289            "audio_outputs": 1 + rng.range(3),
290            "video_inputs": rng.range(2)
291        },
292        "webrtc": { "policy": "disabled" },
293        "battery": false,
294        "bluetooth": false,
295        "usb": false
296    });
297
298    serde_json::to_string_pretty(&config).unwrap()
299}
300
301/// Write config JSON to temp file, return the canonical Windows path.
302pub fn write_config_file(profile_index: usize, seed: u64) -> std::io::Result<PathBuf> {
303    let json = generate_config_json(profile_index, seed);
304    let dir = std::env::temp_dir().join("clawser_configs");
305    std::fs::create_dir_all(&dir)?;
306    let file = dir.join(format!("profile_{}_{}.json", profile_index % PROFILES.len(), seed));
307    std::fs::write(&file, &json)?;
308    let canonical = file.canonicalize()?;
309    // Strip \\?\ UNC prefix on Windows
310    let s = canonical.to_string_lossy();
311    if let Some(stripped) = s.strip_prefix("\\\\?\\") {
312        Ok(PathBuf::from(stripped))
313    } else {
314        Ok(canonical)
315    }
316}