playwright-cdp 0.1.1

Drive Chromium directly via the Chrome DevTools Protocol (CDP) — no Playwright driver required.
Documentation
//! Shared value types used across the public API.

use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;

/// Default action timeout in milliseconds (matches Playwright's default).
pub const DEFAULT_TIMEOUT_MS: f64 = 30_000.0;

/// A viewport size.
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct Viewport {
    pub width: u32,
    pub height: u32,
}

impl Viewport {
    pub fn new(width: u32, height: u32) -> Self {
        Self { width, height }
    }
}

/// A point in viewport coordinates.
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
pub struct Position {
    pub x: f64,
    pub y: f64,
}

/// Mouse button for click/hover actions.
///
/// Note: the discriminant values are an ordering, **not** the CDP `buttons`
/// bitmask. Use [`MouseButton::bitmask`] for the `Input.dispatchMouseEvent`
/// `buttons` field.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
#[repr(u8)]
pub enum MouseButton {
    #[default]
    Left = 0,
    Middle = 1,
    Right = 2,
    Back = 3,
    Forward = 4,
}

impl MouseButton {
    pub fn as_str(&self) -> &'static str {
        match self {
            MouseButton::Left => "left",
            MouseButton::Middle => "middle",
            MouseButton::Right => "right",
            MouseButton::Back => "back",
            MouseButton::Forward => "forward",
        }
    }

    /// CDP `Input.dispatchMouseEvent` `buttons` bitmask for this button:
    /// Left=1, Right=2, Middle=4, Back=8, Forward=16.
    pub fn bitmask(&self) -> u8 {
        match self {
            MouseButton::Left => 1,
            MouseButton::Right => 2,
            MouseButton::Middle => 4,
            MouseButton::Back => 8,
            MouseButton::Forward => 16,
        }
    }
}

/// A rectangle in viewport coordinates (element bounds).
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct BoundingBox {
    pub x: f64,
    pub y: f64,
    pub width: f64,
    pub height: f64,
}

/// A clip rectangle for screenshots.
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct ScreenshotClip {
    pub x: f64,
    pub y: f64,
    pub width: f64,
    pub height: f64,
}

/// Keyboard modifiers for actions.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyboardModifier {
    Alt,
    Control,
    ControlOrMeta,
    Meta,
    Shift,
}

/// Proxy server configuration.
#[derive(Debug, Clone, Default)]
pub struct ProxySettings {
    pub server: String,
    pub bypass: Option<String>,
    pub username: Option<String>,
    pub password: Option<String>,
}

/// An ARIA role, used by `get_by_role`.
///
/// Mirrors Playwright's `AriaRole` set.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AriaRole {
    Alert,
    Alertdialog,
    Application,
    Article,
    Banner,
    Blockquote,
    Button,
    Caption,
    Cell,
    Checkbox,
    Code,
    Columnheader,
    Combobox,
    Complementary,
    Contentinfo,
    Definition,
    Deletion,
    Dialog,
    Directory,
    Document,
    Embed,
    Figure,
    Footer,
    Form,
    Generic,
    Grid,
    Gridcell,
    Group,
    Heading,
    Img,
    Image,
    Insertion,
    Link,
    List,
    Listbox,
    Listitem,
    Log,
    Main,
    Marquee,
    Math,
    Menu,
    Menubar,
    Menuitem,
    Menuitemcheckbox,
    Menuitemradio,
    Meter,
    Navigation,
    None,
    Note,
    Option,
    Paragraph,
    Presentation,
    Progressbar,
    Radio,
    Radiogroup,
    Region,
    Row,
    Rowgroup,
    Rowheader,
    Scrollbar,
    Search,
    Searchbox,
    Separator,
    Slider,
    Spinbutton,
    Status,
    Strong,
    Subscript,
    Superscript,
    Switch,
    Tab,
    Table,
    Tablist,
    Tabpanel,
    Term,
    Textbox,
    Time,
    Timer,
    Toolbar,
    Tooltip,
    Tree,
    Treegrid,
    Treeitem,
}

impl AriaRole {
    pub fn as_str(&self) -> &'static str {
        use AriaRole::*;
        match self {
            Alert => "alert",
            Alertdialog => "alertdialog",
            Application => "application",
            Article => "article",
            Banner => "banner",
            Blockquote => "blockquote",
            Button => "button",
            Caption => "caption",
            Cell => "cell",
            Checkbox => "checkbox",
            Code => "code",
            Columnheader => "columnheader",
            Combobox => "combobox",
            Complementary => "complementary",
            Contentinfo => "contentinfo",
            Definition => "definition",
            Deletion => "deletion",
            Dialog => "dialog",
            Directory => "directory",
            Document => "document",
            Embed => "embed",
            Figure => "figure",
            Footer => "footer",
            Form => "form",
            Generic => "generic",
            Grid => "grid",
            Gridcell => "gridcell",
            Group => "group",
            Heading => "heading",
            Img => "img",
            Image => "image",
            Insertion => "insertion",
            Link => "link",
            List => "list",
            Listbox => "listbox",
            Listitem => "listitem",
            Log => "log",
            Main => "main",
            Marquee => "marquee",
            Math => "math",
            Menu => "menu",
            Menubar => "menubar",
            Menuitem => "menuitem",
            Menuitemcheckbox => "menuitemcheckbox",
            Menuitemradio => "menuitemradio",
            Meter => "meter",
            Navigation => "navigation",
            None => "none",
            Note => "note",
            Option => "option",
            Paragraph => "paragraph",
            Presentation => "presentation",
            Progressbar => "progressbar",
            Radio => "radio",
            Radiogroup => "radiogroup",
            Region => "region",
            Row => "row",
            Rowgroup => "rowgroup",
            Rowheader => "rowheader",
            Scrollbar => "scrollbar",
            Search => "search",
            Searchbox => "searchbox",
            Separator => "separator",
            Slider => "slider",
            Spinbutton => "spinbutton",
            Status => "status",
            Strong => "strong",
            Subscript => "subscript",
            Superscript => "superscript",
            Switch => "switch",
            Tab => "tab",
            Table => "table",
            Tablist => "tablist",
            Tabpanel => "tabpanel",
            Term => "term",
            Textbox => "textbox",
            Time => "time",
            Timer => "timer",
            Toolbar => "toolbar",
            Tooltip => "tooltip",
            Tree => "tree",
            Treegrid => "treegrid",
            Treeitem => "treeitem",
        }
    }
}

/// Screenshot image format.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum ScreenshotType {
    #[default]
    Png,
    Jpeg,
    Webp,
}

/// A cookie, shaped for `add_cookies` / `cookies`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Cookie {
    pub name: String,
    pub value: String,
    /// Either `url` or `domain`+`path` must be supplied.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub url: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub domain: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub path: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub expires: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub http_only: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub secure: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub same_site: Option<String>,
}

/// A name/value pair, e.g. a single localStorage entry.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NameValue {
    pub name: String,
    pub value: String,
}

/// localStorage entries grouped by origin.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct OriginStorage {
    pub origin: String,
    // Named to match the JS/Playwright `localStorage` key.
    pub localStorage: Vec<NameValue>,
}

/// A serializable snapshot of a context's storage: cookies plus per-origin
/// localStorage. Mirrors Playwright's `storageState` shape. Cookies stay as
/// `serde_json::Value` (the raw CDP/`Storage` cookie objects) so they can be
/// fed straight back to `set_storage_state`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageState {
    pub cookies: Vec<Value>,
    pub origins: Vec<OriginStorage>,
}

/// Extra HTTP headers map.
pub type Headers = HashMap<String, String>;

/// A console message captured from the page.
#[derive(Debug, Clone)]
pub struct ConsoleMessage {
    pub text: String,
    pub r#type: String,
}

impl ConsoleMessage {
    pub fn text(&self) -> &str {
        &self.text
    }
    pub fn r#type(&self) -> &str {
        &self.r#type
    }
}