Skip to content

Commit

Permalink
Auto merge of #7548 - jgraham:webdriver_prefs, r=metajack
Browse files Browse the repository at this point in the history
Add get/set pref extensions to webdriver server.

This can be used by the test framework to ensure that the correct prefs are
set for a test without restarting the browser

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7548)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Sep 15, 2015
2 parents e3d36bf + e0a7b2b commit 67cf241
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 17 deletions.
4 changes: 3 additions & 1 deletion components/servo/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions components/webdriver_server/Cargo.toml
Expand Up @@ -29,5 +29,7 @@ features = [ "serde_serialization" ]

[dependencies]
log = "0.3"
hyper = "0.6"
rustc-serialize = "0.3.4"
regex = "0.1.33"
uuid = "0.1"
174 changes: 159 additions & 15 deletions components/webdriver_server/lib.rs
Expand Up @@ -18,37 +18,45 @@ extern crate util;
extern crate rustc_serialize;
extern crate uuid;
extern crate ipc_channel;
extern crate regex;
extern crate hyper;

use hyper::method::Method::{self, Post};
use ipc_channel::ipc::{self, IpcSender, IpcReceiver};
use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, LoadData, FrameId, PipelineId};
use msg::constellation_msg::{NavigationDirection, WebDriverCommandMsg};
use msg::webdriver_msg::{WebDriverFrameId, WebDriverScriptCommand, WebDriverJSError, WebDriverJSResult, LoadStatus};

use ipc_channel::ipc::{self, IpcSender, IpcReceiver};
use regex::Captures;
use rustc_serialize::base64::{Config, ToBase64, CharacterSet, Newline};
use rustc_serialize::json::{Json, ToJson};
use std::borrow::ToOwned;
use std::collections::BTreeMap;
use std::net::SocketAddr;
use std::thread::{self, sleep_ms};
use url::Url;
use util::prefs::{get_pref, set_pref};
use util::task::spawn_named;
use uuid::Uuid;
use webdriver::command::{GetParameters, JavascriptCommandParameters, LocatorParameters};
use webdriver::command::{SwitchToFrameParameters, TimeoutsParameters};
use webdriver::command::{WebDriverMessage, WebDriverCommand};
use webdriver::command::{SwitchToFrameParameters, TimeoutsParameters, Parameters};
use webdriver::command::{WebDriverMessage, WebDriverCommand, WebDriverExtensionCommand};
use webdriver::common::{LocatorStrategy, WebElement};
use webdriver::error::{WebDriverResult, WebDriverError, ErrorStatus};
use webdriver::httpapi::{WebDriverExtensionRoute};
use webdriver::response::{WebDriverResponse, NewSessionResponse, ValueResponse};
use webdriver::server::{self, WebDriverHandler, Session};

use rustc_serialize::base64::{Config, ToBase64, CharacterSet, Newline};
use rustc_serialize::json::{Json, ToJson};
use std::borrow::ToOwned;
use std::collections::BTreeMap;
use std::net::SocketAddr;

use std::thread::{self, sleep_ms};
fn extension_routes() -> Vec<(Method, &'static str, ServoExtensionRoute)> {
return vec![(Post, "/session/{sessionId}/servo/prefs/get", ServoExtensionRoute::GetPrefs),
(Post, "/session/{sessionId}/servo/prefs/set", ServoExtensionRoute::SetPrefs)]
}

pub fn start_server(port: u16, constellation_chan: ConstellationChan) {
let handler = Handler::new(constellation_chan);

spawn_named("WebdriverHttpServer".to_owned(), move || {
server::start(SocketAddr::new("0.0.0.0".parse().unwrap(), port), handler);
server::start(SocketAddr::new("0.0.0.0".parse().unwrap(), port), handler,
extension_routes());
});
}

Expand All @@ -65,6 +73,119 @@ struct Handler {
implicit_wait_timeout: u32
}

#[derive(Clone, Copy, PartialEq)]
enum ServoExtensionRoute {
GetPrefs,
SetPrefs,
}

impl WebDriverExtensionRoute for ServoExtensionRoute {
type Command = ServoExtensionCommand;

fn command(&self,
_captures: &Captures,
body_data: &Json) -> WebDriverResult<WebDriverCommand<ServoExtensionCommand>> {
let command = match self {
&ServoExtensionRoute::GetPrefs => {
let parameters: GetPrefsParameters = try!(Parameters::from_json(&body_data));
ServoExtensionCommand::GetPrefs(parameters)
}
&ServoExtensionRoute::SetPrefs => {
let parameters: SetPrefsParameters = try!(Parameters::from_json(&body_data));
ServoExtensionCommand::SetPrefs(parameters)
}
};
Ok(WebDriverCommand::Extension(command))
}
}

#[derive(Clone, PartialEq)]
enum ServoExtensionCommand {
GetPrefs(GetPrefsParameters),
SetPrefs(SetPrefsParameters)
}

impl WebDriverExtensionCommand for ServoExtensionCommand {
fn parameters_json(&self) -> Option<Json> {
match self {
&ServoExtensionCommand::GetPrefs(ref x) => Some(x.to_json()),
&ServoExtensionCommand::SetPrefs(ref x) => Some(x.to_json())
}
}
}

#[derive(Clone, PartialEq)]
struct GetPrefsParameters {
prefs: Vec<String>
}

impl Parameters for GetPrefsParameters {
fn from_json(body: &Json) -> WebDriverResult<GetPrefsParameters> {
let data = try!(body.as_object().ok_or(
WebDriverError::new(ErrorStatus::InvalidArgument,
"Message body was not an object")));
let prefs_value = try!(data.get("prefs").ok_or(
WebDriverError::new(ErrorStatus::InvalidArgument,
"Missing prefs key")));
let items = try!(prefs_value.as_array().ok_or(
WebDriverError::new(
ErrorStatus::InvalidArgument,
"prefs was not an array")));
let params = try!(items.iter().map(|x| x.as_string().map(|y| y.to_owned()).ok_or(
WebDriverError::new(ErrorStatus::InvalidArgument,
"Pref is not a string"))).collect::<Result<Vec<_>, _>>());
Ok(GetPrefsParameters {
prefs: params
})
}
}

impl ToJson for GetPrefsParameters {
fn to_json(&self) -> Json {
let mut data = BTreeMap::new();
data.insert("prefs".to_owned(), self.prefs.to_json());
Json::Object(data)
}
}

#[derive(Clone, PartialEq)]
struct SetPrefsParameters {
prefs: Vec<(String, bool)>
}

impl Parameters for SetPrefsParameters {
fn from_json(body: &Json) -> WebDriverResult<SetPrefsParameters> {
let data = try!(body.as_object().ok_or(
WebDriverError::new(ErrorStatus::InvalidArgument,
"Message body was not an object")));
let items = try!(try!(data.get("prefs").ok_or(
WebDriverError::new(ErrorStatus::InvalidArgument,
"Missing prefs key"))).as_object().ok_or(
WebDriverError::new(
ErrorStatus::InvalidArgument,
"prefs was not an array")));
let mut params = Vec::with_capacity(items.len());
for (name, val) in items.iter() {
let value = try!(val.as_boolean().ok_or(
WebDriverError::new(ErrorStatus::InvalidArgument,
"Pref is not a bool")));
let key = name.to_owned();
params.push((key, value));
}
Ok(SetPrefsParameters {
prefs: params
})
}
}

impl ToJson for SetPrefsParameters {
fn to_json(&self) -> Json {
let mut data = BTreeMap::new();
data.insert("prefs".to_owned(), self.prefs.to_json());
Json::Object(data)
}
}

impl WebDriverSession {
pub fn new() -> WebDriverSession {
WebDriverSession {
Expand Down Expand Up @@ -505,12 +626,29 @@ impl Handler {
let encoded = img_vec.to_base64(config);
Ok(WebDriverResponse::Generic(ValueResponse::new(encoded.to_json())))
}

fn handle_get_prefs(&self,
parameters: &GetPrefsParameters) -> WebDriverResult<WebDriverResponse> {
let prefs = parameters.prefs
.iter()
.map(|item| (item.clone(), get_pref(item).to_json()))
.collect::<BTreeMap<_, _>>();
Ok(WebDriverResponse::Generic(ValueResponse::new(prefs.to_json())))
}

fn handle_set_prefs(&self,
parameters: &SetPrefsParameters) -> WebDriverResult<WebDriverResponse> {
for &(ref key, ref value) in parameters.prefs.iter() {
set_pref(key, *value);
}
Ok(WebDriverResponse::Void)
}
}

impl WebDriverHandler for Handler {
impl WebDriverHandler<ServoExtensionRoute> for Handler {
fn handle_command(&mut self,
_session: &Option<Session>,
msg: &WebDriverMessage) -> WebDriverResult<WebDriverResponse> {
msg: &WebDriverMessage<ServoExtensionRoute>) -> WebDriverResult<WebDriverResponse> {

// Unless we are trying to create a new session, we need to ensure that a
// session has previously been created
Expand Down Expand Up @@ -542,6 +680,12 @@ impl WebDriverHandler for Handler {
WebDriverCommand::ExecuteAsyncScript(ref x) => self.handle_execute_async_script(x),
WebDriverCommand::SetTimeouts(ref x) => self.handle_set_timeouts(x),
WebDriverCommand::TakeScreenshot => self.handle_take_screenshot(),
WebDriverCommand::Extension(ref extension) => {
match extension {
&ServoExtensionCommand::GetPrefs(ref x) => self.handle_get_prefs(x),
&ServoExtensionCommand::SetPrefs(ref x) => self.handle_set_prefs(x),
}
}
_ => Err(WebDriverError::new(ErrorStatus::UnsupportedOperation,
"Command not implemented"))
}
Expand Down
4 changes: 3 additions & 1 deletion ports/cef/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 67cf241

Please sign in to comment.