@@ -20,7 +20,8 @@ use crate::config::ManagerConfig;
2020use crate :: config:: ARCH :: { ARM64 , X32 } ;
2121use crate :: config:: OS :: { LINUX , MACOS , WINDOWS } ;
2222use crate :: downloads:: {
23- parse_generic_json_from_url, read_content_from_link, read_redirect_from_link,
23+ parse_generic_json_from_url, parse_json_from_url, read_content_from_link,
24+ read_redirect_from_link,
2425} ;
2526use crate :: files:: { compose_driver_path_in_cache, BrowserPath } ;
2627use crate :: metadata:: {
@@ -33,13 +34,16 @@ use crate::{
3334use anyhow:: anyhow;
3435use anyhow:: Error ;
3536use reqwest:: Client ;
37+ use serde:: Deserialize ;
38+ use serde:: Serialize ;
3639use std:: collections:: HashMap ;
3740use std:: path:: PathBuf ;
3841
3942pub const FIREFOX_NAME : & str = "firefox" ;
4043pub const GECKODRIVER_NAME : & str = "geckodriver" ;
4144const DRIVER_URL : & str = "https://github.com/mozilla/geckodriver/releases/" ;
4245const LATEST_RELEASE : & str = "latest" ;
46+ const DRIVER_VERSIONS_URL : & str = "https://raw.githubusercontent.com/SeleniumHQ/selenium/trunk/common/geckodriver/geckodriver-support.json" ;
4347const BROWSER_URL : & str = "https://ftp.mozilla.org/pub/firefox/releases/" ;
4448const FIREFOX_DEFAULT_LANG : & str = "en-US" ;
4549const FIREFOX_MACOS_APP_NAME : & str = "Firefox.app/Contents/MacOS/firefox" ;
@@ -212,13 +216,55 @@ impl SeleniumManager for FirefoxManager {
212216 _ => {
213217 self . assert_online_or_err ( OFFLINE_REQUEST_ERR_MSG ) ?;
214218
215- let latest_url = format ! (
216- "{}{}" ,
217- self . get_driver_mirror_url_or_default( DRIVER_URL ) ,
218- LATEST_RELEASE
219+ let driver_releases_result = parse_json_from_url :: < GeckodriverReleases > (
220+ self . get_http_client ( ) ,
221+ DRIVER_VERSIONS_URL . to_string ( ) ,
219222 ) ;
220- let driver_version =
221- read_redirect_from_link ( self . get_http_client ( ) , latest_url, self . get_logger ( ) ) ?;
223+ let driver_version = if driver_releases_result. is_ok ( ) {
224+ let driver_releases = driver_releases_result. unwrap ( ) ;
225+ let major_browser_version_int =
226+ major_browser_version. parse :: < u32 > ( ) . unwrap_or_default ( ) ;
227+ let filtered_versions: Vec < String > = driver_releases
228+ . geckodriver_releases
229+ . into_iter ( )
230+ . filter ( |r| {
231+ major_browser_version_int >= r. min_firefox_version
232+ && ( r. max_firefox_version . is_none ( )
233+ || ( r. max_firefox_version . is_some ( )
234+ && major_browser_version_int
235+ <= r. max_firefox_version . unwrap ( ) ) )
236+ } )
237+ . map ( |r| r. geckodriver_version )
238+ . collect ( ) ;
239+ self . log . debug ( format ! (
240+ "Valid {} versions for {} {}: {:?}" ,
241+ & self . driver_name,
242+ & self . browser_name,
243+ major_browser_version_int,
244+ filtered_versions
245+ ) ) ;
246+ if filtered_versions. is_empty ( ) {
247+ return Err ( anyhow ! ( format!(
248+ "Not valid {} version found for {} {}" ,
249+ & self . driver_name, & self . browser_name, major_browser_version_int
250+ ) ) ) ;
251+ } else {
252+ filtered_versions. first ( ) . unwrap ( ) . to_string ( )
253+ }
254+ } else {
255+ self . log . warn ( format ! (
256+ "Problem reading {} versions: {}. Using latest {} version" ,
257+ & self . driver_name,
258+ driver_releases_result. err( ) . unwrap( ) ,
259+ & self . driver_name,
260+ ) ) ;
261+ let latest_url = format ! (
262+ "{}{}" ,
263+ self . get_driver_mirror_url_or_default( DRIVER_URL ) ,
264+ LATEST_RELEASE
265+ ) ;
266+ read_redirect_from_link ( self . get_http_client ( ) , latest_url, self . get_logger ( ) ) ?
267+ } ;
222268
223269 let driver_ttl = self . get_ttl ( ) ;
224270 if driver_ttl > 0 && !major_browser_version. is_empty ( ) {
@@ -545,6 +591,22 @@ impl SeleniumManager for FirefoxManager {
545591 }
546592}
547593
594+ #[ derive( Serialize , Deserialize , Debug ) ]
595+ pub struct GeckodriverReleases {
596+ #[ serde( rename = "geckodriver-releases" ) ]
597+ pub geckodriver_releases : Vec < GeckodriverRelease > ,
598+ }
599+
600+ #[ derive( Serialize , Deserialize , Debug ) ]
601+ pub struct GeckodriverRelease {
602+ #[ serde( rename = "geckodriver-version" ) ]
603+ pub geckodriver_version : String ,
604+ #[ serde( rename = "min-firefox-version" ) ]
605+ pub min_firefox_version : u32 ,
606+ #[ serde( rename = "max-firefox-version" ) ]
607+ pub max_firefox_version : Option < u32 > ,
608+ }
609+
548610#[ cfg( test) ]
549611mod unit_tests {
550612 use super :: * ;
0 commit comments