diff options
author | Henrik Skupin <mail@hskupin.info> | 2021-09-16 15:51:52 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-16 15:51:52 +0300 |
commit | d06ed1be13ef77e4f75ef06beb6ab829e2eef191 (patch) | |
tree | 9de4504cf6ac3855b904127451145faa31d544b9 /src/capabilities.rs | |
parent | 87fc845210fceb8b8dfcb28ca09335e99e240698 (diff) |
Import of v0.30.0 (#1931)v0.30.0
Diffstat (limited to 'src/capabilities.rs')
-rw-r--r-- | src/capabilities.rs | 288 |
1 files changed, 186 insertions, 102 deletions
diff --git a/src/capabilities.rs b/src/capabilities.rs index a409cfe..278530e 100644 --- a/src/capabilities.rs +++ b/src/capabilities.rs @@ -4,16 +4,18 @@ use crate::command::LogOptions; use crate::logging::Level; -use base64; +use crate::marionette::MarionetteSettings; use mozdevice::AndroidStorageInput; use mozprofile::preferences::Pref; use mozprofile::profile::Profile; +use mozrunner::firefox_args::{get_arg_value, parse_args, Arg}; use mozrunner::runner::platform::firefox_default_path; use mozversion::{self, firefox_binary_version, firefox_version, Version}; use regex::bytes::Regex; use serde_json::{Map, Value}; use std::collections::BTreeMap; use std::default::Default; +use std::ffi::OsString; use std::fmt::{self, Display}; use std::fs; use std::io; @@ -23,7 +25,6 @@ use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; use webdriver::capabilities::{BrowserCapabilities, Capabilities}; use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult}; -use zip; #[derive(Clone, Debug)] enum VersionError { @@ -154,6 +155,10 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> { Ok(true) } + fn accept_proxy(&mut self, _: &Capabilities, _: &Capabilities) -> WebDriverResult<bool> { + Ok(true) + } + fn set_window_rect(&mut self, _: &Capabilities) -> WebDriverResult<bool> { Ok(true) } @@ -164,7 +169,7 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> { comparison: &str, ) -> WebDriverResult<bool> { Version::from_str(version) - .map_err(|err| VersionError::from(err))? + .map_err(VersionError::from)? .matches(comparison) .map_err(|err| VersionError::from(err).into()) } @@ -173,8 +178,10 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> { Ok(true) } - fn accept_proxy(&mut self, _: &Capabilities, _: &Capabilities) -> WebDriverResult<bool> { - Ok(true) + fn web_socket_url(&mut self, caps: &Capabilities) -> WebDriverResult<bool> { + self.browser_version(caps)? + .map(|v| self.compare_browser_version(&v, ">=90")) + .unwrap_or(Ok(false)) } fn validate_custom(&mut self, name: &str, value: &Value) -> WebDriverResult<()> { @@ -377,6 +384,7 @@ pub struct FirefoxOptions { pub log: LogOptions, pub prefs: Vec<(String, Pref)>, pub android: Option<AndroidOptions>, + pub use_websocket: bool, } impl FirefoxOptions { @@ -384,9 +392,9 @@ impl FirefoxOptions { Default::default() } - pub fn from_capabilities( + pub(crate) fn from_capabilities( binary_path: Option<PathBuf>, - android_storage: AndroidStorageInput, + settings: &MarionetteSettings, matched: &mut Capabilities, ) -> WebDriverResult<FirefoxOptions> { let mut rv = FirefoxOptions::new(); @@ -401,7 +409,7 @@ impl FirefoxOptions { ) })?; - rv.android = FirefoxOptions::load_android(android_storage, &options)?; + rv.android = FirefoxOptions::load_android(settings.android_storage, &options)?; rv.args = FirefoxOptions::load_args(&options)?; rv.env = FirefoxOptions::load_env(&options)?; rv.log = FirefoxOptions::load_log(&options)?; @@ -409,32 +417,62 @@ impl FirefoxOptions { rv.profile = FirefoxOptions::load_profile(&options)?; } - if let Some(json) = matched.remove("moz:debuggerAddress") { - let use_web_socket = json.as_bool().ok_or_else(|| { - WebDriverError::new( - ErrorStatus::InvalidArgument, - "moz:debuggerAddress is not a boolean", - ) - })?; + if let Some(args) = rv.args.as_ref() { + let os_args = parse_args(args.iter().map(OsString::from).collect::<Vec<_>>().iter()); + if let Some(path) = get_arg_value(os_args.iter(), Arg::Profile) { + if rv.profile.is_some() { + return Err(WebDriverError::new( + ErrorStatus::InvalidArgument, + "Can't provide both a --profile argument and a profile", + )); + } + let path_buf = PathBuf::from(path); + rv.profile = Some(Profile::new_from_path(&path_buf)?); + } - if use_web_socket { - let mut remote_args = Vec::new(); - remote_args.push("--remote-debugging-port".to_owned()); - remote_args.push("0".to_owned()); + if get_arg_value(os_args.iter(), Arg::NamedProfile).is_some() && rv.profile.is_some() { + return Err(WebDriverError::new( + ErrorStatus::InvalidArgument, + "Can't provide both a -P argument and a profile", + )); + } + } - if let Some(ref mut args) = rv.args { - args.append(&mut remote_args); - } else { - rv.args = Some(remote_args); - } + let has_web_socket_url = matched + .get("webSocketUrl") + .and_then(|x| x.as_bool()) + .unwrap_or(false); + + let has_debugger_address = matched + .remove("moz:debuggerAddress") + .and_then(|x| x.as_bool()) + .unwrap_or(false); + + // Set a command line provided port for the Remote Agent for now. + // It needs to be the same on the host and the Android device. + if has_web_socket_url || has_debugger_address { + rv.use_websocket = true; + + // Bug 1722863: Setting of command line arguments would be + // better suited in the individual Browser implementations. + let mut remote_args = Vec::new(); + remote_args.push("--remote-debugging-port".to_owned()); + remote_args.push(settings.websocket_port.to_string()); + + if let Some(ref mut args) = rv.args { + args.append(&mut remote_args); + } else { + rv.args = Some(remote_args); + } + } - // Force Fission disabled until Remote Agent is compatible, - // and preference hasn't been already set - let has_fission_pref = rv.prefs.iter().find(|&x| x.0 == "fission.autostart"); - if has_fission_pref.is_none() { - rv.prefs - .push(("fission.autostart".to_owned(), Pref::new(false))); - } + // Force Fission disabled until the CDP implementation is compatible, + // and preference hasn't been already set + if has_debugger_address { + let has_fission_pref = rv.prefs.iter().find(|&x| x.0 == "fission.autostart"); + if has_fission_pref.is_none() { + rv.prefs + .push(("fission.autostart".to_owned(), Pref::new(false))); } } @@ -597,7 +635,7 @@ impl FirefoxOptions { })? .to_owned(); - if activity.contains("/") { + if activity.contains('/') { return Err(WebDriverError::new( ErrorStatus::InvalidArgument, "androidActivity should not contain '/", @@ -671,7 +709,7 @@ impl FirefoxOptions { "-d".to_string(), "about:blank".to_string(), ]) - }, + } }; Ok(Some(android)) @@ -751,10 +789,7 @@ mod tests { use self::mozprofile::preferences::Pref; use super::*; - use crate::marionette::MarionetteHandler; - use mozdevice::AndroidStorageInput; - use serde_json::json; - use std::default::Default; + use serde_json::{json, Map, Value}; use std::fs::File; use std::io::Read; @@ -767,16 +802,19 @@ mod tests { Value::String(base64::encode(&profile_data)) } - fn make_options(firefox_opts: Capabilities) -> WebDriverResult<FirefoxOptions> { + fn make_options( + firefox_opts: Capabilities, + marionette_settings: Option<MarionetteSettings>, + ) -> WebDriverResult<FirefoxOptions> { let mut caps = Capabilities::new(); caps.insert("moz:firefoxOptions".into(), Value::Object(firefox_opts)); - FirefoxOptions::from_capabilities(None, AndroidStorageInput::Auto, &mut caps) + FirefoxOptions::from_capabilities(None, &marionette_settings.unwrap_or_default(), &mut caps) } #[test] fn fx_options_default() { - let opts = FirefoxOptions::new(); + let opts: FirefoxOptions = Default::default(); assert_eq!(opts.android, None); assert_eq!(opts.args, None); assert_eq!(opts.binary, None); @@ -787,11 +825,12 @@ mod tests { } #[test] - fn fx_options_from_capabilities_no_binary_and_caps() { + fn fx_options_from_capabilities_no_binary_and_empty_caps() { let mut caps = Capabilities::new(); - let opts = - FirefoxOptions::from_capabilities(None, AndroidStorageInput::Auto, &mut caps).unwrap(); + let marionette_settings = Default::default(); + let opts = FirefoxOptions::from_capabilities(None, &marionette_settings, &mut caps) + .expect("valid firefox options"); assert_eq!(opts.android, None); assert_eq!(opts.args, None); assert_eq!(opts.binary, None); @@ -808,13 +847,14 @@ mod tests { ); let binary = PathBuf::from("foo"); + let marionette_settings = Default::default(); let opts = FirefoxOptions::from_capabilities( Some(binary.clone()), - AndroidStorageInput::Auto, + &marionette_settings, &mut caps, ) - .unwrap(); + .expect("valid firefox options"); assert_eq!(opts.android, None); assert_eq!(opts.args, None); assert_eq!(opts.binary, Some(binary)); @@ -823,10 +863,11 @@ mod tests { } #[test] - fn fx_options_from_capabilities_with_debugger_address_not_set() { + fn fx_options_from_capabilities_with_websocket_url_not_set() { let mut caps = Capabilities::new(); - let opts = FirefoxOptions::from_capabilities(None, AndroidStorageInput::Auto, &mut caps) + let marionette_settings = Default::default(); + let opts = FirefoxOptions::from_capabilities(None, &marionette_settings, &mut caps) .expect("Valid Firefox options"); assert!( @@ -836,16 +877,63 @@ mod tests { } #[test] - fn fx_options_from_capabilities_with_debugger_address_false() { + fn fx_options_from_capabilities_with_websocket_url_false() { let mut caps = Capabilities::new(); - caps.insert("moz:debuggerAddress".into(), json!(false)); + caps.insert("webSocketUrl".into(), json!(false)); - let opts = FirefoxOptions::from_capabilities(None, AndroidStorageInput::Auto, &mut caps) + let marionette_settings = Default::default(); + let opts = FirefoxOptions::from_capabilities(None, &marionette_settings, &mut caps) .expect("Valid Firefox options"); assert!( opts.args.is_none(), - "CLI arguments for remote protocol unexpectedly found" + "CLI arguments for Firefox unexpectedly found" + ); + } + + #[test] + fn fx_options_from_capabilities_with_websocket_url_true() { + let mut caps = Capabilities::new(); + caps.insert("webSocketUrl".into(), json!(true)); + + let settings = MarionetteSettings { + websocket_port: 1234, + ..Default::default() + }; + let opts = FirefoxOptions::from_capabilities(None, &settings, &mut caps) + .expect("Valid Firefox options"); + + if let Some(args) = opts.args { + let mut iter = args.iter(); + assert!(iter + .find(|&arg| arg == &"--remote-debugging-port".to_owned()) + .is_some()); + assert_eq!(iter.next(), Some(&"1234".to_owned())); + } else { + assert!(false, "CLI arguments for Firefox not found"); + } + } + + #[test] + fn fx_options_from_capabilities_with_debugger_address_not_set() { + let caps = Capabilities::new(); + + let opts = make_options(caps, None).expect("valid firefox options"); + assert!( + opts.args.is_none(), + "CLI arguments for Firefox unexpectedly found" + ); + } + + #[test] + fn fx_options_from_capabilities_with_debugger_address_false() { + let mut caps = Capabilities::new(); + caps.insert("moz:debuggerAddress".into(), json!(false)); + + let opts = make_options(caps, None).expect("valid firefox options"); + assert!( + opts.args.is_none(), + "CLI arguments for Firefox unexpectedly found" ); } @@ -854,7 +942,11 @@ mod tests { let mut caps = Capabilities::new(); caps.insert("moz:debuggerAddress".into(), json!(true)); - let opts = FirefoxOptions::from_capabilities(None, AndroidStorageInput::Auto, &mut caps) + let settings = MarionetteSettings { + websocket_port: 1234, + ..Default::default() + }; + let opts = FirefoxOptions::from_capabilities(None, &settings, &mut caps) .expect("Valid Firefox options"); if let Some(args) = opts.args { @@ -862,9 +954,9 @@ mod tests { assert!(iter .find(|&arg| arg == &"--remote-debugging-port".to_owned()) .is_some()); - assert_eq!(iter.next(), Some(&"0".to_owned())); + assert_eq!(iter.next(), Some(&"1234".to_owned())); } else { - assert!(false, "CLI arguments for remote protocol not found"); + assert!(false, "CLI arguments for Firefox not found"); } assert!(opts @@ -878,7 +970,8 @@ mod tests { let mut caps = Capabilities::new(); caps.insert("moz:firefoxOptions".into(), json!(42)); - FirefoxOptions::from_capabilities(None, AndroidStorageInput::Auto, &mut caps) + let marionette_settings = Default::default(); + FirefoxOptions::from_capabilities(None, &marionette_settings, &mut caps) .expect_err("Firefox options need to be of type object"); } @@ -887,7 +980,7 @@ mod tests { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("androidAvtivity".into(), json!("foo")); - let opts = make_options(firefox_opts).expect("valid firefox options"); + let opts = make_options(firefox_opts, None).expect("valid firefox options"); assert_eq!(opts.android, None); } @@ -897,7 +990,7 @@ mod tests { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("androidPackage".into(), json!(value)); - let opts = make_options(firefox_opts).expect("valid firefox options"); + let opts = make_options(firefox_opts, None).expect("valid firefox options"); assert_eq!(opts.android.unwrap().package, value.to_string()); } } @@ -907,7 +1000,7 @@ mod tests { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("androidPackage".into(), json!(42)); - make_options(firefox_opts).expect_err("invalid firefox options"); + make_options(firefox_opts, None).expect_err("invalid firefox options"); } #[test] @@ -915,7 +1008,7 @@ mod tests { for value in ["../foo", "\\foo\n", "foo", "_foo", "0foo"].iter() { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("androidPackage".into(), json!(value)); - make_options(firefox_opts).expect_err("invalid firefox options"); + make_options(firefox_opts, None).expect_err("invalid firefox options"); } } @@ -937,7 +1030,7 @@ mod tests { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("androidPackage".into(), json!(package)); - let opts = make_options(firefox_opts).expect("valid firefox options"); + let opts = make_options(firefox_opts, None).expect("valid firefox options"); assert!(opts .android .unwrap() @@ -955,7 +1048,7 @@ mod tests { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("androidPackage".into(), json!(package)); - let opts = make_options(firefox_opts).expect("valid firefox options"); + let opts = make_options(firefox_opts, None).expect("valid firefox options"); assert_eq!(opts.android.unwrap().activity, None); } @@ -965,7 +1058,7 @@ mod tests { json!("org.mozilla.geckoview_example"), ); - let opts = make_options(firefox_opts).expect("valid firefox options"); + let opts = make_options(firefox_opts, None).expect("valid firefox options"); assert_eq!(opts.android.unwrap().activity, None); } @@ -975,7 +1068,7 @@ mod tests { firefox_opts.insert("androidPackage".into(), json!("foo.bar")); firefox_opts.insert("androidActivity".into(), json!("foo")); - let opts = make_options(firefox_opts).expect("valid firefox options"); + let opts = make_options(firefox_opts, None).expect("valid firefox options"); assert_eq!(opts.android.unwrap().activity, Some("foo".to_string())); } @@ -985,7 +1078,7 @@ mod tests { firefox_opts.insert("androidPackage".into(), json!("foo.bar")); firefox_opts.insert("androidActivity".into(), json!(42)); - make_options(firefox_opts).expect_err("invalid firefox options"); + make_options(firefox_opts, None).expect_err("invalid firefox options"); } #[test] @@ -994,7 +1087,7 @@ mod tests { firefox_opts.insert("androidPackage".into(), json!("foo.bar")); firefox_opts.insert("androidActivity".into(), json!("foo.bar/cheese")); - make_options(firefox_opts).expect_err("invalid firefox options"); + make_options(firefox_opts, None).expect_err("invalid firefox options"); } #[test] @@ -1003,7 +1096,7 @@ mod tests { firefox_opts.insert("androidPackage".into(), json!("foo.bar")); firefox_opts.insert("androidDeviceSerial".into(), json!("cheese")); - let opts = make_options(firefox_opts).expect("valid firefox options"); + let opts = make_options(firefox_opts, None).expect("valid firefox options"); assert_eq!( opts.android.unwrap().device_serial, Some("cheese".to_string()) @@ -1016,7 +1109,7 @@ mod tests { firefox_opts.insert("androidPackage".into(), json!("foo.bar")); firefox_opts.insert("androidDeviceSerial".into(), json!(42)); - make_options(firefox_opts).expect_err("invalid firefox options"); + make_options(firefox_opts, None).expect_err("invalid firefox options"); } #[test] @@ -1035,7 +1128,7 @@ mod tests { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("androidPackage".into(), json!(package)); - let opts = make_options(firefox_opts).expect("valid firefox options"); + let opts = make_options(firefox_opts, None).expect("valid firefox options"); assert_eq!( opts.android.unwrap().intent_arguments, Some(vec![ @@ -1054,7 +1147,7 @@ mod tests { firefox_opts.insert("androidPackage".into(), json!("foo.bar")); firefox_opts.insert("androidIntentArguments".into(), json!(["lorem", "ipsum"])); - let opts = make_options(firefox_opts).expect("valid firefox options"); + let opts = make_options(firefox_opts, None).expect("valid firefox options"); assert_eq!( opts.android.unwrap().intent_arguments, Some(vec!["lorem".to_string(), "ipsum".to_string()]) @@ -1067,7 +1160,7 @@ mod tests { firefox_opts.insert("androidPackage".into(), json!("foo.bar")); firefox_opts.insert("androidIntentArguments".into(), json!(42)); - make_options(firefox_opts).expect_err("invalid firefox options"); + make_options(firefox_opts, None).expect_err("invalid firefox options"); } #[test] @@ -1076,7 +1169,7 @@ mod tests { firefox_opts.insert("androidPackage".into(), json!("foo.bar")); firefox_opts.insert("androidIntentArguments".into(), json!(["lorem", 42])); - make_options(firefox_opts).expect_err("invalid firefox options"); + make_options(firefox_opts, None).expect_err("invalid firefox options"); } #[test] @@ -1088,7 +1181,7 @@ mod tests { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("env".into(), env.into()); - let mut opts = make_options(firefox_opts).expect("valid firefox options"); + let mut opts = make_options(firefox_opts, None).expect("valid firefox options"); for sorted in opts.env.iter_mut() { sorted.sort() } @@ -1108,7 +1201,7 @@ mod tests { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("env".into(), env.into()); - make_options(firefox_opts).expect_err("invalid firefox options"); + make_options(firefox_opts, None).expect_err("invalid firefox options"); } #[test] @@ -1119,7 +1212,7 @@ mod tests { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("env".into(), env.into()); - make_options(firefox_opts).expect_err("invalid firefox options"); + make_options(firefox_opts, None).expect_err("invalid firefox options"); } #[test] @@ -1128,7 +1221,7 @@ mod tests { let mut firefox_opts = Capabilities::new(); firefox_opts.insert("profile".into(), encoded_profile); - let opts = make_options(firefox_opts).expect("valid firefox options"); + let opts = make_options(firefox_opts, None).expect("valid firefox options"); let mut profile = opts.profile.expect("valid firefox profile"); let prefs = profile.user_prefs().expect("valid preferences"); @@ -1141,37 +1234,28 @@ mod tests { } #[test] - fn test_prefs() { - let encoded_profile = example_profile(); - let mut prefs: Map<String, Value> = Map::new(); - prefs.insert( - "browser.display.background_color".into(), - Value::String("#00ff00".into()), - ); - + fn fx_options_args_profile() { let mut firefox_opts = Capabilities::new(); - firefox_opts.insert("profile".into(), encoded_profile); - firefox_opts.insert("prefs".into(), Value::Object(prefs)); + firefox_opts.insert("args".into(), json!(["--profile", "foo"])); - let opts = make_options(firefox_opts).expect("valid profile and prefs"); - let mut profile = opts.profile.expect("valid firefox profile"); + make_options(firefox_opts, None).expect("Valid args"); + } - let handler = MarionetteHandler::new(Default::default()); - handler - .set_prefs(2828, &mut profile, true, opts.prefs) - .expect("set preferences"); + #[test] + fn fx_options_args_profile_and_profile() { + let mut firefox_opts = Capabilities::new(); + firefox_opts.insert("args".into(), json!(["--profile", "foo"])); + firefox_opts.insert("profile".into(), json!("foo")); - let prefs_set = profile.user_prefs().expect("valid user preferences"); - println!("{:#?}", prefs_set.prefs); + make_options(firefox_opts, None).expect_err("Invalid args"); + } - assert_eq!( - prefs_set.get("startup.homepage_welcome_url"), - Some(&Pref::new("data:text/html,PASS")) - ); - assert_eq!( - prefs_set.get("browser.display.background_color"), - Some(&Pref::new("#00ff00")) - ); - assert_eq!(prefs_set.get("marionette.port"), Some(&Pref::new(2828))); + #[test] + fn fx_options_args_p_and_profile() { + let mut firefox_opts = Capabilities::new(); + firefox_opts.insert("args".into(), json!(["-P"])); + firefox_opts.insert("profile".into(), json!("foo")); + + make_options(firefox_opts, None).expect_err("Invalid args"); } } |