use std::time::Duration;
use drission::prelude::*;
#[tokio::main]
async fn main() -> drission::Result<()> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| "warn".into()),
)
.init();
println!("[*] 启动 Camoufox(headless)…");
let browser = Browser::launch(
BrowserOptions::new()
.headless(true)
.bypass_csp(true)
.ignore_https_errors(true),
)
.await?;
let tab = browser.latest_tab().await?;
tab.get("about:blank").await?;
tab.set().window().size(800, 600).await?;
let mut iw = 0.0;
let mut ih = 0.0;
for _ in 0..20 {
let v = tab.run_js("[window.innerWidth, window.innerHeight]").await?;
iw = v.get(0).and_then(|x| x.as_f64()).unwrap_or(0.0);
ih = v.get(1).and_then(|x| x.as_f64()).unwrap_or(0.0);
if iw as u32 == 800 && ih as u32 == 600 {
break;
}
tokio::time::sleep(Duration::from_millis(100)).await;
}
let size_ok = iw as u32 == 800 && ih as u32 == 600;
println!("[1] window().size(800,600) → innerWidth={iw} innerHeight={ih} (ok={size_ok})");
let avail = tab.run_js("[screen.availWidth, screen.availHeight]").await?;
let aw = avail.get(0).and_then(|x| x.as_f64()).unwrap_or(0.0) as u32;
tab.set().window().max().await?;
let mut max_w = 0u32;
for _ in 0..20 {
let v = tab.run_js("window.innerWidth").await?;
max_w = v.as_f64().unwrap_or(0.0) as u32;
if max_w == aw && aw > 0 {
break;
}
tokio::time::sleep(Duration::from_millis(100)).await;
}
let max_ok = aw > 0 && max_w == aw;
println!("[2] window().max() → innerWidth={max_w} (availWidth={aw}, ok={max_ok})");
let before = tab.intercept().is_intercepting().await;
tab.intercept().start_xhr(&["/api/"]).await?;
let during = tab.intercept().is_intercepting().await;
tab.run_js(
"window.__hijacked = null; \
fetch('http://drission.test/api/profile') \
.then(r => r.json()).then(j => window.__hijacked = j) \
.catch(e => window.__hijacked = { error: String(e) }); true",
)
.await?;
let req = tab.intercept().next().await?;
println!("[3] 拦截到: {} {} [{}]", req.method, req.url, req.resource_type);
req.fulfill(
200,
vec![
("content-type".to_string(), "application/json".to_string()),
("access-control-allow-origin".to_string(), "*".to_string()),
],
r#"{"id":1,"name":"drission","hijacked":true}"#,
)
.await?;
let mut got = serde_json::Value::Null;
for _ in 0..40 {
let v = tab.run_js("window.__hijacked").await?;
if !v.is_null() {
got = v;
break;
}
tokio::time::sleep(Duration::from_millis(100)).await;
}
let intercept_ok = got.get("name").and_then(|v| v.as_str()) == Some("drission")
&& got.get("hijacked").and_then(|v| v.as_bool()) == Some(true);
println!("[4] 页面读到(已伪造)={got} (ok={intercept_ok})");
tab.intercept().stop().await?;
let after = tab.intercept().is_intercepting().await;
let state_ok = !before && during && !after;
println!("[5] is_intercepting 前={before} 中={during} 后={after} (ok={state_ok})");
let pass = size_ok && max_ok && intercept_ok && state_ok;
println!(
"\n==== {} ====",
if pass {
"ALL CHECKS PASSED"
} else {
"SOME CHECKS FAILED"
}
);
browser.quit().await?;
if pass {
Ok(())
} else {
Err(drission::Error::msg("intercept_window 自验证未通过"))
}
}