Skip to content

Commit 65e3eb6

Browse files
authored
[rust] Allow Selenium Manager to be used as a Rust lib crate (#11132) (#11371)
1 parent 6399429 commit 65e3eb6

File tree

10 files changed

+661
-487
lines changed

10 files changed

+661
-487
lines changed

rust/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
name = "selenium-manager"
33
version = "1.0.0-M2"
44
edition = "2021"
5+
authors = ["Selenium <selenium-developers@googlegroups.com"]
6+
license = "Apache-2.0"
7+
homepage = "https://www.selenium.dev/"
8+
repository = "https://github.com/SeleniumHQ/selenium"
9+
documentation = "https://www.selenium.dev/documentation/"
10+
description = """
11+
Selenium Manager is a CLI tool that automatically manages the browser/driver infrastructure required by Selenium.
12+
"""
513

614
[dependencies]
715
clap = { version = "4.0.22", features = ["derive"] }

rust/src/chrome.rs

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,22 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
use crate::config::ManagerConfig;
1819
use std::collections::HashMap;
1920
use std::error::Error;
2021
use std::path::PathBuf;
2122

23+
use crate::config::ARCH::ARM64;
24+
use crate::config::OS::{LINUX, MACOS, WINDOWS};
2225
use crate::downloads::read_content_from_link;
23-
use crate::files::compose_driver_path_in_cache;
24-
use crate::is_unstable;
25-
use crate::manager::ARCH::ARM64;
26-
use crate::manager::OS::{LINUX, MACOS, WINDOWS};
27-
use crate::manager::{
28-
detect_browser_version, format_one_arg, format_two_args, get_major_version, BrowserManager,
29-
BrowserPath, BETA, DASH_DASH_VERSION, DEV, ENV_LOCALAPPDATA, ENV_PROGRAM_FILES,
30-
ENV_PROGRAM_FILES_X86, NIGHTLY, REG_QUERY, STABLE, WMIC_COMMAND,
31-
};
26+
use crate::files::{compose_driver_path_in_cache, BrowserPath};
3227
use crate::metadata::{
3328
create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata,
3429
};
30+
use crate::{
31+
SeleniumManager, BETA, DASH_DASH_VERSION, DEV, ENV_LOCALAPPDATA, ENV_PROGRAM_FILES,
32+
ENV_PROGRAM_FILES_X86, NIGHTLY, REG_QUERY, STABLE, WMIC_COMMAND,
33+
};
3534

3635
const BROWSER_NAME: &str = "chrome";
3736
const DRIVER_NAME: &str = "chromedriver";
@@ -41,18 +40,20 @@ const LATEST_RELEASE: &str = "LATEST_RELEASE";
4140
pub struct ChromeManager {
4241
pub browser_name: &'static str,
4342
pub driver_name: &'static str,
43+
pub config: ManagerConfig,
4444
}
4545

4646
impl ChromeManager {
4747
pub fn new() -> Box<Self> {
4848
Box::new(ChromeManager {
4949
browser_name: BROWSER_NAME,
5050
driver_name: DRIVER_NAME,
51+
config: ManagerConfig::default(),
5152
})
5253
}
5354
}
5455

55-
impl BrowserManager for ChromeManager {
56+
impl SeleniumManager for ChromeManager {
5657
fn get_browser_name(&self) -> &str {
5758
self.browser_name
5859
}
@@ -97,30 +98,31 @@ impl BrowserManager for ChromeManager {
9798
])
9899
}
99100

100-
fn get_browser_version(&self, os: &str, browser_version: &str) -> Option<String> {
101-
match self.get_browser_path(os, browser_version) {
101+
fn discover_browser_version(&self) -> Option<String> {
102+
match self.get_browser_path() {
102103
Some(browser_path) => {
103-
let (shell, flag, args) = if WINDOWS.is(os) {
104-
let mut commands = vec![
105-
format_two_args(WMIC_COMMAND, ENV_PROGRAM_FILES, browser_path),
106-
format_two_args(WMIC_COMMAND, ENV_PROGRAM_FILES_X86, browser_path),
107-
format_two_args(WMIC_COMMAND, ENV_LOCALAPPDATA, browser_path),
108-
];
109-
if !is_unstable(browser_version) {
110-
commands.push(format_one_arg(
111-
REG_QUERY,
112-
r#"HKCU\Software\Google\Chrome\BLBeacon"#,
113-
));
114-
}
115-
("cmd", "/C", commands)
116-
} else {
117-
(
118-
"sh",
119-
"-c",
120-
vec![format_one_arg(DASH_DASH_VERSION, browser_path)],
121-
)
122-
};
123-
detect_browser_version(self.browser_name, shell, flag, args)
104+
let (shell, flag, args) =
105+
if WINDOWS.is(self.get_os()) {
106+
let mut commands = vec![
107+
self.format_two_args(WMIC_COMMAND, ENV_PROGRAM_FILES, browser_path),
108+
self.format_two_args(WMIC_COMMAND, ENV_PROGRAM_FILES_X86, browser_path),
109+
self.format_two_args(WMIC_COMMAND, ENV_LOCALAPPDATA, browser_path),
110+
];
111+
if !self.is_browser_version_unstable() {
112+
commands.push(self.format_one_arg(
113+
REG_QUERY,
114+
r#"HKCU\Software\Google\Chrome\BLBeacon"#,
115+
));
116+
}
117+
("cmd", "/C", commands)
118+
} else {
119+
(
120+
"sh",
121+
"-c",
122+
vec![self.format_one_arg(DASH_DASH_VERSION, browser_path)],
123+
)
124+
};
125+
self.detect_browser_version(shell, flag, args)
124126
}
125127
_ => None,
126128
}
@@ -130,11 +132,8 @@ impl BrowserManager for ChromeManager {
130132
self.driver_name
131133
}
132134

133-
fn get_driver_version(
134-
&self,
135-
browser_version: &str,
136-
_os: &str,
137-
) -> Result<String, Box<dyn Error>> {
135+
fn request_driver_version(&self) -> Result<String, Box<dyn Error>> {
136+
let browser_version = self.get_browser_version();
138137
let mut metadata = get_metadata();
139138

140139
match get_driver_version_from_metadata(&metadata.drivers, self.driver_name, browser_version)
@@ -168,19 +167,18 @@ impl BrowserManager for ChromeManager {
168167
}
169168
}
170169

171-
fn get_driver_url(
172-
&self,
173-
driver_version: &str,
174-
os: &str,
175-
arch: &str,
176-
) -> Result<String, Box<dyn Error>> {
170+
fn get_driver_url(&self) -> Result<String, Box<dyn Error>> {
171+
let driver_version = self.get_driver_version();
172+
let os = self.get_os();
173+
let arch = self.get_arch();
177174
let driver_label = if WINDOWS.is(os) {
178175
"win32"
179176
} else if MACOS.is(os) {
180177
if ARM64.is(arch) {
181178
// As of chromedriver 106, the naming convention for macOS ARM64 releases changed. See:
182179
// https://groups.google.com/g/chromedriver-users/c/JRuQzH3qr2c
183-
let major_driver_version = get_major_version(driver_version)?
180+
let major_driver_version = self
181+
.get_major_version(driver_version)?
184182
.parse::<i32>()
185183
.unwrap_or_default();
186184
if major_driver_version < 106 {
@@ -200,7 +198,10 @@ impl BrowserManager for ChromeManager {
200198
))
201199
}
202200

203-
fn get_driver_path_in_cache(&self, driver_version: &str, os: &str, arch: &str) -> PathBuf {
201+
fn get_driver_path_in_cache(&self) -> PathBuf {
202+
let driver_version = self.get_driver_version();
203+
let os = self.get_os();
204+
let arch = self.get_arch();
204205
let arch_folder = if WINDOWS.is(os) {
205206
"win32"
206207
} else if MACOS.is(os) {
@@ -214,4 +215,12 @@ impl BrowserManager for ChromeManager {
214215
};
215216
compose_driver_path_in_cache(self.driver_name, os, arch_folder, driver_version)
216217
}
218+
219+
fn get_config(&self) -> &ManagerConfig {
220+
&self.config
221+
}
222+
223+
fn set_config(&mut self, config: ManagerConfig) {
224+
self.config = config;
225+
}
217226
}

rust/src/config.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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::OS::{LINUX, MACOS, WINDOWS};
19+
use std::env::consts::{ARCH, OS};
20+
21+
pub struct ManagerConfig {
22+
pub browser_version: String,
23+
pub driver_version: String,
24+
pub os: String,
25+
pub arch: String,
26+
}
27+
28+
impl ManagerConfig {
29+
pub fn default() -> ManagerConfig {
30+
ManagerConfig {
31+
browser_version: "".to_string(),
32+
driver_version: "".to_string(),
33+
os: OS.to_string(),
34+
arch: ARCH.to_string(),
35+
}
36+
}
37+
38+
#[allow(clippy::should_implement_trait)]
39+
pub fn clone(config: &ManagerConfig) -> ManagerConfig {
40+
ManagerConfig {
41+
browser_version: config.browser_version.as_str().to_string(),
42+
driver_version: config.driver_version.as_str().to_string(),
43+
os: config.os.as_str().to_string(),
44+
arch: config.arch.as_str().to_string(),
45+
}
46+
}
47+
}
48+
49+
#[allow(dead_code)]
50+
#[allow(clippy::upper_case_acronyms)]
51+
#[derive(Hash, Eq, PartialEq, Debug)]
52+
pub enum OS {
53+
WINDOWS,
54+
MACOS,
55+
LINUX,
56+
}
57+
58+
impl OS {
59+
pub fn to_str(&self) -> &str {
60+
match self {
61+
WINDOWS => "windows",
62+
MACOS => "macos",
63+
LINUX => "linux",
64+
}
65+
}
66+
67+
pub fn is(&self, os: &str) -> bool {
68+
self.to_str().eq_ignore_ascii_case(os)
69+
}
70+
}
71+
72+
pub fn str_to_os(os: &str) -> OS {
73+
if WINDOWS.is(os) {
74+
WINDOWS
75+
} else if MACOS.is(os) {
76+
MACOS
77+
} else {
78+
LINUX
79+
}
80+
}
81+
82+
#[allow(dead_code)]
83+
#[allow(clippy::upper_case_acronyms)]
84+
pub enum ARCH {
85+
X32,
86+
X64,
87+
ARM64,
88+
}
89+
90+
impl ARCH {
91+
pub fn to_str(&self) -> &str {
92+
match self {
93+
ARCH::X32 => "x86",
94+
ARCH::X64 => "x86_64",
95+
ARCH::ARM64 => "aarch64",
96+
}
97+
}
98+
99+
pub fn is(&self, arch: &str) -> bool {
100+
self.to_str().eq_ignore_ascii_case(arch)
101+
}
102+
}

0 commit comments

Comments
 (0)