Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions rust/src/chrome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use std::path::PathBuf;

use crate::config::ARCH::ARM64;
use crate::config::OS::{LINUX, MACOS, WINDOWS};
use crate::downloads::read_content_from_link;
use crate::downloads::read_version_from_link;
use crate::files::{compose_driver_path_in_cache, BrowserPath, PARSE_ERROR};
use crate::logger::Logger;
use crate::metadata::{
Expand Down Expand Up @@ -176,7 +176,7 @@ impl SeleniumManager for ChromeManager {
"Reading {} version from {}",
&self.driver_name, driver_url
));
match read_content_from_link(self.get_http_client(), driver_url) {
match read_version_from_link(self.get_http_client(), driver_url) {
Ok(version) => {
driver_version = version;
break;
Expand Down
6 changes: 5 additions & 1 deletion rust/src/downloads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,16 @@ pub async fn download_driver_to_tmp_folder(
Ok((tmp_dir, target_path))
}

pub fn read_version_from_link(http_client: &Client, url: String) -> Result<String, Box<dyn Error>> {
parse_version(read_content_from_link(http_client, url)?)
}

#[tokio::main]
pub async fn read_content_from_link(
http_client: &Client,
url: String,
) -> Result<String, Box<dyn Error>> {
parse_version(http_client.get(url).send().await?.text().await?)
Ok(http_client.get(url).send().await?.text().await?)
}

#[tokio::main]
Expand Down
4 changes: 2 additions & 2 deletions rust/src/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use std::path::PathBuf;

use crate::config::ARCH::{ARM64, X32};
use crate::config::OS::{LINUX, MACOS, WINDOWS};
use crate::downloads::read_content_from_link;
use crate::downloads::read_version_from_link;
use crate::files::{compose_driver_path_in_cache, BrowserPath};
use crate::metadata::{
create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata,
Expand Down Expand Up @@ -176,7 +176,7 @@ impl SeleniumManager for EdgeManager {
"Reading {} version from {}",
&self.driver_name, driver_url
));
let driver_version = read_content_from_link(self.get_http_client(), driver_url)?;
let driver_version = read_version_from_link(self.get_http_client(), driver_url)?;

if !browser_version.is_empty() {
metadata.drivers.push(create_driver_metadata(
Expand Down
3 changes: 3 additions & 0 deletions rust/src/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,5 +192,8 @@ pub fn parse_version(version_text: String) -> Result<String, Box<dyn Error>> {
break;
}
}
if parsed_version.ends_with('.') {
parsed_version = parsed_version[0..parsed_version.len() - 1].to_string();
}
Ok(parsed_version)
}
89 changes: 69 additions & 20 deletions rust/src/iexplorer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@

use crate::config::ManagerConfig;
use reqwest::Client;
use std::cell::RefCell;
use std::collections::HashMap;
use std::error::Error;
use std::path::PathBuf;

use crate::downloads::read_redirect_from_link;
use crate::files::{compose_driver_path_in_cache, BrowserPath};

use crate::{create_default_http_client, Logger, SeleniumManager};
use crate::{create_default_http_client, parse_version, Logger, SeleniumManager};

use crate::metadata::{
create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata,
};
use crate::mirror::{get_mirror_response, Assets, SeleniumRelease};

pub const IE_NAMES: &[&str] = &[
"iexplorer",
Expand All @@ -39,7 +40,9 @@ pub const IE_NAMES: &[&str] = &[
];
pub const IEDRIVER_NAME: &str = "IEDriverServer";
const DRIVER_URL: &str = "https://github.com/SeleniumHQ/selenium/releases/";
const LATEST_RELEASE: &str = "latest";
const IEDRIVER_RELEASE: &str = "IEDriverServer_Win32_";

thread_local!(static RELEASE_URL: RefCell<String> = RefCell::new("".to_string()));

pub struct IExplorerManager {
pub browser_name: &'static str,
Expand Down Expand Up @@ -100,29 +103,75 @@ impl SeleniumManager for IExplorerManager {
Ok(driver_version)
}
_ => {
let latest_url = format!("{}{}", DRIVER_URL, LATEST_RELEASE);
let driver_version = read_redirect_from_link(self.get_http_client(), latest_url)?;

if !browser_version.is_empty() {
metadata.drivers.push(create_driver_metadata(
browser_version,
self.driver_name,
&driver_version,
));
write_metadata(&metadata, self.get_logger());
let selenium_releases = get_mirror_response(self.get_http_client())?;

let filtered_releases: Vec<SeleniumRelease> = selenium_releases
.into_iter()
.filter(|r| {
r.assets
.iter()
.any(|url| url.browser_download_url.contains(IEDRIVER_RELEASE))
})
.collect();

if !filtered_releases.is_empty() {
let assets = &filtered_releases.get(0).unwrap().assets;
let driver_releases: Vec<&Assets> = assets
.iter()
.filter(|url| url.browser_download_url.contains(IEDRIVER_RELEASE))
.collect();
let driver_url = &driver_releases.last().unwrap().browser_download_url;
RELEASE_URL.with(|url| {
*url.borrow_mut() = driver_url.to_string();
});

let index_release =
driver_url.rfind(IEDRIVER_RELEASE).unwrap() + IEDRIVER_RELEASE.len();
let driver_version =
parse_version(driver_url.as_str()[index_release..].to_string())?;

if !browser_version.is_empty() {
metadata.drivers.push(create_driver_metadata(
browser_version,
self.driver_name,
&driver_version,
));
write_metadata(&metadata, self.get_logger());
}

Ok(driver_version)
} else {
Err(format!("{} release not available", self.get_driver_name()).into())
}

Ok(driver_version)
}
}
}

fn get_driver_url(&self) -> Result<String, Box<dyn Error>> {
let driver_version = self.get_driver_version();
Ok(format!(
"{}download/selenium-{}/IEDriverServer_Win32_{}.zip",
DRIVER_URL, driver_version, driver_version
))
let mut driver_url = "".to_string();
RELEASE_URL.with(|url| {
driver_url = url.borrow().to_string();
});
if driver_url.is_empty() {
let driver_version = self.get_driver_version();
let mut release_version = driver_version.to_string();
if !driver_version.ends_with('0') {
// E.g.: version 4.8.1 is shipped within release 4.8.0
let error_message = format!(
"Wrong {} version: '{}'",
self.get_driver_name(),
driver_version
);
let index = release_version.rfind('.').ok_or(error_message)? + 1;
release_version = release_version[..index].to_string();
release_version.push('0');
}
driver_url = format!(
"{}download/selenium-{}/{}{}.zip",
DRIVER_URL, release_version, IEDRIVER_RELEASE, driver_version
);
}
Ok(driver_url)
}

fn get_driver_path_in_cache(&self) -> PathBuf {
Expand Down
1 change: 1 addition & 0 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub mod firefox;
pub mod iexplorer;
pub mod logger;
pub mod metadata;
pub mod mirror;
pub mod safari;
pub mod safaritp;

Expand Down
41 changes: 41 additions & 0 deletions rust/src/mirror.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

use crate::downloads::read_content_from_link;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::error::Error;

pub const MIRROR_URL: &str =
"https://raw.githubusercontent.com/SeleniumHQ/selenium/trunk/common/mirror/selenium";

#[derive(Serialize, Deserialize)]
pub struct Assets {
pub browser_download_url: String,
}

#[derive(Serialize, Deserialize)]
pub struct SeleniumRelease {
pub tag_name: String,
pub assets: Vec<Assets>,
}

pub fn get_mirror_response(http_client: &Client) -> Result<Vec<SeleniumRelease>, Box<dyn Error>> {
let content = read_content_from_link(http_client, MIRROR_URL.to_string())?;
let mirror_response: Vec<SeleniumRelease> = serde_json::from_str(&content)?;
Ok(mirror_response)
}
36 changes: 36 additions & 0 deletions rust/tests/iexplorer_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

use assert_cmd::Command;

use rstest::rstest;

#[rstest]
#[case("4.8.0")]
#[case("4.8.1")]
fn iexplorer_test(#[case] driver_version: String) {
let mut cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap();
let cmd_assert = cmd
.args([
"--browser",
"iexplorer",
"--driver-version",
&driver_version,
])
.assert();
cmd_assert.success();
}