@@ -20,7 +20,8 @@ use crate::config::ManagerConfig;
20
20
use crate :: config:: ARCH :: { ARM64 , X32 } ;
21
21
use crate :: config:: OS :: { LINUX , MACOS , WINDOWS } ;
22
22
use 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,
24
25
} ;
25
26
use crate :: files:: { compose_driver_path_in_cache, BrowserPath } ;
26
27
use crate :: metadata:: {
@@ -33,13 +34,16 @@ use crate::{
33
34
use anyhow:: anyhow;
34
35
use anyhow:: Error ;
35
36
use reqwest:: Client ;
37
+ use serde:: Deserialize ;
38
+ use serde:: Serialize ;
36
39
use std:: collections:: HashMap ;
37
40
use std:: path:: PathBuf ;
38
41
39
42
pub const FIREFOX_NAME : & str = "firefox" ;
40
43
pub const GECKODRIVER_NAME : & str = "geckodriver" ;
41
44
const DRIVER_URL : & str = "https://github.com/mozilla/geckodriver/releases/" ;
42
45
const LATEST_RELEASE : & str = "latest" ;
46
+ const DRIVER_VERSIONS_URL : & str = "https://raw.githubusercontent.com/SeleniumHQ/selenium/trunk/common/geckodriver/geckodriver-support.json" ;
43
47
const BROWSER_URL : & str = "https://ftp.mozilla.org/pub/firefox/releases/" ;
44
48
const FIREFOX_DEFAULT_LANG : & str = "en-US" ;
45
49
const FIREFOX_MACOS_APP_NAME : & str = "Firefox.app/Contents/MacOS/firefox" ;
@@ -212,13 +216,55 @@ impl SeleniumManager for FirefoxManager {
212
216
_ => {
213
217
self . assert_online_or_err ( OFFLINE_REQUEST_ERR_MSG ) ?;
214
218
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 ( ) ,
219
222
) ;
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
+ } ;
222
268
223
269
let driver_ttl = self . get_ttl ( ) ;
224
270
if driver_ttl > 0 && !major_browser_version. is_empty ( ) {
@@ -545,6 +591,22 @@ impl SeleniumManager for FirefoxManager {
545
591
}
546
592
}
547
593
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
+
548
610
#[ cfg( test) ]
549
611
mod unit_tests {
550
612
use super :: * ;
0 commit comments