Bug 1396821 - [geckodriver] Apply rustfmt other geckodriver modules. r=ato

MozReview-Commit-ID: IW15TkjVeLT

--HG--
extra : rebase_source : 12f26d848d34f979a696191eb2fe1eeb8835019b
This commit is contained in:
Henrik Skupin 2018-08-20 16:36:27 +02:00
parent 35d04474d0
commit 1fc0887dc1
3 changed files with 225 additions and 163 deletions

View File

@ -11,9 +11,9 @@ use std::collections::BTreeMap;
use std::default::Default;
use std::error::Error;
use std::fs;
use std::io;
use std::io::BufWriter;
use std::io::Cursor;
use std::io;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::str::{self, FromStr};
@ -34,7 +34,6 @@ pub struct FirefoxCapabilities<'a> {
version_cache: BTreeMap<PathBuf, String>,
}
impl<'a> FirefoxCapabilities<'a> {
pub fn new(fallback_binary: Option<&'a PathBuf>) -> FirefoxCapabilities<'a> {
FirefoxCapabilities {
@ -69,8 +68,7 @@ impl<'a> FirefoxCapabilities<'a> {
});
if let Some(ref version) = rv {
debug!("Found version {}", version);
self.version_cache
.insert(binary.clone(), version.clone());
self.version_cache.insert(binary.clone(), version.clone());
} else {
debug!("Failed to get binary version");
}
@ -81,7 +79,8 @@ impl<'a> FirefoxCapabilities<'a> {
}
fn version_from_binary(&self, binary: &PathBuf) -> Option<String> {
let version_regexp = Regex::new(r#"\d+\.\d+(?:[a-z]\d+)?"#).expect("Error parsing version regexp");
let version_regexp =
Regex::new(r#"\d+\.\d+(?:[a-z]\d+)?"#).expect("Error parsing version regexp");
let output = Command::new(binary)
.args(&["-version"])
.stdout(Stdio::piped())
@ -90,7 +89,8 @@ impl<'a> FirefoxCapabilities<'a> {
.ok();
if let Some(x) = output {
version_regexp.captures(&*x.stdout)
version_regexp
.captures(&*x.stdout)
.and_then(|captures| captures.get(0))
.and_then(|m| str::from_utf8(m.as_bytes()).ok())
.map(|x| x.into())
@ -104,7 +104,8 @@ impl<'a> FirefoxCapabilities<'a> {
fn convert_version_error(err: mozversion::Error) -> WebDriverError {
WebDriverError::new(
ErrorStatus::SessionNotCreated,
err.description().to_string())
err.description().to_string(),
)
}
impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> {
@ -122,8 +123,8 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> {
fn platform_name(&mut self, _: &Capabilities) -> WebDriverResult<Option<String>> {
Ok(if cfg!(target_os = "windows") {
Some("windows".into())
} else if cfg!(target_os = "macos") {
Some("windows".into())
} else if cfg!(target_os = "macos") {
Some("mac".into())
} else if cfg!(target_os = "linux") {
Some("linux".into())
@ -145,10 +146,11 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> {
Ok(true)
}
fn compare_browser_version(&mut self,
version: &str,
comparison: &str)
-> WebDriverResult<bool> {
fn compare_browser_version(
&mut self,
version: &str,
comparison: &str,
) -> WebDriverResult<bool> {
try!(Version::from_str(version).or_else(|x| Err(convert_version_error(x))))
.matches(comparison)
.or_else(|x| Err(convert_version_error(x)))
@ -158,78 +160,100 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> {
Ok(true)
}
fn validate_custom(&self, name: &str, value: &Value) -> WebDriverResult<()> {
fn validate_custom(&self, name: &str, value: &Value) -> WebDriverResult<()> {
if !name.starts_with("moz:") {
return Ok(())
return Ok(());
}
match name {
"moz:firefoxOptions" => {
let data = try_opt!(value.as_object(),
ErrorStatus::InvalidArgument,
"moz:firefoxOptions is not an object");
let data = try_opt!(
value.as_object(),
ErrorStatus::InvalidArgument,
"moz:firefoxOptions is not an object"
);
for (key, value) in data.iter() {
match &**key {
"binary" => {
if !value.is_string() {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
"binary path is not a string"));
"binary path is not a string",
));
}
},
}
"args" => {
if !try_opt!(value.as_array(),
ErrorStatus::InvalidArgument,
"args is not an array")
.iter()
.all(|value| value.is_string()) {
if !try_opt!(
value.as_array(),
ErrorStatus::InvalidArgument,
"args is not an array"
).iter()
.all(|value| value.is_string())
{
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
"args entry is not a string"));
}
},
"args entry is not a string",
));
}
}
"profile" => {
if !value.is_string() {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
"profile is not a string"));
"profile is not a string",
));
}
},
}
"log" => {
let log_data = try_opt!(value.as_object(),
ErrorStatus::InvalidArgument,
"log value is not an object");
let log_data = try_opt!(
value.as_object(),
ErrorStatus::InvalidArgument,
"log value is not an object"
);
for (log_key, log_value) in log_data.iter() {
match &**log_key {
"level" => {
let level = try_opt!(log_value.as_str(),
ErrorStatus::InvalidArgument,
"log level is not a string");
let level = try_opt!(
log_value.as_str(),
ErrorStatus::InvalidArgument,
"log level is not a string"
);
if Level::from_str(level).is_err() {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
format!("Not a valid log level: {}", level)))
format!("Not a valid log level: {}", level),
));
}
}
x => return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
format!("Invalid log field {}", x)))
x => {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
format!("Invalid log field {}", x),
))
}
}
}
},
"prefs" => {
let prefs_data = try_opt!(value.as_object(),
ErrorStatus::InvalidArgument,
"prefs value is not an object");
if !prefs_data.values()
.all(|x| x.is_string() || x.is_i64() || x.is_u64() || x.is_boolean()) {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
"Preference values not all string or integer or boolean"));
}
}
x => return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
format!("Invalid moz:firefoxOptions field {}", x)))
"prefs" => {
let prefs_data = try_opt!(
value.as_object(),
ErrorStatus::InvalidArgument,
"prefs value is not an object"
);
if !prefs_data.values().all(|x| {
x.is_string() || x.is_i64() || x.is_u64() || x.is_boolean()
}) {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
"Preference values not all string or integer or boolean",
));
}
}
x => {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
format!("Invalid moz:firefoxOptions field {}", x),
))
}
}
}
}
@ -237,18 +261,24 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> {
if !value.is_boolean() {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
"moz:useNonSpecCompliantPointerOrigin is not a boolean"));
"moz:useNonSpecCompliantPointerOrigin is not a boolean",
));
}
}
"moz:webdriverClick" => {
if !value.is_boolean() {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
"moz:webdriverClick is not a boolean"));
"moz:webdriverClick is not a boolean",
));
}
}
_ => return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
format!("Unrecognised option {}", name)))
_ => {
return Err(WebDriverError::new(
ErrorStatus::InvalidArgument,
format!("Unrecognised option {}", name),
))
}
}
Ok(())
}
@ -278,17 +308,19 @@ impl FirefoxOptions {
Default::default()
}
pub fn from_capabilities(binary_path: Option<PathBuf>,
matched: &mut Capabilities)
-> WebDriverResult<FirefoxOptions> {
pub fn from_capabilities(
binary_path: Option<PathBuf>,
matched: &mut Capabilities,
) -> WebDriverResult<FirefoxOptions> {
let mut rv = FirefoxOptions::new();
rv.binary = binary_path;
if let Some(json) = matched.remove("moz:firefoxOptions") {
let options = try!(json.as_object()
.ok_or(WebDriverError::new(ErrorStatus::InvalidArgument,
"'moz:firefoxOptions' \
capability is not an object")));
let options = try!(json.as_object().ok_or(WebDriverError::new(
ErrorStatus::InvalidArgument,
"'moz:firefoxOptions' \
capability is not an object"
)));
rv.profile = try!(FirefoxOptions::load_profile(&options));
rv.args = try!(FirefoxOptions::load_args(&options));
@ -301,21 +333,22 @@ impl FirefoxOptions {
fn load_profile(options: &Capabilities) -> WebDriverResult<Option<Profile>> {
if let Some(profile_json) = options.get("profile") {
let profile_base64 =
try!(profile_json
.as_str()
.ok_or(WebDriverError::new(ErrorStatus::UnknownError,
"Profile is not a string")));
let profile_base64 = try!(profile_json.as_str().ok_or(WebDriverError::new(
ErrorStatus::UnknownError,
"Profile is not a string"
)));
let profile_zip = &*try!(base64::decode(profile_base64));
// Create an emtpy profile directory
let profile = try!(Profile::new(None));
try!(unzip_buffer(profile_zip,
profile
.temp_dir
.as_ref()
.expect("Profile doesn't have a path")
.path()));
try!(unzip_buffer(
profile_zip,
profile
.temp_dir
.as_ref()
.expect("Profile doesn't have a path")
.path()
));
Ok(Some(profile))
} else {
@ -325,18 +358,22 @@ impl FirefoxOptions {
fn load_args(options: &Capabilities) -> WebDriverResult<Option<Vec<String>>> {
if let Some(args_json) = options.get("args") {
let args_array = try!(args_json
.as_array()
.ok_or(WebDriverError::new(ErrorStatus::UnknownError,
"Arguments were not an \
array")));
let args = try!(args_array
.iter()
.map(|x| x.as_str().map(|x| x.to_owned()))
.collect::<Option<Vec<String>>>()
.ok_or(WebDriverError::new(ErrorStatus::UnknownError,
"Arguments entries were not all \
strings")));
let args_array = try!(args_json.as_array().ok_or(WebDriverError::new(
ErrorStatus::UnknownError,
"Arguments were not an \
array"
)));
let args = try!(
args_array
.iter()
.map(|x| x.as_str().map(|x| x.to_owned()))
.collect::<Option<Vec<String>>>()
.ok_or(WebDriverError::new(
ErrorStatus::UnknownError,
"Arguments entries were not all \
strings"
))
);
Ok(Some(args))
} else {
Ok(None)
@ -372,10 +409,10 @@ impl FirefoxOptions {
pub fn load_prefs(options: &Capabilities) -> WebDriverResult<Vec<(String, Pref)>> {
if let Some(prefs_data) = options.get("prefs") {
let prefs = try!(prefs_data
.as_object()
.ok_or(WebDriverError::new(ErrorStatus::UnknownError,
"Prefs were not an object")));
let prefs = try!(prefs_data.as_object().ok_or(WebDriverError::new(
ErrorStatus::UnknownError,
"Prefs were not an object"
)));
let mut rv = Vec::with_capacity(prefs.len());
for (key, value) in prefs.iter() {
rv.push((key.clone(), try!(pref_from_json(value))));
@ -392,21 +429,25 @@ fn pref_from_json(value: &Value) -> WebDriverResult<Pref> {
&Value::String(ref x) => Ok(Pref::new(x.clone())),
&Value::Number(ref x) => Ok(Pref::new(x.as_i64().unwrap())),
&Value::Bool(x) => Ok(Pref::new(x)),
_ => Err(WebDriverError::new(ErrorStatus::UnknownError,
"Could not convert pref value to string, boolean, or integer"))
_ => Err(WebDriverError::new(
ErrorStatus::UnknownError,
"Could not convert pref value to string, boolean, or integer",
)),
}
}
fn unzip_buffer(buf: &[u8], dest_dir: &Path) -> WebDriverResult<()> {
let reader = Cursor::new(buf);
let mut zip = try!(zip::ZipArchive::new(reader).map_err(|_| {
WebDriverError::new(ErrorStatus::UnknownError, "Failed to unzip profile")
}));
let mut zip = try!(
zip::ZipArchive::new(reader)
.map_err(|_| WebDriverError::new(ErrorStatus::UnknownError, "Failed to unzip profile"))
);
for i in 0..zip.len() {
let mut file = try!(zip.by_index(i).map_err(|_| {
WebDriverError::new(ErrorStatus::UnknownError, "Processing profile zip file failed")
}));
let mut file = try!(zip.by_index(i).map_err(|_| WebDriverError::new(
ErrorStatus::UnknownError,
"Processing profile zip file failed"
)));
let unzip_path = {
let name = file.name();
let is_dir = name.ends_with("/");
@ -486,8 +527,10 @@ mod tests {
println!("{:#?}", prefs.prefs);
assert_eq!(prefs.get("startup.homepage_welcome_url"),
Some(&Pref::new("data:text/html,PASS")));
assert_eq!(
prefs.get("startup.homepage_welcome_url"),
Some(&Pref::new("data:text/html,PASS"))
);
}
#[test]

View File

@ -279,7 +279,10 @@ mod tests {
];
for &(lvl, s) in tests.iter() {
let expected = Pref { value: PrefValue::String(s.to_string()), sticky: false };
let expected = Pref {
value: PrefValue::String(s.to_string()),
sticky: false,
};
assert_eq!(Into::<Pref>::into(lvl), expected);
}
}

View File

@ -14,8 +14,8 @@ extern crate serde;
extern crate serde_derive;
extern crate serde_json;
extern crate uuid;
extern crate zip;
extern crate webdriver;
extern crate zip;
#[macro_use]
extern crate log;
@ -28,25 +28,25 @@ use std::str::FromStr;
use clap::{App, Arg};
macro_rules! try_opt {
($expr:expr, $err_type:expr, $err_msg:expr) => ({
($expr:expr, $err_type:expr, $err_msg:expr) => {{
match $expr {
Some(x) => x,
None => return Err(WebDriverError::new($err_type, $err_msg))
None => return Err(WebDriverError::new($err_type, $err_msg)),
}
})
}};
}
mod build;
mod logging;
mod prefs;
mod marionette;
mod capabilities;
mod logging;
mod marionette;
mod prefs;
#[cfg(test)]
pub mod test;
use build::BuildInfo;
use marionette::{MarionetteHandler, MarionetteSettings, extension_routes};
use marionette::{extension_routes, MarionetteHandler, MarionetteSettings};
type ProgramResult = std::result::Result<(), (ExitCode, String)>;
@ -69,52 +69,70 @@ fn print_version() {
fn app<'a, 'b>() -> App<'a, 'b> {
App::new(format!("geckodriver {}", crate_version!()))
.about("WebDriver implementation for Firefox.")
.arg(Arg::with_name("webdriver_host")
.long("host")
.value_name("HOST")
.help("Host ip to use for WebDriver server (default: 127.0.0.1)")
.takes_value(true))
.arg(Arg::with_name("webdriver_port")
.short("p")
.long("port")
.value_name("PORT")
.help("Port to use for WebDriver server (default: 4444)")
.takes_value(true)
.alias("webdriver-port"))
.arg(Arg::with_name("binary")
.short("b")
.long("binary")
.value_name("BINARY")
.help("Path to the Firefox binary")
.takes_value(true))
.arg(Arg::with_name("marionette_port")
.long("marionette-port")
.value_name("PORT")
.help("Port to use to connect to Gecko (default: random free port)")
.takes_value(true))
.arg(Arg::with_name("connect_existing")
.long("connect-existing")
.requires("marionette_port")
.help("Connect to an existing Firefox instance"))
.arg(Arg::with_name("jsdebugger")
.long("jsdebugger")
.takes_value(false)
.help("Attach browser toolbox debugger for Firefox"))
.arg(Arg::with_name("verbosity")
.short("v")
.multiple(true)
.conflicts_with("log_level")
.help("Log level verbosity (-v for debug and -vv for trace level)"))
.arg(Arg::with_name("log_level")
.long("log")
.takes_value(true)
.value_name("LEVEL")
.possible_values(&["fatal", "error", "warn", "info", "config", "debug", "trace"])
.help("Set Gecko log level"))
.arg(Arg::with_name("version")
.short("V")
.long("version")
.help("Prints version and copying information"))
.arg(
Arg::with_name("webdriver_host")
.long("host")
.value_name("HOST")
.help("Host ip to use for WebDriver server (default: 127.0.0.1)")
.takes_value(true),
)
.arg(
Arg::with_name("webdriver_port")
.short("p")
.long("port")
.value_name("PORT")
.help("Port to use for WebDriver server (default: 4444)")
.takes_value(true)
.alias("webdriver-port"),
)
.arg(
Arg::with_name("binary")
.short("b")
.long("binary")
.value_name("BINARY")
.help("Path to the Firefox binary")
.takes_value(true),
)
.arg(
Arg::with_name("marionette_port")
.long("marionette-port")
.value_name("PORT")
.help("Port to use to connect to Gecko (default: random free port)")
.takes_value(true),
)
.arg(
Arg::with_name("connect_existing")
.long("connect-existing")
.requires("marionette_port")
.help("Connect to an existing Firefox instance"),
)
.arg(
Arg::with_name("jsdebugger")
.long("jsdebugger")
.takes_value(false)
.help("Attach browser toolbox debugger for Firefox"),
)
.arg(
Arg::with_name("verbosity")
.short("v")
.multiple(true)
.conflicts_with("log_level")
.help("Log level verbosity (-v for debug and -vv for trace level)"),
)
.arg(
Arg::with_name("log_level")
.long("log")
.takes_value(true)
.value_name("LEVEL")
.possible_values(&["fatal", "error", "warn", "info", "config", "debug", "trace"])
.help("Set Gecko log level"),
)
.arg(
Arg::with_name("version")
.short("V")
.long("version")
.help("Prints version and copying information"),
)
}
fn run() -> ProgramResult {
@ -143,12 +161,10 @@ fn run() -> ProgramResult {
let binary = matches.value_of("binary").map(|x| PathBuf::from(x));
let marionette_port = match matches.value_of("marionette_port") {
Some(x) => {
match u16::from_str(x) {
Ok(x) => Some(x),
Err(_) => return Err((ExitCode::Usage, "invalid Marionette port".into())),
}
}
Some(x) => match u16::from_str(x) {
Ok(x) => Some(x),
Err(_) => return Err((ExitCode::Usage, "invalid Marionette port".into())),
},
None => None,
};