"Fossies" - the Fresh Open Source Software Archive

Member "selenium-selenium-4.8.1/rust/src/firefox.rs" (17 Feb 2023, 12073 Bytes) of package /linux/www/selenium-selenium-4.8.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Rust source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "firefox.rs": 4.8.0_vs_4.8.1.

    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 
   24 use crate::config::ARCH::{ARM64, X32};
   25 use crate::config::OS::{LINUX, MACOS, WINDOWS};
   26 use crate::downloads::read_redirect_from_link;
   27 use crate::files::{compose_driver_path_in_cache, BrowserPath};
   28 use crate::metadata::{
   29     create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata,
   30 };
   31 use crate::{
   32     create_default_http_client, format_one_arg, format_two_args, Logger, SeleniumManager, BETA,
   33     DASH_VERSION, DEV, ENV_PROGRAM_FILES, ENV_PROGRAM_FILES_X86, NIGHTLY, STABLE, WMIC_COMMAND,
   34     WMIC_COMMAND_ENV,
   35 };
   36 
   37 const BROWSER_NAME: &str = "firefox";
   38 const DRIVER_NAME: &str = "geckodriver";
   39 const DRIVER_URL: &str = "https://github.com/mozilla/geckodriver/releases/";
   40 const LATEST_RELEASE: &str = "latest";
   41 
   42 pub struct FirefoxManager {
   43     pub browser_name: &'static str,
   44     pub driver_name: &'static str,
   45     pub config: ManagerConfig,
   46     pub http_client: Client,
   47     pub log: Logger,
   48 }
   49 
   50 impl FirefoxManager {
   51     pub fn new() -> Box<Self> {
   52         Box::new(FirefoxManager {
   53             browser_name: BROWSER_NAME,
   54             driver_name: DRIVER_NAME,
   55             config: ManagerConfig::default(),
   56             http_client: create_default_http_client(),
   57             log: Logger::default(),
   58         })
   59     }
   60 }
   61 
   62 impl SeleniumManager for FirefoxManager {
   63     fn get_browser_name(&self) -> &str {
   64         self.browser_name
   65     }
   66 
   67     fn get_http_client(&self) -> &Client {
   68         &self.http_client
   69     }
   70 
   71     fn set_http_client(&mut self, http_client: Client) {
   72         self.http_client = http_client;
   73     }
   74 
   75     fn get_browser_path_map(&self) -> HashMap<BrowserPath, &str> {
   76         HashMap::from([
   77             (
   78                 BrowserPath::new(WINDOWS, STABLE),
   79                 r#"\\Mozilla Firefox\\firefox.exe"#,
   80             ),
   81             (
   82                 BrowserPath::new(WINDOWS, BETA),
   83                 r#"\\Mozilla Firefox\\firefox.exe"#,
   84             ),
   85             (
   86                 BrowserPath::new(WINDOWS, DEV),
   87                 r#"\\Firefox Developer Edition\\firefox.exe"#,
   88             ),
   89             (
   90                 BrowserPath::new(WINDOWS, NIGHTLY),
   91                 r#"\\Firefox Nightly\\firefox.exe"#,
   92             ),
   93             (
   94                 BrowserPath::new(MACOS, STABLE),
   95                 r#"/Applications/Firefox.app/Contents/MacOS/firefox"#,
   96             ),
   97             (
   98                 BrowserPath::new(MACOS, BETA),
   99                 r#"/Applications/Firefox.app/Contents/MacOS/firefox"#,
  100             ),
  101             (
  102                 BrowserPath::new(MACOS, DEV),
  103                 r#"/Applications/Firefox\ Developer\ Edition.app/Contents/MacOS/firefox"#,
  104             ),
  105             (
  106                 BrowserPath::new(MACOS, NIGHTLY),
  107                 r#"/Applications/Firefox\ Nightly.app/Contents/MacOS/firefox"#,
  108             ),
  109             (BrowserPath::new(LINUX, STABLE), "firefox"),
  110             (BrowserPath::new(LINUX, BETA), "firefox"),
  111             (BrowserPath::new(LINUX, DEV), "firefox"),
  112             (BrowserPath::new(LINUX, NIGHTLY), "firefox-trunk"),
  113         ])
  114     }
  115 
  116     fn discover_browser_version(&self) -> Option<String> {
  117         let mut commands;
  118         let mut browser_path = self.get_browser_path();
  119         if browser_path.is_empty() {
  120             match self.detect_browser_path() {
  121                 Some(path) => {
  122                     browser_path = path;
  123                     commands = vec![
  124                         format_two_args(WMIC_COMMAND_ENV, ENV_PROGRAM_FILES, browser_path),
  125                         format_two_args(WMIC_COMMAND_ENV, ENV_PROGRAM_FILES_X86, browser_path),
  126                     ];
  127                 }
  128                 _ => return None,
  129             }
  130         } else {
  131             commands = vec![format_one_arg(WMIC_COMMAND, browser_path)];
  132         }
  133         if !WINDOWS.is(self.get_os()) {
  134             commands = vec![format_one_arg(DASH_VERSION, browser_path)]
  135         }
  136         self.detect_browser_version(commands)
  137     }
  138 
  139     fn get_driver_name(&self) -> &str {
  140         self.driver_name
  141     }
  142 
  143     fn request_driver_version(&self) -> Result<String, Box<dyn Error>> {
  144         let browser_version = self.get_browser_version();
  145         let mut metadata = get_metadata(self.get_logger());
  146 
  147         match get_driver_version_from_metadata(&metadata.drivers, self.driver_name, browser_version)
  148         {
  149             Some(driver_version) => {
  150                 self.log.trace(format!(
  151                     "Driver TTL is valid. Getting {} version from metadata",
  152                     &self.driver_name
  153                 ));
  154                 Ok(driver_version)
  155             }
  156             _ => {
  157                 let latest_url = format!("{}{}", DRIVER_URL, LATEST_RELEASE);
  158                 let driver_version = read_redirect_from_link(self.get_http_client(), latest_url)?;
  159 
  160                 if !browser_version.is_empty() {
  161                     metadata.drivers.push(create_driver_metadata(
  162                         browser_version,
  163                         self.driver_name,
  164                         &driver_version,
  165                     ));
  166                     write_metadata(&metadata, self.get_logger());
  167                 }
  168 
  169                 Ok(driver_version)
  170             }
  171         }
  172     }
  173 
  174     fn get_driver_url(&self) -> Result<String, Box<dyn Error>> {
  175         let driver_version = self.get_driver_version();
  176         let os = self.get_os();
  177         let arch = self.get_arch();
  178 
  179         // As of 0.32.0, geckodriver ships aarch64 binaries for Linux and Windows
  180         // https://github.com/mozilla/geckodriver/releases/tag/v0.32.0
  181         let minor_driver_version = self
  182             .get_minor_version(driver_version)?
  183             .parse::<i32>()
  184             .unwrap_or_default();
  185         let driver_label = if WINDOWS.is(os) {
  186             if X32.is(arch) {
  187                 "win32.zip"
  188             } else if ARM64.is(arch) && minor_driver_version > 31 {
  189                 "win-aarch64.zip"
  190             } else {
  191                 "win64.zip"
  192             }
  193         } else if MACOS.is(os) {
  194             if ARM64.is(arch) {
  195                 "macos-aarch64.tar.gz"
  196             } else {
  197                 "macos.tar.gz"
  198             }
  199         } else if X32.is(arch) {
  200             "linux32.tar.gz"
  201         } else if ARM64.is(arch) && minor_driver_version > 31 {
  202             "linux-aarch64.tar.gz"
  203         } else {
  204             "linux64.tar.gz"
  205         };
  206         Ok(format!(
  207             "{}download/v{}/{}-v{}-{}",
  208             DRIVER_URL, driver_version, self.driver_name, driver_version, driver_label
  209         ))
  210     }
  211 
  212     fn get_driver_path_in_cache(&self) -> PathBuf {
  213         let driver_version = self.get_driver_version();
  214         let os = self.get_os();
  215         let arch = self.get_arch();
  216         let minor_driver_version = self
  217             .get_minor_version(driver_version)
  218             .unwrap_or_default()
  219             .parse::<i32>()
  220             .unwrap_or_default();
  221         let arch_folder = if WINDOWS.is(os) {
  222             if X32.is(arch) {
  223                 "win32"
  224             } else if ARM64.is(arch) && minor_driver_version > 31 {
  225                 "win-arm64"
  226             } else {
  227                 "win64"
  228             }
  229         } else if MACOS.is(os) {
  230             if ARM64.is(arch) {
  231                 "mac-arm64"
  232             } else {
  233                 "mac64"
  234             }
  235         } else if X32.is(arch) {
  236             "linux32"
  237         } else if ARM64.is(arch) && minor_driver_version > 31 {
  238             "linux-arm64"
  239         } else {
  240             "linux64"
  241         };
  242         compose_driver_path_in_cache(self.driver_name, os, arch_folder, driver_version)
  243     }
  244 
  245     fn get_config(&self) -> &ManagerConfig {
  246         &self.config
  247     }
  248 
  249     fn set_config(&mut self, config: ManagerConfig) {
  250         self.config = config;
  251     }
  252 
  253     fn get_logger(&self) -> &Logger {
  254         &self.log
  255     }
  256 
  257     fn set_logger(&mut self, log: Logger) {
  258         self.log = log;
  259     }
  260 }
  261 
  262 #[cfg(test)]
  263 mod unit_tests {
  264     use super::*;
  265 
  266     #[test]
  267     fn test_driver_url() {
  268         let mut firefox_manager = FirefoxManager::new();
  269 
  270         let data = vec!(
  271             vec!("0.32.0", "linux", "x86", "https://github.com/mozilla/geckodriver/releases/download/v0.32.0/geckodriver-v0.32.0-linux32.tar.gz"),
  272             vec!("0.32.0", "linux", "x86_64", "https://github.com/mozilla/geckodriver/releases/download/v0.32.0/geckodriver-v0.32.0-linux64.tar.gz"),
  273             vec!("0.32.0", "linux", "aarch64", "https://github.com/mozilla/geckodriver/releases/download/v0.32.0/geckodriver-v0.32.0-linux-aarch64.tar.gz"),
  274             vec!("0.32.0", "windows", "x86", "https://github.com/mozilla/geckodriver/releases/download/v0.32.0/geckodriver-v0.32.0-win32.zip"),
  275             vec!("0.32.0", "windows", "x86_64", "https://github.com/mozilla/geckodriver/releases/download/v0.32.0/geckodriver-v0.32.0-win64.zip"),
  276             vec!("0.32.0", "windows", "aarch64", "https://github.com/mozilla/geckodriver/releases/download/v0.32.0/geckodriver-v0.32.0-win-aarch64.zip"),
  277             vec!("0.32.0", "macos", "x86", "https://github.com/mozilla/geckodriver/releases/download/v0.32.0/geckodriver-v0.32.0-macos.tar.gz"),
  278             vec!("0.32.0", "macos", "x86_64", "https://github.com/mozilla/geckodriver/releases/download/v0.32.0/geckodriver-v0.32.0-macos.tar.gz"),
  279             vec!("0.32.0", "macos", "aarch64", "https://github.com/mozilla/geckodriver/releases/download/v0.32.0/geckodriver-v0.32.0-macos-aarch64.tar.gz"),
  280             vec!("0.31.0", "linux", "x86", "https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-linux32.tar.gz"),
  281             vec!("0.31.0", "linux", "x86_64", "https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-linux64.tar.gz"),
  282             vec!("0.31.0", "linux", "aarch64", "https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-linux64.tar.gz"),
  283             vec!("0.31.0", "windows", "x86", "https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-win32.zip"),
  284             vec!("0.31.0", "windows", "x86_64", "https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-win64.zip"),
  285             vec!("0.31.0", "windows", "aarch64", "https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-win64.zip"),
  286             vec!("0.31.0", "macos", "x86", "https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-macos.tar.gz"),
  287             vec!("0.31.0", "macos", "x86_64", "https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-macos.tar.gz"),
  288             vec!("0.31.0", "macos", "aarch64", "https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-macos-aarch64.tar.gz"),
  289         );
  290 
  291         data.iter().for_each(|d| {
  292             firefox_manager.set_driver_version(d.first().unwrap().to_string());
  293             firefox_manager.set_os(d.get(1).unwrap().to_string());
  294             firefox_manager.set_arch(d.get(2).unwrap().to_string());
  295             let driver_url = firefox_manager.get_driver_url().unwrap();
  296             assert_eq!(d.get(3).unwrap().to_string(), driver_url);
  297         });
  298     }
  299 }