use pastey::paste;
use serde::{Deserialize, Serialize};
use serde_json::{Value, from_value, json, to_value};
pub use crate::common::log::LoggingPrefsLogLevel;
use crate::error::WebDriverResult;
use crate::{BrowserCapabilitiesHelper, Capabilities, CapabilitiesHelper};
#[derive(Debug, Clone, Serialize)]
#[serde(transparent)]
pub struct FirefoxCapabilities {
capabilities: Capabilities,
}
impl Default for FirefoxCapabilities {
fn default() -> Self {
Self::new()
}
}
macro_rules! firefox_arg_wrapper {
($($fname:ident => $opt:literal),*) => {
paste! {
$(
#[doc = concat!("Set the ", $opt, " option.")]
pub fn [<set_ $fname>](&mut self) -> WebDriverResult<()> {
self.add_arg($opt)
}
#[doc = concat!("Unset the ", $opt, " option.")]
pub fn [<unset_ $fname>](&mut self) -> WebDriverResult<()> {
self.remove_arg($opt)
}
#[doc = concat!("Return true if the ", $opt, " option is set.")]
pub fn [<is_ $fname>](&mut self) -> bool {
self.has_arg($opt)
}
)*
}
}
}
impl FirefoxCapabilities {
pub fn new() -> Self {
let mut capabilities = Capabilities::new();
capabilities.set("browserName", "firefox").expect("infallible");
FirefoxCapabilities {
capabilities,
}
}
pub fn set_logging_prefs(
&mut self,
component: String,
log_level: LoggingPrefsLogLevel,
) -> WebDriverResult<()> {
self.set("loggingPrefs", json!({ component: log_level }))
}
pub fn log_level(&self) -> WebDriverResult<LogLevel> {
let level: LogLevel = match self.browser_option("log") {
Some(Value::Object(x)) => {
x.get("level").map(|x| from_value(x.clone())).transpose()?.unwrap_or_default()
}
_ => LogLevel::default(),
};
Ok(level)
}
pub fn set_log_level(&mut self, log_level: LogLevel) -> WebDriverResult<()> {
self.set_browser_option("log", json!({ "level": log_level }))
}
pub fn set_firefox_binary(&mut self, start_cmd: &str) -> WebDriverResult<()> {
self.set_browser_option("binary", start_cmd)
}
pub fn set_preferences(&mut self, preferences: FirefoxPreferences) -> WebDriverResult<()> {
self.set_browser_option("prefs", preferences)
}
pub fn encoded_profile(&self) -> Option<String> {
self.browser_option("profile")
}
pub fn set_encoded_profile(&mut self, profile: &str) -> WebDriverResult<()> {
self.set_browser_option("profile", profile)
}
pub fn add_arg(&mut self, arg: &str) -> WebDriverResult<()> {
let mut args = self.args();
let arg_string = arg.to_string();
if !args.contains(&arg_string) {
args.push(arg_string);
}
self.set_browser_option("args", to_value(args)?)
}
firefox_arg_wrapper! {
headless => "-headless"
}
}
impl From<FirefoxCapabilities> for Capabilities {
fn from(caps: FirefoxCapabilities) -> Capabilities {
caps.capabilities
}
}
impl AsRef<Capabilities> for FirefoxCapabilities {
fn as_ref(&self) -> &Capabilities {
&self.capabilities
}
}
impl AsMut<Capabilities> for FirefoxCapabilities {
fn as_mut(&mut self) -> &mut Capabilities {
&mut self.capabilities
}
}
impl BrowserCapabilitiesHelper for FirefoxCapabilities {
const KEY: &'static str = "moz:firefoxOptions";
}
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LogLevel {
Trace,
Debug,
Config,
Info,
Warn,
Error,
Fatal,
#[default]
Default,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct FirefoxPreferences {
preferences: serde_json::Map<String, Value>,
}
impl FirefoxPreferences {
pub fn new() -> Self {
FirefoxPreferences::default()
}
pub fn set<T>(&mut self, key: &str, value: T) -> WebDriverResult<()>
where
T: Serialize,
{
self.preferences.insert(key.into(), to_value(value)?);
Ok(())
}
pub fn unset(&mut self, key: &str) -> WebDriverResult<()> {
self.preferences.remove(key);
Ok(())
}
pub fn set_accept_untrusted_certs(&mut self, value: bool) -> WebDriverResult<()> {
self.set("webdriver_accept_untrusted_certs", value)
}
pub fn unset_accept_untrusted_certs(&mut self) -> WebDriverResult<()> {
self.unset("webdriver_accept_untrusted_certs")
}
pub fn set_assume_untrusted_issuer(&mut self, value: bool) -> WebDriverResult<()> {
self.set("webdriver_assume_untrusted_issuer", value)
}
pub fn unset_assume_untrusted_issuer(&mut self) -> WebDriverResult<()> {
self.unset("webdriver_assume_untrusted_issuer")
}
pub fn set_log_driver(&mut self, value: FirefoxProfileLogDriver) -> WebDriverResult<()> {
self.set("webdriver.log.driver", value)
}
pub fn unset_log_driver(&mut self) -> WebDriverResult<()> {
self.unset("webdriver.log.driver")
}
pub fn set_log_file(&mut self, value: String) -> WebDriverResult<()> {
self.set("webdriver.log.file", value)
}
pub fn unset_log_file(&mut self) -> WebDriverResult<()> {
self.unset("webdriver.log.file")
}
pub fn set_load_strategy(&mut self, value: String) -> WebDriverResult<()> {
self.set("webdriver.load.strategy", value)
}
pub fn unset_load_strategy(&mut self) -> WebDriverResult<()> {
self.unset("webdriver.load.strategy")
}
pub fn set_webdriver_port(&mut self, value: u16) -> WebDriverResult<()> {
self.set("webdriver_firefox_port", value)
}
pub fn unset_webdriver_port(&mut self) -> WebDriverResult<()> {
self.unset("webdriver_firefox_port")
}
pub fn set_user_agent(&mut self, value: String) -> WebDriverResult<()> {
self.set("general.useragent.override", value)
}
pub fn unset_user_agent(&mut self) -> WebDriverResult<()> {
self.unset("general.useragent.override")
}
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum FirefoxProfileLogDriver {
Debug,
Info,
Warning,
Error,
Off,
}