Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mozilla/geckodriver.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/capabilities.rs292
-rw-r--r--src/main.rs89
-rw-r--r--src/marionette.rs199
3 files changed, 297 insertions, 283 deletions
diff --git a/src/capabilities.rs b/src/capabilities.rs
new file mode 100644
index 0000000..9fe1dc4
--- /dev/null
+++ b/src/capabilities.rs
@@ -0,0 +1,292 @@
+use std::collections::BTreeMap;
+use std::fs;
+use std::io;
+use std::io::BufWriter;
+use std::io::Cursor;
+use std::path::{Path, PathBuf};
+use std::str::FromStr;
+
+use marionette::LogOptions;
+use mozprofile::preferences::Pref;
+use mozprofile::profile::Profile;
+use rustc_serialize::base64::FromBase64;
+use rustc_serialize::json::Json;
+use webdriver::command::NewSessionParameters;
+use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
+use zip;
+
+use logging::LogLevel;
+
+#[derive(Default)]
+pub struct FirefoxOptions {
+ pub binary: Option<PathBuf>,
+ pub profile: Option<Profile>,
+ pub args: Option<Vec<String>>,
+ pub log: LogOptions,
+ pub prefs: Vec<(String, Pref)>
+}
+
+impl FirefoxOptions {
+ pub fn from_capabilities(capabilities: &mut NewSessionParameters) -> WebDriverResult<FirefoxOptions> {
+ if let Some(options) = capabilities.consume("moz:firefoxOptions") {
+ let firefox_options = try!(options
+ .as_object()
+ .ok_or(WebDriverError::new(
+ ErrorStatus::InvalidArgument,
+ "'moz:firefoxOptions' capability was not an object")));
+ let binary = try!(FirefoxOptions::load_binary(&firefox_options));
+ let profile = try!(FirefoxOptions::load_profile(&firefox_options));
+ let args = try!(FirefoxOptions::load_args(&firefox_options));
+ let log = try!(FirefoxOptions::load_log(&firefox_options));
+ let prefs = try!(FirefoxOptions::load_prefs(&firefox_options));
+
+ Ok(FirefoxOptions {
+ binary: binary,
+ profile: profile,
+ args: args,
+ log: log,
+ prefs: prefs,
+ })
+ } else {
+ Ok(Default::default())
+ }
+ }
+
+ fn load_binary(options: &BTreeMap<String, Json>) -> WebDriverResult<Option<PathBuf>> {
+ if let Some(path) = options.get("binary") {
+ Ok(Some(PathBuf::from(try!(path
+ .as_string()
+ .ok_or(WebDriverError::new(
+ ErrorStatus::InvalidArgument,
+ "'binary' capability was not a string"))))))
+ } else {
+ Ok(None)
+ }
+ }
+
+ fn load_profile(options: &BTreeMap<String, Json>) -> WebDriverResult<Option<Profile>> {
+ if let Some(profile_json) = options.get("profile") {
+ let profile_base64 = try!(profile_json
+ .as_string()
+ .ok_or(
+ WebDriverError::new(ErrorStatus::UnknownError,
+ "Profile was not a string")));
+ let profile_zip = &*try!(profile_base64.from_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()));
+
+ Ok(Some(profile))
+ } else {
+ Ok(None)
+ }
+ }
+
+ fn load_args(options: &BTreeMap<String, Json>) -> 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_string().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)
+ }
+ }
+
+ fn load_log(options: &BTreeMap<String, Json>) -> WebDriverResult<LogOptions> {
+ if let Some(json) = options.get("log") {
+ let log = try!(json.as_object()
+ .ok_or(WebDriverError::new(ErrorStatus::InvalidArgument, "Log section is not an object")));
+
+ let level = match log.get("level") {
+ Some(json) => {
+ let s = try!(json.as_string()
+ .ok_or(WebDriverError::new(ErrorStatus::InvalidArgument, "Log level is not a string")));
+ Some(try!(LogLevel::from_str(s).ok()
+ .ok_or(WebDriverError::new(ErrorStatus::InvalidArgument, "Log level is unknown"))))
+ },
+ None => None,
+ };
+
+ Ok(LogOptions { level: level })
+
+ } else {
+ Ok(Default::default())
+ }
+ }
+
+ pub fn load_prefs(options: &BTreeMap<String, Json>) -> 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 mut rv = Vec::with_capacity(prefs.len());
+ for (key, value) in prefs.iter() {
+ rv.push((key.clone(), try!(pref_from_json(value))));
+ };
+ Ok(rv)
+ } else {
+ Ok(vec![])
+ }
+ }
+}
+
+fn pref_from_json(value: &Json) -> WebDriverResult<Pref> {
+ match value {
+ &Json::String(ref x) => Ok(Pref::new(x.clone())),
+ &Json::I64(x) => Ok(Pref::new(x)),
+ &Json::U64(x) => Ok(Pref::new(x as i64)),
+ &Json::Boolean(x) => Ok(Pref::new(x)),
+ _ => 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")
+ }));
+
+ 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 unzip_path = {
+ let name = file.name();
+ let is_dir = name.ends_with("/");
+ let rel_path = Path::new(name);
+ let dest_path = dest_dir.join(rel_path);
+
+ {
+ let create_dir = if is_dir {
+ Some(dest_path.as_path())
+ } else {
+ dest_path.parent()
+ };
+ if let Some(dir) = create_dir {
+ if !dir.exists() {
+ debug!("Creating profile directory tree {}", dir.to_string_lossy());
+ try!(fs::create_dir_all(dir));
+ }
+ }
+ }
+
+ if is_dir {
+ None
+ } else {
+ Some(dest_path)
+ }
+ };
+
+ if let Some(unzip_path) = unzip_path {
+ debug!("Extracting profile to {}", unzip_path.to_string_lossy());
+ let dest = try!(fs::File::create(unzip_path));
+ let mut writer = BufWriter::new(dest);
+ try!(io::copy(&mut file, &mut writer));
+ }
+ }
+
+ Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+ extern crate mozprofile;
+ extern crate rustc_serialize;
+
+ use std::collections::BTreeMap;
+ use std::default::Default;
+ use std::fs::File;
+ use std::io::Read;
+
+ use self::mozprofile::preferences::Pref;
+ use self::rustc_serialize::base64::{ToBase64, Config, CharacterSet, Newline};
+ use self::rustc_serialize::json::Json;
+
+ use webdriver::command::NewSessionParameters;
+ use marionette::MarionetteHandler;
+ use super::FirefoxOptions;
+
+ fn example_profile() -> Json {
+ let mut profile_data = Vec::with_capacity(1024);
+ let mut profile = File::open("src/tests/profile.zip").unwrap();
+ profile.read_to_end(&mut profile_data).unwrap();
+ let base64_config = Config {
+ char_set: CharacterSet::Standard,
+ newline: Newline::LF,
+ pad: true,
+ line_length: None
+ };
+ Json::String(profile_data.to_base64(base64_config))
+ }
+
+ fn capabilities() -> NewSessionParameters {
+ let desired: BTreeMap<String, Json> = BTreeMap::new();
+ let required: BTreeMap<String, Json> = BTreeMap::new();
+ NewSessionParameters {
+ desired: desired,
+ required: required
+ }
+ }
+
+ #[test]
+ fn test_profile() {
+ let encoded_profile = example_profile();
+
+ let mut capabilities = capabilities();
+ let mut firefox_options: BTreeMap<String, Json> = BTreeMap::new();
+ firefox_options.insert("profile".into(), encoded_profile);
+ capabilities.required.insert("moz:firefoxOptions".into(), Json::Object(firefox_options));
+
+ let options = FirefoxOptions::from_capabilities(&mut capabilities).unwrap();
+ let mut profile = options.profile.unwrap();
+ let prefs = profile.user_prefs().unwrap();
+
+ println!("{:?}",prefs.prefs);
+
+ assert_eq!(prefs.get("startup.homepage_welcome_url"),
+ Some(&Pref::new("data:text/html,PASS")));
+ }
+
+ #[test]
+ fn test_prefs() {
+ let encoded_profile = example_profile();
+
+ let mut capabilities = capabilities();
+ let mut firefox_options: BTreeMap<String, Json> = BTreeMap::new();
+ firefox_options.insert("profile".into(), encoded_profile);
+ let mut prefs: BTreeMap<String, Json> = BTreeMap::new();
+ prefs.insert("browser.display.background_color".into(), Json::String("#00ff00".into()));
+ firefox_options.insert("prefs".into(), Json::Object(prefs));
+ capabilities.required.insert("moz:firefoxOptions".into(), Json::Object(firefox_options));
+
+
+ let options = FirefoxOptions::from_capabilities(&mut capabilities).unwrap();
+ let mut profile = options.profile.unwrap();
+
+ let handler = MarionetteHandler::new(Default::default());
+ handler.set_prefs(2828, &mut profile, true, options.prefs).unwrap();
+
+ let prefs_set = profile.user_prefs().unwrap();
+ println!("{:?}",prefs_set.prefs);
+ 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.defaultPrefs.port"),
+ Some(&Pref::new(2828)));
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index f6741db..8ab6b96 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -39,6 +39,7 @@ macro_rules! try_opt {
mod logging;
mod marionette;
+mod capabilities;
use logging::LogLevel;
use marionette::{MarionetteHandler, MarionetteSettings, extension_routes};
@@ -177,91 +178,3 @@ fn main() {
std::io::stdout().flush().unwrap();
std::process::exit(exit_code as i32);
}
-
-#[cfg(test)]
-mod tests {
- extern crate mozprofile;
- extern crate rustc_serialize;
-
- use std::collections::BTreeMap;
- use std::default::Default;
- use std::fs::File;
- use std::io::Read;
-
- use self::mozprofile::preferences::Pref;
- use self::rustc_serialize::base64::{ToBase64, Config, CharacterSet, Newline};
- use self::rustc_serialize::json::Json;
-
- use webdriver::command::NewSessionParameters;
- use marionette::{FirefoxOptions, MarionetteHandler};
-
- fn example_profile() -> Json {
- let mut profile_data = Vec::with_capacity(1024);
- let mut profile = File::open("src/tests/profile.zip").unwrap();
- profile.read_to_end(&mut profile_data).unwrap();
- let base64_config = Config {
- char_set: CharacterSet::Standard,
- newline: Newline::LF,
- pad: true,
- line_length: None
- };
- Json::String(profile_data.to_base64(base64_config))
- }
-
- fn capabilities() -> NewSessionParameters {
- let desired: BTreeMap<String, Json> = BTreeMap::new();
- let required: BTreeMap<String, Json> = BTreeMap::new();
- NewSessionParameters {
- desired: desired,
- required: required
- }
- }
-
- #[test]
- fn test_profile() {
- let encoded_profile = example_profile();
-
- let mut capabilities = capabilities();
- let mut firefox_options: BTreeMap<String, Json> = BTreeMap::new();
- firefox_options.insert("profile".into(), encoded_profile);
- capabilities.required.insert("moz:firefoxOptions".into(), Json::Object(firefox_options));
-
- let options = FirefoxOptions::from_capabilities(&mut capabilities).unwrap();
- let mut profile = options.profile.unwrap();
- let prefs = profile.user_prefs().unwrap();
-
- println!("{:?}",prefs.prefs);
-
- assert_eq!(prefs.get("startup.homepage_welcome_url"),
- Some(&Pref::new("data:text/html,PASS")));
- }
-
- #[test]
- fn test_prefs() {
- let encoded_profile = example_profile();
-
- let mut capabilities = capabilities();
- let mut firefox_options: BTreeMap<String, Json> = BTreeMap::new();
- firefox_options.insert("profile".into(), encoded_profile);
- let mut prefs: BTreeMap<String, Json> = BTreeMap::new();
- prefs.insert("browser.display.background_color".into(), Json::String("#00ff00".into()));
- firefox_options.insert("prefs".into(), Json::Object(prefs));
- capabilities.required.insert("moz:firefoxOptions".into(), Json::Object(firefox_options));
-
-
- let options = FirefoxOptions::from_capabilities(&mut capabilities).unwrap();
- let mut profile = options.profile.unwrap();
-
- let handler = MarionetteHandler::new(Default::default());
- handler.set_prefs(2828, &mut profile, true, options.prefs).unwrap();
-
- let prefs_set = profile.user_prefs().unwrap();
- println!("{:?}",prefs_set.prefs);
- 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.defaultPrefs.port"),
- Some(&Pref::new(2828)));
- }
-}
diff --git a/src/marionette.rs b/src/marionette.rs
index 88f9e07..227203e 100644
--- a/src/marionette.rs
+++ b/src/marionette.rs
@@ -6,22 +6,16 @@ use mozprofile::profile::Profile;
use mozrunner::runner::{Runner, FirefoxRunner};
use mozrunner::runner::platform::firefox_default_path;
use regex::Captures;
-use rustc_serialize::base64::FromBase64;
use rustc_serialize::json;
use rustc_serialize::json::{Json, ToJson};
use std::collections::BTreeMap;
use std::error::Error;
-use std::fs;
-use std::io;
-use std::io::BufWriter;
-use std::io::Cursor;
use std::io::Error as IoError;
use std::io::ErrorKind;
use std::io::prelude::*;
+use std::path::PathBuf;
use std::io::Result as IoResult;
use std::net::{TcpListener, TcpStream};
-use std::path::{Path, PathBuf};
-use std::str::FromStr;
use std::sync::Mutex;
use std::thread::sleep;
use std::time::Duration;
@@ -51,11 +45,11 @@ use webdriver::response::{
WindowPositionResponse, ElementRectResponse, CookieResponse, Cookie};
use webdriver::common::{
Date, Nullable, WebElement, FrameId, ELEMENT_KEY};
-use webdriver::error::{
- WebDriverResult, WebDriverError, ErrorStatus};
+use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
use webdriver::server::{WebDriverHandler, Session};
use webdriver::httpapi::{WebDriverExtensionRoute};
-use zip;
+
+use capabilities::FirefoxOptions;
const DEFAULT_HOST: &'static str = "localhost";
@@ -307,132 +301,6 @@ pub struct LogOptions {
}
#[derive(Default)]
-pub struct FirefoxOptions {
- pub binary: Option<PathBuf>,
- pub profile: Option<Profile>,
- pub args: Option<Vec<String>>,
- pub log: LogOptions,
- pub prefs: Vec<(String, Pref)>,
-}
-
-impl FirefoxOptions {
- pub fn from_capabilities(capabilities: &mut NewSessionParameters) -> WebDriverResult<FirefoxOptions> {
- if let Some(options) = capabilities.consume("moz:firefoxOptions") {
- let firefox_options = try!(options
- .as_object()
- .ok_or(WebDriverError::new(
- ErrorStatus::InvalidArgument,
- "'moz:firefoxOptions' capability was not an object")));
- let binary = try!(FirefoxOptions::load_binary(&firefox_options));
- let profile = try!(FirefoxOptions::load_profile(&firefox_options));
- let args = try!(FirefoxOptions::load_args(&firefox_options));
- let log = try!(FirefoxOptions::load_log(&firefox_options));
- let prefs = try!(FirefoxOptions::load_prefs(&firefox_options));
-
- Ok(FirefoxOptions {
- binary: binary,
- profile: profile,
- args: args,
- log: log,
- prefs: prefs,
- })
- } else {
- Ok(Default::default())
- }
- }
-
- fn load_binary(options: &BTreeMap<String, Json>) -> WebDriverResult<Option<PathBuf>> {
- if let Some(path) = options.get("binary") {
- Ok(Some(PathBuf::from(try!(path
- .as_string()
- .ok_or(WebDriverError::new(
- ErrorStatus::InvalidArgument,
- "'binary' capability was not a string"))))))
- } else {
- Ok(None)
- }
- }
-
- fn load_profile(options: &BTreeMap<String, Json>) -> WebDriverResult<Option<Profile>> {
- if let Some(profile_json) = options.get("profile") {
- let profile_base64 = try!(profile_json
- .as_string()
- .ok_or(
- WebDriverError::new(ErrorStatus::UnknownError,
- "Profile was not a string")));
- let profile_zip = &*try!(profile_base64.from_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()));
-
- Ok(Some(profile))
- } else {
- Ok(None)
- }
- }
-
- fn load_args(options: &BTreeMap<String, Json>) -> 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_string().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)
- }
- }
-
- fn load_log(options: &BTreeMap<String, Json>) -> WebDriverResult<LogOptions> {
- if let Some(json) = options.get("log") {
- let log = try!(json.as_object()
- .ok_or(WebDriverError::new(ErrorStatus::InvalidArgument, "Log section is not an object")));
-
- let level = match log.get("level") {
- Some(json) => {
- let s = try!(json.as_string()
- .ok_or(WebDriverError::new(ErrorStatus::InvalidArgument, "Log level is not a string")));
- Some(try!(LogLevel::from_str(s).ok()
- .ok_or(WebDriverError::new(ErrorStatus::InvalidArgument, "Log level is unknown"))))
- },
- None => None,
- };
-
- Ok(LogOptions { level: level })
-
- } else {
- Ok(Default::default())
- }
- }
-
- pub fn load_prefs(options: &BTreeMap<String, Json>) -> 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 mut rv = Vec::with_capacity(prefs.len());
- for (key, value) in prefs.iter() {
- rv.push((key.clone(), try!(pref_from_json(value))));
- };
- Ok(rv)
- } else {
- Ok(vec![])
- }
- }
-}
-
-#[derive(Default)]
pub struct MarionetteSettings {
pub port: Option<u16>,
pub binary: Option<PathBuf>,
@@ -544,65 +412,6 @@ impl MarionetteHandler {
}
}
-fn pref_from_json(value: &Json) -> WebDriverResult<Pref> {
- match value {
- &Json::String(ref x) => Ok(Pref::new(x.clone())),
- &Json::I64(x) => Ok(Pref::new(x)),
- &Json::U64(x) => Ok(Pref::new(x as i64)),
- &Json::Boolean(x) => Ok(Pref::new(x)),
- _ => 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")
- }));
-
- 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 unzip_path = {
- let name = file.name();
- let is_dir = name.ends_with("/");
- let rel_path = Path::new(name);
- let dest_path = dest_dir.join(rel_path);
-
- {
- let create_dir = if is_dir {
- Some(dest_path.as_path())
- } else {
- dest_path.parent()
- };
- if let Some(dir) = create_dir {
- if !dir.exists() {
- debug!("Creating profile directory tree {}", dir.to_string_lossy());
- try!(fs::create_dir_all(dir));
- }
- }
- }
-
- if is_dir {
- None
- } else {
- Some(dest_path)
- }
- };
-
- if let Some(unzip_path) = unzip_path {
- debug!("Extracting profile to {}", unzip_path.to_string_lossy());
- let dest = try!(fs::File::create(unzip_path));
- let mut writer = BufWriter::new(dest);
- try!(io::copy(&mut file, &mut writer));
- }
- }
-
- Ok(())
-}
-
impl WebDriverHandler<GeckoExtensionRoute> for MarionetteHandler {
fn handle_command(&mut self, _: &Option<Session>, mut msg: WebDriverMessage<GeckoExtensionRoute>) -> WebDriverResult<WebDriverResponse> {
{