Skip to content

Commit 50d1ae9

Browse files
authored
[rust] Include support for Safari in Selenium Manager (#11609)
* [rust] Include support for Safari in Selenium Manager * [rust] Include separate test for Safari * [rust] Fix Safari logic after latest refactoring * [rust] Include SafariTP as a different browser than Safari
1 parent b5a118a commit 50d1ae9

File tree

4 files changed

+346
-35
lines changed

4 files changed

+346
-35
lines changed

rust/src/lib.rs

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::edge::EdgeManager;
2020
use crate::files::compose_cache_folder;
2121
use crate::firefox::FirefoxManager;
2222
use crate::iexplorer::IExplorerManager;
23+
use crate::safari::{SafariManager, SAFARI};
2324
use std::fs;
2425

2526
use crate::config::OS::WINDOWS;
@@ -37,6 +38,7 @@ use crate::logger::Logger;
3738
use crate::metadata::{
3839
create_browser_metadata, get_browser_version_from_metadata, get_metadata, write_metadata,
3940
};
41+
use crate::safaritp::SafariTPManager;
4042

4143
pub mod chrome;
4244
pub mod config;
@@ -47,6 +49,8 @@ pub mod firefox;
4749
pub mod iexplorer;
4850
pub mod logger;
4951
pub mod metadata;
52+
pub mod safari;
53+
pub mod safaritp;
5054

5155
pub const REQUEST_TIMEOUT_SEC: u64 = 120; // The timeout is applied from when the request starts connecting until the response body has finished
5256
pub const STABLE: &str = "stable";
@@ -57,6 +61,8 @@ pub const NIGHTLY: &str = "nightly";
5761
pub const WMIC_COMMAND: &str = r#"wmic datafile where name='{}' get Version /value"#;
5862
pub const WMIC_COMMAND_ENV: &str = r#"wmic datafile where name='%{}:\=\\%{}' get Version /value"#;
5963
pub const REG_QUERY: &str = r#"REG QUERY {} /v version"#;
64+
pub const PLIST_COMMAND: &str =
65+
r#"/usr/libexec/PlistBuddy -c "print :CFBundleShortVersionString" {}/Contents/Info.plist"#;
6066
pub const DASH_VERSION: &str = "{} -v";
6167
pub const DASH_DASH_VERSION: &str = "{} --version";
6268
pub const ENV_PROGRAM_FILES: &str = "PROGRAMFILES";
@@ -160,11 +166,12 @@ pub trait SeleniumManager {
160166
}
161167
break;
162168
}
163-
164-
metadata
165-
.browsers
166-
.push(create_browser_metadata(browser_name, &browser_version));
167-
write_metadata(&metadata, self.get_logger());
169+
if !self.is_safari() {
170+
metadata
171+
.browsers
172+
.push(create_browser_metadata(browser_name, &browser_version));
173+
write_metadata(&metadata, self.get_logger());
174+
}
168175
if !browser_version.is_empty() {
169176
Some(browser_version)
170177
} else {
@@ -179,12 +186,14 @@ pub trait SeleniumManager {
179186
if browser_version.is_empty() || self.is_browser_version_unstable() {
180187
match self.discover_browser_version() {
181188
Some(version) => {
182-
self.get_logger().debug(format!(
183-
"Detected browser: {} {}",
184-
self.get_browser_name(),
185-
version
186-
));
187-
self.set_browser_version(version);
189+
if !self.is_safari() {
190+
self.get_logger().debug(format!(
191+
"Detected browser: {} {}",
192+
self.get_browser_name(),
193+
version
194+
));
195+
self.set_browser_version(version);
196+
}
188197
}
189198
None => {
190199
if self.is_browser_version_unstable() {
@@ -247,6 +256,10 @@ pub trait SeleniumManager {
247256
}
248257
}
249258

259+
fn is_safari(&self) -> bool {
260+
self.get_browser_name().contains(SAFARI)
261+
}
262+
250263
fn is_browser_version_unstable(&self) -> bool {
251264
let browser_version = self.get_browser_version();
252265
browser_version.eq_ignore_ascii_case(BETA)
@@ -261,34 +274,38 @@ pub trait SeleniumManager {
261274
self.set_driver_version(driver_version);
262275
}
263276

264-
let (in_path_driver_version, in_path_driver_path) = self.find_driver_in_path();
265-
if let (Some(found_driver_version), Some(found_driver_path)) =
266-
(in_path_driver_version, in_path_driver_path)
267-
{
268-
if found_driver_version.eq(self.get_driver_version()) {
269-
self.get_logger().debug(format!(
270-
"Found {} {} in PATH: {}",
271-
self.get_driver_name(),
272-
found_driver_version,
273-
found_driver_path
274-
));
275-
return Ok(PathBuf::from(found_driver_path));
276-
} else {
277-
self.get_logger().warn(format!(
278-
"Incompatible release of {} (version {}) detected in PATH: {}",
279-
self.get_driver_name(),
280-
found_driver_version,
281-
found_driver_path
282-
));
277+
if !self.is_safari() {
278+
let (in_path_driver_version, in_path_driver_path) = self.find_driver_in_path();
279+
if let (Some(found_driver_version), Some(found_driver_path)) =
280+
(in_path_driver_version, in_path_driver_path)
281+
{
282+
if found_driver_version.eq(self.get_driver_version()) {
283+
self.get_logger().debug(format!(
284+
"Found {} {} in PATH: {}",
285+
self.get_driver_name(),
286+
found_driver_version,
287+
found_driver_path
288+
));
289+
return Ok(PathBuf::from(found_driver_path));
290+
} else {
291+
self.get_logger().warn(format!(
292+
"Incompatible release of {} (version {}) detected in PATH: {}",
293+
self.get_driver_name(),
294+
found_driver_version,
295+
found_driver_path
296+
));
297+
}
283298
}
284299
}
285300
let driver_path = self.get_driver_path_in_cache();
286301
if driver_path.exists() {
287-
self.get_logger().debug(format!(
288-
"{} {} already in the cache",
289-
self.get_driver_name(),
290-
self.get_driver_version()
291-
));
302+
if !self.is_safari() {
303+
self.get_logger().debug(format!(
304+
"{} {} already in the cache",
305+
self.get_driver_name(),
306+
self.get_driver_version()
307+
));
308+
}
292309
} else {
293310
self.download_driver()?;
294311
}
@@ -434,6 +451,17 @@ pub fn get_manager_by_browser(browser_name: String) -> Result<Box<dyn SeleniumMa
434451
.contains(&browser_name_lower_case.as_str())
435452
{
436453
Ok(IExplorerManager::new())
454+
} else if browser_name.eq("safari") {
455+
Ok(SafariManager::new())
456+
} else if vec![
457+
"safari technology preview",
458+
r#"safari\ technology\ preview"#,
459+
"safaritechnologypreview",
460+
"safaritp",
461+
]
462+
.contains(&browser_name_lower_case.as_str())
463+
{
464+
Ok(SafariTPManager::new())
437465
} else {
438466
Err(format!("Invalid browser name: {browser_name}"))
439467
}
@@ -448,6 +476,8 @@ pub fn get_manager_by_driver(driver_name: String) -> Result<Box<dyn SeleniumMana
448476
Ok(EdgeManager::new())
449477
} else if driver_name.eq_ignore_ascii_case("iedriverserver") {
450478
Ok(IExplorerManager::new())
479+
} else if driver_name.eq_ignore_ascii_case("safaridriver") {
480+
Ok(SafariManager::new())
451481
} else {
452482
Err(format!("Invalid driver name: {driver_name}"))
453483
}

rust/src/safari.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
use crate::config::ManagerConfig;
19+
use reqwest::Client;
20+
use std::collections::HashMap;
21+
use std::error::Error;
22+
use std::path::PathBuf;
23+
use std::string::ToString;
24+
25+
use crate::files::BrowserPath;
26+
27+
use crate::config::OS::MACOS;
28+
use crate::{
29+
create_default_http_client, format_one_arg, Logger, SeleniumManager, PLIST_COMMAND,
30+
STABLE,
31+
};
32+
33+
pub const SAFARI: &str = "safari";
34+
const DRIVER_NAME: &str = "safaridriver";
35+
36+
pub struct SafariManager {
37+
pub browser_name: &'static str,
38+
pub driver_name: &'static str,
39+
pub config: ManagerConfig,
40+
pub http_client: Client,
41+
pub log: Logger,
42+
}
43+
44+
impl SafariManager {
45+
pub fn new() -> Box<Self> {
46+
Box::new(SafariManager {
47+
browser_name: SAFARI,
48+
driver_name: DRIVER_NAME,
49+
config: ManagerConfig::default(),
50+
http_client: create_default_http_client(),
51+
log: Logger::default(),
52+
})
53+
}
54+
}
55+
56+
impl SeleniumManager for SafariManager {
57+
fn get_browser_name(&self) -> &str {
58+
self.browser_name
59+
}
60+
61+
fn get_http_client(&self) -> &Client {
62+
&self.http_client
63+
}
64+
65+
fn set_http_client(&mut self, http_client: Client) {
66+
self.http_client = http_client;
67+
}
68+
69+
fn get_browser_path_map(&self) -> HashMap<BrowserPath, &str> {
70+
HashMap::from([(
71+
BrowserPath::new(MACOS, STABLE),
72+
r#"/Applications/Safari.app"#,
73+
)])
74+
}
75+
76+
fn discover_browser_version(&self) -> Option<String> {
77+
let mut browser_path = self.get_browser_path();
78+
if browser_path.is_empty() {
79+
match self.detect_browser_path() {
80+
Some(path) => {
81+
browser_path = path;
82+
}
83+
_ => return None,
84+
}
85+
}
86+
let command = if MACOS.is(self.get_os()) {
87+
vec![format_one_arg(PLIST_COMMAND, browser_path)]
88+
} else {
89+
return None;
90+
};
91+
self.detect_browser_version(command)
92+
}
93+
94+
fn get_driver_name(&self) -> &str {
95+
self.driver_name
96+
}
97+
98+
fn request_driver_version(&self) -> Result<String, Box<dyn Error>> {
99+
Ok("(local)".to_string())
100+
}
101+
102+
fn get_driver_url(&self) -> Result<String, Box<dyn Error>> {
103+
Err(format!("{} not available for download", self.get_driver_name()).into())
104+
}
105+
106+
fn get_driver_path_in_cache(&self) -> PathBuf {
107+
PathBuf::from("/usr/bin/safaridriver")
108+
}
109+
110+
fn get_config(&self) -> &ManagerConfig {
111+
&self.config
112+
}
113+
114+
fn set_config(&mut self, config: ManagerConfig) {
115+
self.config = config;
116+
}
117+
118+
fn get_logger(&self) -> &Logger {
119+
&self.log
120+
}
121+
122+
fn set_logger(&mut self, log: Logger) {
123+
self.log = log;
124+
}
125+
}

0 commit comments

Comments
 (0)