From b61c4887e1b728d16bba2472f22ae1b58b7564f1 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Fri, 7 Jul 2023 20:50:48 +0200 Subject: [PATCH 01/11] [rust] Download latest version of Chrome for Testing (#11676) --- rust/Cargo.Bazel.lock | 8 +- rust/Cargo.lock | 2 +- rust/Cargo.toml | 2 +- rust/README.md | 8 +- rust/src/chrome.rs | 127 +++++++++++++++++-- rust/src/config.rs | 2 + rust/src/downloads.rs | 2 +- rust/src/edge.rs | 14 +++ rust/src/files.rs | 55 ++++++--- rust/src/firefox.rs | 14 +++ rust/src/grid.rs | 14 +++ rust/src/iexplorer.rs | 14 +++ rust/src/lib.rs | 181 ++++++++++++++++------------ rust/src/logger.rs | 22 +++- rust/src/main.rs | 24 ++-- rust/src/safari.rs | 14 +++ rust/src/safaritp.rs | 14 +++ rust/tests/chrome_download_tests.rs | 51 ++++++++ rust/tests/output_tests.rs | 13 +- 19 files changed, 453 insertions(+), 128 deletions(-) create mode 100644 rust/tests/chrome_download_tests.rs diff --git a/rust/Cargo.Bazel.lock b/rust/Cargo.Bazel.lock index 1bcfec94e2f28..d75fc4293825d 100644 --- a/rust/Cargo.Bazel.lock +++ b/rust/Cargo.Bazel.lock @@ -7075,9 +7075,9 @@ }, "license": "Apache-2.0/ISC/MIT" }, - "selenium-manager 1.0.0-M3": { + "selenium-manager 1.0.0-M4": { "name": "selenium-manager", - "version": "1.0.0-M3", + "version": "1.0.0-M4", "repository": null, "targets": [ { @@ -7182,7 +7182,7 @@ "selects": {} }, "edition": "2021", - "version": "1.0.0-M3" + "version": "1.0.0-M4" }, "license": "Apache-2.0" }, @@ -11822,7 +11822,7 @@ }, "binary_crates": [], "workspace_members": { - "selenium-manager 1.0.0-M3": "rust" + "selenium-manager 1.0.0-M4": "rust" }, "conditions": { "aarch64-apple-darwin": [ diff --git a/rust/Cargo.lock b/rust/Cargo.lock index cb8463149da17..8f3786303d02e 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1315,7 +1315,7 @@ dependencies = [ [[package]] name = "selenium-manager" -version = "1.0.0-M3" +version = "1.0.0-M4" dependencies = [ "assert_cmd", "clap", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 2218bce92a472..d6d1dcd695425 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "selenium-manager" -version = "1.0.0-M3" +version = "1.0.0-M4" edition = "2021" authors = ["Selenium HTTP proxy for network connection (e.g., https://myproxy.net:8080) --timeout - Timeout for network requests (in seconds) [default: 180] + Timeout for network requests (in seconds) [default: 300] --driver-ttl Driver TTL (time-to-live) [default: 3600] --browser-ttl - Browser TTL (time-to-live) [default: 0] + Browser TTL (time-to-live) [default: 86400] --clear-cache Clear cache folder (~/.cache/selenium) --clear-metadata @@ -53,6 +53,8 @@ Options: Display TRACE messages --offline Offline mode (i.e., disabling network requests and downloads) + --force-browser-download + Force to download browser. Currently Chrome for Testing (CfT) is supported -h, --help Print help -V, --version diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index a00569871b38a..3cf83b4a02016 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -26,13 +26,14 @@ use std::path::PathBuf; use crate::config::ARCH::{ARM64, X32}; use crate::config::OS::{LINUX, MACOS, WINDOWS}; use crate::downloads::{parse_json_from_url, read_version_from_link}; -use crate::files::{compose_driver_path_in_cache, BrowserPath}; +use crate::files::{compose_driver_path_in_cache, get_cache_folder, BrowserPath}; use crate::logger::Logger; use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, }; use crate::{ - create_http_client, format_one_arg, format_three_args, SeleniumManager, BETA, + create_browser_metadata, create_http_client, download_to_tmp_folder, format_one_arg, + format_three_args, get_browser_version_from_metadata, uncompress, SeleniumManager, BETA, DASH_DASH_VERSION, DEV, ENV_LOCALAPPDATA, ENV_PROGRAM_FILES, ENV_PROGRAM_FILES_X86, NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY, REMOVE_X86, STABLE, WMIC_COMMAND, WMIC_COMMAND_ENV, }; @@ -51,6 +52,7 @@ pub struct ChromeManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, + pub downloaded_browser: Option, pub driver_url: Option, } @@ -68,6 +70,7 @@ impl ChromeManager { config, log: Logger::default(), driver_url: None, + downloaded_browser: None, })) } @@ -107,10 +110,8 @@ impl ChromeManager { where T: Serialize + for<'a> Deserialize<'a>, { - self.log.debug(format!( - "Reading {} metadata from {}", - &self.driver_name, driver_url - )); + self.log + .debug(format!("Reading metadata from {}", driver_url)); parse_json_from_url::(self.get_http_client(), driver_url) } @@ -131,14 +132,18 @@ impl ChromeManager { return self.request_driver_version_from_latest(self.create_latest_release_url()); } - let url: Vec<&PlatformUrl> = chromedriver + let platform_url: Vec<&PlatformUrl> = chromedriver .as_ref() .unwrap() .iter() .filter(|p| p.platform.eq_ignore_ascii_case(self.get_platform_label())) .collect(); - self.log.trace(format!("URLs for CfT: {:?}", url)); - self.driver_url = Some(url.first().unwrap().url.to_string()); + self.log.trace(format!( + "CfT URLs for downloading {}: {:?}", + self.get_driver_name(), + platform_url + )); + self.driver_url = Some(platform_url.first().unwrap().url.to_string()); Ok(stable_channel.version) } @@ -204,6 +209,13 @@ impl ChromeManager { "linux64" } } + + fn get_browser_path_in_cache(&self) -> PathBuf { + get_cache_folder() + .join(self.get_browser_name()) + .join(self.get_platform_label()) + .join(self.get_browser_version()) + } } impl SeleniumManager for ChromeManager { @@ -421,6 +433,103 @@ impl SeleniumManager for ChromeManager { fn set_logger(&mut self, log: Logger) { self.log = log; } + + fn download_browser(&mut self) -> Result, Box> { + let browser_name = self.browser_name; + + // Checking latest version of Chrome for Testing (CfT) + let mut metadata = get_metadata(self.get_logger()); + let browser_version; + let mut browser_url = None; + match get_browser_version_from_metadata(&metadata.browsers, browser_name) { + Some(version) => { + self.get_logger().trace(format!( + "Browser with valid TTL. Getting {} version from metadata", + browser_name + )); + browser_version = version; + self.set_browser_version(browser_version.clone()); + } + _ => { + self.get_logger().debug(format!( + "Using Chrome for Testing (CfT) endpoints to find out latest stable {} version", + browser_name + )); + let versions_with_downloads = self + .request_versions_from_cft::( + self.create_latest_versions_url(), + )?; + + let stable_channel = versions_with_downloads.channels.stable; + let chrome = stable_channel.downloads.chrome; + let platform_url: Vec<&PlatformUrl> = chrome + .iter() + .filter(|p| p.platform.eq_ignore_ascii_case(self.get_platform_label())) + .collect(); + self.log.trace(format!( + "CfT URLs for downloading {}: {:?}", + self.get_browser_name(), + platform_url + )); + browser_url = Some(platform_url.first().unwrap().url.to_string()); + browser_version = stable_channel.version; + + self.set_browser_version(browser_version.clone()); + let browser_ttl = self.get_browser_ttl(); + if browser_ttl > 0 && !browser_version.is_empty() { + metadata.browsers.push(create_browser_metadata( + browser_name, + &browser_version, + browser_ttl, + )); + write_metadata(&metadata, self.get_logger()); + } + } + } + self.get_logger().debug(format!( + "Required browser: {} {}", + browser_name, browser_version + )); + + // Checking if that browser version is in the cache + let browser_path_in_cache = Self::get_browser_path_in_cache(self); + let browser_path = Some(browser_path_in_cache.join(self.get_browser_name_with_extension())); + if browser_path.clone().unwrap().exists() { + self.get_logger().debug(format!( + "{} {} already in the cache", + browser_name, browser_version + )); + } else { + // If browser is not in the cache, download it + let download_url = browser_url.unwrap(); + self.get_logger().debug(format!( + "Downloading {} {} from {}", + self.get_browser_name(), + self.get_browser_version(), + download_url + )); + let (_tmp_folder, driver_zip_file) = + download_to_tmp_folder(self.get_http_client(), download_url, self.get_logger())?; + + uncompress( + &driver_zip_file, + &browser_path_in_cache, + self.get_logger(), + None, + )?; + } + self.set_downloaded_browser(browser_path.clone()); + + Ok(browser_path) + } + + fn get_downloaded_browser(&self) -> Option { + self.downloaded_browser.to_owned() + } + + fn set_downloaded_browser(&mut self, downloaded_browser: Option) { + self.downloaded_browser = downloaded_browser; + } } #[derive(Serialize, Deserialize)] diff --git a/rust/src/config.rs b/rust/src/config.rs index 7f27d4617a587..7f74661199934 100644 --- a/rust/src/config.rs +++ b/rust/src/config.rs @@ -42,6 +42,7 @@ pub struct ManagerConfig { pub browser_ttl: u64, pub driver_ttl: u64, pub offline: bool, + pub force_browser_download: bool, } impl ManagerConfig { @@ -89,6 +90,7 @@ impl ManagerConfig { browser_ttl: IntegerKey("browser-ttl", TTL_BROWSERS_SEC).get_value(), driver_ttl: IntegerKey("driver-ttl", TTL_DRIVERS_SEC).get_value(), offline: BooleanKey("offline", false).get_value(), + force_browser_download: BooleanKey("force_browser_download", false).get_value(), } } } diff --git a/rust/src/downloads.rs b/rust/src/downloads.rs index 50d37c625a3e0..d21b8cf2025e0 100644 --- a/rust/src/downloads.rs +++ b/rust/src/downloads.rs @@ -28,7 +28,7 @@ use crate::files::parse_version; use crate::Logger; #[tokio::main] -pub async fn download_driver_to_tmp_folder( +pub async fn download_to_tmp_folder( http_client: &Client, url: String, log: &Logger, diff --git a/rust/src/edge.rs b/rust/src/edge.rs index 5daa3920ab474..0a77b0fa0c5ec 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -46,6 +46,7 @@ pub struct EdgeManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, + pub downloaded_browser: Option, } impl EdgeManager { @@ -61,6 +62,7 @@ impl EdgeManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), + downloaded_browser: None, })) } } @@ -299,4 +301,16 @@ impl SeleniumManager for EdgeManager { fn set_logger(&mut self, log: Logger) { self.log = log; } + + fn download_browser(&mut self) -> Result, Box> { + Ok(None) + } + + fn get_downloaded_browser(&self) -> Option { + self.downloaded_browser.to_owned() + } + + fn set_downloaded_browser(&mut self, downloaded_browser: Option) { + self.downloaded_browser = downloaded_browser; + } } diff --git a/rust/src/files.rs b/rust/src/files.rs index 6d62d7bc924e8..ba4acf0db9780 100644 --- a/rust/src/files.rs +++ b/rust/src/files.rs @@ -70,6 +70,7 @@ pub fn uncompress( compressed_file: &str, target: &Path, log: &Logger, + single_file: Option, ) -> Result<(), Box> { let file = File::open(compressed_file)?; let kind = infer::get_from_path(compressed_file)? @@ -81,7 +82,7 @@ pub fn uncompress( )); if extension.eq_ignore_ascii_case(ZIP) { - unzip(file, target, log)? + unzip(file, target, log, single_file)? } else if extension.eq_ignore_ascii_case(GZ) { untargz(file, target, log)? } else if extension.eq_ignore_ascii_case(XML) || extension.eq_ignore_ascii_case(HTML) { @@ -113,37 +114,53 @@ pub fn untargz(file: File, target: &Path, log: &Logger) -> Result<(), Box Result<(), Box> { +pub fn unzip( + file: File, + target: &Path, + log: &Logger, + single_file: Option, +) -> Result<(), Box> { log.trace(format!("Unzipping file to {}", target.display())); + let mut out_path = target.to_path_buf(); let mut archive = ZipArchive::new(file)?; for i in 0..archive.len() { let mut file = archive.by_index(i)?; - if target.exists() { - continue; + let path: PathBuf = match file.enclosed_name() { + Some(p) => p.to_owned().iter().skip(1).collect(), + None => continue, + }; + if single_file.is_none() { + create_path_if_not_exists(target); + out_path = target.join(path); } - let target_file_name = target.file_name().unwrap().to_str().unwrap(); - if target_file_name.eq(get_raw_file_name(file.name())) { - log.debug(format!( + + if single_file.is_none() && file.name().ends_with('/') { + log.trace(format!("File {} extracted to {}", i, out_path.display())); + fs::create_dir_all(&out_path)?; + } else if single_file.is_none() + || (single_file.is_some() + && get_raw_file_name(file.name()).eq(&single_file.clone().unwrap())) + { + log.trace(format!( "File extracted to {} ({} bytes)", - target.display(), + out_path.display(), file.size() )); - create_parent_path_if_not_exists(target); - if !target.exists() { - let mut outfile = File::create(target)?; + create_parent_path_if_not_exists(out_path.as_path()); - // Set permissions in Unix-like systems - #[cfg(unix)] - { - use std::os::unix::fs::PermissionsExt; + let mut outfile = File::create(&out_path)?; + io::copy(&mut file, &mut outfile)?; - fs::set_permissions(&target, fs::Permissions::from_mode(0o755))?; - } + // Set permissions in Unix-like systems + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; - io::copy(&mut file, &mut outfile)?; + if let Some(mode) = file.unix_mode() { + fs::set_permissions(&out_path, fs::Permissions::from_mode(mode)).unwrap(); + } } - break; } } Ok(()) diff --git a/rust/src/firefox.rs b/rust/src/firefox.rs index a758ea8b3c520..a22c3fdab1420 100644 --- a/rust/src/firefox.rs +++ b/rust/src/firefox.rs @@ -45,6 +45,7 @@ pub struct FirefoxManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, + pub downloaded_browser: Option, } impl FirefoxManager { @@ -60,6 +61,7 @@ impl FirefoxManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), + downloaded_browser: None, })) } } @@ -290,6 +292,18 @@ impl SeleniumManager for FirefoxManager { fn set_logger(&mut self, log: Logger) { self.log = log; } + + fn download_browser(&mut self) -> Result, Box> { + Ok(None) + } + + fn get_downloaded_browser(&self) -> Option { + self.downloaded_browser.to_owned() + } + + fn set_downloaded_browser(&mut self, downloaded_browser: Option) { + self.downloaded_browser = downloaded_browser; + } } #[cfg(test)] diff --git a/rust/src/grid.rs b/rust/src/grid.rs index 20604b82906cc..8a44508274b49 100644 --- a/rust/src/grid.rs +++ b/rust/src/grid.rs @@ -47,6 +47,7 @@ pub struct GridManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, + pub downloaded_browser: Option, pub driver_url: Option, } @@ -65,6 +66,7 @@ impl GridManager { config, log: Logger::default(), driver_url: None, + downloaded_browser: None, })) } } @@ -209,4 +211,16 @@ impl SeleniumManager for GridManager { fn set_logger(&mut self, log: Logger) { self.log = log; } + + fn download_browser(&mut self) -> Result, Box> { + Ok(None) + } + + fn get_downloaded_browser(&self) -> Option { + self.downloaded_browser.to_owned() + } + + fn set_downloaded_browser(&mut self, downloaded_browser: Option) { + self.downloaded_browser = downloaded_browser; + } } diff --git a/rust/src/iexplorer.rs b/rust/src/iexplorer.rs index 508c9ec4b803a..874a229f5d7cf 100644 --- a/rust/src/iexplorer.rs +++ b/rust/src/iexplorer.rs @@ -49,6 +49,7 @@ pub struct IExplorerManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, + pub downloaded_browser: Option, pub driver_url: Option, } @@ -66,6 +67,7 @@ impl IExplorerManager { config, log: Logger::default(), driver_url: None, + downloaded_browser: None, })) } } @@ -205,4 +207,16 @@ impl SeleniumManager for IExplorerManager { fn set_logger(&mut self, log: Logger) { self.log = log; } + + fn download_browser(&mut self) -> Result, Box> { + Ok(None) + } + + fn get_downloaded_browser(&self) -> Option { + self.downloaded_browser.to_owned() + } + + fn set_downloaded_browser(&mut self, downloaded_browser: Option) { + self.downloaded_browser = downloaded_browser; + } } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 9ca4eaae18462..e46b140923775 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -17,7 +17,7 @@ use crate::chrome::{ChromeManager, CHROMEDRIVER_NAME, CHROME_NAME}; use crate::edge::{EdgeManager, EDGEDRIVER_NAME, EDGE_NAMES}; -use crate::files::{compose_cache_folder, create_parent_path_if_not_exists}; +use crate::files::{compose_cache_folder, create_parent_path_if_not_exists, get_binary_extension}; use crate::firefox::{FirefoxManager, FIREFOX_NAME, GECKODRIVER_NAME}; use crate::iexplorer::{IExplorerManager, IEDRIVER_NAME, IE_NAMES}; use crate::safari::{SafariManager, SAFARIDRIVER_NAME, SAFARI_NAME}; @@ -33,13 +33,11 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::Duration; -use crate::downloads::download_driver_to_tmp_folder; +use crate::downloads::download_to_tmp_folder; use crate::files::{parse_version, uncompress, BrowserPath}; use crate::grid::GRID_NAME; use crate::logger::Logger; -use crate::metadata::{ - create_browser_metadata, get_browser_version_from_metadata, get_metadata, write_metadata, -}; +use crate::metadata::{create_browser_metadata, get_browser_version_from_metadata}; use crate::safaritp::{SafariTPManager, SAFARITP_NAMES}; pub mod chrome; @@ -56,7 +54,7 @@ pub mod mirror; pub mod safari; pub mod safaritp; -pub const REQUEST_TIMEOUT_SEC: u64 = 180; // The timeout is applied from when the request starts connecting until the response body has finished +pub const REQUEST_TIMEOUT_SEC: u64 = 300; // The timeout is applied from when the request starts connecting until the response body has finished pub const STABLE: &str = "stable"; pub const BETA: &str = "beta"; pub const DEV: &str = "dev"; @@ -82,7 +80,7 @@ pub const ARCH_ARM64: &str = "arm64"; pub const ENV_PROCESSOR_ARCHITECTURE: &str = "PROCESSOR_ARCHITECTURE"; pub const WHERE_COMMAND: &str = "where {}"; pub const WHICH_COMMAND: &str = "which {}"; -pub const TTL_BROWSERS_SEC: u64 = 0; +pub const TTL_BROWSERS_SEC: u64 = 86400; pub const TTL_DRIVERS_SEC: u64 = 3600; pub const UNAME_COMMAND: &str = "uname -{}"; pub const CRLF: &str = "\r\n"; @@ -124,6 +122,12 @@ pub trait SeleniumManager { fn set_logger(&mut self, log: Logger); + fn download_browser(&mut self) -> Result, Box>; + + fn get_downloaded_browser(&self) -> Option; + + fn set_downloaded_browser(&mut self, downloaded_browser: Option); + // ---------------------------------------------------------- // Shared functions // ---------------------------------------------------------- @@ -133,7 +137,7 @@ pub trait SeleniumManager { self.get_logger() .debug(format!("Driver URL: {}", driver_url)); let (_tmp_folder, driver_zip_file) = - download_driver_to_tmp_folder(self.get_http_client(), driver_url, self.get_logger())?; + download_to_tmp_folder(self.get_http_client(), driver_url, self.get_logger())?; if self.is_grid() { let driver_path_in_cache = Self::get_driver_path_in_cache(self); @@ -141,7 +145,13 @@ pub trait SeleniumManager { Ok(fs::rename(driver_zip_file, driver_path_in_cache)?) } else { let driver_path_in_cache = Self::get_driver_path_in_cache(self); - uncompress(&driver_zip_file, &driver_path_in_cache, self.get_logger()) + let driver_name_with_extension = self.get_driver_name_with_extension(); + uncompress( + &driver_zip_file, + &driver_path_in_cache, + self.get_logger(), + Some(driver_name_with_extension), + ) } } @@ -158,57 +168,38 @@ pub trait SeleniumManager { } fn detect_browser_version(&self, commands: Vec) -> Option { - let mut metadata = get_metadata(self.get_logger()); let browser_name = &self.get_browser_name(); - match get_browser_version_from_metadata(&metadata.browsers, browser_name) { - Some(version) => { - self.get_logger().trace(format!( - "Browser with valid TTL. Getting {} version from metadata", - browser_name - )); - Some(version) + self.get_logger().debug(format!( + "Using shell command to find out {} version", + browser_name + )); + let mut browser_version: Option = None; + for command in commands.iter() { + let output = match self.run_shell_command_with_log(command.to_string()) { + Ok(out) => out, + Err(_e) => continue, + }; + let full_browser_version = parse_version(output, self.get_logger()).unwrap_or_default(); + if full_browser_version.is_empty() { + continue; } - _ => { - self.get_logger().debug(format!( - "Using shell command to find out {} version", - browser_name - )); - let mut browser_version: Option = None; - for command in commands.iter() { - let output = match self.run_shell_command_with_log(command.to_string()) { - Ok(out) => out, - Err(_e) => continue, - }; - let full_browser_version = - parse_version(output, self.get_logger()).unwrap_or_default(); - if full_browser_version.is_empty() { - continue; - } - self.get_logger().trace(format!( - "The version of {} is {}", - browser_name, full_browser_version - )); + self.get_logger().trace(format!( + "The version of {} is {}", + browser_name, full_browser_version + )); - browser_version = Some(full_browser_version); - break; - } - - let browser_ttl = self.get_browser_ttl(); - if browser_ttl > 0 && browser_version.is_some() && !self.is_safari() { - metadata.browsers.push(create_browser_metadata( - browser_name, - browser_version.as_ref().unwrap(), - browser_ttl, - )); - write_metadata(&metadata, self.get_logger()); - } - browser_version - } + browser_version = Some(full_browser_version); + break; } + + browser_version } - fn discover_driver_version(&mut self) -> Result { + fn discover_driver_version(&mut self) -> Result> { + if self.is_force_browser_download() { + self.download_browser()?; + } let browser_version = self.get_major_browser_version(); if browser_version.is_empty() || self.is_browser_version_unstable() { match self.discover_browser_version() { @@ -223,8 +214,20 @@ pub trait SeleniumManager { } } None => { - if self.is_browser_version_unstable() { - return Err(format!("Browser version '{browser_version}' not found")); + self.get_logger().debug(format!( + "{} has not been discovered in the system", + self.get_browser_name() + )); + let browser_path = self.download_browser()?; + if browser_path.is_some() { + self.get_logger().debug(format!( + "{} {} downloaded to {}", + self.get_browser_name(), + self.get_browser_version(), + browser_path.unwrap().display() + )); + } else if self.is_browser_version_unstable() { + return Err(format!("Browser version '{browser_version}' not found").into()); } else if !self.is_iexplorer() && !self.is_grid() { self.get_logger().warn(format!( "The version of {} cannot be detected. Trying with latest driver version", @@ -234,26 +237,21 @@ pub trait SeleniumManager { } } } - let driver_version = match self.request_driver_version() { - Ok(version) => { - if version.is_empty() { - return Err(format!( - "The {} version cannot be discovered", - self.get_driver_name() - )); - } - version - } - Err(err) => { - return Err(err.to_string()); - } - }; - self.get_logger().debug(format!( - "Required driver: {} {}", - self.get_driver_name(), - driver_version - )); - Ok(driver_version) + let driver_version = self.request_driver_version()?; + if driver_version.is_empty() { + Err(format!( + "The {} version cannot be discovered", + self.get_driver_name() + ) + .into()) + } else { + self.get_logger().debug(format!( + "Required driver: {} {}", + self.get_driver_name(), + driver_version + )); + Ok(driver_version) + } } fn find_driver_in_path(&self) -> (Option, Option) { @@ -324,6 +322,8 @@ pub trait SeleniumManager { // Try to find driver in PATH if !self.is_safari() && !self.is_grid() { + self.get_logger() + .debug(format!("Checking {} in PATH", self.get_driver_name())); (driver_in_path_version, driver_in_path) = self.find_driver_in_path(); if let (Some(version), Some(path)) = (&driver_in_path_version, &driver_in_path) { self.get_logger().debug(format!( @@ -332,6 +332,9 @@ pub trait SeleniumManager { version, path )); + } else { + self.get_logger() + .debug(format!("{} not found in PATH", self.get_driver_name())); } } @@ -349,7 +352,7 @@ pub trait SeleniumManager { err )); } else { - return Err(err.into()); + return Err(err); } } } @@ -438,6 +441,22 @@ pub trait SeleniumManager { Ok(()) } + fn get_driver_name_with_extension(&self) -> String { + format!( + "{}{}", + self.get_driver_name(), + get_binary_extension(self.get_os()) + ) + } + + fn get_browser_name_with_extension(&self) -> String { + format!( + "{}{}", + self.get_browser_name(), + get_binary_extension(self.get_os()) + ) + } + // ---------------------------------------------------------- // Getters and setters for configuration parameters // ---------------------------------------------------------- @@ -574,6 +593,16 @@ pub trait SeleniumManager { self.get_config_mut().offline = true; } } + + fn is_force_browser_download(&self) -> bool { + self.get_config().force_browser_download + } + + fn set_force_browser_download(&mut self, force_browser_download: bool) { + if force_browser_download { + self.get_config_mut().force_browser_download = true; + } + } } // ---------------------------------------------------------- diff --git a/rust/src/logger.rs b/rust/src/logger.rs index 8ffb877300481..df19517be7518 100644 --- a/rust/src/logger.rs +++ b/rust/src/logger.rs @@ -29,6 +29,9 @@ use std::io::Write; use std::ops::Deref; use Color::{Blue, Cyan, Green, Red, Yellow}; +pub const DRIVER_PATH: &str = "Driver path: "; +pub const BROWSER_PATH: &str = "Browser path: "; + #[derive(Default)] enum OutputType { #[default] @@ -56,6 +59,8 @@ pub struct Logs { pub struct Result { pub code: i32, pub message: String, + pub driver_path: String, + pub browser_path: String, } #[derive(Default, Serialize, Deserialize)] @@ -125,6 +130,8 @@ impl Logger { result: Result { code: 0, message: "".to_string(), + driver_path: "".to_string(), + browser_path: "".to_string(), }, }), } @@ -163,14 +170,23 @@ impl Logger { .push(self.create_json_log(message.to_string(), level)); } if level == Level::Info || level <= Level::Error { - self.json.borrow_mut().result.message = message; + if message.starts_with(DRIVER_PATH) { + let driver_path = message.replace(DRIVER_PATH, ""); + self.json.borrow_mut().result.driver_path = driver_path.to_owned(); + self.json.borrow_mut().result.message = driver_path; + } else if message.starts_with(BROWSER_PATH) { + let browser_path = message.replace(BROWSER_PATH, ""); + self.json.borrow_mut().result.browser_path = browser_path; + } else { + self.json.borrow_mut().result.message = message; + } } } OutputType::Shell => { if level == Level::Info { - print!("{}", message); + println!("{}", message); } else if level == Level::Error { - eprint!("{}", message); + eprintln!("{}", message); } } _ => { diff --git a/rust/src/main.rs b/rust/src/main.rs index a51496dd162ac..34c125b2f36a2 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -20,12 +20,10 @@ use std::process::exit; use clap::Parser; use exitcode::DATAERR; -use exitcode::UNAVAILABLE; - use exitcode::OK; use selenium_manager::config::BooleanKey; use selenium_manager::grid::GridManager; -use selenium_manager::logger::Logger; +use selenium_manager::logger::{Logger, BROWSER_PATH, DRIVER_PATH}; use selenium_manager::REQUEST_TIMEOUT_SEC; use selenium_manager::TTL_BROWSERS_SEC; use selenium_manager::TTL_DRIVERS_SEC; @@ -108,6 +106,10 @@ struct Cli { /// Offline mode (i.e., disabling network requests and downloads) #[clap(long)] offline: bool, + + /// Force to download browser. Currently Chrome for Testing (CfT) is supported + #[clap(long)] + force_browser_download: bool, } fn main() { @@ -155,6 +157,7 @@ fn main() { selenium_manager.set_driver_ttl(cli.driver_ttl); selenium_manager.set_browser_ttl(cli.browser_ttl); selenium_manager.set_offline(cli.offline); + selenium_manager.set_force_browser_download(cli.force_browser_download); selenium_manager .set_timeout(cli.timeout) @@ -162,13 +165,16 @@ fn main() { .and_then(|_| selenium_manager.resolve_driver()) .map(|path| { let log = selenium_manager.get_logger(); - if path.exists() { - log.info(path.display()); - flush_and_exit(OK, log); - } else { - log.error("Driver unavailable in the cache".to_string()); - flush_and_exit(UNAVAILABLE, log); + log.info(format!("{}{}", DRIVER_PATH, path.display())); + let downloaded_browser = selenium_manager.get_downloaded_browser(); + if downloaded_browser.is_some() { + log.info(format!( + "{}{}", + BROWSER_PATH, + downloaded_browser.unwrap().display() + )); } + flush_and_exit(OK, log); }) .unwrap_or_else(|err| { let log = selenium_manager.get_logger(); diff --git a/rust/src/safari.rs b/rust/src/safari.rs index 1ef13264381a0..ff2780df2dde6 100644 --- a/rust/src/safari.rs +++ b/rust/src/safari.rs @@ -36,6 +36,7 @@ pub struct SafariManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, + pub downloaded_browser: Option, } impl SafariManager { @@ -51,6 +52,7 @@ impl SafariManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), + downloaded_browser: None, })) } } @@ -129,4 +131,16 @@ impl SeleniumManager for SafariManager { fn set_logger(&mut self, log: Logger) { self.log = log; } + + fn download_browser(&mut self) -> Result, Box> { + Ok(None) + } + + fn get_downloaded_browser(&self) -> Option { + self.downloaded_browser.to_owned() + } + + fn set_downloaded_browser(&mut self, downloaded_browser: Option) { + self.downloaded_browser = downloaded_browser; + } } diff --git a/rust/src/safaritp.rs b/rust/src/safaritp.rs index 6a4b40eea17cb..a5fb7dc78478d 100644 --- a/rust/src/safaritp.rs +++ b/rust/src/safaritp.rs @@ -41,6 +41,7 @@ pub struct SafariTPManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, + pub downloaded_browser: Option, } impl SafariTPManager { @@ -56,6 +57,7 @@ impl SafariTPManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), + downloaded_browser: None, })) } } @@ -134,4 +136,16 @@ impl SeleniumManager for SafariTPManager { fn set_logger(&mut self, log: Logger) { self.log = log; } + + fn download_browser(&mut self) -> Result, Box> { + Ok(None) + } + + fn get_downloaded_browser(&self) -> Option { + self.downloaded_browser.to_owned() + } + + fn set_downloaded_browser(&mut self, downloaded_browser: Option) { + self.downloaded_browser = downloaded_browser; + } } diff --git a/rust/tests/chrome_download_tests.rs b/rust/tests/chrome_download_tests.rs new file mode 100644 index 0000000000000..3355f422d46da --- /dev/null +++ b/rust/tests/chrome_download_tests.rs @@ -0,0 +1,51 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use assert_cmd::Command; +use std::path::Path; + +use is_executable::is_executable; +use selenium_manager::logger::JsonOutput; +use std::str; + +#[test] +fn chrome_download_test() { + let mut cmd = Command::new(env!("CARGO_BIN_EXE_selenium-manager")); + cmd.args([ + "--browser", + "chrome", + "--force-browser-download", + "--output", + "json", + ]) + .assert() + .success() + .code(0); + + let stdout = &cmd.unwrap().stdout; + let output = str::from_utf8(stdout).unwrap(); + println!("{}", output); + + let json: JsonOutput = serde_json::from_str(output).unwrap(); + let driver_path = Path::new(&json.result.driver_path); + assert!(driver_path.exists()); + assert!(is_executable(driver_path)); + + let browser_path = Path::new(&json.result.browser_path); + assert!(browser_path.exists()); + assert!(is_executable(browser_path)); +} diff --git a/rust/tests/output_tests.rs b/rust/tests/output_tests.rs index 5e0b847dc0ce2..fa2b1251bd3c6 100644 --- a/rust/tests/output_tests.rs +++ b/rust/tests/output_tests.rs @@ -18,7 +18,7 @@ use assert_cmd::Command; use std::path::Path; -use selenium_manager::logger::JsonOutput; +use selenium_manager::logger::{JsonOutput, DRIVER_PATH}; use std::str; #[test] @@ -55,6 +55,15 @@ fn shell_output_test() { let output = str::from_utf8(stdout).unwrap(); println!("{}", output); - let driver = Path::new(output); + let cleaned_output = output.replace(DRIVER_PATH, ""); + let driver_path = strip_trailing_newline(cleaned_output.as_str()); + let driver = Path::new(driver_path); assert!(driver.exists()); } + +fn strip_trailing_newline(input: &str) -> &str { + input + .strip_suffix("\r\n") + .or(input.strip_suffix('\n')) + .unwrap_or(input) +} From 076afa27ee45283af1e6c996dd92eed063c25f4a Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Thu, 13 Jul 2023 14:51:44 +0200 Subject: [PATCH 02/11] [rust] Fix differences about CfT binaries in macOS --- rust/src/chrome.rs | 81 ++++++++++++++++++++++---------------- rust/src/files.rs | 4 +- rust/tests/cli_tests.rs | 1 - rust/tests/output_tests.rs | 13 +----- 4 files changed, 52 insertions(+), 47 deletions(-) diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index 3cf83b4a02016..5ded6486597e7 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -45,6 +45,8 @@ const LATEST_RELEASE: &str = "LATEST_RELEASE"; const CFT_URL: &str = "https://googlechromelabs.github.io/chrome-for-testing/"; const GOOD_VERSIONS_ENDPOINT: &str = "known-good-versions-with-downloads.json"; const LATEST_VERSIONS_ENDPOINT: &str = "last-known-good-versions-with-downloads.json"; +const CFT_MACOS_APP_NAME: &str = + "Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing"; pub struct ChromeManager { pub browser_name: &'static str, @@ -53,7 +55,7 @@ pub struct ChromeManager { pub http_client: Client, pub log: Logger, pub downloaded_browser: Option, - pub driver_url: Option, + pub download_url: Option, } impl ChromeManager { @@ -69,7 +71,7 @@ impl ChromeManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), - driver_url: None, + download_url: None, downloaded_browser: None, })) } @@ -143,7 +145,7 @@ impl ChromeManager { self.get_driver_name(), platform_url )); - self.driver_url = Some(platform_url.first().unwrap().url.to_string()); + self.download_url = Some(platform_url.first().unwrap().url.to_string()); Ok(stable_channel.version) } @@ -185,7 +187,7 @@ impl ChromeManager { .filter(|p| p.platform.eq_ignore_ascii_case(self.get_platform_label())) .collect(); self.log.trace(format!("URLs for CfT: {:?}", url)); - self.driver_url = Some(url.first().unwrap().url.to_string()); + self.download_url = Some(url.first().unwrap().url.to_string()); Ok(driver_version.version.to_string()) } @@ -216,6 +218,33 @@ impl ChromeManager { .join(self.get_platform_label()) .join(self.get_browser_version()) } + + fn request_latest_cft(&mut self) -> Result> { + let browser_name = self.browser_name; + self.get_logger().debug(format!( + "Using Chrome for Testing (CfT) endpoints to find out latest stable {} version", + browser_name + )); + let versions_with_downloads = self + .request_versions_from_cft::( + self.create_latest_versions_url(), + )?; + let stable_channel = versions_with_downloads.channels.stable; + let chrome = stable_channel.downloads.chrome; + let platform_url: Vec<&PlatformUrl> = chrome + .iter() + .filter(|p| p.platform.eq_ignore_ascii_case(self.get_platform_label())) + .collect(); + self.log.trace(format!( + "CfT URLs for downloading {}: {:?}", + self.get_browser_name(), + platform_url + )); + let browser_version = stable_channel.version; + self.download_url = Some(platform_url.first().unwrap().url.to_string()); + + Ok(browser_version) + } } impl SeleniumManager for ChromeManager { @@ -371,14 +400,14 @@ impl SeleniumManager for ChromeManager { .parse::() .unwrap_or_default(); - if major_driver_version >= 115 && self.driver_url.is_none() { + if major_driver_version >= 115 && self.download_url.is_none() { // This case happens when driver_version is set (e.g. using CLI flag) self.request_good_version_from_cft()?; } // As of Chrome 115+, the driver URL is already gathered thanks to the CfT endpoints - if self.driver_url.is_some() { - return Ok(self.driver_url.as_ref().unwrap().to_string()); + if self.download_url.is_some() { + return Ok(self.download_url.as_ref().unwrap().to_string()); } let driver_version = self.get_driver_version(); @@ -440,7 +469,6 @@ impl SeleniumManager for ChromeManager { // Checking latest version of Chrome for Testing (CfT) let mut metadata = get_metadata(self.get_logger()); let browser_version; - let mut browser_url = None; match get_browser_version_from_metadata(&metadata.browsers, browser_name) { Some(version) => { self.get_logger().trace(format!( @@ -451,29 +479,7 @@ impl SeleniumManager for ChromeManager { self.set_browser_version(browser_version.clone()); } _ => { - self.get_logger().debug(format!( - "Using Chrome for Testing (CfT) endpoints to find out latest stable {} version", - browser_name - )); - let versions_with_downloads = self - .request_versions_from_cft::( - self.create_latest_versions_url(), - )?; - - let stable_channel = versions_with_downloads.channels.stable; - let chrome = stable_channel.downloads.chrome; - let platform_url: Vec<&PlatformUrl> = chrome - .iter() - .filter(|p| p.platform.eq_ignore_ascii_case(self.get_platform_label())) - .collect(); - self.log.trace(format!( - "CfT URLs for downloading {}: {:?}", - self.get_browser_name(), - platform_url - )); - browser_url = Some(platform_url.first().unwrap().url.to_string()); - browser_version = stable_channel.version; - + browser_version = self.request_latest_cft()?; self.set_browser_version(browser_version.clone()); let browser_ttl = self.get_browser_ttl(); if browser_ttl > 0 && !browser_version.is_empty() { @@ -493,7 +499,11 @@ impl SeleniumManager for ChromeManager { // Checking if that browser version is in the cache let browser_path_in_cache = Self::get_browser_path_in_cache(self); - let browser_path = Some(browser_path_in_cache.join(self.get_browser_name_with_extension())); + let browser_path = if MACOS.is(self.get_os()) { + Some(browser_path_in_cache.join(CFT_MACOS_APP_NAME)) + } else { + Some(browser_path_in_cache.join(self.get_browser_name_with_extension())) + }; if browser_path.clone().unwrap().exists() { self.get_logger().debug(format!( "{} {} already in the cache", @@ -501,7 +511,12 @@ impl SeleniumManager for ChromeManager { )); } else { // If browser is not in the cache, download it - let download_url = browser_url.unwrap(); + let download_url = if let Some(url) = self.download_url.clone() { + url + } else { + self.request_latest_cft()?; + self.download_url.clone().unwrap() + }; self.get_logger().debug(format!( "Downloading {} {} from {}", self.get_browser_name(), diff --git a/rust/src/files.rs b/rust/src/files.rs index ba4acf0db9780..6999cf5e6b247 100644 --- a/rust/src/files.rs +++ b/rust/src/files.rs @@ -157,7 +157,9 @@ pub fn unzip( { use std::os::unix::fs::PermissionsExt; - if let Some(mode) = file.unix_mode() { + if single_file.is_some() { + fs::set_permissions(&out_path, fs::Permissions::from_mode(0o755))?; + } else if let Some(mode) = file.unix_mode() { fs::set_permissions(&out_path, fs::Permissions::from_mode(mode)).unwrap(); } } diff --git a/rust/tests/cli_tests.rs b/rust/tests/cli_tests.rs index 26307db8c689e..c2bd4f2cc96f5 100644 --- a/rust/tests/cli_tests.rs +++ b/rust/tests/cli_tests.rs @@ -64,7 +64,6 @@ fn ok_test( if !browser_version.is_empty() && output.contains("cache") { assert!(output.contains(&driver_version)); } - assert!(!output.contains("Trying with latest driver version")); } #[rstest] diff --git a/rust/tests/output_tests.rs b/rust/tests/output_tests.rs index fa2b1251bd3c6..762fccd3abd38 100644 --- a/rust/tests/output_tests.rs +++ b/rust/tests/output_tests.rs @@ -54,16 +54,5 @@ fn shell_output_test() { let stdout = &cmd.unwrap().stdout; let output = str::from_utf8(stdout).unwrap(); println!("{}", output); - - let cleaned_output = output.replace(DRIVER_PATH, ""); - let driver_path = strip_trailing_newline(cleaned_output.as_str()); - let driver = Path::new(driver_path); - assert!(driver.exists()); -} - -fn strip_trailing_newline(input: &str) -> &str { - input - .strip_suffix("\r\n") - .or(input.strip_suffix('\n')) - .unwrap_or(input) + assert!(output.contains(DRIVER_PATH)); } From 7618cce56aedfc70aad8839f6272d3f6f35d2d88 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Thu, 13 Jul 2023 20:25:44 +0200 Subject: [PATCH 03/11] [rust] Refactor function to request latest browser version from CfT --- rust/src/chrome.rs | 67 +++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index 5ded6486597e7..e6b67f1178c43 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -117,12 +117,46 @@ impl ChromeManager { parse_json_from_url::(self.get_http_client(), driver_url) } - fn request_latest_driver_version_from_cft(&mut self) -> Result> { + fn request_latest_browser_version_from_cft(&mut self) -> Result> { + let browser_name = self.browser_name; + self.get_logger().trace(format!( + "Using Chrome for Testing (CfT) endpoints to find out latest stable {} version", + browser_name + )); + let versions_with_downloads = self .request_versions_from_cft::( self.create_latest_versions_url(), )?; + let stable_channel = versions_with_downloads.channels.stable; + let chrome = stable_channel.downloads.chrome; + let platform_url: Vec<&PlatformUrl> = chrome + .iter() + .filter(|p| p.platform.eq_ignore_ascii_case(self.get_platform_label())) + .collect(); + self.log.trace(format!( + "CfT URLs for downloading {}: {:?}", + self.get_browser_name(), + platform_url + )); + let browser_version = stable_channel.version; + self.download_url = Some(platform_url.first().unwrap().url.to_string()); + + Ok(browser_version) + } + + fn request_latest_driver_version_from_cft(&mut self) -> Result> { + let driver_name = self.driver_name; + self.get_logger().trace(format!( + "Using Chrome for Testing (CfT) endpoints to find out latest stable {} version", + driver_name + )); + + let versions_with_downloads = self + .request_versions_from_cft::( + self.create_latest_versions_url(), + )?; let stable_channel = versions_with_downloads.channels.stable; let chromedriver = stable_channel.downloads.chromedriver; if chromedriver.is_none() { @@ -218,33 +252,6 @@ impl ChromeManager { .join(self.get_platform_label()) .join(self.get_browser_version()) } - - fn request_latest_cft(&mut self) -> Result> { - let browser_name = self.browser_name; - self.get_logger().debug(format!( - "Using Chrome for Testing (CfT) endpoints to find out latest stable {} version", - browser_name - )); - let versions_with_downloads = self - .request_versions_from_cft::( - self.create_latest_versions_url(), - )?; - let stable_channel = versions_with_downloads.channels.stable; - let chrome = stable_channel.downloads.chrome; - let platform_url: Vec<&PlatformUrl> = chrome - .iter() - .filter(|p| p.platform.eq_ignore_ascii_case(self.get_platform_label())) - .collect(); - self.log.trace(format!( - "CfT URLs for downloading {}: {:?}", - self.get_browser_name(), - platform_url - )); - let browser_version = stable_channel.version; - self.download_url = Some(platform_url.first().unwrap().url.to_string()); - - Ok(browser_version) - } } impl SeleniumManager for ChromeManager { @@ -479,7 +486,7 @@ impl SeleniumManager for ChromeManager { self.set_browser_version(browser_version.clone()); } _ => { - browser_version = self.request_latest_cft()?; + browser_version = self.request_latest_browser_version_from_cft()?; self.set_browser_version(browser_version.clone()); let browser_ttl = self.get_browser_ttl(); if browser_ttl > 0 && !browser_version.is_empty() { @@ -514,7 +521,7 @@ impl SeleniumManager for ChromeManager { let download_url = if let Some(url) = self.download_url.clone() { url } else { - self.request_latest_cft()?; + self.request_latest_browser_version_from_cft()?; self.download_url.clone().unwrap() }; self.get_logger().debug(format!( From 5abd4a27012e7d1156878557d0caea24f1a2ef02 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Wed, 19 Jul 2023 16:24:30 +0200 Subject: [PATCH 04/11] [rust] Update checksum in cargo lock file --- rust/Cargo.Bazel.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/Cargo.Bazel.lock b/rust/Cargo.Bazel.lock index d75fc4293825d..da69ac1bc2c03 100644 --- a/rust/Cargo.Bazel.lock +++ b/rust/Cargo.Bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "e324d731a7a745741843d13e869e9d16f097a4e797b827d05d06dcbd0a5cb7b0", + "checksum": "0a20f0fe60fda64d9bb35f8a482f95239754a053b83e53e92d2a259eab911369", "crates": { "addr2line 0.19.0": { "name": "addr2line", From 7c5f46f5e5f95991b18738d18a792488a6a829d5 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Tue, 18 Jul 2023 14:55:18 +0200 Subject: [PATCH 05/11] [rust] Return browser path also when browser is local --- rust/README.md | 2 +- rust/src/chrome.rs | 74 +++++++++++++++++--------------------- rust/src/edge.rs | 72 ++++++++++++++++--------------------- rust/src/firefox.rs | 66 ++++++++++++++-------------------- rust/src/grid.rs | 14 ++++---- rust/src/iexplorer.rs | 14 ++++---- rust/src/lib.rs | 79 ++++++++++++++++++++++++++++++----------- rust/src/main.rs | 8 ++--- rust/src/safari.rs | 21 ++++++----- rust/src/safaritp.rs | 21 ++++++----- rust/tests/cli_tests.rs | 7 +++- 11 files changed, 194 insertions(+), 184 deletions(-) diff --git a/rust/README.md b/rust/README.md index 0e2e167176488..9b83ba1ee4ff9 100644 --- a/rust/README.md +++ b/rust/README.md @@ -32,7 +32,7 @@ Options: --browser-version Major browser version (e.g., 105, 106, etc. Also: beta, dev, canary -or nightly- is accepted) --browser-path - Browser path (absolute) for browser version detection (e.g., /usr/bin/google-chrome, "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome", "C:\Program Files\Google\Chrome\Application\chrome.exe") + Browser path (absolute) for browser version detection (e.g., /usr/bin/google-chrome, "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", "C:\Program Files\Google\Chrome\Application\chrome.exe") --output Output type: LOGGER (using INFO, WARN, etc.), JSON (custom JSON notation), or SHELL (Unix-like) [default: LOGGER] --proxy diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index e6b67f1178c43..141efaefc8f43 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -33,9 +33,8 @@ use crate::metadata::{ }; use crate::{ create_browser_metadata, create_http_client, download_to_tmp_folder, format_one_arg, - format_three_args, get_browser_version_from_metadata, uncompress, SeleniumManager, BETA, - DASH_DASH_VERSION, DEV, ENV_LOCALAPPDATA, ENV_PROGRAM_FILES, ENV_PROGRAM_FILES_X86, NIGHTLY, - OFFLINE_REQUEST_ERR_MSG, REG_QUERY, REMOVE_X86, STABLE, WMIC_COMMAND, WMIC_COMMAND_ENV, + get_browser_version_from_metadata, uncompress, SeleniumManager, BETA, DASH_DASH_VERSION, DEV, + NIGHTLY, REG_QUERY, STABLE, WMIC_COMMAND, }; pub const CHROME_NAME: &str = "chrome"; @@ -54,7 +53,7 @@ pub struct ChromeManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub downloaded_browser: Option, + pub resolved_browser_path: Option, pub download_url: Option, } @@ -72,7 +71,7 @@ impl ChromeManager { config, log: Logger::default(), download_url: None, - downloaded_browser: None, + resolved_browser_path: None, })) } @@ -271,65 +270,53 @@ impl SeleniumManager for ChromeManager { HashMap::from([ ( BrowserPath::new(WINDOWS, STABLE), - r#"\\Google\\Chrome\\Application\\chrome.exe"#, + r#"Google\Chrome\Application\chrome.exe"#, ), ( BrowserPath::new(WINDOWS, BETA), - r#"\\Google\\Chrome Beta\\Application\\chrome.exe"#, + r#"Google\Chrome Beta\Application\chrome.exe"#, ), ( BrowserPath::new(WINDOWS, DEV), - r#"\\Google\\Chrome Dev\\Application\\chrome.exe"#, + r#"Google\Chrome Dev\Application\chrome.exe"#, ), ( BrowserPath::new(WINDOWS, NIGHTLY), - r#"\\Google\\Chrome SxS\\Application\\chrome.exe"#, + r#"Google\Chrome SxS\Application\chrome.exe"#, ), ( BrowserPath::new(MACOS, STABLE), - r#"/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"#, + r#"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"#, ), ( BrowserPath::new(MACOS, BETA), - r#"/Applications/Google\ Chrome\ Beta.app/Contents/MacOS/Google\ Chrome\ Beta"#, + r#"/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta"#, ), ( BrowserPath::new(MACOS, DEV), - r#"/Applications/Google\ Chrome\ Dev.app/Contents/MacOS/Google\ Chrome\ Dev"#, + r#"/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev"#, ), ( BrowserPath::new(MACOS, NIGHTLY), - r#"/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary"#, + r#"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"#, + ), + (BrowserPath::new(LINUX, STABLE), "/usr/bin/google-chrome"), + (BrowserPath::new(LINUX, BETA), "/usr/bin/google-chrome-beta"), + ( + BrowserPath::new(LINUX, DEV), + "/usr/bin/google-chrome-unstable", ), - (BrowserPath::new(LINUX, STABLE), "google-chrome"), - (BrowserPath::new(LINUX, BETA), "google-chrome-beta"), - (BrowserPath::new(LINUX, DEV), "google-chrome-unstable"), ]) } - fn discover_browser_version(&self) -> Option { + fn discover_browser_version(&mut self) -> Option { let mut commands; - let escaped_browser_path = self.get_escaped_browser_path(); - let mut browser_path = escaped_browser_path.as_str(); + let mut browser_path = self.get_browser_path().to_string(); if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { - browser_path = path; - commands = vec![ - format_three_args( - WMIC_COMMAND_ENV, - ENV_PROGRAM_FILES, - REMOVE_X86, - browser_path, - ), - format_three_args( - WMIC_COMMAND_ENV, - ENV_PROGRAM_FILES_X86, - "", - browser_path, - ), - format_three_args(WMIC_COMMAND_ENV, ENV_LOCALAPPDATA, "", browser_path), - ]; + browser_path = self.get_escaped_path_buf(path); + commands = vec![format_one_arg(WMIC_COMMAND, &browser_path)]; if !self.is_browser_version_unstable() { commands.push(format_one_arg( REG_QUERY, @@ -340,10 +327,13 @@ impl SeleniumManager for ChromeManager { _ => return None, } } else { - commands = vec![format_one_arg(WMIC_COMMAND, browser_path)]; + commands = vec![format_one_arg( + WMIC_COMMAND, + &self.get_escaped_path(browser_path.to_string()), + )]; } if !WINDOWS.is(self.get_os()) { - commands = vec![format_one_arg(DASH_DASH_VERSION, browser_path)] + commands = vec![format_one_arg(DASH_DASH_VERSION, &browser_path)] } self.detect_browser_version(commands) } @@ -540,17 +530,17 @@ impl SeleniumManager for ChromeManager { None, )?; } - self.set_downloaded_browser(browser_path.clone()); + self.set_resolved_browser_path(browser_path.clone()); Ok(browser_path) } - fn get_downloaded_browser(&self) -> Option { - self.downloaded_browser.to_owned() + fn get_resolved_browser_path(&self) -> Option { + self.resolved_browser_path.to_owned() } - fn set_downloaded_browser(&mut self, downloaded_browser: Option) { - self.downloaded_browser = downloaded_browser; + fn set_resolved_browser_path(&mut self, browser_path: Option) { + self.resolved_browser_path = browser_path; } } diff --git a/rust/src/edge.rs b/rust/src/edge.rs index 0a77b0fa0c5ec..b0c37ac76ac99 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -29,9 +29,8 @@ use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, }; use crate::{ - create_http_client, format_one_arg, format_three_args, Logger, SeleniumManager, BETA, - DASH_DASH_VERSION, DEV, ENV_LOCALAPPDATA, ENV_PROGRAM_FILES, ENV_PROGRAM_FILES_X86, NIGHTLY, - OFFLINE_REQUEST_ERR_MSG, REG_QUERY, REMOVE_X86, STABLE, WMIC_COMMAND, WMIC_COMMAND_ENV, + create_http_client, format_one_arg, Logger, SeleniumManager, BETA, DASH_DASH_VERSION, DEV, + NIGHTLY, REG_QUERY, STABLE, WMIC_COMMAND, }; pub const EDGE_NAMES: &[&str] = &["edge", "msedge", "microsoftedge"]; @@ -46,7 +45,7 @@ pub struct EdgeManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub downloaded_browser: Option, + pub resolved_browser_path: Option, } impl EdgeManager { @@ -62,7 +61,7 @@ impl EdgeManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), - downloaded_browser: None, + resolved_browser_path: None, })) } } @@ -84,65 +83,53 @@ impl SeleniumManager for EdgeManager { HashMap::from([ ( BrowserPath::new(WINDOWS, STABLE), - r#"\\Microsoft\\Edge\\Application\\msedge.exe"#, + r#"Microsoft\Edge\Application\msedge.exe"#, ), ( BrowserPath::new(WINDOWS, BETA), - r#"\\Microsoft\\Edge Beta\\Application\\msedge.exe"#, + r#"Microsoft\Edge Beta\Application\msedge.exe"#, ), ( BrowserPath::new(WINDOWS, DEV), - r#"\\Microsoft\\Edge Dev\\Application\\msedge.exe"#, + r#"Microsoft\Edge Dev\Application\msedge.exe"#, ), ( BrowserPath::new(WINDOWS, NIGHTLY), - r#"\\Microsoft\\Edge SxS\\Application\\msedge.exe"#, + r#"Microsoft\Edge SxS\Application\msedge.exe"#, ), ( BrowserPath::new(MACOS, STABLE), - r#"/Applications/Microsoft\ Edge.app/Contents/MacOS/Microsoft\ Edge"#, + r#"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"#, ), ( BrowserPath::new(MACOS, BETA), - r#"/Applications/Microsoft\ Edge\ Beta.app/Contents/MacOS/Microsoft\ Edge\ Beta"#, + r#"/Applications/Microsoft Edge Beta.app/Contents/MacOS/Microsoft Edge Beta"#, ), ( BrowserPath::new(MACOS, DEV), - r#"/Applications/Microsoft\ Edge\ Dev.app/Contents/MacOS/Microsoft\ Edge\ Dev"#, + r#"/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev"#, ), ( BrowserPath::new(MACOS, NIGHTLY), - r#"/Applications/Microsoft\ Edge\ Canary.app/Contents/MacOS/Microsoft\ Edge\ Canary"#, + r#"/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary"#, ), - (BrowserPath::new(LINUX, STABLE), "microsoft-edge"), - (BrowserPath::new(LINUX, BETA), "microsoft-edge-beta"), - (BrowserPath::new(LINUX, DEV), "microsoft-edge-dev"), + (BrowserPath::new(LINUX, STABLE), "/usr/bin/microsoft-edge"), + ( + BrowserPath::new(LINUX, BETA), + "/usr/bin/microsoft-edge-beta", + ), + (BrowserPath::new(LINUX, DEV), "/usr/bin/microsoft-edge-dev"), ]) } - fn discover_browser_version(&self) -> Option { + fn discover_browser_version(&mut self) -> Option { let mut commands; - let escaped_browser_path = self.get_escaped_browser_path(); - let mut browser_path = escaped_browser_path.as_str(); + let mut browser_path = self.get_browser_path().to_string(); if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { - browser_path = path; - commands = vec![ - format_three_args( - WMIC_COMMAND_ENV, - ENV_PROGRAM_FILES_X86, - "", - browser_path, - ), - format_three_args( - WMIC_COMMAND_ENV, - ENV_PROGRAM_FILES, - REMOVE_X86, - browser_path, - ), - format_three_args(WMIC_COMMAND_ENV, ENV_LOCALAPPDATA, "", browser_path), - ]; + browser_path = self.get_escaped_path_buf(path); + commands = vec![format_one_arg(WMIC_COMMAND, &browser_path)]; if !self.is_browser_version_unstable() { commands.push(format_one_arg( REG_QUERY, @@ -153,10 +140,13 @@ impl SeleniumManager for EdgeManager { _ => return None, } } else { - commands = vec![format_one_arg(WMIC_COMMAND, browser_path)]; + commands = vec![format_one_arg( + WMIC_COMMAND, + &self.get_escaped_path(browser_path.to_string()), + )]; } if !WINDOWS.is(self.get_os()) { - commands = vec![format_one_arg(DASH_DASH_VERSION, browser_path)] + commands = vec![format_one_arg(DASH_DASH_VERSION, &browser_path)] } self.detect_browser_version(commands) } @@ -306,11 +296,11 @@ impl SeleniumManager for EdgeManager { Ok(None) } - fn get_downloaded_browser(&self) -> Option { - self.downloaded_browser.to_owned() + fn get_resolved_browser_path(&self) -> Option { + self.resolved_browser_path.to_owned() } - fn set_downloaded_browser(&mut self, downloaded_browser: Option) { - self.downloaded_browser = downloaded_browser; + fn set_resolved_browser_path(&mut self, browser_path: Option) { + self.resolved_browser_path = browser_path; } } diff --git a/rust/src/firefox.rs b/rust/src/firefox.rs index a22c3fdab1420..6eee7354bd711 100644 --- a/rust/src/firefox.rs +++ b/rust/src/firefox.rs @@ -29,9 +29,8 @@ use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, }; use crate::{ - create_http_client, format_one_arg, format_three_args, format_two_args, Logger, - SeleniumManager, BETA, DASH_VERSION, DEV, ENV_PROGRAM_FILES, ENV_PROGRAM_FILES_X86, NIGHTLY, - OFFLINE_REQUEST_ERR_MSG, REG_QUERY_FIND, REMOVE_X86, STABLE, WMIC_COMMAND, WMIC_COMMAND_ENV, + create_http_client, format_one_arg, format_two_args, Logger, SeleniumManager, BETA, + DASH_VERSION, DEV, NIGHTLY, REG_QUERY_FIND, STABLE, WMIC_COMMAND, }; pub const FIREFOX_NAME: &str = "firefox"; @@ -45,7 +44,7 @@ pub struct FirefoxManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub downloaded_browser: Option, + pub resolved_browser_path: Option, } impl FirefoxManager { @@ -61,7 +60,7 @@ impl FirefoxManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), - downloaded_browser: None, + resolved_browser_path: None, })) } } @@ -83,19 +82,19 @@ impl SeleniumManager for FirefoxManager { HashMap::from([ ( BrowserPath::new(WINDOWS, STABLE), - r#"\\Mozilla Firefox\\firefox.exe"#, + r#"Mozilla Firefox\firefox.exe"#, ), ( BrowserPath::new(WINDOWS, BETA), - r#"\\Mozilla Firefox\\firefox.exe"#, + r#"Mozilla Firefox\firefox.exe"#, ), ( BrowserPath::new(WINDOWS, DEV), - r#"\\Firefox Developer Edition\\firefox.exe"#, + r#"Firefox Developer Edition\firefox.exe"#, ), ( BrowserPath::new(WINDOWS, NIGHTLY), - r#"\\Firefox Nightly\\firefox.exe"#, + r#"Firefox Nightly\firefox.exe"#, ), ( BrowserPath::new(MACOS, STABLE), @@ -107,41 +106,27 @@ impl SeleniumManager for FirefoxManager { ), ( BrowserPath::new(MACOS, DEV), - r#"/Applications/Firefox\ Developer\ Edition.app/Contents/MacOS/firefox"#, + r#"/Applications/Firefox Developer Edition.app/Contents/MacOS/firefox"#, ), ( BrowserPath::new(MACOS, NIGHTLY), - r#"/Applications/Firefox\ Nightly.app/Contents/MacOS/firefox"#, + r#"/Applications/Firefox Nightly.app/Contents/MacOS/firefox"#, ), - (BrowserPath::new(LINUX, STABLE), "firefox"), - (BrowserPath::new(LINUX, BETA), "firefox"), - (BrowserPath::new(LINUX, DEV), "firefox"), - (BrowserPath::new(LINUX, NIGHTLY), "firefox-trunk"), + (BrowserPath::new(LINUX, STABLE), "/usr/bin/firefox"), + (BrowserPath::new(LINUX, BETA), "/usr/bin/firefox"), + (BrowserPath::new(LINUX, DEV), "/usr/bin/firefox"), + (BrowserPath::new(LINUX, NIGHTLY), "/usr/bin/firefox-trunk"), ]) } - fn discover_browser_version(&self) -> Option { + fn discover_browser_version(&mut self) -> Option { let mut commands; - let escaped_browser_path = self.get_escaped_browser_path(); - let mut browser_path = escaped_browser_path.as_str(); + let mut browser_path = self.get_browser_path().to_string(); if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { - browser_path = path; - commands = vec![ - format_three_args( - WMIC_COMMAND_ENV, - ENV_PROGRAM_FILES, - REMOVE_X86, - browser_path, - ), - format_three_args( - WMIC_COMMAND_ENV, - ENV_PROGRAM_FILES_X86, - "", - browser_path, - ), - ]; + browser_path = self.get_escaped_path_buf(path); + commands = vec![format_one_arg(WMIC_COMMAND, &browser_path)]; if !self.is_browser_version_unstable() { commands.push(format_two_args( REG_QUERY_FIND, @@ -153,10 +138,13 @@ impl SeleniumManager for FirefoxManager { _ => return None, } } else { - commands = vec![format_one_arg(WMIC_COMMAND, browser_path)]; + commands = vec![format_one_arg( + WMIC_COMMAND, + &self.get_escaped_path(browser_path.to_string()), + )]; } if !WINDOWS.is(self.get_os()) { - commands = vec![format_one_arg(DASH_VERSION, browser_path)] + commands = vec![format_one_arg(DASH_VERSION, &browser_path)] } self.detect_browser_version(commands) } @@ -297,12 +285,12 @@ impl SeleniumManager for FirefoxManager { Ok(None) } - fn get_downloaded_browser(&self) -> Option { - self.downloaded_browser.to_owned() + fn get_resolved_browser_path(&self) -> Option { + self.resolved_browser_path.to_owned() } - fn set_downloaded_browser(&mut self, downloaded_browser: Option) { - self.downloaded_browser = downloaded_browser; + fn set_resolved_browser_path(&mut self, browser_path: Option) { + self.resolved_browser_path = browser_path; } } diff --git a/rust/src/grid.rs b/rust/src/grid.rs index 8a44508274b49..d36d8fc2d92d1 100644 --- a/rust/src/grid.rs +++ b/rust/src/grid.rs @@ -47,7 +47,7 @@ pub struct GridManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub downloaded_browser: Option, + pub resolved_browser_path: Option, pub driver_url: Option, } @@ -66,7 +66,7 @@ impl GridManager { config, log: Logger::default(), driver_url: None, - downloaded_browser: None, + resolved_browser_path: None, })) } } @@ -88,7 +88,7 @@ impl SeleniumManager for GridManager { HashMap::new() } - fn discover_browser_version(&self) -> Option { + fn discover_browser_version(&mut self) -> Option { None } @@ -216,11 +216,11 @@ impl SeleniumManager for GridManager { Ok(None) } - fn get_downloaded_browser(&self) -> Option { - self.downloaded_browser.to_owned() + fn get_resolved_browser_path(&self) -> Option { + self.resolved_browser_path.to_owned() } - fn set_downloaded_browser(&mut self, downloaded_browser: Option) { - self.downloaded_browser = downloaded_browser; + fn set_resolved_browser_path(&mut self, browser_path: Option) { + self.resolved_browser_path = browser_path; } } diff --git a/rust/src/iexplorer.rs b/rust/src/iexplorer.rs index 874a229f5d7cf..95bea339bd0ef 100644 --- a/rust/src/iexplorer.rs +++ b/rust/src/iexplorer.rs @@ -49,7 +49,7 @@ pub struct IExplorerManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub downloaded_browser: Option, + pub resolved_browser_path: Option, pub driver_url: Option, } @@ -67,7 +67,7 @@ impl IExplorerManager { config, log: Logger::default(), driver_url: None, - downloaded_browser: None, + resolved_browser_path: None, })) } } @@ -89,7 +89,7 @@ impl SeleniumManager for IExplorerManager { HashMap::new() } - fn discover_browser_version(&self) -> Option { + fn discover_browser_version(&mut self) -> Option { None } @@ -212,11 +212,11 @@ impl SeleniumManager for IExplorerManager { Ok(None) } - fn get_downloaded_browser(&self) -> Option { - self.downloaded_browser.to_owned() + fn get_resolved_browser_path(&self) -> Option { + self.resolved_browser_path.to_owned() } - fn set_downloaded_browser(&mut self, downloaded_browser: Option) { - self.downloaded_browser = downloaded_browser; + fn set_resolved_browser_path(&mut self, browser_path: Option) { + self.resolved_browser_path = browser_path; } } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index e46b140923775..1854b517508fc 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -21,7 +21,7 @@ use crate::files::{compose_cache_folder, create_parent_path_if_not_exists, get_b use crate::firefox::{FirefoxManager, FIREFOX_NAME, GECKODRIVER_NAME}; use crate::iexplorer::{IExplorerManager, IEDRIVER_NAME, IE_NAMES}; use crate::safari::{SafariManager, SAFARIDRIVER_NAME, SAFARI_NAME}; -use std::fs; +use std::{env, fs}; use crate::config::OS::WINDOWS; use crate::config::{str_to_os, ManagerConfig}; @@ -61,8 +61,6 @@ pub const DEV: &str = "dev"; pub const CANARY: &str = "canary"; pub const NIGHTLY: &str = "nightly"; pub const WMIC_COMMAND: &str = r#"wmic datafile where name='{}' get Version /value"#; -pub const WMIC_COMMAND_ENV: &str = - r#"set PFILES=%{}{}%&& wmic datafile where name='!PFILES:\=\\!{}' get Version /value"#; pub const WMIC_COMMAND_OS: &str = r#"wmic os get osarchitecture"#; pub const REG_QUERY: &str = r#"REG QUERY {} /v version"#; pub const REG_QUERY_FIND: &str = r#"REG QUERY {} /f {}"#; @@ -73,7 +71,7 @@ pub const DASH_DASH_VERSION: &str = "{} --version"; pub const ENV_PROGRAM_FILES: &str = "PROGRAMFILES"; pub const ENV_PROGRAM_FILES_X86: &str = "PROGRAMFILES(X86)"; pub const ENV_LOCALAPPDATA: &str = "LOCALAPPDATA"; -pub const REMOVE_X86: &str = ": (x86)="; +pub const ENV_X86: &str = " (x86)"; pub const ARCH_X86: &str = "x86"; pub const ARCH_AMD64: &str = "amd64"; pub const ARCH_ARM64: &str = "arm64"; @@ -102,7 +100,7 @@ pub trait SeleniumManager { fn get_browser_path_map(&self) -> HashMap; - fn discover_browser_version(&self) -> Option; + fn discover_browser_version(&mut self) -> Option; fn get_driver_name(&self) -> &str; @@ -124,9 +122,9 @@ pub trait SeleniumManager { fn download_browser(&mut self) -> Result, Box>; - fn get_downloaded_browser(&self) -> Option; + fn get_resolved_browser_path(&self) -> Option; - fn set_downloaded_browser(&mut self, downloaded_browser: Option); + fn set_resolved_browser_path(&mut self, browser_path: Option); // ---------------------------------------------------------- // Shared functions @@ -155,16 +153,50 @@ pub trait SeleniumManager { } } - fn detect_browser_path(&self) -> Option<&str> { + fn detect_browser_path(&mut self) -> Option { let mut browser_version = self.get_browser_version(); if browser_version.eq_ignore_ascii_case(CANARY) { browser_version = NIGHTLY; } else if browser_version.is_empty() { browser_version = STABLE; } - self.get_browser_path_map() + let browser_path = self + .get_browser_path_map() .get(&BrowserPath::new(str_to_os(self.get_os()), browser_version)) .cloned() + .unwrap_or_default(); + + let mut full_browser_path = Path::new(browser_path).to_path_buf(); + if WINDOWS.is(self.get_os()) { + let envs = vec![ENV_PROGRAM_FILES, ENV_PROGRAM_FILES_X86, ENV_LOCALAPPDATA]; + + for env in envs { + let mut env_value = env::var(env).unwrap_or_default(); + if env.eq(ENV_PROGRAM_FILES) && env_value.contains(ENV_X86) { + // This special case is required to keep compliance between x32 and x64 + // architectures (since the selenium-manager in Windows is compiled as x32 binary) + env_value = env_value.replace(ENV_X86, ""); + } + let parent_path = Path::new(&env_value); + full_browser_path = parent_path.join(browser_path); + if full_browser_path.exists() { + break; + } + } + } + + if full_browser_path.exists() { + self.get_logger().debug(format!( + "{} detected at {}", + self.get_browser_name(), + full_browser_path.display() + )); + let browser_path = Some(full_browser_path); + self.set_resolved_browser_path(browser_path.clone()); + browser_path + } else { + None + } } fn detect_browser_version(&self, commands: Vec) -> Option { @@ -399,7 +431,7 @@ pub trait SeleniumManager { fn run_shell_command_with_log(&self, command: String) -> Result> { self.get_logger() - .debug(format!("Running command: {:?}", command)); + .debug(format!("Running command: {}", command)); let output = run_shell_command(self.get_os(), command)?; self.get_logger().debug(format!("Output: {:?}", output)); Ok(output) @@ -511,20 +543,27 @@ pub trait SeleniumManager { self.get_config().browser_path.as_str() } - fn get_escaped_browser_path(&self) -> String { - let mut browser_path = self.get_browser_path().to_string(); - let path = Path::new(&browser_path); - if path.exists() && WINDOWS.is(self.get_os()) { - browser_path = Path::new(path) + fn get_escaped_path(&self, string_path: String) -> String { + let mut escaped_path = string_path.clone(); + let path = Path::new(&string_path); + if path.exists() { + escaped_path = Path::new(path) .canonicalize() .unwrap() .to_str() .unwrap() - .to_string() - .replace("\\\\?\\", "") - .replace('\\', "\\\\"); + .to_string(); + if WINDOWS.is(self.get_os()) { + escaped_path = escaped_path.replace("\\\\?\\", "").replace('\\', "\\\\"); + } else { + escaped_path = escaped_path.replace(' ', "\\ "); + } } - browser_path + escaped_path + } + + fn get_escaped_path_buf(&self, path_buf: PathBuf) -> String { + self.get_escaped_path(path_buf.into_os_string().into_string().unwrap_or_default()) } fn set_browser_path(&mut self, browser_path: String) { @@ -681,7 +720,7 @@ pub fn create_http_client(timeout: u64, proxy: &str) -> Result Result> { let (shell, flag) = if WINDOWS.is(os) { - ("cmd", "/v/c") + ("cmd", "/c") } else { ("sh", "-c") }; diff --git a/rust/src/main.rs b/rust/src/main.rs index 34c125b2f36a2..45ff6eb88fb7b 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -62,7 +62,7 @@ struct Cli { browser_version: Option, /// Browser path (absolute) for browser version detection (e.g., /usr/bin/google-chrome, - /// "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome", + /// "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", /// "C:\Program Files\Google\Chrome\Application\chrome.exe") #[clap(long, value_parser)] browser_path: Option, @@ -166,12 +166,12 @@ fn main() { .map(|path| { let log = selenium_manager.get_logger(); log.info(format!("{}{}", DRIVER_PATH, path.display())); - let downloaded_browser = selenium_manager.get_downloaded_browser(); - if downloaded_browser.is_some() { + let resolved_browser_path = selenium_manager.get_resolved_browser_path(); + if resolved_browser_path.is_some() { log.info(format!( "{}{}", BROWSER_PATH, - downloaded_browser.unwrap().display() + resolved_browser_path.unwrap().display() )); } flush_and_exit(OK, log); diff --git a/rust/src/safari.rs b/rust/src/safari.rs index ff2780df2dde6..5943e0498ed1c 100644 --- a/rust/src/safari.rs +++ b/rust/src/safari.rs @@ -36,7 +36,7 @@ pub struct SafariManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub downloaded_browser: Option, + pub resolved_browser_path: Option, } impl SafariManager { @@ -52,7 +52,7 @@ impl SafariManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), - downloaded_browser: None, + resolved_browser_path: None, })) } } @@ -77,19 +77,18 @@ impl SeleniumManager for SafariManager { )]) } - fn discover_browser_version(&self) -> Option { - let escaped_browser_path = self.get_escaped_browser_path(); - let mut browser_path = escaped_browser_path.as_str(); + fn discover_browser_version(&mut self) -> Option { + let mut browser_path = self.get_browser_path().to_string(); if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { - browser_path = path; + browser_path = self.get_escaped_path_buf(path); } _ => return None, } } let command = if MACOS.is(self.get_os()) { - vec![format_one_arg(PLIST_COMMAND, browser_path)] + vec![format_one_arg(PLIST_COMMAND, &browser_path)] } else { return None; }; @@ -136,11 +135,11 @@ impl SeleniumManager for SafariManager { Ok(None) } - fn get_downloaded_browser(&self) -> Option { - self.downloaded_browser.to_owned() + fn get_resolved_browser_path(&self) -> Option { + self.resolved_browser_path.to_owned() } - fn set_downloaded_browser(&mut self, downloaded_browser: Option) { - self.downloaded_browser = downloaded_browser; + fn set_resolved_browser_path(&mut self, browser_path: Option) { + self.resolved_browser_path = browser_path; } } diff --git a/rust/src/safaritp.rs b/rust/src/safaritp.rs index a5fb7dc78478d..cebe2c93aba07 100644 --- a/rust/src/safaritp.rs +++ b/rust/src/safaritp.rs @@ -41,7 +41,7 @@ pub struct SafariTPManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub downloaded_browser: Option, + pub resolved_browser_path: Option, } impl SafariTPManager { @@ -57,7 +57,7 @@ impl SafariTPManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), - downloaded_browser: None, + resolved_browser_path: None, })) } } @@ -82,19 +82,18 @@ impl SeleniumManager for SafariTPManager { )]) } - fn discover_browser_version(&self) -> Option { - let escaped_browser_path = self.get_escaped_browser_path(); - let mut browser_path = escaped_browser_path.as_str(); + fn discover_browser_version(&mut self) -> Option { + let mut browser_path = self.get_browser_path().to_string(); if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { - browser_path = path; + browser_path = self.get_escaped_path_buf(path); } _ => return None, } } let command = if MACOS.is(self.get_os()) { - vec![format_one_arg(PLIST_COMMAND, browser_path)] + vec![format_one_arg(PLIST_COMMAND, &browser_path)] } else { return None; }; @@ -141,11 +140,11 @@ impl SeleniumManager for SafariTPManager { Ok(None) } - fn get_downloaded_browser(&self) -> Option { - self.downloaded_browser.to_owned() + fn get_resolved_browser_path(&self) -> Option { + self.resolved_browser_path.to_owned() } - fn set_downloaded_browser(&mut self, downloaded_browser: Option) { - self.downloaded_browser = downloaded_browser; + fn set_resolved_browser_path(&mut self, browser_path: Option) { + self.resolved_browser_path = browser_path; } } diff --git a/rust/tests/cli_tests.rs b/rust/tests/cli_tests.rs index c2bd4f2cc96f5..a0d1385deecec 100644 --- a/rust/tests/cli_tests.rs +++ b/rust/tests/cli_tests.rs @@ -147,6 +147,11 @@ fn beta_test(#[case] browser: String, #[case] driver_name: String) { "chrome", r#"/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"# )] +#[case( + "macos", + "chrome", + r#"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"# +)] fn path_test(#[case] os: String, #[case] browser: String, #[case] browser_path: String) { println!( "Path test browser={} -- browser_path={}", @@ -162,7 +167,7 @@ fn path_test(#[case] os: String, #[case] browser: String, #[case] browser_path: if OS.eq(&os) { let stdout = &cmd.unwrap().stdout; let output = str::from_utf8(stdout).unwrap(); - println!("output {:?}", output); + println!("{}", output); assert!(!output.contains("WARN")); } } From a0084904efcd4885f1406c1f5ca0e532cd8973f9 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Wed, 19 Jul 2023 12:21:39 +0200 Subject: [PATCH 06/11] [rust] Check browser in PATH --- rust/src/chrome.rs | 2 +- rust/src/edge.rs | 2 +- rust/src/firefox.rs | 2 +- rust/src/lib.rs | 95 +++++++++++++++++++++++++++++++-------------- 4 files changed, 69 insertions(+), 32 deletions(-) diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index 141efaefc8f43..301253d94e47c 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -34,7 +34,7 @@ use crate::metadata::{ use crate::{ create_browser_metadata, create_http_client, download_to_tmp_folder, format_one_arg, get_browser_version_from_metadata, uncompress, SeleniumManager, BETA, DASH_DASH_VERSION, DEV, - NIGHTLY, REG_QUERY, STABLE, WMIC_COMMAND, + NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY, STABLE, WMIC_COMMAND, }; pub const CHROME_NAME: &str = "chrome"; diff --git a/rust/src/edge.rs b/rust/src/edge.rs index b0c37ac76ac99..cf0437881ebbb 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -30,7 +30,7 @@ use crate::metadata::{ }; use crate::{ create_http_client, format_one_arg, Logger, SeleniumManager, BETA, DASH_DASH_VERSION, DEV, - NIGHTLY, REG_QUERY, STABLE, WMIC_COMMAND, + NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY, STABLE, WMIC_COMMAND, }; pub const EDGE_NAMES: &[&str] = &["edge", "msedge", "microsoftedge"]; diff --git a/rust/src/firefox.rs b/rust/src/firefox.rs index 6eee7354bd711..1f29f60ac6119 100644 --- a/rust/src/firefox.rs +++ b/rust/src/firefox.rs @@ -30,7 +30,7 @@ use crate::metadata::{ }; use crate::{ create_http_client, format_one_arg, format_two_args, Logger, SeleniumManager, BETA, - DASH_VERSION, DEV, NIGHTLY, REG_QUERY_FIND, STABLE, WMIC_COMMAND, + DASH_VERSION, DEV, NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY_FIND, STABLE, WMIC_COMMAND, }; pub const FIREFOX_NAME: &str = "firefox"; diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 1854b517508fc..a7c2207536d9a 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -195,7 +195,22 @@ pub trait SeleniumManager { self.set_resolved_browser_path(browser_path.clone()); browser_path } else { - None + // Check browser in PATH + let browser_name = self.get_browser_name(); + self.get_logger() + .debug(format!("Checking {} in PATH", browser_name)); + let browser_in_path = self.find_browser_in_path(); + if let Some(path) = &browser_in_path { + self.get_logger().debug(format!( + "Found {} in PATH: {}", + browser_name, + path.display() + )); + } else { + self.get_logger() + .debug(format!("{} not found in PATH", browser_name)); + } + browser_in_path } } @@ -253,7 +268,7 @@ pub trait SeleniumManager { let browser_path = self.download_browser()?; if browser_path.is_some() { self.get_logger().debug(format!( - "{} {} downloaded to {}", + "{} {} has been downloaded at {}", self.get_browser_name(), self.get_browser_version(), browser_path.unwrap().display() @@ -286,6 +301,14 @@ pub trait SeleniumManager { } } + fn find_browser_in_path(&self) -> Option { + let browser_path = self.execute_which_in_shell(self.get_browser_name()); + if let Some(path) = browser_path { + return Some(Path::new(&path).to_path_buf()); + } + None + } + fn find_driver_in_path(&self) -> (Option, Option) { match self .run_shell_command_with_log(format_one_arg(DASH_DASH_VERSION, self.get_driver_name())) @@ -293,33 +316,7 @@ pub trait SeleniumManager { Ok(output) => { let parsed_version = parse_version(output, self.get_logger()).unwrap_or_default(); if !parsed_version.is_empty() { - let which_command = if WINDOWS.is(self.get_os()) { - WHERE_COMMAND - } else { - WHICH_COMMAND - }; - let driver_path = match self.run_shell_command_with_log(format_one_arg( - which_command, - self.get_driver_name(), - )) { - Ok(path) => { - let path_vector = split_lines(path.as_str()); - if path_vector.len() == 1 { - Some(path_vector.first().unwrap().to_string()) - } else { - let exec_paths: Vec<&str> = path_vector - .into_iter() - .filter(|p| Path::new(p).is_executable()) - .collect(); - if exec_paths.is_empty() { - None - } else { - Some(exec_paths.first().unwrap().to_string()) - } - } - } - Err(_) => None, - }; + let driver_path = self.execute_which_in_shell(self.get_driver_name()); return (Some(parsed_version), driver_path); } (None, None) @@ -328,6 +325,46 @@ pub trait SeleniumManager { } } + fn execute_which_in_shell(&self, command: &str) -> Option { + let which_command = if WINDOWS.is(self.get_os()) { + WHERE_COMMAND + } else { + WHICH_COMMAND + }; + let path = match self.run_shell_command_with_log(format_one_arg(which_command, command)) { + Ok(path) => { + let path_vector = split_lines(path.as_str()); + if path_vector.len() == 1 { + self.get_first_in_vector(path_vector) + } else { + let exec_paths: Vec<&str> = path_vector + .into_iter() + .filter(|p| Path::new(p).is_executable()) + .collect(); + if exec_paths.is_empty() { + None + } else { + self.get_first_in_vector(exec_paths) + } + } + } + Err(_) => None, + }; + path + } + + fn get_first_in_vector(&self, vector: Vec<&str>) -> Option { + if vector.is_empty() { + return None; + } + let first = vector.first().unwrap().to_string(); + if first.is_empty() { + None + } else { + Some(first) + } + } + fn is_safari(&self) -> bool { self.get_browser_name().contains(SAFARI_NAME) } From 03d0dacf53a3cdf3ef857a344500fddac705447a Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Fri, 21 Jul 2023 15:42:01 +0200 Subject: [PATCH 07/11] [rust] Set default TTL_browsers to 3600s (1 hour), like new TTL_drivers --- rust/README.md | 2 +- rust/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/README.md b/rust/README.md index 9b83ba1ee4ff9..0c30b25ad866c 100644 --- a/rust/README.md +++ b/rust/README.md @@ -42,7 +42,7 @@ Options: --driver-ttl Driver TTL (time-to-live) [default: 3600] --browser-ttl - Browser TTL (time-to-live) [default: 86400] + Browser TTL (time-to-live) [default: 3600] --clear-cache Clear cache folder (~/.cache/selenium) --clear-metadata diff --git a/rust/src/lib.rs b/rust/src/lib.rs index a7c2207536d9a..aaea7611319be 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -78,7 +78,7 @@ pub const ARCH_ARM64: &str = "arm64"; pub const ENV_PROCESSOR_ARCHITECTURE: &str = "PROCESSOR_ARCHITECTURE"; pub const WHERE_COMMAND: &str = "where {}"; pub const WHICH_COMMAND: &str = "which {}"; -pub const TTL_BROWSERS_SEC: u64 = 86400; +pub const TTL_BROWSERS_SEC: u64 = 3600; pub const TTL_DRIVERS_SEC: u64 = 3600; pub const UNAME_COMMAND: &str = "uname -{}"; pub const CRLF: &str = "\r\n"; From f17b9e7b26023eca5882ccd3eb0bc2115d708c74 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Sat, 22 Jul 2023 10:12:27 +0200 Subject: [PATCH 08/11] [rust] Improve error handling for unavailable driver --- rust/src/files.rs | 9 +++++++++ rust/src/main.rs | 10 ++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/rust/src/files.rs b/rust/src/files.rs index 6999cf5e6b247..18ae04ab70320 100644 --- a/rust/src/files.rs +++ b/rust/src/files.rs @@ -123,6 +123,7 @@ pub fn unzip( log.trace(format!("Unzipping file to {}", target.display())); let mut out_path = target.to_path_buf(); let mut archive = ZipArchive::new(file)?; + let mut unzipped_files = 0; for i in 0..archive.len() { let mut file = archive.by_index(i)?; @@ -151,6 +152,7 @@ pub fn unzip( let mut outfile = File::create(&out_path)?; io::copy(&mut file, &mut outfile)?; + unzipped_files += 1; // Set permissions in Unix-like systems #[cfg(unix)] @@ -165,6 +167,13 @@ pub fn unzip( } } } + if unzipped_files == 0 || (single_file.is_some() && unzipped_files != 1) { + return Err(format!( + "Problem uncompressing zip ({} files extracted)", + unzipped_files + ) + .into()); + } Ok(()) } diff --git a/rust/src/main.rs b/rust/src/main.rs index 45ff6eb88fb7b..3198cb0c4957d 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -21,6 +21,7 @@ use clap::Parser; use exitcode::DATAERR; use exitcode::OK; +use exitcode::UNAVAILABLE; use selenium_manager::config::BooleanKey; use selenium_manager::grid::GridManager; use selenium_manager::logger::{Logger, BROWSER_PATH, DRIVER_PATH}; @@ -163,9 +164,14 @@ fn main() { .set_timeout(cli.timeout) .and_then(|_| selenium_manager.set_proxy(cli.proxy.unwrap_or_default())) .and_then(|_| selenium_manager.resolve_driver()) - .map(|path| { + .map(|driver_path| { let log = selenium_manager.get_logger(); - log.info(format!("{}{}", DRIVER_PATH, path.display())); + if driver_path.exists() { + log.info(format!("{}{}", DRIVER_PATH, driver_path.display())); + } else { + log.error(format!("Driver unavailable: {}", DRIVER_PATH)); + flush_and_exit(UNAVAILABLE, log); + } let resolved_browser_path = selenium_manager.get_resolved_browser_path(); if resolved_browser_path.is_some() { log.info(format!( From 48835df32f1d3995b6ce7a8e914855cce39cf030 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Sun, 23 Jul 2023 11:04:37 +0200 Subject: [PATCH 09/11] [rust] Force operating system to Windows in for IExplorer --- rust/src/iexplorer.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rust/src/iexplorer.rs b/rust/src/iexplorer.rs index 95bea339bd0ef..ea6f2d79cf15d 100644 --- a/rust/src/iexplorer.rs +++ b/rust/src/iexplorer.rs @@ -24,7 +24,7 @@ use std::path::PathBuf; use crate::files::{compose_driver_path_in_cache, BrowserPath}; use crate::downloads::parse_json_from_url; -use crate::{create_http_client, parse_version, Logger, SeleniumManager, OFFLINE_REQUEST_ERR_MSG}; +use crate::{create_http_client, parse_version, Logger, SeleniumManager, OFFLINE_REQUEST_ERR_MSG, WINDOWS}; use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, @@ -57,9 +57,10 @@ impl IExplorerManager { pub fn new() -> Result, Box> { let browser_name = IE_NAMES[0]; let driver_name = IEDRIVER_NAME; - let config = ManagerConfig::default(browser_name, driver_name); + let mut config = ManagerConfig::default(browser_name, driver_name); let default_timeout = config.timeout.to_owned(); let default_proxy = &config.proxy; + config.os = WINDOWS.to_str().to_string(); Ok(Box::new(IExplorerManager { browser_name, driver_name, From fb9933ed28c4dc8b9fc6320369cd0158fe1235a4 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Sun, 23 Jul 2023 13:16:13 +0200 Subject: [PATCH 10/11] [rust] Improve path escaping in Linux and macOS for browser discovery --- rust/src/chrome.rs | 21 +++++++++++++------ rust/src/config.rs | 8 +++---- rust/src/edge.rs | 19 +++++++++++------ rust/src/files.rs | 4 ++++ rust/src/firefox.rs | 19 +++++++++++------ rust/src/iexplorer.rs | 4 +++- rust/src/lib.rs | 49 +++++++++++++++++++++++++++++-------------- rust/src/safari.rs | 4 ++-- rust/src/safaritp.rs | 4 ++-- 9 files changed, 89 insertions(+), 43 deletions(-) diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index 301253d94e47c..789863c20e889 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -26,15 +26,18 @@ use std::path::PathBuf; use crate::config::ARCH::{ARM64, X32}; use crate::config::OS::{LINUX, MACOS, WINDOWS}; use crate::downloads::{parse_json_from_url, read_version_from_link}; -use crate::files::{compose_driver_path_in_cache, get_cache_folder, BrowserPath}; +use crate::files::{ + compose_driver_path_in_cache, get_cache_folder, path_buf_to_string, BrowserPath, +}; use crate::logger::Logger; use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, }; use crate::{ create_browser_metadata, create_http_client, download_to_tmp_folder, format_one_arg, - get_browser_version_from_metadata, uncompress, SeleniumManager, BETA, DASH_DASH_VERSION, DEV, - NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY, STABLE, WMIC_COMMAND, + format_three_args, get_browser_version_from_metadata, uncompress, SeleniumManager, BETA, + DASH_DASH_VERSION, DEV, DOUBLE_QUOTE, NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY, + SINGLE_QUOTE, STABLE, WMIC_COMMAND, }; pub const CHROME_NAME: &str = "chrome"; @@ -312,11 +315,13 @@ impl SeleniumManager for ChromeManager { fn discover_browser_version(&mut self) -> Option { let mut commands; let mut browser_path = self.get_browser_path().to_string(); + let mut escaped_browser_path = self.get_browser_path().to_string(); if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { - browser_path = self.get_escaped_path_buf(path); - commands = vec![format_one_arg(WMIC_COMMAND, &browser_path)]; + browser_path = path_buf_to_string(path); + escaped_browser_path = self.get_escaped_path(browser_path.to_string()); + commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; if !self.is_browser_version_unstable() { commands.push(format_one_arg( REG_QUERY, @@ -333,7 +338,11 @@ impl SeleniumManager for ChromeManager { )]; } if !WINDOWS.is(self.get_os()) { - commands = vec![format_one_arg(DASH_DASH_VERSION, &browser_path)] + commands = vec![ + format_three_args(DASH_DASH_VERSION, "", &escaped_browser_path, ""), + format_three_args(DASH_DASH_VERSION, DOUBLE_QUOTE, &browser_path, DOUBLE_QUOTE), + format_three_args(DASH_DASH_VERSION, SINGLE_QUOTE, &browser_path, SINGLE_QUOTE), + ] } self.detect_browser_version(commands) } diff --git a/rust/src/config.rs b/rust/src/config.rs index 7f74661199934..bb1662a912dea 100644 --- a/rust/src/config.rs +++ b/rust/src/config.rs @@ -17,7 +17,7 @@ use crate::config::OS::{LINUX, MACOS, WINDOWS}; use crate::files::get_cache_folder; -use crate::{format_one_arg, run_shell_command, REQUEST_TIMEOUT_SEC, UNAME_COMMAND}; +use crate::{format_one_arg, run_shell_command_by_os, REQUEST_TIMEOUT_SEC, UNAME_COMMAND}; use crate::{ARCH_AMD64, ARCH_ARM64, ARCH_X86, TTL_BROWSERS_SEC, TTL_DRIVERS_SEC, WMIC_COMMAND_OS}; use std::env; use std::env::consts::OS; @@ -50,7 +50,7 @@ impl ManagerConfig { let self_os = OS; let self_arch = if WINDOWS.is(self_os) { let wmic_output = - run_shell_command(self_os, WMIC_COMMAND_OS.to_string()).unwrap_or_default(); + run_shell_command_by_os(self_os, WMIC_COMMAND_OS.to_string()).unwrap_or_default(); if wmic_output.contains("32") { ARCH_X86.to_string() } else if wmic_output.contains("ARM") { @@ -60,7 +60,7 @@ impl ManagerConfig { } } else { let uname_a = format_one_arg(UNAME_COMMAND, "a"); - if run_shell_command(self_os, uname_a) + if run_shell_command_by_os(self_os, uname_a) .unwrap_or_default() .to_ascii_lowercase() .contains(ARCH_ARM64) @@ -68,7 +68,7 @@ impl ManagerConfig { ARCH_ARM64.to_string() } else { let uname_m = format_one_arg(UNAME_COMMAND, "m"); - run_shell_command(self_os, uname_m).unwrap_or_default() + run_shell_command_by_os(self_os, uname_m).unwrap_or_default() } }; diff --git a/rust/src/edge.rs b/rust/src/edge.rs index cf0437881ebbb..38e2205462ec4 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -24,13 +24,14 @@ use std::path::PathBuf; use crate::config::ARCH::{ARM64, X32}; use crate::config::OS::{LINUX, MACOS, WINDOWS}; use crate::downloads::read_version_from_link; -use crate::files::{compose_driver_path_in_cache, BrowserPath}; +use crate::files::{compose_driver_path_in_cache, path_buf_to_string, BrowserPath}; use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, }; use crate::{ - create_http_client, format_one_arg, Logger, SeleniumManager, BETA, DASH_DASH_VERSION, DEV, - NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY, STABLE, WMIC_COMMAND, + create_http_client, format_one_arg, format_three_args, Logger, SeleniumManager, BETA, + DASH_DASH_VERSION, DEV, DOUBLE_QUOTE, NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY, + SINGLE_QUOTE, STABLE, WMIC_COMMAND, }; pub const EDGE_NAMES: &[&str] = &["edge", "msedge", "microsoftedge"]; @@ -125,11 +126,13 @@ impl SeleniumManager for EdgeManager { fn discover_browser_version(&mut self) -> Option { let mut commands; let mut browser_path = self.get_browser_path().to_string(); + let mut escaped_browser_path = self.get_browser_path().to_string(); if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { - browser_path = self.get_escaped_path_buf(path); - commands = vec![format_one_arg(WMIC_COMMAND, &browser_path)]; + browser_path = path_buf_to_string(path); + escaped_browser_path = self.get_escaped_path(browser_path.to_string()); + commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; if !self.is_browser_version_unstable() { commands.push(format_one_arg( REG_QUERY, @@ -146,7 +149,11 @@ impl SeleniumManager for EdgeManager { )]; } if !WINDOWS.is(self.get_os()) { - commands = vec![format_one_arg(DASH_DASH_VERSION, &browser_path)] + commands = vec![ + format_three_args(DASH_DASH_VERSION, "", &escaped_browser_path, ""), + format_three_args(DASH_DASH_VERSION, DOUBLE_QUOTE, &browser_path, DOUBLE_QUOTE), + format_three_args(DASH_DASH_VERSION, SINGLE_QUOTE, &browser_path, SINGLE_QUOTE), + ] } self.detect_browser_version(commands) } diff --git a/rust/src/files.rs b/rust/src/files.rs index 18ae04ab70320..28a359af6f865 100644 --- a/rust/src/files.rs +++ b/rust/src/files.rs @@ -244,3 +244,7 @@ pub fn parse_version(version_text: String, log: &Logger) -> Result String { + path_buf.into_os_string().into_string().unwrap_or_default() +} diff --git a/rust/src/firefox.rs b/rust/src/firefox.rs index 1f29f60ac6119..90833c2635f8f 100644 --- a/rust/src/firefox.rs +++ b/rust/src/firefox.rs @@ -24,13 +24,14 @@ use std::path::PathBuf; use crate::config::ARCH::{ARM64, X32}; use crate::config::OS::{LINUX, MACOS, WINDOWS}; use crate::downloads::read_redirect_from_link; -use crate::files::{compose_driver_path_in_cache, BrowserPath}; +use crate::files::{compose_driver_path_in_cache, path_buf_to_string, BrowserPath}; use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, }; use crate::{ - create_http_client, format_one_arg, format_two_args, Logger, SeleniumManager, BETA, - DASH_VERSION, DEV, NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY_FIND, STABLE, WMIC_COMMAND, + create_http_client, format_one_arg, format_three_args, format_two_args, Logger, + SeleniumManager, BETA, DASH_VERSION, DEV, DOUBLE_QUOTE, NIGHTLY, OFFLINE_REQUEST_ERR_MSG, + REG_QUERY_FIND, SINGLE_QUOTE, STABLE, WMIC_COMMAND, }; pub const FIREFOX_NAME: &str = "firefox"; @@ -122,11 +123,13 @@ impl SeleniumManager for FirefoxManager { fn discover_browser_version(&mut self) -> Option { let mut commands; let mut browser_path = self.get_browser_path().to_string(); + let mut escaped_browser_path = self.get_browser_path().to_string(); if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { - browser_path = self.get_escaped_path_buf(path); - commands = vec![format_one_arg(WMIC_COMMAND, &browser_path)]; + browser_path = path_buf_to_string(path); + escaped_browser_path = self.get_escaped_path(browser_path.to_string()); + commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; if !self.is_browser_version_unstable() { commands.push(format_two_args( REG_QUERY_FIND, @@ -144,7 +147,11 @@ impl SeleniumManager for FirefoxManager { )]; } if !WINDOWS.is(self.get_os()) { - commands = vec![format_one_arg(DASH_VERSION, &browser_path)] + commands = vec![ + format_three_args(DASH_VERSION, "", &escaped_browser_path, ""), + format_three_args(DASH_VERSION, DOUBLE_QUOTE, &browser_path, DOUBLE_QUOTE), + format_three_args(DASH_VERSION, SINGLE_QUOTE, &browser_path, SINGLE_QUOTE), + ] } self.detect_browser_version(commands) } diff --git a/rust/src/iexplorer.rs b/rust/src/iexplorer.rs index ea6f2d79cf15d..0ed9ba574c3be 100644 --- a/rust/src/iexplorer.rs +++ b/rust/src/iexplorer.rs @@ -24,7 +24,9 @@ use std::path::PathBuf; use crate::files::{compose_driver_path_in_cache, BrowserPath}; use crate::downloads::parse_json_from_url; -use crate::{create_http_client, parse_version, Logger, SeleniumManager, OFFLINE_REQUEST_ERR_MSG, WINDOWS}; +use crate::{ + create_http_client, parse_version, Logger, SeleniumManager, OFFLINE_REQUEST_ERR_MSG, WINDOWS, +}; use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, diff --git a/rust/src/lib.rs b/rust/src/lib.rs index aaea7611319be..d8f5c1561735a 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -66,8 +66,10 @@ pub const REG_QUERY: &str = r#"REG QUERY {} /v version"#; pub const REG_QUERY_FIND: &str = r#"REG QUERY {} /f {}"#; pub const PLIST_COMMAND: &str = r#"/usr/libexec/PlistBuddy -c "print :CFBundleShortVersionString" {}/Contents/Info.plist"#; -pub const DASH_VERSION: &str = "{} -v"; -pub const DASH_DASH_VERSION: &str = "{} --version"; +pub const DASH_VERSION: &str = "{}{}{} -v"; +pub const DASH_DASH_VERSION: &str = "{}{}{} --version"; +pub const DOUBLE_QUOTE: &str = "\""; +pub const SINGLE_QUOTE: &str = "'"; pub const ENV_PROGRAM_FILES: &str = "PROGRAMFILES"; pub const ENV_PROGRAM_FILES_X86: &str = "PROGRAMFILES(X86)"; pub const ENV_LOCALAPPDATA: &str = "LOCALAPPDATA"; @@ -81,6 +83,7 @@ pub const WHICH_COMMAND: &str = "which {}"; pub const TTL_BROWSERS_SEC: u64 = 3600; pub const TTL_DRIVERS_SEC: u64 = 3600; pub const UNAME_COMMAND: &str = "uname -{}"; +pub const ESCAPE_COMMAND: &str = "printf %q \"{}\""; pub const CRLF: &str = "\r\n"; pub const LF: &str = "\n"; pub const SNAPSHOT: &str = "SNAPSHOT"; @@ -469,7 +472,7 @@ pub trait SeleniumManager { fn run_shell_command_with_log(&self, command: String) -> Result> { self.get_logger() .debug(format!("Running command: {}", command)); - let output = run_shell_command(self.get_os(), command)?; + let output = run_shell_command_by_os(self.get_os(), command)?; self.get_logger().debug(format!("Output: {:?}", output)); Ok(output) } @@ -581,8 +584,9 @@ pub trait SeleniumManager { } fn get_escaped_path(&self, string_path: String) -> String { - let mut escaped_path = string_path.clone(); - let path = Path::new(&string_path); + let original_path = string_path.clone(); + let mut escaped_path = string_path; + let path = Path::new(&original_path); if path.exists() { escaped_path = Path::new(path) .canonicalize() @@ -593,16 +597,21 @@ pub trait SeleniumManager { if WINDOWS.is(self.get_os()) { escaped_path = escaped_path.replace("\\\\?\\", "").replace('\\', "\\\\"); } else { - escaped_path = escaped_path.replace(' ', "\\ "); + escaped_path = run_shell_command( + "bash", + "-c", + format_one_arg(ESCAPE_COMMAND, escaped_path.as_str()), + ) + .unwrap_or_default(); } } + self.get_logger().trace(format!( + "Original path: {} - Escaped path: {}", + original_path, escaped_path + )); escaped_path } - fn get_escaped_path_buf(&self, path_buf: PathBuf) -> String { - self.get_escaped_path(path_buf.into_os_string().into_string().unwrap_or_default()) - } - fn set_browser_path(&mut self, browser_path: String) { if !browser_path.is_empty() { self.get_config_mut().browser_path = browser_path; @@ -755,12 +764,11 @@ pub fn create_http_client(timeout: u64, proxy: &str) -> Result Result> { - let (shell, flag) = if WINDOWS.is(os) { - ("cmd", "/c") - } else { - ("sh", "-c") - }; +pub fn run_shell_command( + shell: &str, + flag: &str, + command: String, +) -> Result> { let output = Command::new(shell) .args([flag, command.as_str()]) .output()?; @@ -770,6 +778,15 @@ pub fn run_shell_command(os: &str, command: String) -> Result Result> { + let (shell, flag) = if WINDOWS.is(os) { + ("cmd", "/c") + } else { + ("sh", "-c") + }; + run_shell_command(shell, flag, command) +} + pub fn format_one_arg(string: &str, arg1: &str) -> String { string.replacen("{}", arg1, 1) } diff --git a/rust/src/safari.rs b/rust/src/safari.rs index 5943e0498ed1c..9b83bd0ec54e8 100644 --- a/rust/src/safari.rs +++ b/rust/src/safari.rs @@ -22,7 +22,7 @@ use std::error::Error; use std::path::PathBuf; use std::string::ToString; -use crate::files::BrowserPath; +use crate::files::{path_buf_to_string, BrowserPath}; use crate::config::OS::MACOS; use crate::{create_http_client, format_one_arg, Logger, SeleniumManager, PLIST_COMMAND, STABLE}; @@ -82,7 +82,7 @@ impl SeleniumManager for SafariManager { if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { - browser_path = self.get_escaped_path_buf(path); + browser_path = self.get_escaped_path(path_buf_to_string(path)); } _ => return None, } diff --git a/rust/src/safaritp.rs b/rust/src/safaritp.rs index cebe2c93aba07..dec7b852882b2 100644 --- a/rust/src/safaritp.rs +++ b/rust/src/safaritp.rs @@ -22,7 +22,7 @@ use std::error::Error; use std::path::PathBuf; use std::string::ToString; -use crate::files::BrowserPath; +use crate::files::{path_buf_to_string, BrowserPath}; use crate::config::OS::MACOS; use crate::{create_http_client, format_one_arg, Logger, SeleniumManager, PLIST_COMMAND, STABLE}; @@ -87,7 +87,7 @@ impl SeleniumManager for SafariTPManager { if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { - browser_path = self.get_escaped_path_buf(path); + browser_path = self.get_escaped_path(path_buf_to_string(path)); } _ => return None, } From 68e7901a70d269765c002dc183651cc5b3bdf4d2 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Sun, 23 Jul 2023 13:39:45 +0200 Subject: [PATCH 11/11] [rust] Return always browser path in results --- rust/src/chrome.rs | 23 +++++++---------------- rust/src/edge.rs | 19 ++++--------------- rust/src/firefox.rs | 19 ++++--------------- rust/src/grid.rs | 10 ---------- rust/src/iexplorer.rs | 10 ---------- rust/src/lib.rs | 39 ++++++++++++++++++++++----------------- rust/src/main.rs | 10 +++------- rust/src/safari.rs | 10 ---------- rust/src/safaritp.rs | 10 ---------- 9 files changed, 40 insertions(+), 110 deletions(-) diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index 789863c20e889..84b479b3f527d 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -56,7 +56,6 @@ pub struct ChromeManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub resolved_browser_path: Option, pub download_url: Option, } @@ -74,7 +73,6 @@ impl ChromeManager { config, log: Logger::default(), download_url: None, - resolved_browser_path: None, })) } @@ -315,7 +313,7 @@ impl SeleniumManager for ChromeManager { fn discover_browser_version(&mut self) -> Option { let mut commands; let mut browser_path = self.get_browser_path().to_string(); - let mut escaped_browser_path = self.get_browser_path().to_string(); + let escaped_browser_path; if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { @@ -332,16 +330,15 @@ impl SeleniumManager for ChromeManager { _ => return None, } } else { - commands = vec![format_one_arg( - WMIC_COMMAND, - &self.get_escaped_path(browser_path.to_string()), - )]; + escaped_browser_path = self.get_escaped_path(browser_path.to_string()); + commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; } if !WINDOWS.is(self.get_os()) { commands = vec![ format_three_args(DASH_DASH_VERSION, "", &escaped_browser_path, ""), format_three_args(DASH_DASH_VERSION, DOUBLE_QUOTE, &browser_path, DOUBLE_QUOTE), format_three_args(DASH_DASH_VERSION, SINGLE_QUOTE, &browser_path, SINGLE_QUOTE), + format_three_args(DASH_DASH_VERSION, "", &browser_path, ""), ] } self.detect_browser_version(commands) @@ -539,18 +536,12 @@ impl SeleniumManager for ChromeManager { None, )?; } - self.set_resolved_browser_path(browser_path.clone()); + if browser_path.is_some() { + self.set_browser_path(path_buf_to_string(browser_path.clone().unwrap())); + } Ok(browser_path) } - - fn get_resolved_browser_path(&self) -> Option { - self.resolved_browser_path.to_owned() - } - - fn set_resolved_browser_path(&mut self, browser_path: Option) { - self.resolved_browser_path = browser_path; - } } #[derive(Serialize, Deserialize)] diff --git a/rust/src/edge.rs b/rust/src/edge.rs index 38e2205462ec4..98c8c307c7777 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -46,7 +46,6 @@ pub struct EdgeManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub resolved_browser_path: Option, } impl EdgeManager { @@ -62,7 +61,6 @@ impl EdgeManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), - resolved_browser_path: None, })) } } @@ -126,7 +124,7 @@ impl SeleniumManager for EdgeManager { fn discover_browser_version(&mut self) -> Option { let mut commands; let mut browser_path = self.get_browser_path().to_string(); - let mut escaped_browser_path = self.get_browser_path().to_string(); + let escaped_browser_path; if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { @@ -143,16 +141,15 @@ impl SeleniumManager for EdgeManager { _ => return None, } } else { - commands = vec![format_one_arg( - WMIC_COMMAND, - &self.get_escaped_path(browser_path.to_string()), - )]; + escaped_browser_path = self.get_escaped_path(browser_path.to_string()); + commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; } if !WINDOWS.is(self.get_os()) { commands = vec![ format_three_args(DASH_DASH_VERSION, "", &escaped_browser_path, ""), format_three_args(DASH_DASH_VERSION, DOUBLE_QUOTE, &browser_path, DOUBLE_QUOTE), format_three_args(DASH_DASH_VERSION, SINGLE_QUOTE, &browser_path, SINGLE_QUOTE), + format_three_args(DASH_DASH_VERSION, "", &browser_path, ""), ] } self.detect_browser_version(commands) @@ -302,12 +299,4 @@ impl SeleniumManager for EdgeManager { fn download_browser(&mut self) -> Result, Box> { Ok(None) } - - fn get_resolved_browser_path(&self) -> Option { - self.resolved_browser_path.to_owned() - } - - fn set_resolved_browser_path(&mut self, browser_path: Option) { - self.resolved_browser_path = browser_path; - } } diff --git a/rust/src/firefox.rs b/rust/src/firefox.rs index 90833c2635f8f..319c111bacf08 100644 --- a/rust/src/firefox.rs +++ b/rust/src/firefox.rs @@ -45,7 +45,6 @@ pub struct FirefoxManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub resolved_browser_path: Option, } impl FirefoxManager { @@ -61,7 +60,6 @@ impl FirefoxManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), - resolved_browser_path: None, })) } } @@ -123,7 +121,7 @@ impl SeleniumManager for FirefoxManager { fn discover_browser_version(&mut self) -> Option { let mut commands; let mut browser_path = self.get_browser_path().to_string(); - let mut escaped_browser_path = self.get_browser_path().to_string(); + let escaped_browser_path; if browser_path.is_empty() { match self.detect_browser_path() { Some(path) => { @@ -141,16 +139,15 @@ impl SeleniumManager for FirefoxManager { _ => return None, } } else { - commands = vec![format_one_arg( - WMIC_COMMAND, - &self.get_escaped_path(browser_path.to_string()), - )]; + escaped_browser_path = self.get_escaped_path(browser_path.to_string()); + commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; } if !WINDOWS.is(self.get_os()) { commands = vec![ format_three_args(DASH_VERSION, "", &escaped_browser_path, ""), format_three_args(DASH_VERSION, DOUBLE_QUOTE, &browser_path, DOUBLE_QUOTE), format_three_args(DASH_VERSION, SINGLE_QUOTE, &browser_path, SINGLE_QUOTE), + format_three_args(DASH_VERSION, "", &browser_path, ""), ] } self.detect_browser_version(commands) @@ -291,14 +288,6 @@ impl SeleniumManager for FirefoxManager { fn download_browser(&mut self) -> Result, Box> { Ok(None) } - - fn get_resolved_browser_path(&self) -> Option { - self.resolved_browser_path.to_owned() - } - - fn set_resolved_browser_path(&mut self, browser_path: Option) { - self.resolved_browser_path = browser_path; - } } #[cfg(test)] diff --git a/rust/src/grid.rs b/rust/src/grid.rs index d36d8fc2d92d1..83a3e478d46f1 100644 --- a/rust/src/grid.rs +++ b/rust/src/grid.rs @@ -47,7 +47,6 @@ pub struct GridManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub resolved_browser_path: Option, pub driver_url: Option, } @@ -66,7 +65,6 @@ impl GridManager { config, log: Logger::default(), driver_url: None, - resolved_browser_path: None, })) } } @@ -215,12 +213,4 @@ impl SeleniumManager for GridManager { fn download_browser(&mut self) -> Result, Box> { Ok(None) } - - fn get_resolved_browser_path(&self) -> Option { - self.resolved_browser_path.to_owned() - } - - fn set_resolved_browser_path(&mut self, browser_path: Option) { - self.resolved_browser_path = browser_path; - } } diff --git a/rust/src/iexplorer.rs b/rust/src/iexplorer.rs index 0ed9ba574c3be..ebaab73ad8007 100644 --- a/rust/src/iexplorer.rs +++ b/rust/src/iexplorer.rs @@ -51,7 +51,6 @@ pub struct IExplorerManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub resolved_browser_path: Option, pub driver_url: Option, } @@ -70,7 +69,6 @@ impl IExplorerManager { config, log: Logger::default(), driver_url: None, - resolved_browser_path: None, })) } } @@ -214,12 +212,4 @@ impl SeleniumManager for IExplorerManager { fn download_browser(&mut self) -> Result, Box> { Ok(None) } - - fn get_resolved_browser_path(&self) -> Option { - self.resolved_browser_path.to_owned() - } - - fn set_resolved_browser_path(&mut self, browser_path: Option) { - self.resolved_browser_path = browser_path; - } } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index d8f5c1561735a..152f8cae4529c 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -17,7 +17,10 @@ use crate::chrome::{ChromeManager, CHROMEDRIVER_NAME, CHROME_NAME}; use crate::edge::{EdgeManager, EDGEDRIVER_NAME, EDGE_NAMES}; -use crate::files::{compose_cache_folder, create_parent_path_if_not_exists, get_binary_extension}; +use crate::files::{ + compose_cache_folder, create_parent_path_if_not_exists, get_binary_extension, + path_buf_to_string, +}; use crate::firefox::{FirefoxManager, FIREFOX_NAME, GECKODRIVER_NAME}; use crate::iexplorer::{IExplorerManager, IEDRIVER_NAME, IE_NAMES}; use crate::safari::{SafariManager, SAFARIDRIVER_NAME, SAFARI_NAME}; @@ -125,10 +128,6 @@ pub trait SeleniumManager { fn download_browser(&mut self) -> Result, Box>; - fn get_resolved_browser_path(&self) -> Option; - - fn set_resolved_browser_path(&mut self, browser_path: Option); - // ---------------------------------------------------------- // Shared functions // ---------------------------------------------------------- @@ -194,9 +193,9 @@ pub trait SeleniumManager { self.get_browser_name(), full_browser_path.display() )); - let browser_path = Some(full_browser_path); - self.set_resolved_browser_path(browser_path.clone()); - browser_path + self.set_browser_path(path_buf_to_string(full_browser_path.clone())); + + Some(full_browser_path) } else { // Check browser in PATH let browser_name = self.get_browser_name(); @@ -313,9 +312,12 @@ pub trait SeleniumManager { } fn find_driver_in_path(&self) -> (Option, Option) { - match self - .run_shell_command_with_log(format_one_arg(DASH_DASH_VERSION, self.get_driver_name())) - { + match self.run_shell_command_with_log(format_three_args( + DASH_DASH_VERSION, + self.get_driver_name(), + "", + "", + )) { Ok(output) => { let parsed_version = parse_version(output, self.get_logger()).unwrap_or_default(); if !parsed_version.is_empty() { @@ -583,6 +585,12 @@ pub trait SeleniumManager { self.get_config().browser_path.as_str() } + fn set_browser_path(&mut self, browser_path: String) { + if !browser_path.is_empty() { + self.get_config_mut().browser_path = browser_path; + } + } + fn get_escaped_path(&self, string_path: String) -> String { let original_path = string_path.clone(); let mut escaped_path = string_path; @@ -603,6 +611,9 @@ pub trait SeleniumManager { format_one_arg(ESCAPE_COMMAND, escaped_path.as_str()), ) .unwrap_or_default(); + if escaped_path.is_empty() { + escaped_path = original_path.clone(); + } } } self.get_logger().trace(format!( @@ -612,12 +623,6 @@ pub trait SeleniumManager { escaped_path } - fn set_browser_path(&mut self, browser_path: String) { - if !browser_path.is_empty() { - self.get_config_mut().browser_path = browser_path; - } - } - fn get_proxy(&self) -> &str { self.get_config().proxy.as_str() } diff --git a/rust/src/main.rs b/rust/src/main.rs index 3198cb0c4957d..fd47523e3a01b 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -172,13 +172,9 @@ fn main() { log.error(format!("Driver unavailable: {}", DRIVER_PATH)); flush_and_exit(UNAVAILABLE, log); } - let resolved_browser_path = selenium_manager.get_resolved_browser_path(); - if resolved_browser_path.is_some() { - log.info(format!( - "{}{}", - BROWSER_PATH, - resolved_browser_path.unwrap().display() - )); + let browser_path = selenium_manager.get_browser_path(); + if !browser_path.is_empty() { + log.info(format!("{}{}", BROWSER_PATH, browser_path)); } flush_and_exit(OK, log); }) diff --git a/rust/src/safari.rs b/rust/src/safari.rs index 9b83bd0ec54e8..7620af0c0588b 100644 --- a/rust/src/safari.rs +++ b/rust/src/safari.rs @@ -36,7 +36,6 @@ pub struct SafariManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub resolved_browser_path: Option, } impl SafariManager { @@ -52,7 +51,6 @@ impl SafariManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), - resolved_browser_path: None, })) } } @@ -134,12 +132,4 @@ impl SeleniumManager for SafariManager { fn download_browser(&mut self) -> Result, Box> { Ok(None) } - - fn get_resolved_browser_path(&self) -> Option { - self.resolved_browser_path.to_owned() - } - - fn set_resolved_browser_path(&mut self, browser_path: Option) { - self.resolved_browser_path = browser_path; - } } diff --git a/rust/src/safaritp.rs b/rust/src/safaritp.rs index dec7b852882b2..3b118a5993b07 100644 --- a/rust/src/safaritp.rs +++ b/rust/src/safaritp.rs @@ -41,7 +41,6 @@ pub struct SafariTPManager { pub config: ManagerConfig, pub http_client: Client, pub log: Logger, - pub resolved_browser_path: Option, } impl SafariTPManager { @@ -57,7 +56,6 @@ impl SafariTPManager { http_client: create_http_client(default_timeout, default_proxy)?, config, log: Logger::default(), - resolved_browser_path: None, })) } } @@ -139,12 +137,4 @@ impl SeleniumManager for SafariTPManager { fn download_browser(&mut self) -> Result, Box> { Ok(None) } - - fn get_resolved_browser_path(&self) -> Option { - self.resolved_browser_path.to_owned() - } - - fn set_resolved_browser_path(&mut self, browser_path: Option) { - self.resolved_browser_path = browser_path; - } }