use chromiumoxide::cdp::browser_protocol::emulation::SetCpuThrottlingRateParams;
#[allow(deprecated)]
use chromiumoxide::cdp::browser_protocol::network::EmulateNetworkConditionsParams;
use chromiumoxide::cdp::browser_protocol::network::SetCacheDisabledParams;
use chromiumoxide::Page;
use serde::{Deserialize, Serialize};
use tracing::debug;
use crate::error::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ThrottleProfile {
Unthrottled,
Slow3G,
Fast3G,
LhMobile,
}
impl ThrottleProfile {
pub const AUTO_PROFILES: &'static [ThrottleProfile] = &[
ThrottleProfile::Slow3G,
ThrottleProfile::Fast3G,
ThrottleProfile::LhMobile,
];
pub fn label(self) -> &'static str {
match self {
ThrottleProfile::Unthrottled => "unthrottled",
ThrottleProfile::Slow3G => "slow-3g",
ThrottleProfile::Fast3G => "fast-3g",
ThrottleProfile::LhMobile => "lh-mobile",
}
}
pub fn cpu_slowdown(self) -> f64 {
match self {
ThrottleProfile::Unthrottled => 1.0,
ThrottleProfile::Slow3G => 6.0,
ThrottleProfile::Fast3G => 4.0,
ThrottleProfile::LhMobile => 4.0,
}
}
}
#[allow(deprecated)]
pub async fn apply_throttling(page: &Page, profile: ThrottleProfile) -> Result<()> {
let (download, upload, latency_ms) = match profile {
ThrottleProfile::Unthrottled => (-1.0, -1.0, 0.0),
ThrottleProfile::Slow3G => (62_500.0, 62_500.0, 400.0),
ThrottleProfile::Fast3G => (187_500.0, 93_750.0, 40.0),
ThrottleProfile::LhMobile => (200_000.0, 96_000.0, 150.0),
};
debug!(
"Applying network throttle {:?}: down={:.0} B/s, up={:.0} B/s, latency={:.0} ms",
profile, download, upload, latency_ms
);
page.execute(
EmulateNetworkConditionsParams::builder()
.offline(false)
.latency(latency_ms)
.download_throughput(download)
.upload_throughput(upload)
.build()
.expect("static network-throttle params are valid"),
)
.await
.map_err(|e| crate::error::AuditError::NavigationFailed {
url: "network-throttle".to_string(),
reason: e.to_string(),
})?;
Ok(())
}
pub async fn apply_cpu_throttling(page: &Page, profile: ThrottleProfile) -> Result<()> {
let rate = profile.cpu_slowdown();
debug!("Applying CPU throttle {:?}: {:.0}x slowdown", profile, rate);
page.execute(SetCpuThrottlingRateParams::new(rate))
.await
.map_err(|e| crate::error::AuditError::NavigationFailed {
url: "cpu-throttle".to_string(),
reason: e.to_string(),
})?;
Ok(())
}
pub async fn disable_cpu_throttling(page: &Page) -> Result<()> {
page.execute(SetCpuThrottlingRateParams::new(1.0_f64))
.await
.map_err(|e| crate::error::AuditError::NavigationFailed {
url: "cpu-throttle-disable".to_string(),
reason: e.to_string(),
})?;
Ok(())
}
pub async fn disable_cache(page: &Page) -> Result<()> {
page.execute(SetCacheDisabledParams::new(true))
.await
.map_err(|e| crate::error::AuditError::NavigationFailed {
url: "cache-disable".to_string(),
reason: e.to_string(),
})?;
Ok(())
}
pub async fn enable_cache(page: &Page) -> Result<()> {
page.execute(SetCacheDisabledParams::new(false))
.await
.map_err(|e| crate::error::AuditError::NavigationFailed {
url: "cache-enable".to_string(),
reason: e.to_string(),
})?;
Ok(())
}
#[allow(deprecated)]
pub async fn disable_throttling(page: &Page) -> Result<()> {
page.execute(
EmulateNetworkConditionsParams::builder()
.offline(false)
.latency(0.0)
.download_throughput(-1.0_f64)
.upload_throughput(-1.0_f64)
.build()
.expect("static network-throttle-disable params are valid"),
)
.await
.map_err(|e| crate::error::AuditError::NavigationFailed {
url: "network-throttle-disable".to_string(),
reason: e.to_string(),
})?;
Ok(())
}