stygian_browser/validation/
validators.rs1use std::collections::HashMap;
4use std::sync::Arc;
5use std::time::Instant;
6
7use tracing::debug;
8
9use crate::page::WaitUntil;
10use crate::pool::BrowserPool;
11
12use super::{ValidationResult, ValidationTarget};
13
14pub fn run_creepjs(pool: &Arc<BrowserPool>) -> ValidationResult {
23 let start = Instant::now();
24 let result = creepjs_impl(pool);
25 ValidationResult {
26 elapsed: start.elapsed(),
27 ..result
28 }
29}
30
31fn creepjs_impl(_pool: &Arc<BrowserPool>) -> ValidationResult {
32 ValidationResult {
44 target: ValidationTarget::CreepJs,
45 passed: false,
46 score: None,
47 details: HashMap::from([("phase".to_string(), "stub-not-yet-implemented".to_string())]),
48 screenshot: None,
49 elapsed: std::time::Duration::ZERO,
50 }
51}
52
53pub fn run_browserscan(pool: &Arc<BrowserPool>) -> ValidationResult {
58 let start = Instant::now();
59 let result = browserscan_impl(pool);
60 ValidationResult {
61 elapsed: start.elapsed(),
62 ..result
63 }
64}
65
66fn browserscan_impl(_pool: &Arc<BrowserPool>) -> ValidationResult {
67 ValidationResult {
76 target: ValidationTarget::BrowserScan,
77 passed: false,
78 score: None,
79 details: HashMap::from([("phase".to_string(), "stub-not-yet-implemented".to_string())]),
80 screenshot: None,
81 elapsed: std::time::Duration::ZERO,
82 }
83}
84
85pub async fn run_kasada(pool: &Arc<BrowserPool>) -> ValidationResult {
94 let start = Instant::now();
95 let result = kasada_impl(pool).await;
96 ValidationResult {
97 elapsed: start.elapsed(),
98 ..result
99 }
100}
101
102async fn kasada_impl(pool: &Arc<BrowserPool>) -> ValidationResult {
103 let url = ValidationTarget::Kasada.url();
104 debug!("Kasada validator: navigating to {url}");
105
106 match pool.acquire().await {
107 Ok(session) => {
108 match session.browser() {
109 Some(browser) => {
110 match browser.new_page().await {
111 Ok(mut page) => {
112 let navigate_result = page
114 .navigate(
115 url,
116 WaitUntil::DomContentLoaded,
117 std::time::Duration::from_secs(20),
118 )
119 .await;
120
121 let passed = match navigate_result {
122 Ok(()) => {
123 true
125 }
126 Err(e) => {
127 debug!("Kasada: navigation failed: {}", e);
129 false
130 }
131 };
132
133 page.close().await.ok();
134
135 ValidationResult {
136 target: ValidationTarget::Kasada,
137 passed,
138 score: None,
139 details: HashMap::from([(
140 "phase".to_string(),
141 "load-check".to_string(),
142 )]),
143 screenshot: None,
144 elapsed: std::time::Duration::ZERO,
145 }
146 }
147 Err(e) => {
148 ValidationResult::failed(ValidationTarget::Kasada, &e.to_string())
149 }
150 }
151 }
152 None => ValidationResult::failed(ValidationTarget::Kasada, "browser handle lost"),
153 }
154 }
155 Err(e) => ValidationResult::failed(ValidationTarget::Kasada, &e.to_string()),
156 }
157}
158
159pub async fn run_cloudflare(pool: &Arc<BrowserPool>) -> ValidationResult {
164 let start = Instant::now();
165 let result = cloudflare_impl(pool).await;
166 ValidationResult {
167 elapsed: start.elapsed(),
168 ..result
169 }
170}
171
172async fn cloudflare_impl(pool: &Arc<BrowserPool>) -> ValidationResult {
173 let url = ValidationTarget::Cloudflare.url();
174 debug!("Cloudflare validator: navigating to {url}");
175
176 match pool.acquire().await {
177 Ok(session) => match session.browser() {
178 Some(browser) => match browser.new_page().await {
179 Ok(mut page) => {
180 let navigate_result = page
181 .navigate(
182 url,
183 WaitUntil::DomContentLoaded,
184 std::time::Duration::from_secs(20),
185 )
186 .await;
187
188 let passed = navigate_result.is_ok();
189
190 page.close().await.ok();
191
192 ValidationResult {
193 target: ValidationTarget::Cloudflare,
194 passed,
195 score: None,
196 details: HashMap::from([("phase".to_string(), "load-check".to_string())]),
197 screenshot: None,
198 elapsed: std::time::Duration::ZERO,
199 }
200 }
201 Err(e) => ValidationResult::failed(ValidationTarget::Cloudflare, &e.to_string()),
202 },
203 None => ValidationResult::failed(ValidationTarget::Cloudflare, "browser handle lost"),
204 },
205 Err(e) => ValidationResult::failed(ValidationTarget::Cloudflare, &e.to_string()),
206 }
207}
208
209pub async fn run_akamai(pool: &Arc<BrowserPool>) -> ValidationResult {
214 let start = Instant::now();
215 let result = akamai_impl(pool).await;
216 ValidationResult {
217 elapsed: start.elapsed(),
218 ..result
219 }
220}
221
222async fn akamai_impl(pool: &Arc<BrowserPool>) -> ValidationResult {
223 let url = ValidationTarget::Akamai.url();
224 debug!("Akamai validator: navigating to {url}");
225
226 match pool.acquire().await {
227 Ok(session) => match session.browser() {
228 Some(browser) => match browser.new_page().await {
229 Ok(mut page) => {
230 let navigate_result = page
231 .navigate(
232 url,
233 WaitUntil::DomContentLoaded,
234 std::time::Duration::from_secs(20),
235 )
236 .await;
237
238 let passed = navigate_result.is_ok();
239
240 page.close().await.ok();
241
242 ValidationResult {
243 target: ValidationTarget::Akamai,
244 passed,
245 score: None,
246 details: HashMap::from([("phase".to_string(), "load-check".to_string())]),
247 screenshot: None,
248 elapsed: std::time::Duration::ZERO,
249 }
250 }
251 Err(e) => ValidationResult::failed(ValidationTarget::Akamai, &e.to_string()),
252 },
253 None => ValidationResult::failed(ValidationTarget::Akamai, "browser handle lost"),
254 },
255 Err(e) => ValidationResult::failed(ValidationTarget::Akamai, &e.to_string()),
256 }
257}