#[cfg(any(feature = "expect", feature = "interception"))]
use std::collections::HashMap;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use zendriver::Browser;
#[cfg(feature = "expect")]
pub type ExpectationId = String;
#[cfg(feature = "interception")]
pub type RuleId = String;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum StealthProfileChoice {
#[default]
Auto,
Native,
SpoofMacos,
SpoofLinux,
SpoofWindows,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum StealthPlatformChoice {
Win32,
MacIntel,
LinuxX86_64,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct StealthOverrides {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub platform: Option<StealthPlatformChoice>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub locale: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub timezone: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub memory_gb: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cpu_count: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub chrome_version: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_agent: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bypass_csp: Option<bool>,
}
pub struct SessionState {
pub browser: Option<Browser>,
pub current_tab_id: Option<String>,
pub stealth_profile_choice: StealthProfileChoice,
pub stealth_overrides: StealthOverrides,
#[cfg(feature = "expect")]
pub expectations: HashMap<ExpectationId, ExpectationHandle>,
#[cfg(feature = "interception")]
pub rules: HashMap<RuleId, InterceptRuleHandle>,
}
#[cfg(feature = "expect")]
pub struct ExpectationHandle {
pub kind: &'static str,
pub task: tokio::task::JoinHandle<()>,
pub rx: tokio::sync::oneshot::Receiver<Result<serde_json::Value, String>>,
}
#[cfg(feature = "interception")]
pub struct InterceptRuleHandle {
pub pattern: String,
pub action_kind: &'static str,
pub _handle: zendriver::InterceptHandle,
}
impl SessionState {
pub fn new() -> Self {
Self {
browser: None,
current_tab_id: None,
stealth_profile_choice: StealthProfileChoice::default(),
stealth_overrides: StealthOverrides::default(),
#[cfg(feature = "expect")]
expectations: HashMap::new(),
#[cfg(feature = "interception")]
rules: HashMap::new(),
}
}
}
impl Default for SessionState {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_state_is_empty() {
let s = SessionState::new();
assert!(s.browser.is_none());
assert!(s.current_tab_id.is_none());
assert_eq!(s.stealth_profile_choice, StealthProfileChoice::Auto);
#[cfg(feature = "expect")]
assert!(s.expectations.is_empty());
#[cfg(feature = "interception")]
assert!(s.rules.is_empty());
}
}