Bug 1388365 - Vendor webdriver 0.29.0. r=whimboo
authorAndreas Tolfsen <ato@sny.no>
Tue, 08 Aug 2017 15:10:55 +0100
changeset 373646 ec1bd26e8184982eb3d327831da881292fc09345
parent 373645 535e762772079db364e730f336a068bfd2d6f875
child 373647 65dc7d28c6fce3e55fadea2ad8b65cabf723e789
push id32308
push userarchaeopteryx@coole-files.de
push dateThu, 10 Aug 2017 15:20:33 +0000
treeherdermozilla-central@5322c03f4c85 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswhimboo
bugs1388365
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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 {