browsing 0.1.7

Browser automation: navigate, click, extract, screenshot. Standalone browser control via CDP.
Documentation
# TODO

## Summary

**Overall Progress**: Core functionality complete. Systematically adding browser-use parity features.

## Strategic Roadmap: Beyond Chrome DevTools

The goal is a **standalone browser automation library** built on CDP with semantic DOM understanding and resilient interaction.

### Phase 1: Perception — Semantic DOM Understanding
- [x] **Semantic role inference** — Classify elements by intent (SearchForm, LoginForm, ProductCard, Pagination, etc.)
- [x] **Page intent classification** — Auto-detect page type on load (login, search results, product listing, article, error)
- [x] **Form schema extraction** — Auto-detect form fields, purposes, and validation rules
- [x] **Action affordance tagging** — Tag interactive elements with what they DO, not just what they ARE
- [x] **Content hierarchy detection** — Distinguish main content vs navigation vs sidebar vs ads

### Phase 2: Action — Resilient Element Interaction
- [x] **Fallback element resolution chain** — Index → selector → text match → semantic role → JavaScript evaluation
- [x] **Self-healing selectors** — When an element moves or its ID changes, auto-find the equivalent
- [x] **Multi-factor element addressing** — Combine text, position, visual features, DOM path
- [x] **Smart waiting** — Wait for specific semantic conditions, not just fixed timeouts

### Phase 3: Memory — Persistent Session Context
- [x] **Site-specific strategy memory** — Learn that "this airline's search button is mislabeled"
- [x] **Credential profiles** — Auto-fill known login info on recognized pages
- [x] **Progress tracking** — "Already checked pages 1-3, need to check page 4"
- [x] **Session state persistence** — Save and resume long-running tasks

### Phase 4: Observability — Session Recording & Replay
- [x] **Action traces** — `SessionRecorder` automatically records every action with timestamp, params, URL, result, duration
- [x] **JSON trace export** — Export session trace to file for post-mortem debugging
- [x] **DOM state snapshots** — Capture DOM state at each step for debugging

## Recent Updates (May 2026)

- [x] Added `go_back` / `go_forward` / `reload` navigation actions via CDP
- [x] Added file operations -- `write_file`, `read_file`, and `replace_file` with path traversal protection
- [x] Added `FileHandler` module for disk file I/O within agent workflows
- [x] Added minimal CLI browser render command: `browsing render <url>`
- [x] Added CLI render test cases (argument parsing + render text formatting)
- [x] Headless browser by default -- `BrowserProfile::default()` uses `headless: true`
- [x] Modern headless mode -- `--headless=new` (faster than legacy Chrome headless)
- [x] 17+ lightweight Chrome flags -- disables extensions, sync, background networking, logging, etc.
- [x] Eliminated `Box::leak` memory leak in CDP client
- [x] Cached regex compilation in `JSONExtractor` with `LazyLock`
- [x] Eliminated `Vec<char>` allocation -- uses `char_indices()` directly on `&str`
- [x] Fixed triple JSON parsing in `parse_agent_output`
- [x] Normalized `tag_name` at construction
- [x] Removed double serde round-trip in `to_dict()`
- [x] Deduplicated `Browser::start()` -- unified session setup (~40 lines removed)
- [x] Reduced DOM tree cloning -- `get_serialized_dom` passes ownership to serializer
- [x] Optimized DOM tree builder -- final node moved into lookup instead of cloned
- [x] Reduced launch sleep 1000ms -> 200ms, CDP polling 30s -> 6s max
- [x] Updated all documentation (README, ARCHITECTURE, TODO, examples)
- [x] Removed all ignored tests -- 355+ tests passing (0 failures, 0 ignored)
- [x] Fixed JSON extractor to handle nested JSON structures using brace counting
- [x] Added IBM content download example demonstrating web scraping

## Recent Updates (June 2026)

- [x] **MCP server expanded** — 20 browser automation tools (click, input, scroll, wait, evaluate, go_back, go_forward, reload, dropdown, screenshot)
- [x] **Codebase lean** — `cargo clippy --fix` applied 80+ suggestions; manual Default derives; let-chains for nested ifs
- [x] **Stealth mode** — `BrowserProfile.stealth` injects anti-detection script on every page + disables AutomationControlled blink feature
- [x] **User-agent rotation** — `BrowserProfile.user_agent` + `--user-agent=...` Chrome flag + `BROWSER_USE_USER_AGENT` env var
- [x] **WebDriver masking** — Expanded stealth script: navigator.webdriver deletion, plugins/mimeTypes override, chrome.runtime, iframe masking, navigator.connection, navigator.vendor
- [x] **Observability** — `SessionRecorder` + `RecorderConfig` + `SessionTrace` JSON export; `Tools::act` auto-records every action; 10 unit tests
- [x] **DOM state snapshots** — Fixed `Tools::act` to pass `dom_snapshot` through to `record_action`; integration tests verify capture and config-based omission
- [x] **Cookie management** — `CookieManager` with `get_cookies`, `get_cookies_for_url`, `set_cookie`, `delete_cookies`, `clear_cookies`; wired into `Browser` and `BrowserClient` trait; view types `Cookie` / `CookieParam`
- [x] **Console log capture** — `ConsoleManager` subscribes to CDP `Runtime.consoleAPICalled` and `Log.entryAdded` events via new `CdpClient::subscribe_events()` broadcast channel; `get_logs`, `get_logs_by_level`, `clear_logs`; view type `ConsoleLog`
- [x] **Local/session storage access** — `StorageManager` with `get_local_storage`, `set_local_storage`, `remove_local_storage`, `clear_local_storage`, `get_all_local_storage` (and sessionStorage equivalents); works via `Page.evaluate`; view type `StorageEntry`; wired into `Browser` and `BrowserClient` trait
- [x] **Mobile viewport emulation** — `ViewportManager` with `set_device_metrics`, `clear_device_metrics`, `set_touch_emulation`, `set_user_agent`, `set_geolocation`, `clear_geolocation`, `set_timezone`, `get_metrics`; view types `ViewportConfig` / `DeviceMetrics`; wired into `Browser` and `BrowserClient` trait
- [x] **PDF generation** — `PdfManager` with `save_as_pdf`, `print_to_pdf`, `save_to_file`; view types `PdfConfig` / `PageMargins` (paper size, margins, header/footer templates, page ranges, landscape, background printing); wired into `Browser` and `BrowserClient` trait
- [x] **Shadow DOM support** — `Page.query_shadow_dom`, `Page.query_all_shadow_dom`, `Page.has_shadow_root`, `Page.get_shadow_host_elements`; view type `ShadowElementInfo` (tag_name, text, id, class, name, visible, bounding_box); pierces open shadow roots via JS evaluation
- [x] **Codebase lean pass** — Extracted `mcp_err`, `no_browser`, `success` helpers in `mcp_server/service.rs` eliminating 60+ duplicated error-wrapping patterns; moved 3 inline `base64` imports to file tops; changed `Registry::register_action` to accept `impl Into<String>`, removing 22 `.to_string()` call sites; `cargo clippy --lib --bins` at 0 warnings
- [x] **Drag and drop** — `Mouse::drag` (move, press, drag, release sequence via CDP `Input.dispatchMouseEvent`); `Page::drag_and_drop(start_x, start_y, end_x, end_y)` and `Page::drag_element_to(selector, end_x, end_y)` for coordinate and element-based dragging
- [x] **Download handling** — `DownloadManager` with `set_download_behavior`, `start_tracking`, `get_downloads`, `get_active_downloads`, `clear_downloads`; tracks `Page.downloadWillBegin` and `Page.downloadProgress` events via `CdpClient::subscribe_events`; view types `DownloadInfo` / `DownloadState`; wired into `Browser` and `BrowserClient` trait
- [x] **Basic auth / proxy auth** — `AuthManager` with `set_basic_auth`, `set_proxy_auth`, `set_extra_headers`, `clear_auth`, `authenticate`; uses CDP `Network.setExtraHTTPHeaders` with `Authorization: Basic ...` and `Proxy-Authorization`; view type `AuthCredentials`; wired into `Browser` and `BrowserClient` trait
- [x] **Performance metrics** — `PerformanceManager` with `get_metrics`, `get_metric_values`, `get_heap_usage`; parses CDP `Performance.getMetrics` response into typed fields (timestamp, JSHeapUsedSize, JSHeapTotalSize, Documents, Nodes, JSEventListeners, LayoutDuration, RecalcStyleDuration, ScriptDuration, TaskDuration); view type `PerformanceMetrics` with `#[serde(flatten)] raw` for extensibility; wired into `Browser` and `BrowserClient` trait
- [x] **HAR export** — `HarManager` with `start_capture`, `export_har`, `export_json`, `entry_count`, `clear`; captures `Network.requestWillBeSent`, `Network.responseReceived`, `Network.loadingFinished`, `Network.loadingFailed` via `CdpClient::subscribe_events`; view types `HarLog`, `HarEntry`, `HarRequest`, `HarResponse`, `HarHeader`, `HarCreator`; wired into `Browser` and `BrowserClient` trait
- [x] **Coverage tracking** — `CoverageManager` with `start_js_coverage`, `stop_js_coverage`, `start_css_coverage`, `stop_css_coverage`, `start_all`, `stop_all`; uses CDP `Profiler.startPreciseCoverage` / `takePreciseCoverage` for JS and `CSS.startRuleUsageTracking` / `stopRuleUsageTracking` for CSS; view types `CoverageResult` / `CoverageRange`; wired into `Browser` and `BrowserClient` trait
- [x] **Network interception** — `NetworkInterceptor` with `enable(patterns)`, `disable`, `continue_request`, `fulfill_request`, `fail_request`, `get_intercepted_requests`, `get_request`; captures `Fetch.requestPaused` events via `CdpClient::subscribe_events`; supports URL pattern filtering, request modification, mock responses, and failure simulation; view types `InterceptPattern`, `InterceptedRequest`, `MockResponse`; wired into `Browser` and `BrowserClient` trait
- [x] **Dependency optimization** — Removed 3 dead/unneeded production dependencies (`anyrepair`, `dotenv`, `urlencoding`); replaced `urlencoding::encode` with `url::form_urlencoded::byte_serialize` in `NavigationHandler::search`; removed `json` feature from `tracing-subscriber` (unused); made `clap` + `rmcp` + `schemars` optional behind `cli`/`mcp` feature flags with `default = ["cli", "mcp"]`; removed `anyhow` from library code path (`config.rs::load_from_file` now returns `crate::error::Result`); `cargo check --no-default-features --lib` passes
- [x] **Performance & footprint optimization** — Removed unused `serde` feature from `chrono`; added `[profile.release]` with `opt-level = "z"`, `lto = true`, `codegen-units = 1`, `panic = "abort"`, `strip = true` for significantly smaller release binaries; converted recursive `send_command_with_session_retry` to iterative loop in `cdp.rs` eliminating `Box::pin` heap allocation on every retry; changed `session_id` fields from `String` to `Arc<str>` in `Page`, `Element`, `Mouse`, `DOMCDPClient`, `DOMService` eliminating string clones on every element interaction
- [x] **Dialog handling** — `DialogManager` with `enable`, `accept`, `dismiss`, `get_pending_dialogs`, `next_dialog`, `has_pending_dialog`, `set_auto_dismiss`, `clear`; captures `Page.javascriptDialogOpening` events via `CdpClient::subscribe_events`; supports auto-dismiss mode for hands-free browsing; view types `DialogType` (alert/confirm/prompt/beforeunload) / `DialogInfo`; wired into `Browser` and `BrowserClient` trait
- [x] **File chooser interception** — `FileChooserManager` with `enable`, `disable`, `set_files`, `get_pending`, `next`, `has_pending`, `clear`; uses CDP `Page.setInterceptFileChooserDialog` + captures `Page.fileChooserOpened` events via `CdpClient::subscribe_events`; sets files via `DOM.setFileInputFiles`; view type `FileChooserInfo`; wired into `Browser` and `BrowserClient` trait
- [x] **Mobile device presets** — `DevicePreset` with `iphone_15()`, `iphone_15_pro_max()`, `ipad_air()`, `pixel_8()`, `galaxy_s24()`, `desktop_1080p()`; each includes viewport (width/height/DPR), user agent, accept language; `DevicePreset::by_name()` for lookup; `DevicePreset::list_names()` for enumeration; `ViewportManager::preset_device()` applies preset in one call; wired into `Browser` and `BrowserClient` trait
- [x] **Permissions API** — `PermissionsManager` with `grant(origin, permissions)`, `reset(origin)`, `grant_camera`, `grant_microphone`, `grant_camera_and_microphone`, `grant_notifications`, `grant_geolocation`, `grant_clipboard`, `grant_all_common`; view type `PermissionType` (videoCapture, audioCapture, geolocation, notifications, clipboardReadWrite, displayCapture, sensors, nfc, midi, midiSysex, wakeLockScreen, wakeLockSystem, storageAccess, windowManagement, backgroundSync, paymentHandler); wired into `Browser` and `BrowserClient` trait
- [x] **Tracing / CPU profiling** — `TracingManager` with `start(config)`, `end()`, `export_trace(path, result)`, `event_count()`, `clear()`; uses CDP `Tracing.start` / `Tracing.end` + captures `Tracing.dataCollected` events via `CdpClient::subscribe_events`; default categories include devtools.timeline, v8.execute, cpu_profiler; view types `TraceConfig` / `TraceResult`; wired into `Browser` and `BrowserClient` trait
- [x] **Color scheme / media feature emulation** — `ViewportManager::set_media_features()` + `clear_media_features()` via CDP `Emulation.setEmulatedMedia`; `ViewportManager::set_color_scheme()` convenience wrapper for `prefers-color-scheme`; `ViewportManager::set_vision_deficiency()` via CDP `Emulation.setEmulatedVisionDeficiency`; view types `ColorScheme` (light/dark/no-preference), `MediaFeature`, `VisionDeficiency` (none/achromatopsia/blurredVision/deuteranopia/protanopia/tritanopia); wired into `Browser` and `BrowserClient` trait
- [x] **Protocol monitor / CDP raw access** — `Browser::raw_cdp_command(method, params)` sends any CDP command directly and returns the raw JSON response; `BrowserClient::raw_cdp_command()` trait method provides same access; enables power-users to use any unwrapped CDP domain
- [x] **Touch gesture emulation** — `TouchManager` with `dispatch_touch(event_type, touch_points)`, `tap(x, y)`, `double_tap(x, y)`, `swipe(start_x, start_y, end_x, end_y, steps)`, `pinch(center_x, center_y, scale_factor)`, `long_press(x, y, duration_ms)`; uses CDP `Input.dispatchTouchEvent`; view type `TouchPoint`; wired into `Browser` and `BrowserClient` trait
- [x] **Request/response body access** — `HarManager::new_with_body()` enables response body capture via CDP `Network.getResponseBody`; captures `postData` from `Network.requestWillBeSent` events; `HarRequest` has `post_data` field; `HarResponse` has `body` field; base64-encoded bodies are decoded automatically
- [x] **Font / locale emulation** — `ViewportManager::set_locale()` / `clear_locale()` via CDP `Emulation.setLocaleOverride`; `ViewportManager::override_languages_and_fonts(languages, font_families)` via `Runtime.evaluate` overriding `navigator.languages` and CSS `font-family` for cross-environment consistency; wired into `Browser` and `BrowserClient` trait
- [x] **Web workers** — `WorkerManager` with `start_discovery()`, `stop_discovery()`, `attach(target_id)`, `detach(target_id)`, `evaluate_in_worker(target_id, expression)`, `list_workers()`, `get_worker(target_id)`, `has_workers()`, `worker_count()`, `clear()`; discovers workers via `Target.setDiscoverTargets` + `Target.targetCreated` events; attaches via `Target.attachToTarget` with `flatten: true`; evaluates JS via `Runtime.evaluate` with worker session ID; view type `WorkerInfo`; wired into `Browser` and `BrowserClient` trait
- [x] **Service worker interception** — `ServiceWorkerManager` with `enable()`, `disable()`, `stop_all()`, `start(scope_url)`, `unregister(scope_url)`, `update(scope_url)`, `get_registrations()`, `get_versions()`, `registration_count()`, `version_count()`, `clear()`; tracks registrations/versions via `ServiceWorker.workerRegistrationUpdated` and `ServiceWorker.workerVersionUpdated` events; view types `ServiceWorkerRegistration` / `ServiceWorkerVersion`; wired into `Browser` and `BrowserClient` trait

## Capability Gaps vs browser-use

Browser-use (Python) has several capabilities this Rust implementation is missing. Filling these gaps systematically:

### Navigation (Priority: High)
- [x] `go_back` -- Navigate back in browser history (browser-use: `go_back`)
- [x] `go_forward` -- Navigate forward in browser history (browser-use: not listed but standard)
- [x] `reload` -- Reload the current page (browser-use: not listed but standard)

### File Operations (Priority: High)
- [x] `write_file` -- Write content to a file on disk (browser-use: `write_file`)
- [x] `read_file` -- Read content from a file on disk (browser-use: `read_file`)
- [x] `replace_file` -- Replace text within a file (browser-use: `replace_file`)

### Stealth / Anti-Detection (Priority: Low)
- [x] Stealth mode -- `browser.stealth` flag + `Page.addScriptToEvaluateOnNewDocument` + `--disable-blink-features=AutomationControlled`
- [x] User-agent rotation -- `BrowserProfile.user_agent` + `--user-agent=...` Chrome flag + `BROWSER_USE_USER_AGENT` env var
- [x] WebDriver property masking -- Expanded stealth script: navigator.webdriver deletion, plugins/mimeTypes override, chrome.runtime, iframe masking, navigator.connection, navigator.vendor

## Completed

### Core Library
- [x] Scaffold Rust project structure (single crate)
- [x] Basic module structure (agent, browser, tools, dom, config, error, utils, views)
- [x] Core error types
- [x] Configuration system (from env vars)
- [x] Basic type definitions
- [x] Core view types (Agent, Browser, DOM views)
- [x] Tools/actions registry system
- [x] Browser session and CDP client integration
- [x] DOM serialization and extraction (complete implementation with CDP)
- [x] DOM service integration with tools layer
- [x] Logging setup (tracing integration)
- [x] Configuration with .env support
- [x] JSON repair for agent responses (anyrepair integration)
- [x] Actor implementation (page, element, mouse interactions)
- [x] Keyboard input support (key combinations, modifiers)
- [x] Action execution in tools service (search, navigate, click, input, done)
- [x] Element clicking and input using Page/Element actors
- [x] Selector map integration for element lookup by index

### CLI Interface
- [x] CLI binary with clap argument parsing
- [x] Run command for autonomous browsing tasks
- [x] Launch command for browser management
- [x] Connect command for existing browser instances
- [x] Render command for minimal webpage text output from URL input
- [x] Configuration via environment variables and files
- [x] CLI documentation (docs/CLI_USAGE.md)

### MCP Server
- [x] MCP server binary using rmcp
- [x] Tools: navigate, get_content, click, input, screenshot
- [x] Prompts: browse_task template
- [x] Resources: browser://current for page content
- [x] Lazy browser initialization
- [x] MCP documentation (docs/MCP_USAGE.md)

### Library Interface
- [x] Public API exports in lib.rs
- [x] Browser, Config re-exports
- [x] Example: library_usage.rs - Basic library usage
- [x] Example: custom_actions.rs - Custom action handlers
- [x] Example: ibm_content_download.rs - Web scraping demo
- [x] Example: comprehensive_showcase.rs - Full feature demonstration
- [x] Example: basic_navigation.rs - Simple navigation example
- [x] Example: simple_navigation.rs - Navigation-focused demo
- [x] Library documentation (docs/LIBRARY_USAGE.md)

### Browser Session
- [x] CDP client implementation (WebSocket connection)
- [x] Browser connection via CDP URL
- [x] Navigation handling
- [x] Page actor access
- [x] Browser launch and management (local browser - basic implementation)
- [x] Browser launcher (executable detection, port finding, process management)
- [x] Page state capture (full DOM extraction via get_serialized_dom_tree)
- [x] Screenshot support (Page, Element, and Browser session)
- [x] Tab management (list, switch, close, create tabs with actions)
- [x] Browser state summary (get_browser_state_summary with DOM, tabs, screenshot)

### DOM Service
- [x] Basic HTML parsing and text extraction
- [x] Core CDP tree extraction (_get_all_trees - snapshot, DOM tree, AX tree, device pixel ratio)
- [x] Viewport ratio calculation (_get_viewport_ratio)
- [x] CDP client session_id support (send_command_with_session)
- [x] Full DOM tree building (get_dom_tree, enhanced node construction)
- [x] Enhanced snapshot lookup (build_snapshot_lookup)
- [x] Enhanced DOM tree node types (EnhancedDOMTreeNode, EnhancedSnapshotNode, EnhancedAXNode)
- [x] DOM serializer for text representation (basic implementation)
- [x] get_serialized_dom_tree method
- [x] Element extraction with indices (selector map)
- [x] JSON extraction with brace counting (handles nested objects/arrays)
- [x] Markdown extraction (enhanced) — `dom::extract_markdown` converts HTML to clean Markdown with heading/list/link/code formatting
- [x] Paint order filtering (advanced) — `DomService::filter_by_paint_order` sorts selector_map by visual position (top-to-bottom, left-to-right)
- [x] Enhanced DOM snapshot optimizations — `DomService::get_cached_serialized_dom` caches DOM state per-URL to skip re-serialization

### Tools/Actions
- [x] Action registry system
- [x] Default actions (click, input, navigate, search, done, switch, close, scroll, wait, send_keys, evaluate, find_text, dropdown_options, select_dropdown, upload_file, extract)
- [x] Action execution (basic implementation)
- [x] Element interaction (click, input using Page/Element actors)
- [x] Selector map integration (get element by index, lookup backend_node_id)
- [x] Custom action registration (ActionHandler trait and registration system)

### Actor (Low-level browser interactions)
- [x] Page actor (navigation, evaluation, screenshot, keyboard)
- [x] Element actor (click, fill, text extraction, screenshot, bounding box)
- [x] Mouse actor (click, move, scroll)
- [x] Keyboard input (press keys, key combinations)

### Utilities
- [x] URL detection and parsing
- [x] Logging setup (tracing)
- [x] Configuration with .env support
- [x] Signal handling (SIGINT/SIGTERM for graceful shutdown)
- [x] Telemetry (optional) — `utils::telemetry::Telemetry` event collector with timed events, properties, JSON export, RAII `TelemetryTimer`

### Testing
- [x] Unit tests for core modules (350+ tests passing)
- [x] Actor module tests (page, element, mouse, keyboard operations)
- [x] Browser lifecycle tests
- [x] Browser managers tests (navigation, screenshot, tab management)
- [x] Tools handlers tests (navigation, interaction, content, tabs, advanced, file)
- [x] Traits tests (BrowserClient, DOMProcessor implementations)
- [x] Utilities tests (URL extraction, domain matching, signal handling)
- [x] Signal handling tests
- [x] JSON extraction tests (nested JSON support)
- [x] CLI render tests (argument parsing, text formatting)

### Documentation
- [x] API documentation (cargo doc --open)
- [x] Examples (4 working examples)
- [x] README.md - Complete with architecture and usage
- [x] CLI, MCP, and Library usage guides in docs/

## Notes

- Using single crate structure (not multi-crate workspace)
- Using anyrepair for JSON repair
- Using rmcp for MCP support
- Using clap for CLI argument parsing
- Rust edition 2024

## Usage Modes

### 1. CLI Tool
```bash
# Install
cargo install --path . --bin browsing

# Launch headless browser
browsing launch --headless

# Connect to existing browser
browsing connect ws://localhost:9222/devtools/browser/abc123

# Minimal CLI browser render
browsing render https://example.com --max-chars 1200
```

### 2. MCP Server
```bash
# Build
cargo build --release --bin browsing-mcp

# Run (communicates via stdio)
./target/release/browsing-mcp

# Configure in Claude Desktop
# See docs/MCP_USAGE.md for configuration details
```

### 3. Rust Library
```rust
use browsing::{Browser, Config};

let mut browser = Browser::new(Config::from_env().browser_profile);
browser.start().await?;
browser.navigate("https://example.com").await?;
```

See `docs/LIBRARY_USAGE.md` for complete API documentation.

## Brainstorming / Competitive Intelligence

Researching browser-use, Playwright, Puppeteer, Selenium capabilities for gaps:

### High-Value Missing Features
- [x] **Cookie management** — `get_cookies`, `set_cookie`, `delete_cookies`, `clear_cookies` via CDP `Network.getCookies` / `Network.setCookie`
- [x] **Console log capture** — Subscribe to CDP `Runtime.consoleAPICalled` and `Log.entryAdded` for debugging
- [x] **Local/session storage access** — `get_local_storage`, `set_local_storage`, `clear_storage` via JS evaluation
- [x] **Mobile viewport emulation** — `set_viewport_size`, `set_device_metrics_override` via CDP `Emulation.setDeviceMetricsOverride`
- [x] **PDF generation** — `save_as_pdf` via CDP `Page.printToPDF`
- [x] **Network interception** — `set_request_interception` via CDP `Fetch.enable` (advanced)
- [x] **Download handling** — Intercept `Page.downloadWillBegin` and manage download paths
- [x] **Basic auth / proxy auth** — `authenticate` via CDP `Fetch.continueWithAuth` or `Network.setExtraHTTPHeaders`
- [x] **Drag and drop** — Mouse drag operations (`mouse_down`, `mouse_move`, `mouse_up` sequence)
- [x] **Shadow DOM support** — `get_shadow_root`, pierce shadow DOM for element queries

### Medium Value
- [x] **Har export** — Capture network traffic as HTTP Archive
- [x] **Performance metrics** — `get_metrics` via CDP `Performance.getMetrics`
- [x] **Coverage tracking** — CSS/JS coverage via CDP `Profiler` domain

## Brainstorming / Competitive Intelligence (Next Wave)

Researching Playwright, Puppeteer, Selenium, browser-use for next gaps:

### High Value
- [x] **Dialog handling** — `DialogManager` with `enable`, `accept`, `dismiss`, `get_pending_dialogs`, `next_dialog`, `has_pending_dialog`, `set_auto_dismiss`, `clear`; captures `Page.javascriptDialogOpening` events via `CdpClient::subscribe_events`; supports auto-dismiss mode; view types `DialogType` / `DialogInfo`; wired into `Browser` and `BrowserClient` trait
- [x] **File chooser interception** — `FileChooserManager` with `enable`, `disable`, `set_files`, `get_pending`, `next`, `has_pending`, `clear`; uses CDP `Page.setInterceptFileChooserDialog` + captures `Page.fileChooserOpened` events; sets files via `DOM.setFileInputFiles`; view type `FileChooserInfo`; wired into `Browser` and `BrowserClient` trait
- [x] **Mobile device presets** — `DevicePreset` with `iphone_15()`, `iphone_15_pro_max()`, `ipad_air()`, `pixel_8()`, `galaxy_s24()`, `desktop_1080p()`; each includes viewport (width/height/DPR), user agent, accept language; `DevicePreset::by_name()` for lookup; `DevicePreset::list_names()` for enumeration; `ViewportManager::preset_device()` applies preset in one call; wired into `Browser` and `BrowserClient` trait
- [x] **Request/response body access** — `HarManager::new_with_body()` enables response body capture via CDP `Network.getResponseBody`; captures `postData` from `Network.requestWillBeSent` events; `HarRequest` has `post_data` field; `HarResponse` has `body` field; base64-encoded bodies are decoded automatically
- [x] **Permissions API** — `PermissionsManager` with `grant(origin, permissions)`, `reset(origin)`, `grant_camera`, `grant_microphone`, `grant_camera_and_microphone`, `grant_notifications`, `grant_geolocation`, `grant_clipboard`, `grant_all_common`; view type `PermissionType` (videoCapture, audioCapture, geolocation, notifications, clipboardReadWrite, displayCapture, sensors, nfc, midi, midiSysex, wakeLockScreen, wakeLockSystem, storageAccess, windowManagement, backgroundSync, paymentHandler); wired into `Browser` and `BrowserClient` trait
- [x] **Tracing / CPU profiling** — `TracingManager` with `start(config)`, `end()`, `export_trace(path, result)`, `event_count()`, `clear()`; uses CDP `Tracing.start` / `Tracing.end` + captures `Tracing.dataCollected` events via `CdpClient::subscribe_events`; default categories include devtools.timeline, v8.execute, cpu_profiler; view types `TraceConfig` / `TraceResult`; wired into `Browser` and `BrowserClient` trait
- [x] **Service worker interception** — `ServiceWorkerManager` with `enable()`, `disable()`, `stop_all()`, `start(scope_url)`, `unregister(scope_url)`, `update(scope_url)`, `get_registrations()`, `get_versions()`, `registration_count()`, `version_count()`, `clear()`; tracks registrations/versions via `ServiceWorker.workerRegistrationUpdated` and `ServiceWorker.workerVersionUpdated` events; view types `ServiceWorkerRegistration` / `ServiceWorkerVersion`; wired into `Browser` and `BrowserClient` trait

### Medium Value
- [x] **Web workers** — `WorkerManager` with `start_discovery()`, `stop_discovery()`, `attach(target_id)`, `detach(target_id)`, `evaluate_in_worker(target_id, expression)`, `list_workers()`, `get_worker(target_id)`, `has_workers()`, `worker_count()`, `clear()`; discovers workers via `Target.setDiscoverTargets` + `Target.targetCreated` events; attaches via `Target.attachToTarget` with `flatten: true`; evaluates JS via `Runtime.evaluate` with worker session ID; view type `WorkerInfo`; wired into `Browser` and `BrowserClient` trait
- [x] **Touch gesture emulation** — `TouchManager` with `dispatch_touch(event_type, touch_points)`, `tap(x, y)`, `double_tap(x, y)`, `swipe(start_x, start_y, end_x, end_y, steps)`, `pinch(center_x, center_y, scale_factor)`, `long_press(x, y, duration_ms)`; uses CDP `Input.dispatchTouchEvent`; view type `TouchPoint`; wired into `Browser` and `BrowserClient` trait
- [x] **Color scheme / media feature emulation** — `ViewportManager::set_media_features()` + `clear_media_features()` via CDP `Emulation.setEmulatedMedia`; `ViewportManager::set_color_scheme()` convenience wrapper for `prefers-color-scheme`; `ViewportManager::set_vision_deficiency()` via CDP `Emulation.setEmulatedVisionDeficiency`; view types `ColorScheme` (light/dark/no-preference), `MediaFeature`, `VisionDeficiency` (none/achromatopsia/blurredVision/deuteranopia/protanopia/tritanopia); wired into `Browser` and `BrowserClient` trait
- [x] **Font / locale emulation** — `ViewportManager::set_locale()` / `clear_locale()` via CDP `Emulation.setLocaleOverride`; `ViewportManager::override_languages_and_fonts(languages, font_families)` via `Runtime.evaluate` overriding `navigator.languages` and CSS `font-family` for cross-environment consistency; wired into `Browser` and `BrowserClient` trait
- [x] **Protocol monitor / CDP raw access** — `Browser::raw_cdp_command(method, params)` sends any CDP command directly and returns the raw JSON response; `BrowserClient::raw_cdp_command()` trait method provides same access; enables power-users to use any unwrapped CDP domain