use std::ops::Deref;
use std::sync::Arc;
use crate::Capabilities;
use crate::common::config::WebDriverConfig;
use crate::error::WebDriverResult;
use crate::prelude::WebDriverError;
use crate::session::create::start_session;
use crate::session::handle::SessionHandle;
use crate::session::http::HttpClient;
#[cfg(feature = "reqwest")]
use crate::session::http::create_reqwest_client;
#[derive(Debug, Clone)]
pub struct WebDriver {
pub handle: Arc<SessionHandle>,
}
#[derive(Debug, thiserror::Error)]
#[error("Webdriver has already quit, can't leak an already quit driver")]
pub struct AlreadyQuit(pub(crate) ());
impl WebDriver {
pub async fn new<S, C>(server_url: S, capabilities: C) -> WebDriverResult<Self>
where
S: Into<String>,
C: Into<Capabilities>,
{
Self::new_with_config(server_url, capabilities, WebDriverConfig::default()).await
}
pub async fn new_with_config<S, C>(
server_url: S,
capabilities: C,
config: WebDriverConfig,
) -> WebDriverResult<Self>
where
S: Into<String>,
C: Into<Capabilities>,
{
#[cfg(feature = "reqwest")]
let client = create_reqwest_client(config.reqwest_timeout);
#[cfg(not(feature = "reqwest"))]
let client = crate::session::http::null_client::create_null_client();
Self::new_with_config_and_client(server_url, capabilities, config, client).await
}
pub async fn new_with_config_and_client<S, C>(
server_url: S,
capabilities: C,
config: WebDriverConfig,
client: impl HttpClient,
) -> WebDriverResult<Self>
where
S: Into<String>,
C: Into<Capabilities>,
{
let capabilities = capabilities.into();
let server_url = server_url
.into()
.parse()
.map_err(|e| WebDriverError::ParseError(format!("invalid url: {e}")))?;
let client = Arc::new(client);
let session_id = start_session(client.as_ref(), &server_url, &config, capabilities).await?;
let handle = SessionHandle::new_with_config(client, server_url, session_id, config)?;
Ok(Self {
handle: Arc::new(handle),
})
}
pub fn clone_with_config(&self, config: WebDriverConfig) -> Self {
Self {
handle: Arc::new(self.handle.clone_with_config(config)),
}
}
#[cfg(feature = "manager")]
pub fn managed<C>(capabilities: C) -> crate::manager::WebDriverManagerBuilder
where
C: Into<Capabilities>,
{
let mut builder = crate::manager::WebDriverManager::builder();
builder.preloaded_caps = Some(capabilities.into());
builder
}
#[cfg(feature = "manager")]
pub fn driver_id(&self) -> Option<crate::manager::DriverId> {
let guard = self.handle.driver_guard()?;
let session_guard =
guard.as_any().downcast_ref::<crate::manager::manager_internal::SessionGuard>()?;
Some(session_guard.driver.driver_id)
}
#[cfg(feature = "manager")]
pub fn on_driver_log<F>(&self, f: F) -> Option<crate::manager::DriverLogSubscription>
where
F: Fn(&crate::manager::DriverLogLine) + Send + Sync + 'static,
{
let guard = self.handle.driver_guard()?;
let session_guard =
guard.as_any().downcast_ref::<crate::manager::manager_internal::SessionGuard>()?;
Some(session_guard.driver.subscribe_log(f))
}
pub async fn quit(self) -> WebDriverResult<()> {
self.handle.quit().await
}
pub fn leak(self) -> Result<(), AlreadyQuit> {
self.handle.leak()
}
}
impl Deref for WebDriver {
type Target = Arc<SessionHandle>;
fn deref(&self) -> &Self::Target {
&self.handle
}
}