use async_trait::async_trait;
use thiserror::Error;
use crate::models::{A11yNode, CookieParam, Modifier, Viewport, WaitCondition};
#[derive(Error, Debug)]
pub enum BrowserError {
#[error("Screenshot capture failed: {0}")]
ScreenshotFailed(String),
#[error("Accessibility tree extraction failed: {0}")]
AccessibilityFailed(String),
#[error("Navigation failed: {0}")]
NavigationFailed(String),
#[error("Input injection failed: {0}")]
InputFailed(String),
#[error("Element not found: {0}")]
ElementNotFound(String),
#[error("Platform internal error: {0}")]
PlatformInternal(String),
#[error("Wait condition timed out")]
Timeout,
#[error("Browser not available: {0}")]
NotAvailable(String),
#[error("Not supported: {0}")]
Unsupported(String),
}
#[async_trait]
pub trait BrowserBackend: Send + Sync {
async fn capture_screenshot(&self) -> Result<Vec<u8>, BrowserError>;
async fn get_accessibility_tree(&self) -> Result<Vec<A11yNode>, BrowserError>;
fn get_viewport(&self) -> Result<Viewport, BrowserError>;
fn get_current_url(&self) -> Result<String, BrowserError>;
async fn get_page_title(&self) -> Result<String, BrowserError>;
async fn navigate(&self, url: &str) -> Result<(), BrowserError>;
async fn inject_click(&self, x: f64, y: f64) -> Result<(), BrowserError>;
async fn inject_text(&self, text: &str) -> Result<(), BrowserError>;
async fn inject_keypress(&self, key: &str, modifiers: &[Modifier]) -> Result<(), BrowserError>;
async fn inject_scroll(&self, delta_y: i32) -> Result<(), BrowserError>;
async fn click_element(&self, node_id: &str) -> Result<(), BrowserError>;
async fn type_into_element(&self, node_id: &str, text: &str) -> Result<(), BrowserError>;
async fn focus_element(&self, node_id: &str) -> Result<(), BrowserError>;
async fn is_page_loaded(&self) -> Result<bool, BrowserError>;
async fn wait_until(
&self,
condition: &WaitCondition,
timeout_ms: u64,
) -> Result<bool, BrowserError>;
async fn element_exists_a11y(
&self,
name_contains: &str,
role: Option<&str>,
) -> Result<bool, BrowserError>;
async fn set_cookies(&self, _cookies: &[CookieParam]) -> Result<(), BrowserError> {
Err(BrowserError::Unsupported(
"set_cookies not implemented".into(),
))
}
async fn set_local_storage(
&self,
_origin: &str,
_items: &[(String, String)],
) -> Result<(), BrowserError> {
Err(BrowserError::Unsupported(
"set_local_storage not implemented".into(),
))
}
async fn set_extra_headers(&self, _headers: &[(String, String)]) -> Result<(), BrowserError> {
Err(BrowserError::Unsupported(
"set_extra_headers not implemented".into(),
))
}
async fn shutdown(&self) -> Result<(), BrowserError> {
Ok(())
}
}