Bug 1388365 - Vendor webdriver 0.29.0. r?whimboo draft
authorAndreas Tolfsen <ato@sny.no>
Tue, 08 Aug 2017 15:10:55 +0100
changeset 642586 ebd53f599da19432c4e8f1c86a2d91e9900497a0
parent 642585 c8427211884505978840b261908cff77c0657e40
child 642587 c123ba91e1f23c5100139dae4cd839b0dd0972f2
child 642715 f195c5b537e23ae3ff71831d7d4bfcbd40d4148c
push id72813
push userbmo:ato@sny.no
push dateTue, 08 Aug 2017 14:39:30 +0000
reviewerswhimboo
bugs1388365
milestone57.0a1
Bug 1388365 - Vendor webdriver 0.29.0. r?whimboo MozReview-Commit-ID: 3vhk9kfmDHD
testing/geckodriver/Cargo.lock
third_party/rust/webdriver/.cargo-checksum.json
third_party/rust/webdriver/Cargo.toml
third_party/rust/webdriver/src/capabilities.rs
third_party/rust/webdriver/src/command.rs
third_party/rust/webdriver/src/common.rs
third_party/rust/webdriver/src/error.rs
third_party/rust/webdriver/src/httpapi.rs
third_party/rust/webdriver/src/response.rs
third_party/rust/webdriver/src/server.rs
--- a/testing/geckodriver/Cargo.lock
+++ b/testing/geckodriver/Cargo.lock
@@ -12,17 +12,17 @@ dependencies = [
  "mozversion 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "slog 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "slog-atomic 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "slog-stdlog 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "slog-stream 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "webdriver 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webdriver 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "zip 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "advapi32-sys"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -637,17 +637,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "void"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "webdriver"
-version = "0.28.0"
+version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cookie 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -765,13 +765,13 @@ dependencies = [
 "checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
 "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
 "checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
 "checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
-"checksum webdriver 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9238218a263593f2f143c32d10b0ddec2664a1f9b7be426eb775ee243af44739"
+"checksum webdriver 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3aa46482421441f1954f5df7443a66e5744e8de22a3d825262157b109dbdd535"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum winreg 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e63857fb213f619b4c4fff86b158285c76766aac7e7474967e92fb6dbbfeefe9"
 "checksum zip 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c0deac03fc7d43abcf19f2c2db6bd9289f9ea3d31f350e26eb0ed8b4117983c1"
--- a/third_party/rust/webdriver/.cargo-checksum.json
+++ b/third_party/rust/webdriver/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"78252ef89a407b1d76616b7afbf7afb8205530a7f7039f3a7ea140684e3aa8bc","Cargo.toml":"74d24167dc8948953ab5c43b9a524b8ecff667c2f1ce9c0df539c1b799077998","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"bd0e99ce271903a9f67cf5f8fca2f67f2583e4336fbaf583fcd78ec238d4176e","src/capabilities.rs":"5039c1f80885ca2bab19f2d1c40b405c37c09901918625395141ac2e01600728","src/command.rs":"2e60c1b0eabccc3abef91574dbb94a4044a56fc1f4da18a45c6317c726480c2f","src/common.rs":"d696aabe88061f8315578c42115d976123a8fc4276384e478e14d241dfc9acc0","src/error.rs":"b0acf64e052edbc26e7dbcd1a54e8b9a786f01e9d48e0e5b2f410266bfdb9da2","src/httpapi.rs":"8e54ddc2796863ce7d9905484fb8214883a27a33bd94bee2ae765bccb9895f91","src/lib.rs":"336c146e934711dfe49f4b44bbcf278686b00be8d89abb9c7b7b045254994fbf","src/macros.rs":"93094c48e3880d925e684fba9678693eb8c0c39c7ed47b130b0751c4bca37ddc","src/response.rs":"63cabdc7f9136a0f24c10dc16b11c6991c95fd9fee1d1bc47d48c62c6f69eb33","src/server.rs":"f2110378cfaf7a4facb39d0e45c479a00c95a939536c85a6a105c858fffc2d70"},"package":"9238218a263593f2f143c32d10b0ddec2664a1f9b7be426eb775ee243af44739"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"78252ef89a407b1d76616b7afbf7afb8205530a7f7039f3a7ea140684e3aa8bc","Cargo.toml":"b0f014ae89a79a1923c0209445f65935adf26fabbea19af22a62fc4c51bfb016","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"bd0e99ce271903a9f67cf5f8fca2f67f2583e4336fbaf583fcd78ec238d4176e","src/capabilities.rs":"3ced096444da586e077b0d62fb515f757e7809063e0c65fd7435678c8a8641b3","src/command.rs":"3538491c5e77746eca8d326185903f3336e47f75f69401167acbd655708e736a","src/common.rs":"79d50f6c29f16d370b707988fe7b1747e17372f979df75d30be3e250dce55836","src/error.rs":"7621e0c325c488b537e1bd26dd580b23863bf07bbae52cf8b77e6a7d37df47c3","src/httpapi.rs":"83fec1cefedbadb8bf7458374f909a44ff76d67046e8428fc01067d5d8401dc6","src/lib.rs":"336c146e934711dfe49f4b44bbcf278686b00be8d89abb9c7b7b045254994fbf","src/macros.rs":"93094c48e3880d925e684fba9678693eb8c0c39c7ed47b130b0751c4bca37ddc","src/response.rs":"160bc15135d623d1bc5b33c6edaf69a4034d36c1cd8d9cefb64f436001dda01e","src/server.rs":"4f8976a215783c98f1e3927e5440590fe3a41189bf62fea151434598f904753c"},"package":"3aa46482421441f1954f5df7443a66e5744e8de22a3d825262157b109dbdd535"}
\ No newline at end of file
--- a/third_party/rust/webdriver/Cargo.toml
+++ b/third_party/rust/webdriver/Cargo.toml
@@ -7,40 +7,40 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "webdriver"
-version = "0.28.0"
+version = "0.29.0"
 authors = ["Mozilla Tools and Automation <tools@lists.mozilla.com>"]
 description = "Library implementing the wire protocol for the W3C WebDriver specification"
 documentation = "https://docs.rs/webdriver"
 readme = "README.md"
 keywords = ["webdriver", "browser", "automation", "protocol", "w3c"]
 license = "MPL-2.0"
 repository = "https://github.com/mozilla/webdriver-rust"
+[dependencies.regex]
+version = "0.2"
+
+[dependencies.url]
+version = "1"
+
 [dependencies.log]
 version = "0.3"
 
-[dependencies.backtrace]
-version = "0.3"
-
-[dependencies.regex]
-version = "0.2"
+[dependencies.hyper]
+version = "0.10"
 
 [dependencies.rustc-serialize]
 version = "0.3"
 
 [dependencies.cookie]
 version = "0.9"
 default-features = false
 
 [dependencies.time]
 version = "0.1"
 
-[dependencies.hyper]
-version = "0.10"
-
-[dependencies.url]
-version = "1"
+[dependencies.backtrace]
+version = "0.3"
--- a/third_party/rust/webdriver/src/capabilities.rs
+++ b/third_party/rust/webdriver/src/capabilities.rs
@@ -144,17 +144,17 @@ impl SpecNewSessionParameters {
     fn validate_proxy(proxy_value: &Json) -> WebDriverResult<()> {
         let obj = try_opt!(proxy_value.as_object(),
                            ErrorStatus::InvalidArgument,
                            "proxy was not an object");
         for (key, value) in obj.iter() {
             match &**key {
                 "proxyType" => match value.as_string() {
                     Some("pac") |
-                    Some("noproxy") |
+                    Some("direct") |
                     Some("autodetect") |
                     Some("system") |
                     Some("manual") => {},
                     Some(x) => return Err(WebDriverError::new(
                         ErrorStatus::InvalidArgument,
                         format!("{} was not a valid proxyType value", x))),
                     None => return Err(WebDriverError::new(
                         ErrorStatus::InvalidArgument,
--- a/third_party/rust/webdriver/src/command.rs
+++ b/third_party/rust/webdriver/src/command.rs
@@ -4,17 +4,17 @@ use common::{Date, Nullable, WebElement,
 use error::{WebDriverResult, WebDriverError, ErrorStatus};
 use httpapi::{Route, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
 use regex::Captures;
 use rustc_serialize::json;
 use rustc_serialize::json::{ToJson, Json};
 use std::collections::BTreeMap;
 use std::default::Default;
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum WebDriverCommand<T: WebDriverExtensionCommand> {
     NewSession(NewSessionParameters),
     DeleteSession,
     Get(GetParameters),
     GetCurrentUrl,
     GoBack,
     GoForward,
     Refresh,
@@ -69,26 +69,26 @@ pub enum WebDriverCommand<T: WebDriverEx
     Status,
     Extension(T)
 }
 
 pub trait WebDriverExtensionCommand : Clone + Send + PartialEq {
     fn parameters_json(&self) -> Option<Json>;
 }
 
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct VoidWebDriverExtensionCommand;
 
 impl WebDriverExtensionCommand for VoidWebDriverExtensionCommand {
     fn parameters_json(&self) -> Option<Json> {
         panic!("No extensions implemented");
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct WebDriverMessage <U: WebDriverExtensionRoute=VoidWebDriverExtensionRoute> {
     pub session_id: Option<String>,
     pub command: WebDriverCommand<U::Command>,
 }
 
 impl<U: WebDriverExtensionRoute> WebDriverMessage<U> {
     pub fn new(session_id: Option<String>,
                command: WebDriverCommand<U::Command>)
@@ -485,17 +485,17 @@ impl CapabilitiesMatching for NewSession
         match self {
             &NewSessionParameters::Spec(ref x) => x.match_browser(browser_capabilities),
             &NewSessionParameters::Legacy(ref x) => x.match_browser(browser_capabilities)
         }
     }
 }
 
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct GetParameters {
     pub url: String
 }
 
 impl Parameters for GetParameters {
     fn from_json(body: &Json) -> WebDriverResult<GetParameters> {
         let data = try_opt!(body.as_object(), ErrorStatus::UnknownError,
                             "Message body was not an object");
@@ -514,17 +514,17 @@ impl Parameters for GetParameters {
 impl ToJson for GetParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("url".to_string(), self.url.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct TimeoutsParameters {
     pub script: Option<u64>,
     pub page_load: Option<u64>,
     pub implicit: Option<u64>,
 }
 
 impl Parameters for TimeoutsParameters {
     fn from_json(body: &Json) -> WebDriverResult<TimeoutsParameters> {
@@ -653,17 +653,17 @@ impl ToJson for WindowRectParameters {
         data.insert("x".to_string(), self.x.to_json());
         data.insert("y".to_string(), self.y.to_json());
         data.insert("width".to_string(), self.width.to_json());
         data.insert("height".to_string(), self.height.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct SwitchToWindowParameters {
     pub handle: String
 }
 
 impl Parameters for SwitchToWindowParameters {
     fn from_json(body: &Json) -> WebDriverResult<SwitchToWindowParameters> {
         let data = try_opt!(body.as_object(), ErrorStatus::UnknownError,
                             "Message body was not an object");
@@ -682,17 +682,17 @@ impl Parameters for SwitchToWindowParame
 impl ToJson for SwitchToWindowParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("handle".to_string(), self.handle.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct LocatorParameters {
     pub using: LocatorStrategy,
     pub value: String
 }
 
 impl Parameters for LocatorParameters {
     fn from_json(body: &Json) -> WebDriverResult<LocatorParameters> {
         let data = try_opt!(body.as_object(), ErrorStatus::UnknownError,
@@ -721,17 +721,17 @@ impl ToJson for LocatorParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("using".to_string(), self.using.to_json());
         data.insert("value".to_string(), self.value.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct SwitchToFrameParameters {
     pub id: FrameId
 }
 
 impl Parameters for SwitchToFrameParameters {
     fn from_json(body: &Json) -> WebDriverResult<SwitchToFrameParameters> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::UnknownError,
@@ -749,17 +749,17 @@ impl Parameters for SwitchToFrameParamet
 impl ToJson for SwitchToFrameParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("id".to_string(), self.id.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct SendKeysParameters {
     pub text: String
 }
 
 impl Parameters for SendKeysParameters {
     fn from_json(body: &Json) -> WebDriverResult<SendKeysParameters> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::InvalidArgument,
@@ -779,17 +779,17 @@ impl Parameters for SendKeysParameters {
 impl ToJson for SendKeysParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("value".to_string(), self.text.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct JavascriptCommandParameters {
     pub script: String,
     pub args: Nullable<Vec<Json>>
 }
 
 impl Parameters for JavascriptCommandParameters {
     fn from_json(body: &Json) -> WebDriverResult<JavascriptCommandParameters> {
         let data = try_opt!(body.as_object(),
@@ -827,17 +827,17 @@ impl ToJson for JavascriptCommandParamet
         let mut data = BTreeMap::new();
         //TODO: Wrap script so that it becomes marionette-compatible
         data.insert("script".to_string(), self.script.to_json());
         data.insert("args".to_string(), self.args.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct GetNamedCookieParameters {
     pub name: Nullable<String>,
 }
 
 impl Parameters for GetNamedCookieParameters {
     fn from_json(body: &Json) -> WebDriverResult<GetNamedCookieParameters> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::InvalidArgument,
@@ -858,17 +858,17 @@ impl Parameters for GetNamedCookieParame
 impl ToJson for GetNamedCookieParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("name".to_string(), self.name.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct AddCookieParameters {
     pub name: String,
     pub value: String,
     pub path: Nullable<String>,
     pub domain: Nullable<String>,
     pub expiry: Nullable<Date>,
     pub secure: bool,
     pub httpOnly: bool
@@ -973,17 +973,17 @@ impl ToJson for AddCookieParameters {
         data.insert("domain".to_string(), self.domain.to_json());
         data.insert("expiry".to_string(), self.expiry.to_json());
         data.insert("secure".to_string(), self.secure.to_json());
         data.insert("httpOnly".to_string(), self.httpOnly.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct TakeScreenshotParameters {
     pub element: Nullable<WebElement>
 }
 
 impl Parameters for TakeScreenshotParameters {
     fn from_json(body: &Json) -> WebDriverResult<TakeScreenshotParameters> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::InvalidArgument,
@@ -1006,17 +1006,17 @@ impl Parameters for TakeScreenshotParame
 impl ToJson for TakeScreenshotParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("element".to_string(), self.element.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct ActionsParameters {
     pub actions: Vec<ActionSequence>
 }
 
 impl Parameters for ActionsParameters {
     fn from_json(body: &Json) -> WebDriverResult<ActionsParameters> {
         try_opt!(body.as_object(),
                  ErrorStatus::InvalidArgument,
@@ -1042,17 +1042,17 @@ impl ToJson for ActionsParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("actions".to_owned(),
                     self.actions.iter().map(|x| x.to_json()).collect::<Vec<Json>>().to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct ActionSequence {
     pub id: Nullable<String>,
     pub actions: ActionsType
 }
 
 impl Parameters for ActionSequence {
     fn from_json(body: &Json) -> WebDriverResult<ActionSequence> {
         let data = try_opt!(body.as_object(),
@@ -1108,17 +1108,17 @@ impl ToJson for ActionSequence {
             }
         };
         data.insert("type".into(), action_type.to_json());
         data.insert("actions".into(), actions.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum ActionsType {
     Null(Vec<NullActionItem>),
     Key(Vec<KeyActionItem>),
     Pointer(PointerActionParameters, Vec<PointerActionItem>)
 }
 
 impl Parameters for ActionsType {
     fn from_json(body: &Json) -> WebDriverResult<ActionsType> {
@@ -1157,17 +1157,17 @@ impl Parameters for ActionsType {
                 }
                 Ok(ActionsType::Pointer(parameters, actions))
             }
             _ => panic!("Got unexpected action type after checking type")
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum PointerType {
     Mouse,
     Pen,
     Touch,
 }
 
 impl Parameters for PointerType {
     fn from_json(body: &Json) -> WebDriverResult<PointerType> {
@@ -1198,17 +1198,17 @@ impl ToJson for PointerType {
 }
 
 impl Default for PointerType {
     fn default() -> PointerType {
         PointerType::Mouse
     }
 }
 
-#[derive(Default, PartialEq)]
+#[derive(Debug, Default, PartialEq)]
 pub struct PointerActionParameters {
     pub pointer_type: PointerType
 }
 
 impl Parameters for PointerActionParameters {
     fn from_json(body: &Json) -> WebDriverResult<PointerActionParameters> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::InvalidArgument,
@@ -1227,17 +1227,17 @@ impl ToJson for PointerActionParameters 
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("pointerType".to_owned(),
                     self.pointer_type.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum NullActionItem {
     General(GeneralAction)
 }
 
 impl Parameters for NullActionItem {
     fn from_json(body: &Json) -> WebDriverResult<NullActionItem> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::InvalidArgument,
@@ -1260,17 +1260,17 @@ impl Parameters for NullActionItem {
 impl ToJson for NullActionItem {
     fn to_json(&self) -> Json {
         match self {
             &NullActionItem::General(ref x) => x.to_json(),
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum KeyActionItem {
     General(GeneralAction),
     Key(KeyAction)
 }
 
 impl Parameters for KeyActionItem {
     fn from_json(body: &Json) -> WebDriverResult<KeyActionItem> {
         let data = try_opt!(body.as_object(),
@@ -1295,17 +1295,17 @@ impl ToJson for KeyActionItem {
     fn to_json(&self) -> Json {
         match *self {
             KeyActionItem::General(ref x) => x.to_json(),
             KeyActionItem::Key(ref x) => x.to_json()
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum PointerActionItem {
     General(GeneralAction),
     Pointer(PointerAction)
 }
 
 impl Parameters for PointerActionItem {
     fn from_json(body: &Json) -> WebDriverResult<PointerActionItem> {
         let data = try_opt!(body.as_object(),
@@ -1329,17 +1329,17 @@ impl ToJson for PointerActionItem {
     fn to_json(&self) -> Json {
         match self {
             &PointerActionItem::General(ref x) => x.to_json(),
             &PointerActionItem::Pointer(ref x) => x.to_json()
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum GeneralAction {
     Pause(PauseAction)
 }
 
 impl Parameters for GeneralAction {
     fn from_json(body: &Json) -> WebDriverResult<GeneralAction> {
         match body.find("type").and_then(|x| x.as_string()) {
             Some("pause") => Ok(GeneralAction::Pause(try!(PauseAction::from_json(body)))),
@@ -1352,17 +1352,17 @@ impl Parameters for GeneralAction {
 impl ToJson for GeneralAction {
     fn to_json(&self) -> Json {
         match self {
             &GeneralAction::Pause(ref x) => x.to_json()
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct PauseAction {
     pub duration: u64
 }
 
 impl Parameters for PauseAction {
     fn from_json(body: &Json) -> WebDriverResult<PauseAction> {
         let default = Json::U64(0);
         Ok(PauseAction {
@@ -1379,17 +1379,17 @@ impl ToJson for PauseAction {
         data.insert("type".to_owned(),
                     "pause".to_json());
         data.insert("duration".to_owned(),
                     self.duration.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum KeyAction {
     Up(KeyUpAction),
     Down(KeyDownAction)
 }
 
 impl Parameters for KeyAction {
     fn from_json(body: &Json) -> WebDriverResult<KeyAction> {
         match body.find("type").and_then(|x| x.as_string()) {
@@ -1422,17 +1422,17 @@ fn validate_key_value(value_str: &str) -
     if chars.next().is_some() {
         return Err(WebDriverError::new(
             ErrorStatus::InvalidArgument,
             "Parameter 'value' contained multiple characters"))
     };
     Ok(value)
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct KeyUpAction {
     pub value: char
 }
 
 impl Parameters for KeyUpAction {
     fn from_json(body: &Json) -> WebDriverResult<KeyUpAction> {
         let value_str = try_opt!(
                 try_opt!(body.find("value"),
@@ -1454,17 +1454,17 @@ impl ToJson for KeyUpAction {
         data.insert("type".to_owned(),
                     "keyUp".to_json());
         data.insert("value".to_string(),
                     self.value.to_string().to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct KeyDownAction {
     pub value: char
 }
 
 impl Parameters for KeyDownAction {
     fn from_json(body: &Json) -> WebDriverResult<KeyDownAction> {
         let value_str = try_opt!(
                 try_opt!(body.find("value"),
@@ -1485,17 +1485,17 @@ impl ToJson for KeyDownAction {
         data.insert("type".to_owned(),
                     "keyDown".to_json());
         data.insert("value".to_owned(),
                     self.value.to_string().to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum PointerOrigin {
     Viewport,
     Pointer,
     Element(WebElement),
 }
 
 impl Parameters for PointerOrigin {
     fn from_json(body: &Json) -> WebDriverResult<PointerOrigin> {
@@ -1526,17 +1526,17 @@ impl ToJson for PointerOrigin {
 }
 
 impl Default for PointerOrigin {
     fn default() -> PointerOrigin {
         PointerOrigin::Viewport
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum PointerAction {
     Up(PointerUpAction),
     Down(PointerDownAction),
     Move(PointerMoveAction),
     Cancel
 }
 
 impl Parameters for PointerAction {
@@ -1564,17 +1564,17 @@ impl ToJson for PointerAction {
                 data.insert("type".to_owned(),
                             "pointerCancel".to_json());
                 Json::Object(data)
             }
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct PointerUpAction {
     pub button: u64,
 }
 
 impl Parameters for PointerUpAction {
     fn from_json(body: &Json) -> WebDriverResult<PointerUpAction> {
         let button = try_opt!(
             try_opt!(body.find("button"),
@@ -1594,17 +1594,17 @@ impl ToJson for PointerUpAction {
         let mut data = BTreeMap::new();
         data.insert("type".to_owned(),
                     "pointerUp".to_json());
         data.insert("button".to_owned(), self.button.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct PointerDownAction {
     pub button: u64,
 }
 
 impl Parameters for PointerDownAction {
     fn from_json(body: &Json) -> WebDriverResult<PointerDownAction> {
         let button = try_opt!(
             try_opt!(body.find("button"),
@@ -1624,17 +1624,17 @@ impl ToJson for PointerDownAction {
         let mut data = BTreeMap::new();
         data.insert("type".to_owned(),
                     "pointerDown".to_json());
         data.insert("button".to_owned(), self.button.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct PointerMoveAction {
     pub duration: Nullable<u64>,
     pub origin: PointerOrigin,
     pub x: Nullable<i64>,
     pub y: Nullable<i64>
 }
 
 impl Parameters for PointerMoveAction {
--- a/third_party/rust/webdriver/src/common.rs
+++ b/third_party/rust/webdriver/src/common.rs
@@ -1,33 +1,33 @@
 use rustc_serialize::{Encodable, Encoder};
 use rustc_serialize::json::{Json, ToJson};
 use std::collections::BTreeMap;
 
 use error::{WebDriverResult, WebDriverError, ErrorStatus};
 
 pub static ELEMENT_KEY: &'static str = "element-6066-11e4-a52e-4f735466cecf";
 
-#[derive(RustcEncodable, PartialEq, Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable)]
 pub struct Date(pub u64);
 
 impl Date {
     pub fn new(timestamp: u64) -> Date {
         Date(timestamp)
     }
 }
 
 impl ToJson for Date {
     fn to_json(&self) -> Json {
         let &Date(x) = self;
         x.to_json()
     }
 }
 
-#[derive(PartialEq, Clone, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum Nullable<T: ToJson> {
     Value(T),
     Null
 }
 
 impl<T: ToJson> Nullable<T> {
      pub fn is_null(&self) -> bool {
         match *self {
@@ -137,17 +137,17 @@ impl ToJson for WebElement {
 
 impl <T> From<T> for WebElement
     where T: Into<String> {
     fn from(data: T) -> WebElement {
         WebElement::new(data.into())
     }
 }
 
-#[derive(PartialEq, Debug)]
+#[derive(Debug, PartialEq)]
 pub enum FrameId {
     Short(u16),
     Element(WebElement),
     Null
 }
 
 impl FrameId {
     pub fn from_json(data: &Json) -> WebDriverResult<FrameId> {
@@ -179,29 +179,29 @@ impl ToJson for FrameId {
             },
             FrameId::Null => {
                 Json::Null
             }
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum LocatorStrategy {
     CSSSelector,
     LinkText,
     PartialLinkText,
-    XPath
+    XPath,
 }
 
 impl LocatorStrategy {
     pub fn from_json(body: &Json) -> WebDriverResult<LocatorStrategy> {
         match try_opt!(body.as_string(),
                        ErrorStatus::InvalidArgument,
-                       "Cound not convert strategy to string") {
+                       "Expected locator strategy as string") {
             "css selector" => Ok(LocatorStrategy::CSSSelector),
             "link text" => Ok(LocatorStrategy::LinkText),
             "partial link text" => Ok(LocatorStrategy::PartialLinkText),
             "xpath" => Ok(LocatorStrategy::XPath),
             x => Err(WebDriverError::new(ErrorStatus::InvalidArgument,
                                          format!("Unknown locator strategy {}", x)))
         }
     }
@@ -212,8 +212,60 @@ impl ToJson for LocatorStrategy {
         Json::String(match *self {
             LocatorStrategy::CSSSelector => "css selector",
             LocatorStrategy::LinkText => "link text",
             LocatorStrategy::PartialLinkText => "partial link text",
             LocatorStrategy::XPath => "xpath"
         }.to_string())
     }
 }
+
+/// The top-level browsing context has an associated window state which
+/// describes what visibility state its OS widget window is in.
+///
+/// The default state is [`Normal`].
+///
+/// [`normal`]: #variant.Normal
+#[derive(Debug)]
+pub enum WindowState {
+    /// The window is maximized.
+    Maximized,
+    /// The window is iconified.
+    Minimized,
+    /// The window is shown normally.
+    Normal,
+    /// The window is in full screen mode.
+    Fullscreen,
+}
+
+impl WindowState {
+    pub fn from_json(body: &Json) -> WebDriverResult<WindowState> {
+        use self::WindowState::*;
+        let s = try_opt!(
+            body.as_string(),
+            ErrorStatus::InvalidArgument,
+            "Expecetd window state as string"
+        );
+        match s {
+            "maximized" => Ok(Maximized),
+            "minimized" => Ok(Minimized),
+            "normal" => Ok(Normal),
+            "fullscreen" => Ok(Fullscreen),
+            x => Err(WebDriverError::new(
+                ErrorStatus::InvalidArgument,
+                format!("Unknown window state {}", x),
+            )),
+        }
+    }
+}
+
+impl ToJson for WindowState {
+    fn to_json(&self) -> Json {
+        use self::WindowState::*;
+        let state = match *self {
+            Maximized => "maximized",
+            Minimized => "minimized",
+            Normal => "normal",
+            Fullscreen => "fullscreen",
+        };
+        Json::String(state.to_string())
+    }
+}
--- a/third_party/rust/webdriver/src/error.rs
+++ b/third_party/rust/webdriver/src/error.rs
@@ -4,17 +4,17 @@ use rustc_serialize::base64::FromBase64E
 use rustc_serialize::json::{DecoderError, Json, ParserError, ToJson};
 use std::borrow::Cow;
 use std::collections::BTreeMap;
 use std::convert::From;
 use std::error::Error;
 use std::fmt;
 use std::io;
 
-#[derive(PartialEq, Debug)]
+#[derive(Debug, PartialEq)]
 pub enum ErrorStatus {
     /// The [`ElementClick`] command could not be completed because the
     /// [element] receiving the events is obscuring the element that was
     /// requested clicked.
     ///
     /// [`ElementClick`]:
     /// ../command/enum.WebDriverCommand.html#variant.ElementClick
     /// [element]: ../common/struct.WebElement.html
--- a/third_party/rust/webdriver/src/httpapi.rs
+++ b/third_party/rust/webdriver/src/httpapi.rs
@@ -66,17 +66,17 @@ fn standard_routes<U:WebDriverExtensionR
                 (Post, "/session/{sessionId}/alert/text", Route::SendAlertText),
                 (Get, "/session/{sessionId}/screenshot", Route::TakeScreenshot),
                 (Get, "/session/{sessionId}/element/{elementId}/screenshot", Route::TakeElementScreenshot),
                 (Post, "/session/{sessionId}/actions", Route::PerformActions),
                 (Delete, "/session/{sessionId}/actions", Route::ReleaseActions),
                 (Get, "/status", Route::Status),]
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub enum Route<U:WebDriverExtensionRoute> {
     NewSession,
     DeleteSession,
     Get,
     GetCurrentUrl,
     GoBack,
     GoForward,
     Refresh,
@@ -137,28 +137,28 @@ pub enum Route<U:WebDriverExtensionRoute
 }
 
 pub trait WebDriverExtensionRoute : Clone + Send + PartialEq {
     type Command: WebDriverExtensionCommand + 'static;
 
     fn command(&self, &Captures, &Json) -> WebDriverResult<WebDriverCommand<Self::Command>>;
 }
 
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct VoidWebDriverExtensionRoute;
 
 impl WebDriverExtensionRoute for VoidWebDriverExtensionRoute {
     type Command = VoidWebDriverExtensionCommand;
 
     fn command(&self, _:&Captures, _:&Json) -> WebDriverResult<WebDriverCommand<VoidWebDriverExtensionCommand>> {
         panic!("No extensions implemented");
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 struct RequestMatcher<U: WebDriverExtensionRoute> {
     method: Method,
     path_regexp: Regex,
     match_type: Route<U>
 }
 
 impl <U: WebDriverExtensionRoute> RequestMatcher<U> {
     pub fn new(method: Method, path: &str, match_type: Route<U>) -> RequestMatcher<U> {
@@ -192,16 +192,17 @@ impl <U: WebDriverExtensionRoute> Reques
         //Remove the trailing /
         rv.pop();
         rv.push_str("$");
         //This will fail at runtime if the regexp is invalid
         Regex::new(&rv[..]).unwrap()
     }
 }
 
+#[derive(Debug)]
 pub struct WebDriverHttpApi<U: WebDriverExtensionRoute> {
     routes: Vec<(Method, RequestMatcher<U>)>,
 }
 
 impl <U: WebDriverExtensionRoute> WebDriverHttpApi<U> {
     pub fn new(extension_routes: &[(Method, &str, U)]) -> WebDriverHttpApi<U> {
         let mut rv = WebDriverHttpApi::<U> {
             routes: vec![],
--- a/third_party/rust/webdriver/src/response.rs
+++ b/third_party/rust/webdriver/src/response.rs
@@ -1,59 +1,59 @@
+use common::{Date, Nullable, WindowState};
+use cookie;
 use rustc_serialize::json::{self, Json, ToJson};
-
-use common::{Nullable, Date};
-use cookie;
+use std::collections::BTreeMap;
 use time;
 
 #[derive(Debug)]
 pub enum WebDriverResponse {
     CloseWindow(CloseWindowResponse),
     Cookie(CookieResponse),
     Cookies(CookiesResponse),
     DeleteSession,
-    ElementRect(RectResponse),
+    ElementRect(ElementRectResponse),
     Generic(ValueResponse),
     NewSession(NewSessionResponse),
     Timeouts(TimeoutsResponse),
     Void,
-    WindowRect(RectResponse),
+    WindowRect(WindowRectResponse),
 }
 
 impl WebDriverResponse {
     pub fn to_json_string(self) -> String {
         use response::WebDriverResponse::*;
 
         let obj = match self {
             CloseWindow(ref x) => json::encode(&x.to_json()),
             Cookie(ref x) => json::encode(x),
             Cookies(ref x) => json::encode(x),
             DeleteSession => Ok("{}".to_string()),
             ElementRect(ref x) => json::encode(x),
             Generic(ref x) => json::encode(x),
             NewSession(ref x) => json::encode(x),
             Timeouts(ref x) => json::encode(x),
             Void => Ok("{}".to_string()),
-            WindowRect(ref x) => json::encode(x),
+            WindowRect(ref x) => json::encode(&x.to_json()),
         }.unwrap();
 
         match self {
             Generic(_) | Cookie(_) | Cookies(_) => obj,
             _ => {
                 let mut data = String::with_capacity(11 + obj.len());
                 data.push_str("{\"value\": ");
                 data.push_str(&*obj);
                 data.push_str("}");
                 data
             }
         }
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct CloseWindowResponse {
     pub window_handles: Vec<String>,
 }
 
 impl CloseWindowResponse {
     pub fn new(handles: Vec<String>) -> CloseWindowResponse {
         CloseWindowResponse { window_handles: handles }
     }
@@ -63,81 +63,125 @@ impl ToJson for CloseWindowResponse {
     fn to_json(&self) -> Json {
         Json::Array(self.window_handles
                     .iter()
                     .map(|x| Json::String(x.clone()))
                     .collect::<Vec<Json>>())
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct NewSessionResponse {
     pub sessionId: String,
     pub capabilities: json::Json
 }
 
 impl NewSessionResponse {
     pub fn new(session_id: String, capabilities: json::Json) -> NewSessionResponse {
         NewSessionResponse {
             capabilities: capabilities,
             sessionId: session_id
         }
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct TimeoutsResponse {
     pub script: u64,
     pub pageLoad: u64,
     pub implicit: u64,
 }
 
 impl TimeoutsResponse {
     pub fn new(script: u64, page_load: u64, implicit: u64) -> TimeoutsResponse {
         TimeoutsResponse {
             script: script,
             pageLoad: page_load,
             implicit: implicit,
         }
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct ValueResponse {
     pub value: json::Json
 }
 
 impl ValueResponse {
     pub fn new(value: json::Json) -> ValueResponse {
         ValueResponse {
             value: value
         }
     }
 }
 
-#[derive(RustcEncodable, Debug)]
-pub struct RectResponse {
+#[derive(Debug, RustcEncodable)]
+pub struct ElementRectResponse {
+    /// X axis position of the top-left corner of the element relative
+    // to the current browsing context’s document element in CSS reference
+    // pixels.
     pub x: f64,
+
+    /// Y axis position of the top-left corner of the element relative
+    // to the current browsing context’s document element in CSS reference
+    // pixels.
     pub y: f64,
+
+    /// Height of the element’s [bounding rectangle] in CSS reference
+    /// pixels.
+    ///
+    /// [bounding rectangle]: https://drafts.fxtf.org/geometry/#rectangle
     pub width: f64,
-    pub height: f64
+
+    /// Width of the element’s [bounding rectangle] in CSS reference
+    /// pixels.
+    ///
+    /// [bounding rectangle]: https://drafts.fxtf.org/geometry/#rectangle
+    pub height: f64,
 }
 
-impl RectResponse {
-    pub fn new(x: f64, y: f64, width: f64, height: f64) -> RectResponse {
-        RectResponse {
-            x: x,
-            y: y,
-            width: width,
-            height: height
-        }
+#[derive(Debug)]
+pub struct WindowRectResponse {
+    /// `WindowProxy`’s [screenX] attribute.
+    ///
+    /// [screenX]: https://drafts.csswg.org/cssom-view/#dom-window-screenx
+    pub x: f64,
+
+    /// `WindowProxy`’s [screenY] attribute.
+    ///
+    /// [screenY]: https://drafts.csswg.org/cssom-view/#dom-window-screeny
+    pub y: f64,
+
+    /// Width of the top-level browsing context’s outer dimensions, including
+    /// any browser chrome and externally drawn window decorations in CSS
+    /// reference pixels.
+    pub width: f64,
+
+    /// Height of the top-level browsing context’s outer dimensions, including
+    /// any browser chrome and externally drawn window decorations in CSS
+    /// reference pixels.
+    pub height: f64,
+
+    /// The top-level browsing context’s window state.
+    pub state: WindowState,
+}
+
+impl ToJson for WindowRectResponse {
+    fn to_json(&self) -> Json {
+        let mut body = BTreeMap::new();
+        body.insert("x".to_owned(), self.x.to_json());
+        body.insert("y".to_owned(), self.y.to_json());
+        body.insert("width".to_owned(), self.width.to_json());
+        body.insert("height".to_owned(), self.height.to_json());
+        body.insert("state".to_owned(), self.state.to_json());
+        Json::Object(body)
     }
 }
 
-#[derive(RustcEncodable, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable)]
 pub struct Cookie {
     pub name: String,
     pub value: String,
     pub path: Nullable<String>,
     pub domain: Nullable<String>,
     pub expiry: Nullable<Date>,
     pub secure: bool,
     pub httpOnly: bool,
@@ -161,30 +205,32 @@ impl Into<cookie::Cookie<'static>> for C
                 cookie.expires(time::at(time::Timespec::new(expiry as i64, 0)))
             }
             Nullable::Null => cookie,
         };
         cookie.finish()
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct CookieResponse {
     pub value: Cookie,
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct CookiesResponse {
     pub value: Vec<Cookie>,
 }
 
 #[cfg(test)]
 mod tests {
-    use super::{CloseWindowResponse, Cookie, CookieResponse, CookiesResponse, NewSessionResponse,
-                Nullable, RectResponse, TimeoutsResponse, ValueResponse, WebDriverResponse};
+    use super::{CloseWindowResponse, Cookie, CookieResponse, CookiesResponse, ElementRectResponse,
+                NewSessionResponse, Nullable, TimeoutsResponse, ValueResponse, WebDriverResponse,
+                WindowRectResponse};
+    use common::WindowState;
     use rustc_serialize::json::Json;
     use std::collections::BTreeMap;
 
     fn test(resp: WebDriverResponse, expected_str: &str) {
         let data = resp.to_json_string();
         let actual = Json::from_str(&*data).unwrap();
         let expected = Json::from_str(expected_str).unwrap();
         assert_eq!(actual, expected);
@@ -231,31 +277,38 @@ mod tests {
             ]});
         let expected = r#"{"value": [{"name": "name", "value": "value", "path": "/",
 "domain": null, "expiry": null, "secure": true, "httpOnly": false}]}"#;
         test(resp, expected);
     }
 
     #[test]
     fn test_element_rect() {
-        let resp = WebDriverResponse::ElementRect(RectResponse::new(
-            0f64, 1f64, 2f64, 3f64));
+        let rect = ElementRectResponse {
+            x: 0f64,
+            y: 1f64,
+            width: 2f64,
+            height: 3f64,
+        };
+        let resp = WebDriverResponse::ElementRect(rect);
         let expected = r#"{"value": {"x": 0.0, "y": 1.0, "width": 2.0, "height": 3.0}}"#;
         test(resp, expected);
     }
 
     #[test]
     fn test_window_rect() {
-        let resp = WebDriverResponse::WindowRect(RectResponse {
+        let rect = WindowRectResponse {
             x: 0f64,
             y: 1f64,
             width: 2f64,
             height: 3f64,
-        });
-        let expected = r#"{"value": {"x": 0.0, "y": 1.0, "width": 2.0, "height": 3.0}}"#;
+            state: WindowState::Normal,
+        };
+        let resp = WebDriverResponse::WindowRect(rect);
+        let expected = r#"{"value": {"x": 0.0, "y": 1.0, "width": 2.0, "height": 3.0, "state": "normal"}}"#;
         test(resp, expected);
     }
 
     #[test]
     fn test_new_session() {
         let resp = WebDriverResponse::NewSession(
             NewSessionResponse::new("test".into(),
                                     Json::Object(BTreeMap::new())));
--- a/third_party/rust/webdriver/src/server.rs
+++ b/third_party/rust/webdriver/src/server.rs
@@ -18,17 +18,17 @@ use error::{WebDriverResult, WebDriverEr
 use httpapi::{WebDriverHttpApi, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
 use response::{CloseWindowResponse, WebDriverResponse};
 
 enum DispatchMessage<U: WebDriverExtensionRoute> {
     HandleWebDriver(WebDriverMessage<U>, Sender<WebDriverResult<WebDriverResponse>>),
     Quit
 }
 
-#[derive(PartialEq, Clone)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct Session {
     id: String
 }
 
 impl Session {
     fn new(id: String) -> Session {
         Session {
             id: id
@@ -36,16 +36,17 @@ impl Session {
     }
 }
 
 pub trait WebDriverHandler<U: WebDriverExtensionRoute=VoidWebDriverExtensionRoute> : Send {
     fn handle_command(&mut self, session: &Option<Session>, msg: WebDriverMessage<U>) -> WebDriverResult<WebDriverResponse>;
     fn delete_session(&mut self, session: &Option<Session>);
 }
 
+#[derive(Debug)]
 struct Dispatcher<T: WebDriverHandler<U>,
                   U: WebDriverExtensionRoute> {
     handler: T,
     session: Option<Session>,
     extension_type: PhantomData<U>,
 }
 
 impl<T: WebDriverHandler<U>, U: WebDriverExtensionRoute> Dispatcher<T, U> {
@@ -143,16 +144,17 @@ impl<T: WebDriverHandler<U>, U: WebDrive
                         }
                     }
                 }
             }
         }
     }
 }
 
+#[derive(Debug)]
 struct HttpHandler<U: WebDriverExtensionRoute> {
     chan: Mutex<Sender<DispatchMessage<U>>>,
     api: Mutex<WebDriverHttpApi<U>>
 }
 
 impl <U: WebDriverExtensionRoute> HttpHandler<U> {
     fn new(api: WebDriverHttpApi<U>, chan: Sender<DispatchMessage<U>>) -> HttpHandler<U> {
         HttpHandler {