Bug 1368265 - Remove third_party/rust/webdriver. r?automatedtester draft
authorAndreas Tolfsen <ato@sny.no>
Sun, 03 Sep 2017 16:15:29 +0100
changeset 658615 681516c17e3f7030ede4e64c546bdbcbe5b72797
parent 658614 daf0cc396743344aa4db8d2aa0ba464527e8eb09
child 658616 6935643547daea08791e4dbb8c4771fce6bccde0
push id77827
push userbmo:ato@sny.no
push dateMon, 04 Sep 2017 12:56:18 +0000
reviewersautomatedtester
bugs1368265
milestone57.0a1
Bug 1368265 - Remove third_party/rust/webdriver. r?automatedtester MozReview-Commit-ID: BGi7cVgFYLw
third_party/rust/webdriver/.cargo-checksum.json
third_party/rust/webdriver/.cargo-ok
third_party/rust/webdriver/.travis.yml
third_party/rust/webdriver/Cargo.toml
third_party/rust/webdriver/LICENSE
third_party/rust/webdriver/README.md
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/lib.rs
third_party/rust/webdriver/src/macros.rs
third_party/rust/webdriver/src/response.rs
third_party/rust/webdriver/src/server.rs
deleted file mode 100644
--- a/third_party/rust/webdriver/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"78252ef89a407b1d76616b7afbf7afb8205530a7f7039f3a7ea140684e3aa8bc","Cargo.toml":"9ce1bfb98e94cb9f2494676ef0cc741dcfeab1b60d7f5fa23ae261b02025bc1c","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"bd0e99ce271903a9f67cf5f8fca2f67f2583e4336fbaf583fcd78ec238d4176e","src/capabilities.rs":"12a71bf787f1102435f9c2ae2c357acf397b80fadcb3355710ef9bbc39d8a337","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":"b05f860c230757d0df161f6b2db8820ca636940689b29b148ea53bd8685feb84"}
\ No newline at end of file
deleted file mode 100644
deleted file mode 100644
--- a/third_party/rust/webdriver/.travis.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-language: rust
-
-rust:
-    - nightly
-    - stable
-
-script:
-    - cargo build --verbose
-    - cargo test --verbose
\ No newline at end of file
deleted file mode 100644
--- a/third_party/rust/webdriver/Cargo.toml
+++ /dev/null
@@ -1,46 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
-#
-# 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.30.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.time]
-version = "0.1"
-
-[dependencies.rustc-serialize]
-version = "0.3"
-
-[dependencies.backtrace]
-version = "0.3"
-
-[dependencies.log]
-version = "0.3"
-
-[dependencies.cookie]
-version = "0.9"
-default-features = false
-
-[dependencies.url]
-version = "1"
-
-[dependencies.hyper]
-version = "0.10"
-
-[dependencies.regex]
-version = "0.2"
deleted file mode 100644
--- a/third_party/rust/webdriver/LICENSE
+++ /dev/null
@@ -1,373 +0,0 @@
-Mozilla Public License Version 2.0
-==================================
-
-1. Definitions
---------------
-
-1.1. "Contributor"
-    means each individual or legal entity that creates, contributes to
-    the creation of, or owns Covered Software.
-
-1.2. "Contributor Version"
-    means the combination of the Contributions of others (if any) used
-    by a Contributor and that particular Contributor's Contribution.
-
-1.3. "Contribution"
-    means Covered Software of a particular Contributor.
-
-1.4. "Covered Software"
-    means Source Code Form to which the initial Contributor has attached
-    the notice in Exhibit A, the Executable Form of such Source Code
-    Form, and Modifications of such Source Code Form, in each case
-    including portions thereof.
-
-1.5. "Incompatible With Secondary Licenses"
-    means
-
-    (a) that the initial Contributor has attached the notice described
-        in Exhibit B to the Covered Software; or
-
-    (b) that the Covered Software was made available under the terms of
-        version 1.1 or earlier of the License, but not also under the
-        terms of a Secondary License.
-
-1.6. "Executable Form"
-    means any form of the work other than Source Code Form.
-
-1.7. "Larger Work"
-    means a work that combines Covered Software with other material, in 
-    a separate file or files, that is not Covered Software.
-
-1.8. "License"
-    means this document.
-
-1.9. "Licensable"
-    means having the right to grant, to the maximum extent possible,
-    whether at the time of the initial grant or subsequently, any and
-    all of the rights conveyed by this License.
-
-1.10. "Modifications"
-    means any of the following:
-
-    (a) any file in Source Code Form that results from an addition to,
-        deletion from, or modification of the contents of Covered
-        Software; or
-
-    (b) any new file in Source Code Form that contains any Covered
-        Software.
-
-1.11. "Patent Claims" of a Contributor
-    means any patent claim(s), including without limitation, method,
-    process, and apparatus claims, in any patent Licensable by such
-    Contributor that would be infringed, but for the grant of the
-    License, by the making, using, selling, offering for sale, having
-    made, import, or transfer of either its Contributions or its
-    Contributor Version.
-
-1.12. "Secondary License"
-    means either the GNU General Public License, Version 2.0, the GNU
-    Lesser General Public License, Version 2.1, the GNU Affero General
-    Public License, Version 3.0, or any later versions of those
-    licenses.
-
-1.13. "Source Code Form"
-    means the form of the work preferred for making modifications.
-
-1.14. "You" (or "Your")
-    means an individual or a legal entity exercising rights under this
-    License. For legal entities, "You" includes any entity that
-    controls, is controlled by, or is under common control with You. For
-    purposes of this definition, "control" means (a) the power, direct
-    or indirect, to cause the direction or management of such entity,
-    whether by contract or otherwise, or (b) ownership of more than
-    fifty percent (50%) of the outstanding shares or beneficial
-    ownership of such entity.
-
-2. License Grants and Conditions
---------------------------------
-
-2.1. Grants
-
-Each Contributor hereby grants You a world-wide, royalty-free,
-non-exclusive license:
-
-(a) under intellectual property rights (other than patent or trademark)
-    Licensable by such Contributor to use, reproduce, make available,
-    modify, display, perform, distribute, and otherwise exploit its
-    Contributions, either on an unmodified basis, with Modifications, or
-    as part of a Larger Work; and
-
-(b) under Patent Claims of such Contributor to make, use, sell, offer
-    for sale, have made, import, and otherwise transfer either its
-    Contributions or its Contributor Version.
-
-2.2. Effective Date
-
-The licenses granted in Section 2.1 with respect to any Contribution
-become effective for each Contribution on the date the Contributor first
-distributes such Contribution.
-
-2.3. Limitations on Grant Scope
-
-The licenses granted in this Section 2 are the only rights granted under
-this License. No additional rights or licenses will be implied from the
-distribution or licensing of Covered Software under this License.
-Notwithstanding Section 2.1(b) above, no patent license is granted by a
-Contributor:
-
-(a) for any code that a Contributor has removed from Covered Software;
-    or
-
-(b) for infringements caused by: (i) Your and any other third party's
-    modifications of Covered Software, or (ii) the combination of its
-    Contributions with other software (except as part of its Contributor
-    Version); or
-
-(c) under Patent Claims infringed by Covered Software in the absence of
-    its Contributions.
-
-This License does not grant any rights in the trademarks, service marks,
-or logos of any Contributor (except as may be necessary to comply with
-the notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
-No Contributor makes additional grants as a result of Your choice to
-distribute the Covered Software under a subsequent version of this
-License (see Section 10.2) or under the terms of a Secondary License (if
-permitted under the terms of Section 3.3).
-
-2.5. Representation
-
-Each Contributor represents that the Contributor believes its
-Contributions are its original creation(s) or it has sufficient rights
-to grant the rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
-This License is not intended to limit any rights You have under
-applicable copyright doctrines of fair use, fair dealing, or other
-equivalents.
-
-2.7. Conditions
-
-Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
-in Section 2.1.
-
-3. Responsibilities
--------------------
-
-3.1. Distribution of Source Form
-
-All distribution of Covered Software in Source Code Form, including any
-Modifications that You create or to which You contribute, must be under
-the terms of this License. You must inform recipients that the Source
-Code Form of the Covered Software is governed by the terms of this
-License, and how they can obtain a copy of this License. You may not
-attempt to alter or restrict the recipients' rights in the Source Code
-Form.
-
-3.2. Distribution of Executable Form
-
-If You distribute Covered Software in Executable Form then:
-
-(a) such Covered Software must also be made available in Source Code
-    Form, as described in Section 3.1, and You must inform recipients of
-    the Executable Form how they can obtain a copy of such Source Code
-    Form by reasonable means in a timely manner, at a charge no more
-    than the cost of distribution to the recipient; and
-
-(b) You may distribute such Executable Form under the terms of this
-    License, or sublicense it under different terms, provided that the
-    license for the Executable Form does not attempt to limit or alter
-    the recipients' rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
-You may create and distribute a Larger Work under terms of Your choice,
-provided that You also comply with the requirements of this License for
-the Covered Software. If the Larger Work is a combination of Covered
-Software with a work governed by one or more Secondary Licenses, and the
-Covered Software is not Incompatible With Secondary Licenses, this
-License permits You to additionally distribute such Covered Software
-under the terms of such Secondary License(s), so that the recipient of
-the Larger Work may, at their option, further distribute the Covered
-Software under the terms of either this License or such Secondary
-License(s).
-
-3.4. Notices
-
-You may not remove or alter the substance of any license notices
-(including copyright notices, patent notices, disclaimers of warranty,
-or limitations of liability) contained within the Source Code Form of
-the Covered Software, except that You may alter any license notices to
-the extent required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
-You may choose to offer, and to charge a fee for, warranty, support,
-indemnity or liability obligations to one or more recipients of Covered
-Software. However, You may do so only on Your own behalf, and not on
-behalf of any Contributor. You must make it absolutely clear that any
-such warranty, support, indemnity, or liability obligation is offered by
-You alone, and You hereby agree to indemnify every Contributor for any
-liability incurred by such Contributor as a result of warranty, support,
-indemnity or liability terms You offer. You may include additional
-disclaimers of warranty and limitations of liability specific to any
-jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
----------------------------------------------------
-
-If it is impossible for You to comply with any of the terms of this
-License with respect to some or all of the Covered Software due to
-statute, judicial order, or regulation then You must: (a) comply with
-the terms of this License to the maximum extent possible; and (b)
-describe the limitations and the code they affect. Such description must
-be placed in a text file included with all distributions of the Covered
-Software under this License. Except to the extent prohibited by statute
-or regulation, such description must be sufficiently detailed for a
-recipient of ordinary skill to be able to understand it.
-
-5. Termination
---------------
-
-5.1. The rights granted under this License will terminate automatically
-if You fail to comply with any of its terms. However, if You become
-compliant, then the rights granted under this License from a particular
-Contributor are reinstated (a) provisionally, unless and until such
-Contributor explicitly and finally terminates Your grants, and (b) on an
-ongoing basis, if such Contributor fails to notify You of the
-non-compliance by some reasonable means prior to 60 days after You have
-come back into compliance. Moreover, Your grants from a particular
-Contributor are reinstated on an ongoing basis if such Contributor
-notifies You of the non-compliance by some reasonable means, this is the
-first time You have received notice of non-compliance with this License
-from such Contributor, and You become compliant prior to 30 days after
-Your receipt of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
-infringement claim (excluding declaratory judgment actions,
-counter-claims, and cross-claims) alleging that a Contributor Version
-directly or indirectly infringes any patent, then the rights granted to
-You by any and all Contributors for the Covered Software under Section
-2.1 of this License shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all
-end user license agreements (excluding distributors and resellers) which
-have been validly granted by You or Your distributors under this License
-prior to termination shall survive termination.
-
-************************************************************************
-*                                                                      *
-*  6. Disclaimer of Warranty                                           *
-*  -------------------------                                           *
-*                                                                      *
-*  Covered Software is provided under this License on an "as is"       *
-*  basis, without warranty of any kind, either expressed, implied, or  *
-*  statutory, including, without limitation, warranties that the       *
-*  Covered Software is free of defects, merchantable, fit for a        *
-*  particular purpose or non-infringing. The entire risk as to the     *
-*  quality and performance of the Covered Software is with You.        *
-*  Should any Covered Software prove defective in any respect, You     *
-*  (not any Contributor) assume the cost of any necessary servicing,   *
-*  repair, or correction. This disclaimer of warranty constitutes an   *
-*  essential part of this License. No use of any Covered Software is   *
-*  authorized under this License except under this disclaimer.         *
-*                                                                      *
-************************************************************************
-
-************************************************************************
-*                                                                      *
-*  7. Limitation of Liability                                          *
-*  --------------------------                                          *
-*                                                                      *
-*  Under no circumstances and under no legal theory, whether tort      *
-*  (including negligence), contract, or otherwise, shall any           *
-*  Contributor, or anyone who distributes Covered Software as          *
-*  permitted above, be liable to You for any direct, indirect,         *
-*  special, incidental, or consequential damages of any character      *
-*  including, without limitation, damages for lost profits, loss of    *
-*  goodwill, work stoppage, computer failure or malfunction, or any    *
-*  and all other commercial damages or losses, even if such party      *
-*  shall have been informed of the possibility of such damages. This   *
-*  limitation of liability shall not apply to liability for death or   *
-*  personal injury resulting from such party's negligence to the       *
-*  extent applicable law prohibits such limitation. Some               *
-*  jurisdictions do not allow the exclusion or limitation of           *
-*  incidental or consequential damages, so this exclusion and          *
-*  limitation may not apply to You.                                    *
-*                                                                      *
-************************************************************************
-
-8. Litigation
--------------
-
-Any litigation relating to this License may be brought only in the
-courts of a jurisdiction where the defendant maintains its principal
-place of business and such litigation shall be governed by laws of that
-jurisdiction, without reference to its conflict-of-law provisions.
-Nothing in this Section shall prevent a party's ability to bring
-cross-claims or counter-claims.
-
-9. Miscellaneous
-----------------
-
-This License represents the complete agreement concerning the subject
-matter hereof. If any provision of this License is held to be
-unenforceable, such provision shall be reformed only to the extent
-necessary to make it enforceable. Any law or regulation which provides
-that the language of a contract shall be construed against the drafter
-shall not be used to construe this License against a Contributor.
-
-10. Versions of the License
----------------------------
-
-10.1. New Versions
-
-Mozilla Foundation is the license steward. Except as provided in Section
-10.3, no one other than the license steward has the right to modify or
-publish new versions of this License. Each version will be given a
-distinguishing version number.
-
-10.2. Effect of New Versions
-
-You may distribute the Covered Software under the terms of the version
-of the License under which You originally received the Covered Software,
-or under the terms of any subsequent version published by the license
-steward.
-
-10.3. Modified Versions
-
-If you create software not governed by this License, and you want to
-create a new license for such software, you may create and use a
-modified version of this License if you rename the license and remove
-any references to the name of the license steward (except to note that
-such modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary
-Licenses
-
-If You choose to distribute Source Code Form that is Incompatible With
-Secondary Licenses under the terms of this version of the License, the
-notice described in Exhibit B of this License must be attached.
-
-Exhibit A - Source Code Form License Notice
--------------------------------------------
-
-  This Source Code Form is subject to the terms of the Mozilla Public
-  License, v. 2.0. If a copy of the MPL was not distributed with this
-  file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular
-file, then You may include the notice in a location (such as a LICENSE
-file in a relevant directory) where a recipient would be likely to look
-for such a notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - "Incompatible With Secondary Licenses" Notice
----------------------------------------------------------
-
-  This Source Code Form is "Incompatible With Secondary Licenses", as
-  defined by the Mozilla Public License, v. 2.0.
deleted file mode 100644
--- a/third_party/rust/webdriver/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# webdriver Rust library [![Crate version](https://img.shields.io/crates/v/webdriver.svg)](https://crates.io/crates/webdriver) [![Documentation](https://docs.rs/webdriver/badge.svg)](https://docs.rs/webdriver/) [![Build status](https://travis-ci.org/mozilla/webdriver-rust.svg?branch=master)](https://travis-ci.org/mozilla/webdriver-rust) 
-
-As of right now this is an implementation
-for the server side of the WebDriver API in Rust,
-not the client side.
deleted file mode 100644
--- a/third_party/rust/webdriver/src/capabilities.rs
+++ /dev/null
@@ -1,520 +0,0 @@
-use command::Parameters;
-use error::{ErrorStatus, WebDriverError, WebDriverResult};
-use rustc_serialize::json::{Json, ToJson};
-use std::collections::BTreeMap;
-use url::Url;
-
-pub type Capabilities = BTreeMap<String, Json>;
-
-/// Trait for objects that can be used to inspect browser capabilities
-///
-/// The main methods in this trait are called with a Capabilites object
-/// resulting from a full set of potential capabilites for the session.
-/// Given those Capabilities they return a property of the browser instance
-/// that would be initiated. In many cases this will be independent of the
-/// input, but in the case of e.g. browser version, it might depend on a
-/// path to the binary provided as a capability.
-pub trait BrowserCapabilities {
-    /// Set up the Capabilites object
-    ///
-    /// Typically used to create any internal caches
-    fn init(&mut self, &Capabilities);
-
-    /// Name of the browser
-    fn browser_name(&mut self, &Capabilities) -> WebDriverResult<Option<String>>;
-    /// Version number of the browser
-    fn browser_version(&mut self, &Capabilities) -> WebDriverResult<Option<String>>;
-    /// Compare actual browser version to that provided in a version specifier
-    ///
-    /// Parameters are the actual browser version and the comparison string,
-    /// respectively. The format of the comparison string is implementation-defined.
-    fn compare_browser_version(&mut self, version: &str, comparison: &str) -> WebDriverResult<bool>;
-    /// Name of the platform/OS
-    fn platform_name(&mut self, &Capabilities) -> WebDriverResult<Option<String>>;
-    /// Whether insecure certificates are supported
-    fn accept_insecure_certs(&mut self, &Capabilities) -> WebDriverResult<bool>;
-
-    fn accept_proxy(&mut self, proxy_settings: &BTreeMap<String, Json>, &Capabilities) -> WebDriverResult<bool>;
-
-    /// Type check custom properties
-    ///
-    /// Check that custom properties containing ":" have the correct data types.
-    /// Properties that are unrecognised must be ignored i.e. return without
-    /// error.
-    fn validate_custom(&self, name: &str, value: &Json) -> WebDriverResult<()>;
-    /// Check if custom properties are accepted capabilites
-    ///
-    /// Check that custom properties containing ":" are compatible with
-    /// the implementation.
-    fn accept_custom(&mut self, name: &str, value: &Json, merged: &Capabilities) -> WebDriverResult<bool>;
-}
-
-/// Trait to abstract over various version of the new session parameters
-///
-/// This trait is expected to be implemented on objects holding the capabilities
-/// from a new session command.
-pub trait CapabilitiesMatching {
-    /// Match the BrowserCapabilities against some candidate capabilites
-    ///
-    /// Takes a BrowserCapabilites object and returns a set of capabilites that
-    /// are valid for that browser, if any, or None if there are no matching
-    /// capabilities.
-    fn match_browser<T: BrowserCapabilities>(&self, browser_capabilities: &mut T)
-                                             -> WebDriverResult<Option<Capabilities>>;
-}
-
-#[derive(Debug, PartialEq)]
-pub struct SpecNewSessionParameters {
-    pub alwaysMatch: Capabilities,
-    pub firstMatch: Vec<Capabilities>,
-}
-
-impl SpecNewSessionParameters {
-    fn validate<T: BrowserCapabilities>(&self,
-                                        mut capabilities: Capabilities,
-                                        browser_capabilities: &T) -> WebDriverResult<Capabilities> {
-        // Filter out entries with the value `null`
-        let null_entries = capabilities
-            .iter()
-            .filter(|&(_, ref value)| **value == Json::Null)
-            .map(|(k, _)| k.clone())
-            .collect::<Vec<String>>();
-        for key in null_entries {
-            capabilities.remove(&key);
-        }
-
-        for (key, value) in capabilities.iter() {
-            match &**key {
-                "acceptInsecureCerts" => if !value.is_boolean() {
-                        return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                       "acceptInsecureCerts was not a boolean"))
-                    },
-                x @ "browserName" |
-                x @ "browserVersion" |
-                x @ "platformName" => if !value.is_string() {
-                        return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                       format!("{} was not a boolean", x)))
-                    },
-                "pageLoadStrategy" => {
-                    try!(SpecNewSessionParameters::validate_page_load_strategy(value))
-                }
-                "proxy" => {
-                    try!(SpecNewSessionParameters::validate_proxy(value))
-                },
-                "timeouts" => {
-                    try!(SpecNewSessionParameters::validate_timeouts(value))
-                },
-                "unhandledPromptBehavior" => {
-                    try!(SpecNewSessionParameters::validate_unhandled_prompt_behaviour(value))
-                }
-                x => {
-                    if !x.contains(":") {
-                        return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                       format!("{} was not a the name of a known capability or a valid extension capability", x)))
-                    } else {
-                        try!(browser_capabilities.validate_custom(x, value));
-                    }
-                }
-            }
-        }
-        Ok(capabilities)
-    }
-
-    fn validate_page_load_strategy(value: &Json) -> WebDriverResult<()> {
-        match value {
-            &Json::String(ref x) => {
-                match &**x {
-                    "normal" |
-                    "eager" |
-                    "none" => {},
-                    x => {
-                        return Err(WebDriverError::new(
-                            ErrorStatus::InvalidArgument,
-                            format!("\"{}\" not a valid page load strategy", x)))
-                    }
-                }
-            }
-            _ => return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                "pageLoadStrategy was not a string"))
-        }
-        Ok(())
-    }
-
-    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("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,
-                        "proxyType value was not a string")),
-                },
-                "proxyAutoconfigUrl" => match value.as_string() {
-                    Some(x) => {
-                        try!(Url::parse(x).or(Err(WebDriverError::new(
-                            ErrorStatus::InvalidArgument,
-                            "proxyAutoconfigUrl was not a valid url"))));
-                    },
-                    None => return Err(WebDriverError::new(
-                        ErrorStatus::InvalidArgument,
-                        "proxyAutoconfigUrl was not a string"
-                    ))
-                },
-                "ftpProxy" => try!(SpecNewSessionParameters::validate_host(value)),
-                "httpProxy" => try!(SpecNewSessionParameters::validate_host(value)),
-                "sslProxy" => try!(SpecNewSessionParameters::validate_host(value)),
-                "socksProxy" => try!(SpecNewSessionParameters::validate_host(value)),
-                "socksVersion" => if !value.is_number() {
-                    return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                   "socksVersion was not a number"))
-                },
-                "socksUsername" => if !value.is_string() {
-                    return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                   "socksUsername was not a string"))
-                },
-                "socksPassword" => if !value.is_string() {
-                    return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                   "socksPassword was not a string"))
-                },
-                x => return Err(WebDriverError::new(
-                    ErrorStatus::InvalidArgument,
-                    format!("{} was not a valid proxy configuration capability", x)))
-            }
-        }
-        Ok(())
-    }
-
-    /// Validate whether a named capability is JSON value is a string containing a host
-    /// and possible port
-    fn validate_host(value: &Json) -> WebDriverResult<()> {
-        match value.as_string() {
-            Some(host) => {
-                if host.contains("://") {
-                    return Err(WebDriverError::new(
-                        ErrorStatus::InvalidArgument,
-                        format!("{} contains a scheme", host)));
-                }
-
-                // Temporarily add a scheme so the host can be parsed as URL
-                let s = String::from(format!("http://{}", host));
-                let url = try!(Url::parse(s.as_str()).or(Err(WebDriverError::new(
-                    ErrorStatus::InvalidArgument,
-                    format!("{} is not a valid host", host)))));
-
-                if url.username() != "" ||
-                    url.password() != None ||
-                    url.path() != "/" ||
-                    url.query() != None ||
-                    url.fragment() != None {
-                        return Err(WebDriverError::new(
-                            ErrorStatus::InvalidArgument,
-                            format!("{} was not of the form host[:port]", host)));
-                    }
-            },
-            None => return Err(WebDriverError::new(
-                ErrorStatus::InvalidArgument,
-                format!("{} was not a string", value)
-            ))
-        }
-        Ok(())
-    }
-
-    fn validate_timeouts(value: &Json) -> WebDriverResult<()> {
-        let obj = try_opt!(value.as_object(),
-                           ErrorStatus::InvalidArgument,
-                           "timeouts capability was not an object");
-        for (key, value) in obj.iter() {
-            match &**key {
-                x @ "script" |
-                x @ "pageLoad" |
-                x @ "implicit" => {
-                    let timeout = try_opt!(value.as_i64(),
-                                           ErrorStatus::InvalidArgument,
-                                           format!("{} timeouts value was not an integer", x));
-                    if timeout < 0 {
-                        return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                       format!("{} timeouts value was negative", x)))
-                    }
-                },
-                x => return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                    format!("{} was not a valid timeouts capability", x)))
-            }
-        }
-        Ok(())
-    }
-
-    fn validate_unhandled_prompt_behaviour(value: &Json) -> WebDriverResult<()> {
-        let behaviour = try_opt!(value.as_string(),
-                                 ErrorStatus::InvalidArgument,
-                                 "unhandledPromptBehavior capability was not a string");
-        match behaviour {
-            "dismiss" |
-            "accept" => {},
-            x => return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                format!("{} was not a valid unhandledPromptBehavior value", x)))        }
-        Ok(())
-    }
-}
-
-impl Parameters for SpecNewSessionParameters {
-    fn from_json(body: &Json) -> WebDriverResult<SpecNewSessionParameters> {
-        let data = try_opt!(body.as_object(),
-                            ErrorStatus::UnknownError,
-                            "Message body was not an object");
-
-        let capabilities = try_opt!(
-            try_opt!(data.get("capabilities"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing 'capabilities' parameter").as_object(),
-            ErrorStatus::InvalidArgument,
-                     "'capabilities' parameter is not an object");
-
-        let default_always_match = Json::Object(Capabilities::new());
-        let always_match = try_opt!(capabilities.get("alwaysMatch")
-                                   .unwrap_or(&default_always_match)
-                                   .as_object(),
-                                   ErrorStatus::InvalidArgument,
-                                   "'alwaysMatch' parameter is not an object");
-        let default_first_matches = Json::Array(vec![]);
-        let first_matches = try!(
-            try_opt!(capabilities.get("firstMatch")
-                     .unwrap_or(&default_first_matches)
-                     .as_array(),
-                     ErrorStatus::InvalidArgument,
-                     "'firstMatch' parameter is not an array")
-                .iter()
-                .map(|x| x.as_object()
-                     .map(|x| x.clone())
-                     .ok_or(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                "'firstMatch' entry is not an object")))
-                .collect::<WebDriverResult<Vec<Capabilities>>>());
-
-        return Ok(SpecNewSessionParameters {
-            alwaysMatch: always_match.clone(),
-            firstMatch: first_matches
-        });
-    }
-}
-
-impl ToJson for SpecNewSessionParameters {
-    fn to_json(&self) -> Json {
-        let mut body = BTreeMap::new();
-        let mut capabilities = BTreeMap::new();
-        capabilities.insert("alwaysMatch".into(), self.alwaysMatch.to_json());
-        capabilities.insert("firstMatch".into(), self.firstMatch.to_json());
-        body.insert("capabilities".into(), capabilities.to_json());
-        Json::Object(body)
-    }
-}
-
-impl CapabilitiesMatching for SpecNewSessionParameters {
-    fn match_browser<T: BrowserCapabilities>(&self, browser_capabilities: &mut T)
-                                             -> WebDriverResult<Option<Capabilities>> {
-        let default = vec![BTreeMap::new()];
-        let capabilities_list = if self.firstMatch.len() > 0 {
-            &self.firstMatch
-        } else {
-            &default
-        };
-
-        let merged_capabilities = try!(capabilities_list
-            .iter()
-            .map(|first_match_entry| {
-                if first_match_entry.keys().any(|k| {
-                    self.alwaysMatch.contains_key(k)
-                }) {
-                    return Err(WebDriverError::new(
-                        ErrorStatus::InvalidArgument,
-                        "'firstMatch' key shadowed a value in 'alwaysMatch'"));
-                }
-                let mut merged = self.alwaysMatch.clone();
-                merged.append(&mut first_match_entry.clone());
-                Ok(merged)
-            })
-            .map(|merged| merged.and_then(|x| self.validate(x, browser_capabilities)))
-            .collect::<WebDriverResult<Vec<Capabilities>>>());
-
-        let selected = merged_capabilities
-            .iter()
-            .filter_map(|merged| {
-                browser_capabilities.init(merged);
-
-                for (key, value) in merged.iter() {
-                    match &**key {
-                        "browserName" => {
-                            let browserValue = browser_capabilities
-                                .browser_name(merged)
-                                .ok()
-                                .and_then(|x| x);
-
-                            if value.as_string() != browserValue.as_ref().map(|x| &**x) {
-                                    return None;
-                            }
-                        },
-                        "browserVersion" => {
-                            let browserValue = browser_capabilities
-                                .browser_version(merged)
-                                .ok()
-                                .and_then(|x| x);
-                            // We already validated this was a string
-                            let version_cond = value.as_string().unwrap_or("");
-                            if let Some(version) = browserValue {
-                                if !browser_capabilities
-                                    .compare_browser_version(&*version, version_cond)
-                                    .unwrap_or(false) {
-                                        return None;
-                                    }
-                            } else {
-                                return None
-                            }
-                        },
-                        "platformName" => {
-                            let browserValue = browser_capabilities
-                                .platform_name(merged)
-                                .ok()
-                                .and_then(|x| x);
-                            if value.as_string() != browserValue.as_ref().map(|x| &**x) {
-                                return None;
-                            }
-                        }
-                        "acceptInsecureCerts" => {
-                            if value.as_boolean().unwrap_or(false) &&
-                                !browser_capabilities
-                                .accept_insecure_certs(merged)
-                                .unwrap_or(false) {
-                                return None;
-                            }
-                        },
-                        "proxy" => {
-                            let default = BTreeMap::new();
-                            let proxy = value.as_object().unwrap_or(&default);
-                            if !browser_capabilities.accept_proxy(&proxy,
-                                                                  merged)
-                                .unwrap_or(false) {
-                                return None
-                            }
-                        },
-                        name => {
-                            if name.contains(":") {
-                                if !browser_capabilities
-                                    .accept_custom(name, value, merged)
-                                    .unwrap_or(false) {
-                                        return None
-                                    }
-                            } else {
-                                // Accept the capability
-                            }
-                        }
-                    }
-                }
-
-                return Some(merged)
-            })
-            .next()
-            .map(|x| x.clone());
-            Ok(selected)
-    }
-}
-
-#[derive(Debug, PartialEq)]
-pub struct LegacyNewSessionParameters {
-    pub desired: Capabilities,
-    pub required: Capabilities,
-}
-
-impl CapabilitiesMatching for LegacyNewSessionParameters {
-    fn match_browser<T: BrowserCapabilities>(&self, browser_capabilities: &mut T)
-                                             -> WebDriverResult<Option<Capabilities>> {
-        /* For now don't do anything much, just merge the
-        desired and required and return the merged list. */
-
-        let mut capabilities: Capabilities = BTreeMap::new();
-        self.required.iter()
-            .chain(self.desired.iter())
-            .fold(&mut capabilities,
-                  |mut caps, (key, value)| {
-                      if !caps.contains_key(key) {
-                          caps.insert(key.clone(), value.clone());
-                      }
-                      caps});
-        browser_capabilities.init(&capabilities);
-        Ok(Some(capabilities))
-    }
-}
-
-impl Parameters for LegacyNewSessionParameters {
-    fn from_json(body: &Json) -> WebDriverResult<LegacyNewSessionParameters> {
-        let data = try_opt!(body.as_object(),
-                            ErrorStatus::UnknownError,
-                            "Message body was not an object");
-
-        let desired_capabilities =
-            if let Some(capabilities) = data.get("desiredCapabilities") {
-                try_opt!(capabilities.as_object(),
-                         ErrorStatus::InvalidArgument,
-                         "'desiredCapabilities' parameter is not an object").clone()
-            } else {
-                BTreeMap::new()
-            };
-
-        let required_capabilities =
-            if let Some(capabilities) = data.get("requiredCapabilities") {
-                try_opt!(capabilities.as_object(),
-                         ErrorStatus::InvalidArgument,
-                         "'requiredCapabilities' parameter is not an object").clone()
-            } else {
-                BTreeMap::new()
-            };
-
-        Ok(LegacyNewSessionParameters {
-            desired: desired_capabilities,
-            required: required_capabilities
-        })
-    }
-}
-
-impl ToJson for LegacyNewSessionParameters {
-    fn to_json(&self) -> Json {
-        let mut data = BTreeMap::new();
-        data.insert("desiredCapabilities".to_owned(), self.desired.to_json());
-        data.insert("requiredCapabilities".to_owned(), self.required.to_json());
-        Json::Object(data)
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use rustc_serialize::json::Json;
-    use super::{WebDriverResult, SpecNewSessionParameters};
-
-    fn validate_host(value: &str) -> WebDriverResult<()> {
-        SpecNewSessionParameters::validate_host(&Json::String(value.into()))
-    }
-
-    #[test]
-    fn test_validate_host() {
-        validate_host("127.0.0.1").unwrap();
-        validate_host("127.0.0.1:").unwrap();
-        validate_host("127.0.0.1:3128").unwrap();
-        validate_host("[2001:db8::1]").unwrap();
-        validate_host("[2001:db8::1]:3128").unwrap();
-        validate_host("localhost").unwrap();
-        validate_host("localhost:3128").unwrap();
-        validate_host("example.org").unwrap();
-        validate_host("example.org:3128").unwrap();
-
-        assert!(validate_host("http://example.org").is_err());  // existing scheme
-        assert!(validate_host("example.org:-1").is_err());  // invalid port
-        assert!(validate_host("2001:db8::1").is_err());  // missing brackets
-    }
-}
deleted file mode 100644
--- a/third_party/rust/webdriver/src/command.rs
+++ /dev/null
@@ -1,1743 +0,0 @@
-use capabilities::{SpecNewSessionParameters, LegacyNewSessionParameters,
-                   CapabilitiesMatching, BrowserCapabilities, Capabilities};
-use common::{Date, Nullable, WebElement, FrameId, LocatorStrategy};
-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(Debug, PartialEq)]
-pub enum WebDriverCommand<T: WebDriverExtensionCommand> {
-    NewSession(NewSessionParameters),
-    DeleteSession,
-    Get(GetParameters),
-    GetCurrentUrl,
-    GoBack,
-    GoForward,
-    Refresh,
-    GetTitle,
-    GetPageSource,
-    GetWindowHandle,
-    GetWindowHandles,
-    CloseWindow,
-    GetWindowRect,
-    SetWindowRect(WindowRectParameters),
-    MinimizeWindow,
-    MaximizeWindow,
-    FullscreenWindow,
-    SwitchToWindow(SwitchToWindowParameters),
-    SwitchToFrame(SwitchToFrameParameters),
-    SwitchToParentFrame,
-    FindElement(LocatorParameters),
-    FindElements(LocatorParameters),
-    FindElementElement(WebElement, LocatorParameters),
-    FindElementElements(WebElement, LocatorParameters),
-    GetActiveElement,
-    IsDisplayed(WebElement),
-    IsSelected(WebElement),
-    GetElementAttribute(WebElement, String),
-    GetElementProperty(WebElement, String),
-    GetCSSValue(WebElement, String),
-    GetElementText(WebElement),
-    GetElementTagName(WebElement),
-    GetElementRect(WebElement),
-    IsEnabled(WebElement),
-    ExecuteScript(JavascriptCommandParameters),
-    ExecuteAsyncScript(JavascriptCommandParameters),
-    GetCookies,
-    GetNamedCookie(String),
-    AddCookie(AddCookieParameters),
-    DeleteCookies,
-    DeleteCookie(String),
-    GetTimeouts,
-    SetTimeouts(TimeoutsParameters),
-    ElementClick(WebElement),
-    ElementTap(WebElement),
-    ElementClear(WebElement),
-    ElementSendKeys(WebElement, SendKeysParameters),
-    PerformActions(ActionsParameters),
-    ReleaseActions,
-    DismissAlert,
-    AcceptAlert,
-    GetAlertText,
-    SendAlertText(SendKeysParameters),
-    TakeScreenshot,
-    TakeElementScreenshot(WebElement),
-    Status,
-    Extension(T)
-}
-
-pub trait WebDriverExtensionCommand : Clone + Send + PartialEq {
-    fn parameters_json(&self) -> Option<Json>;
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub struct VoidWebDriverExtensionCommand;
-
-impl WebDriverExtensionCommand for VoidWebDriverExtensionCommand {
-    fn parameters_json(&self) -> Option<Json> {
-        panic!("No extensions implemented");
-    }
-}
-
-#[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>)
-               -> WebDriverMessage<U> {
-        WebDriverMessage {
-            session_id: session_id,
-            command: command,
-        }
-    }
-
-    pub fn from_http(match_type: Route<U>,
-                     params: &Captures,
-                     raw_body: &str,
-                     requires_body: bool)
-                     -> WebDriverResult<WebDriverMessage<U>> {
-        let session_id = WebDriverMessage::<U>::get_session_id(params);
-        let body_data = try!(WebDriverMessage::<U>::decode_body(raw_body, requires_body));
-
-        let command = match match_type {
-            Route::NewSession => {
-                let parameters: NewSessionParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::NewSession(parameters)
-            },
-            Route::DeleteSession => WebDriverCommand::DeleteSession,
-            Route::Get => {
-                let parameters: GetParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::Get(parameters)
-            },
-            Route::GetCurrentUrl => WebDriverCommand::GetCurrentUrl,
-            Route::GoBack => WebDriverCommand::GoBack,
-            Route::GoForward => WebDriverCommand::GoForward,
-            Route::Refresh => WebDriverCommand::Refresh,
-            Route::GetTitle => WebDriverCommand::GetTitle,
-            Route::GetPageSource => WebDriverCommand::GetPageSource,
-            Route::GetWindowHandle => WebDriverCommand::GetWindowHandle,
-            Route::GetWindowHandles => WebDriverCommand::GetWindowHandles,
-            Route::CloseWindow => WebDriverCommand::CloseWindow,
-            Route::GetTimeouts => WebDriverCommand::GetTimeouts,
-            Route::SetTimeouts => {
-                let parameters: TimeoutsParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::SetTimeouts(parameters)
-            },
-            Route::GetWindowRect | Route::GetWindowPosition | Route::GetWindowSize => WebDriverCommand::GetWindowRect,
-            Route::SetWindowRect | Route::SetWindowPosition | Route::SetWindowSize => {
-                let parameters: WindowRectParameters = Parameters::from_json(&body_data)?;
-                WebDriverCommand::SetWindowRect(parameters)
-            },
-            Route::MinimizeWindow => WebDriverCommand::MinimizeWindow,
-            Route::MaximizeWindow => WebDriverCommand::MaximizeWindow,
-            Route::FullscreenWindow => WebDriverCommand::FullscreenWindow,
-            Route::SwitchToWindow => {
-                let parameters: SwitchToWindowParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::SwitchToWindow(parameters)
-            }
-            Route::SwitchToFrame => {
-                let parameters: SwitchToFrameParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::SwitchToFrame(parameters)
-            },
-            Route::SwitchToParentFrame => WebDriverCommand::SwitchToParentFrame,
-            Route::FindElement => {
-                let parameters: LocatorParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::FindElement(parameters)
-            },
-            Route::FindElements => {
-                let parameters: LocatorParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::FindElements(parameters)
-            },
-            Route::FindElementElement => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                let parameters: LocatorParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::FindElementElement(element, parameters)
-            },
-            Route::FindElementElements => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                let parameters: LocatorParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::FindElementElements(element, parameters)
-            },
-            Route::GetActiveElement => WebDriverCommand::GetActiveElement,
-            Route::IsDisplayed => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                WebDriverCommand::IsDisplayed(element)
-            },
-            Route::IsSelected => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                WebDriverCommand::IsSelected(element)
-            },
-            Route::GetElementAttribute => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                let attr = try_opt!(params.name("name"),
-                                    ErrorStatus::InvalidArgument,
-                                    "Missing name parameter").as_str();
-                WebDriverCommand::GetElementAttribute(element, attr.into())
-            },
-            Route::GetElementProperty => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                let property = try_opt!(params.name("name"),
-                                        ErrorStatus::InvalidArgument,
-                                        "Missing name parameter").as_str();
-                WebDriverCommand::GetElementProperty(element, property.into())
-            },
-            Route::GetCSSValue => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                let property = try_opt!(params.name("propertyName"),
-                                        ErrorStatus::InvalidArgument,
-                                        "Missing propertyName parameter").as_str();
-                WebDriverCommand::GetCSSValue(element, property.into())
-            },
-            Route::GetElementText => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                WebDriverCommand::GetElementText(element)
-            },
-            Route::GetElementTagName => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                WebDriverCommand::GetElementTagName(element)
-            },
-            Route::GetElementRect => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                WebDriverCommand::GetElementRect(element)
-            },
-            Route::IsEnabled => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                WebDriverCommand::IsEnabled(element)
-            },
-            Route::ElementClick => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                WebDriverCommand::ElementClick(element)
-            },
-            Route::ElementTap => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                WebDriverCommand::ElementTap(element)
-            },
-            Route::ElementClear => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                WebDriverCommand::ElementClear(element)
-            },
-            Route::ElementSendKeys => {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                let parameters: SendKeysParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::ElementSendKeys(element, parameters)
-            },
-            Route::ExecuteScript => {
-                let parameters: JavascriptCommandParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::ExecuteScript(parameters)
-            },
-            Route::ExecuteAsyncScript => {
-                let parameters: JavascriptCommandParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::ExecuteAsyncScript(parameters)
-            },
-            Route::GetCookies => {
-                WebDriverCommand::GetCookies
-            },
-            Route::GetNamedCookie => {
-                let name = try_opt!(params.name("name"),
-                                    ErrorStatus::InvalidArgument,
-                                    "Missing 'name' parameter").as_str().into();
-                WebDriverCommand::GetNamedCookie(name)
-            },
-            Route::AddCookie => {
-                let parameters: AddCookieParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::AddCookie(parameters)
-            },
-            Route::DeleteCookies => {
-                WebDriverCommand::DeleteCookies
-            },
-            Route::DeleteCookie => {
-                let name = try_opt!(params.name("name"),
-                                    ErrorStatus::InvalidArgument,
-                                    "Missing name parameter").as_str().into();
-                WebDriverCommand::DeleteCookie(name)
-            },
-            Route::PerformActions => {
-                let parameters: ActionsParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::PerformActions(parameters)
-            },
-            Route::ReleaseActions => {
-                WebDriverCommand::ReleaseActions
-            },
-            Route::DismissAlert => {
-                WebDriverCommand::DismissAlert
-            },
-            Route::AcceptAlert => {
-                WebDriverCommand::AcceptAlert
-            },
-            Route::GetAlertText => {
-                WebDriverCommand::GetAlertText
-            },
-            Route::SendAlertText => {
-                let parameters: SendKeysParameters = try!(Parameters::from_json(&body_data));
-                WebDriverCommand::SendAlertText(parameters)
-            },
-            Route::TakeScreenshot => WebDriverCommand::TakeScreenshot,
-            Route::TakeElementScreenshot =>  {
-                let element_id = try_opt!(params.name("elementId"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing elementId parameter");
-                let element = WebElement::new(element_id.as_str().into());
-                WebDriverCommand::TakeElementScreenshot(element)
-            },
-            Route::Status => WebDriverCommand::Status,
-            Route::Extension(ref extension) => {
-                try!(extension.command(params, &body_data))
-            }
-        };
-        Ok(WebDriverMessage::new(session_id, command))
-    }
-
-    fn get_session_id(params: &Captures) -> Option<String> {
-        params.name("sessionId").map(|x| x.as_str().into())
-    }
-
-    fn decode_body(body: &str, requires_body: bool) -> WebDriverResult<Json> {
-        if requires_body {
-            match Json::from_str(body) {
-                Ok(x @ Json::Object(_)) => Ok(x),
-                Ok(_) => {
-                    Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                            "Body was not a JSON Object"))
-                }
-                Err(json::ParserError::SyntaxError(_, line, col)) => {
-                    let msg = format!("Failed to decode request as JSON: {}", body);
-                    let stack = format!("Syntax error at :{}:{}", line, col);
-                    Err(WebDriverError::new_with_stack(ErrorStatus::InvalidArgument, msg, stack))
-                }
-                Err(json::ParserError::IoError(e)) => {
-                    Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                            format!("I/O error whilst decoding body: {}", e)))
-                }
-            }
-        } else {
-            Ok(Json::Null)
-        }
-    }
-}
-
-impl <U:WebDriverExtensionRoute> ToJson for WebDriverMessage<U> {
-    fn to_json(&self) -> Json {
-        let parameters = match self.command {
-            WebDriverCommand::AcceptAlert |
-            WebDriverCommand::CloseWindow |
-            WebDriverCommand::ReleaseActions |
-            WebDriverCommand::DeleteCookie(_) |
-            WebDriverCommand::DeleteCookies |
-            WebDriverCommand::DeleteSession |
-            WebDriverCommand::DismissAlert |
-            WebDriverCommand::ElementClear(_) |
-            WebDriverCommand::ElementClick(_) |
-            WebDriverCommand::ElementTap(_) |
-            WebDriverCommand::GetActiveElement |
-            WebDriverCommand::GetAlertText |
-            WebDriverCommand::GetNamedCookie(_) |
-            WebDriverCommand::GetCookies |
-            WebDriverCommand::GetCSSValue(_, _) |
-            WebDriverCommand::GetCurrentUrl |
-            WebDriverCommand::GetElementAttribute(_, _) |
-            WebDriverCommand::GetElementProperty(_, _) |
-            WebDriverCommand::GetElementRect(_) |
-            WebDriverCommand::GetElementTagName(_) |
-            WebDriverCommand::GetElementText(_) |
-            WebDriverCommand::GetPageSource |
-            WebDriverCommand::GetTimeouts |
-            WebDriverCommand::GetTitle |
-            WebDriverCommand::GetWindowHandle |
-            WebDriverCommand::GetWindowHandles |
-            WebDriverCommand::GetWindowRect |
-            WebDriverCommand::GoBack |
-            WebDriverCommand::GoForward |
-            WebDriverCommand::IsDisplayed(_) |
-            WebDriverCommand::IsEnabled(_) |
-            WebDriverCommand::IsSelected(_) |
-            WebDriverCommand::MinimizeWindow |
-            WebDriverCommand::MaximizeWindow |
-            WebDriverCommand::FullscreenWindow |
-            WebDriverCommand::NewSession(_) |
-            WebDriverCommand::Refresh |
-            WebDriverCommand::Status |
-            WebDriverCommand::SwitchToParentFrame |
-            WebDriverCommand::TakeElementScreenshot(_) |
-            WebDriverCommand::TakeScreenshot => {
-                None
-            },
-
-            WebDriverCommand::AddCookie(ref x) => Some(x.to_json()),
-            WebDriverCommand::ElementSendKeys(_, ref x) => Some(x.to_json()),
-            WebDriverCommand::ExecuteAsyncScript(ref x) |
-            WebDriverCommand::ExecuteScript(ref x) => Some(x.to_json()),
-            WebDriverCommand::FindElementElement(_, ref x) => Some(x.to_json()),
-            WebDriverCommand::FindElementElements(_, ref x) => Some(x.to_json()),
-            WebDriverCommand::FindElement(ref x) => Some(x.to_json()),
-            WebDriverCommand::FindElements(ref x) => Some(x.to_json()),
-            WebDriverCommand::Get(ref x) => Some(x.to_json()),
-            WebDriverCommand::PerformActions(ref x) => Some(x.to_json()),
-            WebDriverCommand::SendAlertText(ref x) => Some(x.to_json()),
-            WebDriverCommand::SetTimeouts(ref x) => Some(x.to_json()),
-            WebDriverCommand::SetWindowRect(ref x) => Some(x.to_json()),
-            WebDriverCommand::SwitchToFrame(ref x) => Some(x.to_json()),
-            WebDriverCommand::SwitchToWindow(ref x) => Some(x.to_json()),
-            WebDriverCommand::Extension(ref x) => x.parameters_json(),
-        };
-
-        let mut data = BTreeMap::new();
-        if let Some(parameters) = parameters {
-            data.insert("parameters".to_string(), parameters);
-        }
-        Json::Object(data)
-    }
-}
-
-pub trait Parameters: Sized {
-    fn from_json(body: &Json) -> WebDriverResult<Self>;
-}
-
-/// Wrapper around the two supported variants of new session paramters
-///
-/// The Spec variant is used for storing spec-compliant parameters whereas
-/// the legacy variant is used to store desiredCapabilities/requiredCapabilities
-/// parameters, and is intended to minimise breakage as we transition users to
-/// the spec design.
-#[derive(Debug, PartialEq)]
-pub enum NewSessionParameters {
-    Spec(SpecNewSessionParameters),
-    Legacy(LegacyNewSessionParameters),
-}
-
-impl Parameters for NewSessionParameters {
-    fn from_json(body: &Json) -> WebDriverResult<NewSessionParameters> {
-        let data = try_opt!(body.as_object(),
-                            ErrorStatus::UnknownError,
-                            "Message body was not an object");
-        if data.get("capabilities").is_some() {
-            Ok(NewSessionParameters::Spec(try!(SpecNewSessionParameters::from_json(body))))
-        } else {
-            Ok(NewSessionParameters::Legacy(try!(LegacyNewSessionParameters::from_json(body))))
-        }
-    }
-}
-
-impl ToJson for NewSessionParameters {
-    fn to_json(&self) -> Json {
-        match self {
-            &NewSessionParameters::Spec(ref x) => x.to_json(),
-            &NewSessionParameters::Legacy(ref x) => x.to_json()
-        }
-    }
-}
-
-impl CapabilitiesMatching for NewSessionParameters {
-    fn match_browser<T: BrowserCapabilities>(&self, browser_capabilities: &mut T)
-                                             -> WebDriverResult<Option<Capabilities>> {
-        match self {
-            &NewSessionParameters::Spec(ref x) => x.match_browser(browser_capabilities),
-            &NewSessionParameters::Legacy(ref x) => x.match_browser(browser_capabilities)
-        }
-    }
-}
-
-
-#[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");
-        let url = try_opt!(
-            try_opt!(data.get("url"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing 'url' parameter").as_string(),
-            ErrorStatus::InvalidArgument,
-            "'url' not a string");
-        Ok(GetParameters {
-            url: url.to_string()
-        })
-    }
-}
-
-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(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> {
-        let data = try_opt!(body.as_object(),
-                            ErrorStatus::UnknownError,
-                            "Message body was not an object");
-
-        let script = match data.get("script") {
-            Some(json) => {
-                Some(try_opt!(json.as_u64(),
-                              ErrorStatus::InvalidArgument,
-                              "Script timeout duration was not a signed integer"))
-            }
-            None => None,
-        };
-
-        let page_load = match data.get("pageLoad") {
-            Some(json) => {
-                Some(try_opt!(json.as_u64(),
-                              ErrorStatus::InvalidArgument,
-                              "Page load timeout duration was not a signed integer"))
-            }
-            None => None,
-        };
-
-        let implicit = match data.get("implicit") {
-            Some(json) => {
-                Some(try_opt!(json.as_u64(),
-                              ErrorStatus::InvalidArgument,
-                              "Implicit timeout duration was not a signed integer"))
-            }
-            None => None,
-        };
-
-        Ok(TimeoutsParameters {
-            script: script,
-            page_load: page_load,
-            implicit: implicit,
-        })
-    }
-}
-
-impl ToJson for TimeoutsParameters {
-    fn to_json(&self) -> Json {
-        let mut data = BTreeMap::new();
-        if let Some(ms) = self.script {
-            data.insert("script".into(), ms.to_json());
-        }
-        if let Some(ms) = self.page_load {
-            data.insert("pageLoad".into(), ms.to_json());
-        }
-        if let Some(ms) = self.implicit {
-            data.insert("implicit".into(), ms.to_json());
-        }
-        Json::Object(data)
-    }
-}
-
-#[derive(Debug, PartialEq)]
-pub struct WindowRectParameters {
-    pub x: Nullable<i64>,
-    pub y: Nullable<i64>,
-    pub width: Nullable<u64>,
-    pub height: Nullable<u64>,
-}
-
-impl Parameters for WindowRectParameters {
-    fn from_json(body: &Json) -> WebDriverResult<WindowRectParameters> {
-        let data = try_opt!(body.as_object(),
-                            ErrorStatus::UnknownError,
-                            "Message body was not an object");
-
-        let x = match data.get("x") {
-            Some(json) => {
-                try!(Nullable::from_json(json, |n| {
-                    Ok((try_opt!(n.as_i64(),
-                                 ErrorStatus::InvalidArgument,
-                                 "'x' is not an integer")))
-                }))
-            }
-            None => Nullable::Null,
-        };
-        let y = match data.get("y") {
-            Some(json) => {
-                try!(Nullable::from_json(json, |n| {
-                    Ok((try_opt!(n.as_i64(),
-                                 ErrorStatus::InvalidArgument,
-                                 "'y' is not an integer")))
-                }))
-            }
-            None => Nullable::Null,
-        };
-        let width = match data.get("width") {
-            Some(json) => {
-                try!(Nullable::from_json(json, |n| {
-                    Ok((try_opt!(n.as_u64(),
-                                 ErrorStatus::InvalidArgument,
-                                 "'width' is not a positive integer")))
-                }))
-            }
-            None => Nullable::Null,
-        };
-        let height = match data.get("height") {
-            Some(json) => {
-                try!(Nullable::from_json(json, |n| {
-                    Ok((try_opt!(n.as_u64(),
-                                 ErrorStatus::InvalidArgument,
-                                 "'height' is not a positive integer")))
-                }))
-            }
-            None => Nullable::Null,
-        };
-
-        Ok(WindowRectParameters {
-               x: x,
-               y: y,
-               width: width,
-               height: height,
-           })
-    }
-}
-
-impl ToJson for WindowRectParameters {
-    fn to_json(&self) -> Json {
-        let mut data = BTreeMap::new();
-        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(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");
-        let handle = try_opt!(
-            try_opt!(data.get("handle"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing 'handle' parameter").as_string(),
-            ErrorStatus::InvalidArgument,
-            "'handle' not a string");
-        return Ok(SwitchToWindowParameters {
-            handle: handle.to_string()
-        })
-    }
-}
-
-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(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,
-                            "Message body was not an object");
-
-        let using = try!(LocatorStrategy::from_json(
-            try_opt!(data.get("using"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing 'using' parameter")));
-
-        let value = try_opt!(
-            try_opt!(data.get("value"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing 'value' parameter").as_string(),
-            ErrorStatus::InvalidArgument,
-            "Could not convert using to string").to_string();
-
-        return Ok(LocatorParameters {
-            using: using,
-            value: value
-        })
-    }
-}
-
-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(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,
-                            "Message body was not an object");
-        let id = try!(FrameId::from_json(try_opt!(data.get("id"),
-                                                  ErrorStatus::UnknownError,
-                                                  "Missing 'id' parameter")));
-
-        Ok(SwitchToFrameParameters {
-            id: id
-        })
-    }
-}
-
-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(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,
-                            "Message body was not an object");
-        let text = try_opt!(try_opt!(data.get("text"),
-                                     ErrorStatus::InvalidArgument,
-                                     "Missing 'text' parameter").as_string(),
-                            ErrorStatus::InvalidArgument,
-                            "Could not convert 'text' to string");
-
-        Ok(SendKeysParameters {
-            text: text.into()
-        })
-    }
-}
-
-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(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(),
-                            ErrorStatus::InvalidArgument,
-                            "Message body was not an object");
-
-        let args_json = try_opt!(data.get("args"),
-                                 ErrorStatus::InvalidArgument,
-                                 "Missing args parameter");
-
-        let args = try!(Nullable::from_json(
-            args_json,
-            |x| {
-                Ok((try_opt!(x.as_array(),
-                             ErrorStatus::InvalidArgument,
-                             "Failed to convert args to Array")).clone())
-            }));
-
-         //TODO: Look for WebElements in args?
-        let script = try_opt!(
-            try_opt!(data.get("script"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing script parameter").as_string(),
-            ErrorStatus::InvalidArgument,
-            "Failed to convert script to String");
-        Ok(JavascriptCommandParameters {
-            script: script.to_string(),
-            args: args.clone()
-        })
-    }
-}
-
-impl ToJson for JavascriptCommandParameters {
-    fn to_json(&self) -> Json {
-        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(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,
-                            "Message body was not an object");
-        let name_json = try_opt!(data.get("name"),
-                                 ErrorStatus::InvalidArgument,
-                                 "Missing 'name' parameter");
-        let name = try!(Nullable::from_json(name_json, |x| {
-            Ok(try_opt!(x.as_string(),
-                        ErrorStatus::InvalidArgument,
-                        "Failed to convert name to string")
-                .to_string())
-        }));
-        return Ok(GetNamedCookieParameters { name: name });
-    }
-}
-
-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(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
-}
-
-impl Parameters for AddCookieParameters {
-    fn from_json(body: &Json) -> WebDriverResult<AddCookieParameters> {
-        if !body.is_object() {
-            return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                           "Message body was not an object"));
-        }
-
-        let data = try_opt!(body.find("cookie").and_then(|x| x.as_object()),
-                            ErrorStatus::UnableToSetCookie,
-                            "Cookie parameter not found or not an object");
-
-        let name = try_opt!(
-            try_opt!(data.get("name"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing 'name' parameter").as_string(),
-            ErrorStatus::InvalidArgument,
-            "'name' is not a string").to_string();
-
-        let value = try_opt!(
-            try_opt!(data.get("value"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing 'value' parameter").as_string(),
-            ErrorStatus::InvalidArgument,
-            "'value' is not a string").to_string();
-
-        let path = match data.get("path") {
-            Some(path_json) => {
-                try!(Nullable::from_json(
-                    path_json,
-                    |x| {
-                        Ok(try_opt!(x.as_string(),
-                                    ErrorStatus::InvalidArgument,
-                                    "Failed to convert path to String").to_string())
-                    }))
-            },
-            None => Nullable::Null
-        };
-
-        let domain = match data.get("domain") {
-            Some(domain_json) => {
-                try!(Nullable::from_json(
-                    domain_json,
-                    |x| {
-                        Ok(try_opt!(x.as_string(),
-                                    ErrorStatus::InvalidArgument,
-                                    "Failed to convert domain to String").to_string())
-                    }))
-            },
-            None => Nullable::Null
-        };
-
-        let expiry = match data.get("expiry") {
-            Some(expiry_json) => {
-                try!(Nullable::from_json(
-                    expiry_json,
-                    |x| {
-                        Ok(Date::new(try_opt!(x.as_u64(),
-                                              ErrorStatus::InvalidArgument,
-                                              "Failed to convert expiry to Date")))
-                    }))
-            },
-            None => Nullable::Null
-        };
-
-        let secure = match data.get("secure") {
-            Some(x) => try_opt!(x.as_boolean(),
-                                ErrorStatus::InvalidArgument,
-                                "Failed to convert secure to boolean"),
-            None => false
-        };
-
-        let http_only = match data.get("httpOnly") {
-            Some(x) => try_opt!(x.as_boolean(),
-                                ErrorStatus::InvalidArgument,
-                                "Failed to convert httpOnly to boolean"),
-            None => false
-        };
-
-        return Ok(AddCookieParameters {
-            name: name,
-            value: value,
-            path: path,
-            domain: domain,
-            expiry: expiry,
-            secure: secure,
-            httpOnly: http_only
-        })
-    }
-}
-
-impl ToJson for AddCookieParameters {
-    fn to_json(&self) -> Json {
-        let mut data = BTreeMap::new();
-        data.insert("name".to_string(), self.name.to_json());
-        data.insert("value".to_string(), self.value.to_json());
-        data.insert("path".to_string(), self.path.to_json());
-        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(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,
-                            "Message body was not an object");
-        let element = match data.get("element") {
-            Some(element_json) => try!(Nullable::from_json(
-                element_json,
-                |x| {
-                    Ok(try!(WebElement::from_json(x)))
-                })),
-            None => Nullable::Null
-        };
-
-        return Ok(TakeScreenshotParameters {
-            element: element
-        })
-    }
-}
-
-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(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,
-                 "Message body was not an object");
-        let actions = try_opt!(
-            try_opt!(body.find("actions"),
-                     ErrorStatus::InvalidArgument,
-                     "No actions parameter found").as_array(),
-            ErrorStatus::InvalidArgument,
-            "Parameter 'actions' was not an array");
-
-        let mut result = Vec::with_capacity(actions.len());
-        for chain in actions.iter() {
-            result.push(try!(ActionSequence::from_json(chain)));
-        }
-        Ok(ActionsParameters {
-            actions: result
-        })
-    }
-}
-
-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(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(),
-                            ErrorStatus::InvalidArgument,
-                            "Actions chain was not an object");
-
-        let type_name = try_opt!(try_opt!(data.get("type"),
-                                          ErrorStatus::InvalidArgument,
-                                          "Missing type parameter").as_string(),
-                                 ErrorStatus::InvalidArgument,
-                                 "Parameter ;type' was not a string");
-
-        let id = match data.get("id") {
-            Some(x) => Some(try_opt!(x.as_string(),
-                                     ErrorStatus::InvalidArgument,
-                                     "Parameter 'id' was not a string").to_owned()),
-            None => None
-        };
-
-
-        // Note that unlike the spec we get the pointer parameters in ActionsType::from_json
-
-        let actions = match type_name {
-            "none" | "key" | "pointer" => try!(ActionsType::from_json(&body)),
-            _ => return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                "Invalid action type"))
-        };
-
-        Ok(ActionSequence {
-            id: id.into(),
-            actions: actions
-        })
-    }
-}
-
-impl ToJson for ActionSequence {
-    fn to_json(&self) -> Json {
-        let mut data: BTreeMap<String, Json> = BTreeMap::new();
-        data.insert("id".into(), self.id.to_json());
-        let (action_type, actions) = match self.actions {
-            ActionsType::Null(ref actions) => {
-                ("none",
-                 actions.iter().map(|x| x.to_json()).collect::<Vec<Json>>())
-            }
-            ActionsType::Key(ref actions) => {
-                ("key",
-                 actions.iter().map(|x| x.to_json()).collect::<Vec<Json>>())
-            }
-            ActionsType::Pointer(ref parameters, ref actions) => {
-                data.insert("parameters".into(), parameters.to_json());
-                ("pointer",
-                 actions.iter().map(|x| x.to_json()).collect::<Vec<Json>>())
-            }
-        };
-        data.insert("type".into(), action_type.to_json());
-        data.insert("actions".into(), actions.to_json());
-        Json::Object(data)
-    }
-}
-
-#[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> {
-        // These unwraps are OK as long as this is only called from ActionSequence::from_json
-        let data = body.as_object().expect("Body should be a JSON Object");
-        let actions_type = body.find("type").and_then(|x| x.as_string()).expect("Type should be a string");
-        let actions_chain = try_opt!(try_opt!(data.get("actions"),
-                                              ErrorStatus::InvalidArgument,
-                                              "Missing actions parameter").as_array(),
-                                     ErrorStatus::InvalidArgument,
-                                     "Parameter 'actions' was not an array");
-        match actions_type {
-            "none" => {
-                let mut actions = Vec::with_capacity(actions_chain.len());
-                for action_body in actions_chain.iter() {
-                    actions.push(try!(NullActionItem::from_json(action_body)));
-                };
-                Ok(ActionsType::Null(actions))
-            },
-            "key" => {
-                let mut actions = Vec::with_capacity(actions_chain.len());
-                for action_body in actions_chain.iter() {
-                    actions.push(try!(KeyActionItem::from_json(action_body)));
-                };
-                Ok(ActionsType::Key(actions))
-            },
-            "pointer" => {
-                let mut actions = Vec::with_capacity(actions_chain.len());
-                let parameters = match data.get("parameters") {
-                    Some(x) => try!(PointerActionParameters::from_json(x)),
-                    None => Default::default()
-                };
-
-                for action_body in actions_chain.iter() {
-                    actions.push(try!(PointerActionItem::from_json(action_body)));
-                }
-                Ok(ActionsType::Pointer(parameters, actions))
-            }
-            _ => panic!("Got unexpected action type after checking type")
-        }
-    }
-}
-
-#[derive(Debug, PartialEq)]
-pub enum PointerType {
-    Mouse,
-    Pen,
-    Touch,
-}
-
-impl Parameters for PointerType {
-    fn from_json(body: &Json) -> WebDriverResult<PointerType> {
-        match body.as_string() {
-            Some("mouse") => Ok(PointerType::Mouse),
-            Some("pen") => Ok(PointerType::Pen),
-            Some("touch") => Ok(PointerType::Touch),
-            Some(_) => Err(WebDriverError::new(
-                ErrorStatus::InvalidArgument,
-                "Unsupported pointer type"
-            )),
-            None => Err(WebDriverError::new(
-                ErrorStatus::InvalidArgument,
-                "Pointer type was not a string"
-            ))
-        }
-    }
-}
-
-impl ToJson for PointerType {
-    fn to_json(&self) -> Json {
-        match *self {
-            PointerType::Mouse => "mouse".to_json(),
-            PointerType::Pen => "pen".to_json(),
-            PointerType::Touch => "touch".to_json(),
-        }.to_json()
-    }
-}
-
-impl Default for PointerType {
-    fn default() -> PointerType {
-        PointerType::Mouse
-    }
-}
-
-#[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,
-                            "Parameter 'parameters' was not an object");
-        let pointer_type = match data.get("pointerType") {
-            Some(x) => try!(PointerType::from_json(x)),
-            None => PointerType::default()
-        };
-        Ok(PointerActionParameters {
-            pointer_type: pointer_type
-        })
-    }
-}
-
-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(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,
-                            "Actions chain was not an object");
-        let type_name = try_opt!(
-            try_opt!(data.get("type"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing 'type' parameter").as_string(),
-            ErrorStatus::InvalidArgument,
-            "Parameter 'type' was not a string");
-        match type_name {
-            "pause" => Ok(NullActionItem::General(
-                try!(GeneralAction::from_json(body)))),
-            _ => return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                "Invalid type attribute"))
-        }
-    }
-}
-
-impl ToJson for NullActionItem {
-    fn to_json(&self) -> Json {
-        match self {
-            &NullActionItem::General(ref x) => x.to_json(),
-        }
-    }
-}
-
-#[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(),
-                            ErrorStatus::InvalidArgument,
-                            "Key action item was not an object");
-        let type_name = try_opt!(
-            try_opt!(data.get("type"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing 'type' parameter").as_string(),
-            ErrorStatus::InvalidArgument,
-            "Parameter 'type' was not a string");
-        match type_name {
-            "pause" => Ok(KeyActionItem::General(
-                try!(GeneralAction::from_json(body)))),
-            _ => Ok(KeyActionItem::Key(
-                try!(KeyAction::from_json(body))))
-        }
-    }
-}
-
-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(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(),
-                            ErrorStatus::InvalidArgument,
-                            "Pointer action item was not an object");
-        let type_name = try_opt!(
-            try_opt!(data.get("type"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing 'type' parameter").as_string(),
-            ErrorStatus::InvalidArgument,
-            "Parameter 'type' was not a string");
-
-        match type_name {
-            "pause" => Ok(PointerActionItem::General(try!(GeneralAction::from_json(body)))),
-            _ => Ok(PointerActionItem::Pointer(try!(PointerAction::from_json(body))))
-        }
-    }
-}
-
-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(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)))),
-            _ => Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                         "Invalid or missing type attribute"))
-        }
-    }
-}
-
-impl ToJson for GeneralAction {
-    fn to_json(&self) -> Json {
-        match self {
-            &GeneralAction::Pause(ref x) => x.to_json()
-        }
-    }
-}
-
-#[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 {
-            duration: try_opt!(body.find("duration").unwrap_or(&default).as_u64(),
-                               ErrorStatus::InvalidArgument,
-                               "Parameter 'duration' was not a positive integer")
-        })
-    }
-}
-
-impl ToJson for PauseAction {
-    fn to_json(&self) -> Json {
-        let mut data = BTreeMap::new();
-        data.insert("type".to_owned(),
-                    "pause".to_json());
-        data.insert("duration".to_owned(),
-                    self.duration.to_json());
-        Json::Object(data)
-    }
-}
-
-#[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()) {
-            Some("keyDown") => Ok(KeyAction::Down(try!(KeyDownAction::from_json(body)))),
-            Some("keyUp") => Ok(KeyAction::Up(try!(KeyUpAction::from_json(body)))),
-            Some(_) | None => Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                      "Invalid type attribute value for key action"))
-        }
-    }
-}
-
-impl ToJson for KeyAction {
-    fn to_json(&self) -> Json {
-        match self {
-            &KeyAction::Down(ref x) => x.to_json(),
-            &KeyAction::Up(ref x) => x.to_json(),
-        }
-    }
-}
-
-fn validate_key_value(value_str: &str) -> WebDriverResult<char> {
-    let mut chars = value_str.chars();
-    let value = if let Some(c) = chars.next() {
-        c
-    } else {
-        return Err(WebDriverError::new(
-            ErrorStatus::InvalidArgument,
-            "Parameter 'value' was an empty string"))
-    };
-    if chars.next().is_some() {
-        return Err(WebDriverError::new(
-            ErrorStatus::InvalidArgument,
-            "Parameter 'value' contained multiple characters"))
-    };
-    Ok(value)
-}
-
-#[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"),
-                         ErrorStatus::InvalidArgument,
-                         "Missing value parameter").as_string(),
-                ErrorStatus::InvalidArgument,
-            "Parameter 'value' was not a string");
-
-        let value = try!(validate_key_value(value_str));
-        Ok(KeyUpAction {
-            value: value
-        })
-    }
-}
-
-impl ToJson for KeyUpAction {
-    fn to_json(&self) -> Json {
-        let mut data = BTreeMap::new();
-        data.insert("type".to_owned(),
-                    "keyUp".to_json());
-        data.insert("value".to_string(),
-                    self.value.to_string().to_json());
-        Json::Object(data)
-    }
-}
-
-#[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"),
-                         ErrorStatus::InvalidArgument,
-                         "Missing value parameter").as_string(),
-                ErrorStatus::InvalidArgument,
-            "Parameter 'value' was not a string");
-        let value = try!(validate_key_value(value_str));
-        Ok(KeyDownAction {
-            value: value
-        })
-    }
-}
-
-impl ToJson for KeyDownAction {
-    fn to_json(&self) -> Json {
-        let mut data = BTreeMap::new();
-        data.insert("type".to_owned(),
-                    "keyDown".to_json());
-        data.insert("value".to_owned(),
-                    self.value.to_string().to_json());
-        Json::Object(data)
-    }
-}
-
-#[derive(Debug, PartialEq)]
-pub enum PointerOrigin {
-    Viewport,
-    Pointer,
-    Element(WebElement),
-}
-
-impl Parameters for PointerOrigin {
-    fn from_json(body: &Json) -> WebDriverResult<PointerOrigin> {
-        match *body {
-            Json::String(ref x) => {
-                match &**x {
-                    "viewport" => Ok(PointerOrigin::Viewport),
-                    "pointer" => Ok(PointerOrigin::Pointer),
-                    _ => Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                                 "Unknown pointer origin"))
-                }
-            },
-            Json::Object(_) => Ok(PointerOrigin::Element(try!(WebElement::from_json(body)))),
-            _ => Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                        "Pointer origin was not a string or an object"))
-        }
-    }
-}
-
-impl ToJson for PointerOrigin {
-    fn to_json(&self) -> Json {
-        match *self {
-            PointerOrigin::Viewport => "viewport".to_json(),
-            PointerOrigin::Pointer => "pointer".to_json(),
-            PointerOrigin::Element(ref x) => x.to_json(),
-        }
-    }
-}
-
-impl Default for PointerOrigin {
-    fn default() -> PointerOrigin {
-        PointerOrigin::Viewport
-    }
-}
-
-#[derive(Debug, PartialEq)]
-pub enum PointerAction {
-    Up(PointerUpAction),
-    Down(PointerDownAction),
-    Move(PointerMoveAction),
-    Cancel
-}
-
-impl Parameters for PointerAction {
-    fn from_json(body: &Json) -> WebDriverResult<PointerAction> {
-        match body.find("type").and_then(|x| x.as_string()) {
-            Some("pointerUp") => Ok(PointerAction::Up(try!(PointerUpAction::from_json(body)))),
-            Some("pointerDown") => Ok(PointerAction::Down(try!(PointerDownAction::from_json(body)))),
-            Some("pointerMove") => Ok(PointerAction::Move(try!(PointerMoveAction::from_json(body)))),
-            Some("pointerCancel") => Ok(PointerAction::Cancel),
-            Some(_) | None => Err(WebDriverError::new(
-                ErrorStatus::InvalidArgument,
-                "Missing or invalid type argument for pointer action"))
-        }
-    }
-}
-
-impl ToJson for PointerAction {
-    fn to_json(&self) -> Json {
-        match self {
-            &PointerAction::Down(ref x) => x.to_json(),
-            &PointerAction::Up(ref x) => x.to_json(),
-            &PointerAction::Move(ref x) => x.to_json(),
-            &PointerAction::Cancel => {
-                let mut data = BTreeMap::new();
-                data.insert("type".to_owned(),
-                            "pointerCancel".to_json());
-                Json::Object(data)
-            }
-        }
-    }
-}
-
-#[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"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing button parameter").as_u64(),
-            ErrorStatus::InvalidArgument,
-            "Parameter 'button' was not a positive integer");
-
-        Ok(PointerUpAction {
-            button: button
-        })
-    }
-}
-
-impl ToJson for PointerUpAction {
-    fn to_json(&self) -> Json {
-        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(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"),
-                     ErrorStatus::InvalidArgument,
-                     "Missing button parameter").as_u64(),
-            ErrorStatus::InvalidArgument,
-            "Parameter 'button' was not a positive integer");
-
-        Ok(PointerDownAction {
-            button: button
-        })
-    }
-}
-
-impl ToJson for PointerDownAction {
-    fn to_json(&self) -> Json {
-        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(Debug, PartialEq)]
-pub struct PointerMoveAction {
-    pub duration: Nullable<u64>,
-    pub origin: PointerOrigin,
-    pub x: Nullable<i64>,
-    pub y: Nullable<i64>
-}
-
-impl Parameters for PointerMoveAction {
-    fn from_json(body: &Json) -> WebDriverResult<PointerMoveAction> {
-        let duration = match body.find("duration") {
-            Some(duration) => Some(try_opt!(duration.as_u64(),
-                                            ErrorStatus::InvalidArgument,
-                                            "Parameter 'duration' was not a positive integer")),
-            None => None
-
-        };
-
-        let origin = match body.find("origin") {
-            Some(o) => try!(PointerOrigin::from_json(o)),
-            None => PointerOrigin::default()
-        };
-
-        let x = match body.find("x") {
-            Some(x) => {
-                Some(try_opt!(x.as_i64(),
-                              ErrorStatus::InvalidArgument,
-                              "Parameter 'x' was not an integer"))
-            },
-            None => None
-        };
-
-        let y = match body.find("y") {
-            Some(y) => {
-                Some(try_opt!(y.as_i64(),
-                              ErrorStatus::InvalidArgument,
-                              "Parameter 'y' was not an integer"))
-            },
-            None => None
-        };
-
-        Ok(PointerMoveAction {
-            duration: duration.into(),
-            origin: origin.into(),
-            x: x.into(),
-            y: y.into(),
-        })
-    }
-}
-
-impl ToJson for PointerMoveAction {
-    fn to_json(&self) -> Json {
-        let mut data = BTreeMap::new();
-        data.insert("type".to_owned(), "pointerMove".to_json());
-        if self.duration.is_value() {
-            data.insert("duration".to_owned(),
-                        self.duration.to_json());
-        }
-
-        data.insert("origin".to_owned(), self.origin.to_json());
-
-        if self.x.is_value() {
-            data.insert("x".to_owned(), self.x.to_json());
-        }
-        if self.y.is_value() {
-            data.insert("y".to_owned(), self.y.to_json());
-        }
-        Json::Object(data)
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use rustc_serialize::json::Json;
-    use super::{Nullable, Parameters, WindowRectParameters};
-
-    #[test]
-    fn test_window_rect() {
-        let expected = WindowRectParameters {
-            x: Nullable::Value(0i64),
-            y: Nullable::Value(1i64),
-            width: Nullable::Value(2u64),
-            height: Nullable::Value(3u64),
-        };
-        let actual = Json::from_str(r#"{"x": 0, "y": 1, "width": 2, "height": 3}"#).unwrap();
-        assert_eq!(expected, Parameters::from_json(&actual).unwrap());
-    }
-
-    #[test]
-    fn test_window_rect_nullable() {
-        let expected = WindowRectParameters {
-            x: Nullable::Value(0i64),
-            y: Nullable::Null,
-            width: Nullable::Value(2u64),
-            height: Nullable::Null,
-        };
-        let actual = Json::from_str(r#"{"x": 0, "y": null, "width": 2, "height": null}"#).unwrap();
-        assert_eq!(expected, Parameters::from_json(&actual).unwrap());
-    }
-
-    #[test]
-    fn test_window_rect_missing_fields() {
-        let expected = WindowRectParameters {
-            x: Nullable::Value(0i64),
-            y: Nullable::Null,
-            width: Nullable::Value(2u64),
-            height: Nullable::Null,
-        };
-        let actual = Json::from_str(r#"{"x": 0, "width": 2}"#).unwrap();
-        assert_eq!(expected, Parameters::from_json(&actual).unwrap());
-    }
-}
deleted file mode 100644
--- a/third_party/rust/webdriver/src/common.rs
+++ /dev/null
@@ -1,271 +0,0 @@
-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(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(Clone, Debug, PartialEq)]
-pub enum Nullable<T: ToJson> {
-    Value(T),
-    Null
-}
-
-impl<T: ToJson> Nullable<T> {
-     pub fn is_null(&self) -> bool {
-        match *self {
-            Nullable::Value(_) => false,
-            Nullable::Null => true
-        }
-    }
-
-     pub fn is_value(&self) -> bool {
-        match *self {
-            Nullable::Value(_) => true,
-            Nullable::Null => false
-        }
-    }
-
-    pub fn map<F, U: ToJson>(self, f: F) -> Nullable<U>
-        where F: FnOnce(T) -> U {
-        match self {
-            Nullable::Value(val) => Nullable::Value(f(val)),
-            Nullable::Null => Nullable::Null
-        }
-    }
-}
-
-impl<T: ToJson> Nullable<T> {
-    //This is not very pretty
-    pub fn from_json<F: FnOnce(&Json) -> WebDriverResult<T>>(value: &Json, f: F) -> WebDriverResult<Nullable<T>> {
-        if value.is_null() {
-            Ok(Nullable::Null)
-        } else {
-            Ok(Nullable::Value(try!(f(value))))
-        }
-    }
-}
-
-impl<T: ToJson> ToJson for Nullable<T> {
-    fn to_json(&self) -> Json {
-        match *self {
-            Nullable::Value(ref x) => x.to_json(),
-            Nullable::Null => Json::Null
-        }
-    }
-}
-
-impl<T: ToJson> Encodable for Nullable<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        match *self {
-            Nullable::Value(ref x) => x.to_json().encode(s),
-            Nullable::Null => s.emit_option_none()
-        }
-    }
-}
-
-impl<T: ToJson> Into<Option<T>> for Nullable<T> {
-    fn into(self) -> Option<T> {
-        match self {
-            Nullable::Value(val) => Some(val),
-            Nullable::Null => None
-        }
-    }
-}
-
-impl<T: ToJson> From<Option<T>> for Nullable<T> {
-    fn from(option: Option<T>) -> Nullable<T> {
-        match option {
-            Some(val) => Nullable::Value(val),
-            None => Nullable::Null,
-        }
-    }
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub struct WebElement {
-    pub id: String
-}
-
-impl WebElement {
-    pub fn new(id: String) -> WebElement {
-        WebElement {
-            id: id
-        }
-    }
-
-    pub fn from_json(data: &Json) -> WebDriverResult<WebElement> {
-        let object = try_opt!(data.as_object(),
-                              ErrorStatus::InvalidArgument,
-                              "Could not convert webelement to object");
-        let id_value = try_opt!(object.get(ELEMENT_KEY),
-                                ErrorStatus::InvalidArgument,
-                                "Could not find webelement key");
-
-        let id = try_opt!(id_value.as_string(),
-                          ErrorStatus::InvalidArgument,
-                          "Could not convert web element to string").to_string();
-
-        Ok(WebElement::new(id))
-    }
-}
-
-impl ToJson for WebElement {
-    fn to_json(&self) -> Json {
-        let mut data = BTreeMap::new();
-        data.insert(ELEMENT_KEY.to_string(), self.id.to_json());
-        Json::Object(data)
-    }
-}
-
-impl <T> From<T> for WebElement
-    where T: Into<String> {
-    fn from(data: T) -> WebElement {
-        WebElement::new(data.into())
-    }
-}
-
-#[derive(Debug, PartialEq)]
-pub enum FrameId {
-    Short(u16),
-    Element(WebElement),
-    Null
-}
-
-impl FrameId {
-    pub fn from_json(data: &Json) -> WebDriverResult<FrameId> {
-        match data {
-            &Json::U64(x) => {
-                if x > u16::max_value() as u64 || x < u16::min_value() as u64 {
-                    return Err(WebDriverError::new(ErrorStatus::NoSuchFrame,
-                                                   "frame id out of range"))
-                };
-                Ok(FrameId::Short(x as u16))
-            },
-            &Json::Null => Ok(FrameId::Null),
-            &Json::Object(_) => Ok(FrameId::Element(
-                try!(WebElement::from_json(data)))),
-            _ => Err(WebDriverError::new(ErrorStatus::NoSuchFrame,
-                                         "frame id has unexpected type"))
-        }
-    }
-}
-
-impl ToJson for FrameId {
-    fn to_json(&self) -> Json {
-        match *self {
-            FrameId::Short(x) => {
-                Json::U64(x as u64)
-            },
-            FrameId::Element(ref x) => {
-                Json::String(x.id.clone())
-            },
-            FrameId::Null => {
-                Json::Null
-            }
-        }
-    }
-}
-
-#[derive(Debug, PartialEq)]
-pub enum LocatorStrategy {
-    CSSSelector,
-    LinkText,
-    PartialLinkText,
-    XPath,
-}
-
-impl LocatorStrategy {
-    pub fn from_json(body: &Json) -> WebDriverResult<LocatorStrategy> {
-        match try_opt!(body.as_string(),
-                       ErrorStatus::InvalidArgument,
-                       "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)))
-        }
-    }
-}
-
-impl ToJson for LocatorStrategy {
-    fn to_json(&self) -> Json {
-        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())
-    }
-}
deleted file mode 100644
--- a/third_party/rust/webdriver/src/error.rs
+++ /dev/null
@@ -1,318 +0,0 @@
-use backtrace::Backtrace;
-use hyper::status::StatusCode;
-use rustc_serialize::base64::FromBase64Error;
-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(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
-    ElementClickIntercepted,
-
-    /// A [command] could not be completed because the element is not pointer-
-    /// or keyboard interactable.
-    ///
-    /// [command]: ../command/index.html
-    ElementNotInteractable,
-
-    /// An attempt was made to select an [element] that cannot be selected.
-    ///
-    /// [element]: ../common/struct.WebElement.html
-    ElementNotSelectable,
-
-    /// Navigation caused the user agent to hit a certificate warning, which is
-    /// usually the result of an expired or invalid TLS certificate.
-    InsecureCertificate,
-
-    /// The arguments passed to a [command] are either invalid or malformed.
-    ///
-    /// [command]: ../command/index.html
-    InvalidArgument,
-
-    /// An illegal attempt was made to set a cookie under a different domain
-    /// than the current page.
-    InvalidCookieDomain,
-
-    /// The coordinates provided to an interactions operation are invalid.
-    InvalidCoordinates,
-
-    /// A [command] could not be completed because the element is an invalid
-    /// state, e.g. attempting to click an element that is no longer attached
-    /// to the document.
-    ///
-    /// [command]: ../command/index.html
-    InvalidElementState,
-
-    /// Argument was an invalid selector.
-    InvalidSelector,
-
-    /// Occurs if the given session ID is not in the list of active sessions,
-    /// meaning the session either does not exist or that it’s not active.
-    InvalidSessionId,
-
-    /// An error occurred while executing JavaScript supplied by the user.
-    JavascriptError,
-
-    /// The target for mouse interaction is not in the browser’s viewport and
-    /// cannot be brought into that viewport.
-    MoveTargetOutOfBounds,
-
-    /// An attempt was made to operate on a modal dialogue when one was not
-    /// open.
-    NoSuchAlert,
-
-    /// No cookie matching the given path name was found amongst the associated
-    /// cookies of the current browsing context’s active document.
-    NoSuchCookie,
-
-    /// An [element] could not be located on the page using the given search
-    /// parameters.
-    ///
-    /// [element]: ../common/struct.WebElement.html
-    NoSuchElement,
-
-    /// A [command] to switch to a frame could not be satisfied because the
-    /// frame could not be found.
-    ///
-    /// [command]: ../command/index.html
-    NoSuchFrame,
-
-    /// A [command] to switch to a window could not be satisfied because the
-    /// window could not be found.
-    ///
-    /// [command]: ../command/index.html
-    NoSuchWindow,
-
-    /// A script did not complete before its timeout expired.
-    ScriptTimeout,
-
-    /// A new session could not be created.
-    SessionNotCreated,
-
-    /// A [command] failed because the referenced [element] is no longer
-    /// attached to the DOM.
-    ///
-    /// [command]: ../command/index.html
-    /// [element]: ../common/struct.WebElement.html
-    StaleElementReference,
-
-    /// An operation did not complete before its timeout expired.
-    Timeout,
-
-    /// A screen capture was made impossible.
-    UnableToCaptureScreen,
-
-    /// Setting the cookie’s value could not be done.
-    UnableToSetCookie,
-
-    /// A modal dialogue was open, blocking this operation.
-    UnexpectedAlertOpen,
-
-    /// The requested command could not be executed because it does not exist.
-    UnknownCommand,
-
-    /// An unknown error occurred in the remote end whilst processing the
-    /// [command].
-    ///
-    /// [command]: ../command/index.html
-    UnknownError,
-
-    /// The requested [command] matched a known endpoint, but did not match a
-    /// method for that endpoint.
-    ///
-    /// [command]: ../command/index.html
-    UnknownMethod,
-
-    UnknownPath,
-
-    /// Indicates that a [command] that should have executed properly is not
-    /// currently supported.
-    UnsupportedOperation,
-}
-
-
-impl ErrorStatus {
-    pub fn error_code(&self) -> &'static str {
-        match *self {
-            ErrorStatus::ElementClickIntercepted => "element click intercepted",
-            ErrorStatus::ElementNotInteractable => "element not interactable",
-            ErrorStatus::ElementNotSelectable => "element not selectable",
-            ErrorStatus::InsecureCertificate => "insecure certificate",
-            ErrorStatus::InvalidArgument => "invalid argument",
-            ErrorStatus::InvalidCookieDomain => "invalid cookie domain",
-            ErrorStatus::InvalidCoordinates => "invalid coordinates",
-            ErrorStatus::InvalidElementState => "invalid element state",
-            ErrorStatus::InvalidSelector => "invalid selector",
-            ErrorStatus::InvalidSessionId => "invalid session id",
-            ErrorStatus::JavascriptError => "javascript error",
-            ErrorStatus::MoveTargetOutOfBounds => "move target out of bounds",
-            ErrorStatus::NoSuchAlert => "no such alert",
-            ErrorStatus::NoSuchCookie => "no such cookie",
-            ErrorStatus::NoSuchElement => "no such element",
-            ErrorStatus::NoSuchFrame => "no such frame",
-            ErrorStatus::NoSuchWindow => "no such window",
-            ErrorStatus::ScriptTimeout => "script timeout",
-            ErrorStatus::SessionNotCreated => "session not created",
-            ErrorStatus::StaleElementReference => "stale element reference",
-            ErrorStatus::Timeout => "timeout",
-            ErrorStatus::UnableToCaptureScreen => "unable to capture screen",
-            ErrorStatus::UnableToSetCookie => "unable to set cookie",
-            ErrorStatus::UnexpectedAlertOpen => "unexpected alert open",
-            ErrorStatus::UnknownCommand |
-            ErrorStatus::UnknownError => "unknown error",
-            ErrorStatus::UnknownMethod => "unknown method",
-            ErrorStatus::UnknownPath => "unknown command",
-            ErrorStatus::UnsupportedOperation => "unsupported operation",
-        }
-    }
-
-    pub fn http_status(&self) -> StatusCode {
-        match *self {
-            ErrorStatus::ElementClickIntercepted => StatusCode::BadRequest,
-            ErrorStatus::ElementNotInteractable => StatusCode::BadRequest,
-            ErrorStatus::ElementNotSelectable => StatusCode::BadRequest,
-            ErrorStatus::InsecureCertificate => StatusCode::BadRequest,
-            ErrorStatus::InvalidArgument => StatusCode::BadRequest,
-            ErrorStatus::InvalidCookieDomain => StatusCode::BadRequest,
-            ErrorStatus::InvalidCoordinates => StatusCode::BadRequest,
-            ErrorStatus::InvalidElementState => StatusCode::BadRequest,
-            ErrorStatus::InvalidSelector => StatusCode::BadRequest,
-            ErrorStatus::InvalidSessionId => StatusCode::NotFound,
-            ErrorStatus::JavascriptError => StatusCode::InternalServerError,
-            ErrorStatus::MoveTargetOutOfBounds => StatusCode::InternalServerError,
-            ErrorStatus::NoSuchAlert => StatusCode::BadRequest,
-            ErrorStatus::NoSuchCookie => StatusCode::NotFound,
-            ErrorStatus::NoSuchElement => StatusCode::NotFound,
-            ErrorStatus::NoSuchFrame => StatusCode::BadRequest,
-            ErrorStatus::NoSuchWindow => StatusCode::BadRequest,
-            ErrorStatus::ScriptTimeout => StatusCode::RequestTimeout,
-            ErrorStatus::SessionNotCreated => StatusCode::InternalServerError,
-            ErrorStatus::StaleElementReference => StatusCode::BadRequest,
-            ErrorStatus::Timeout => StatusCode::RequestTimeout,
-            ErrorStatus::UnableToCaptureScreen => StatusCode::BadRequest,
-            ErrorStatus::UnableToSetCookie => StatusCode::InternalServerError,
-            ErrorStatus::UnexpectedAlertOpen => StatusCode::InternalServerError,
-            ErrorStatus::UnknownCommand => StatusCode::NotFound,
-            ErrorStatus::UnknownError => StatusCode::InternalServerError,
-            ErrorStatus::UnknownMethod => StatusCode::MethodNotAllowed,
-            ErrorStatus::UnknownPath => StatusCode::NotFound,
-            ErrorStatus::UnsupportedOperation => StatusCode::InternalServerError,
-        }
-    }
-}
-
-pub type WebDriverResult<T> = Result<T, WebDriverError>;
-
-#[derive(Debug)]
-pub struct WebDriverError {
-    pub error: ErrorStatus,
-    pub message: Cow<'static, str>,
-    pub stack: Cow<'static, str>,
-    pub delete_session: bool,
-}
-
-impl WebDriverError {
-    pub fn new<S>(error: ErrorStatus, message: S) -> WebDriverError
-        where S: Into<Cow<'static, str>>
-    {
-        WebDriverError {
-            error: error,
-            message: message.into(),
-            stack: format!("{:?}", Backtrace::new()).into(),
-            delete_session: false,
-        }
-    }
-
-    pub fn new_with_stack<S>(error: ErrorStatus, message: S, stack: S) -> WebDriverError
-        where S: Into<Cow<'static, str>>
-    {
-        WebDriverError {
-            error: error,
-            message: message.into(),
-            stack: stack.into(),
-            delete_session: false,
-        }
-    }
-
-    pub fn error_code(&self) -> &'static str {
-        self.error.error_code()
-    }
-
-    pub fn http_status(&self) -> StatusCode {
-        self.error.http_status()
-    }
-
-    pub fn to_json_string(&self) -> String {
-        self.to_json().to_string()
-    }
-}
-
-impl ToJson for WebDriverError {
-    fn to_json(&self) -> Json {
-        let mut data = BTreeMap::new();
-        data.insert("error".into(), self.error_code().to_json());
-        data.insert("message".into(), self.message.to_json());
-        data.insert("stacktrace".into(), self.stack.to_json());
-
-        let mut wrapper = BTreeMap::new();
-        wrapper.insert("value".into(), Json::Object(data));
-        Json::Object(wrapper)
-    }
-}
-
-impl Error for WebDriverError {
-    fn description(&self) -> &str {
-        self.error_code()
-    }
-
-    fn cause(&self) -> Option<&Error> {
-        None
-    }
-}
-
-impl fmt::Display for WebDriverError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.message.fmt(f)
-    }
-}
-
-impl From<ParserError> for WebDriverError {
-    fn from(err: ParserError) -> WebDriverError {
-        WebDriverError::new(ErrorStatus::UnknownError, err.description().to_string())
-    }
-}
-
-impl From<io::Error> for WebDriverError {
-    fn from(err: io::Error) -> WebDriverError {
-        WebDriverError::new(ErrorStatus::UnknownError, err.description().to_string())
-    }
-}
-
-impl From<DecoderError> for WebDriverError {
-    fn from(err: DecoderError) -> WebDriverError {
-        WebDriverError::new(ErrorStatus::UnknownError, err.description().to_string())
-    }
-}
-
-impl From<FromBase64Error> for WebDriverError {
-    fn from(err: FromBase64Error) -> WebDriverError {
-        WebDriverError::new(ErrorStatus::UnknownError, err.description().to_string())
-    }
-}
-
-impl From<Box<Error>> for WebDriverError {
-    fn from(err: Box<Error>) -> WebDriverError {
-        WebDriverError::new(ErrorStatus::UnknownError, err.description().to_string())
-    }
-}
deleted file mode 100644
--- a/third_party/rust/webdriver/src/httpapi.rs
+++ /dev/null
@@ -1,245 +0,0 @@
-use regex::{Regex, Captures};
-use rustc_serialize::json::Json;
-
-use hyper::method::Method;
-use hyper::method::Method::{Get, Post, Delete};
-
-use command::{WebDriverCommand, WebDriverMessage, WebDriverExtensionCommand,
-              VoidWebDriverExtensionCommand};
-use error::{WebDriverResult, WebDriverError, ErrorStatus};
-
-fn standard_routes<U:WebDriverExtensionRoute>() -> Vec<(Method, &'static str, Route<U>)> {
-    return vec![(Post, "/session", Route::NewSession),
-                (Delete, "/session/{sessionId}", Route::DeleteSession),
-                (Post, "/session/{sessionId}/url", Route::Get),
-                (Get, "/session/{sessionId}/url", Route::GetCurrentUrl),
-                (Post, "/session/{sessionId}/back", Route::GoBack),
-                (Post, "/session/{sessionId}/forward", Route::GoForward),
-                (Post, "/session/{sessionId}/refresh", Route::Refresh),
-                (Get, "/session/{sessionId}/title", Route::GetTitle),
-                (Get, "/session/{sessionId}/source", Route::GetPageSource),
-                (Get, "/session/{sessionId}/window", Route::GetWindowHandle),
-                (Get, "/session/{sessionId}/window/handles", Route::GetWindowHandles),
-                (Delete, "/session/{sessionId}/window", Route::CloseWindow),
-                (Get, "/session/{sessionId}/window/size", Route::GetWindowSize),
-                (Post, "/session/{sessionId}/window/size", Route::SetWindowSize),
-                (Get, "/session/{sessionId}/window/position", Route::GetWindowPosition),
-                (Post, "/session/{sessionId}/window/position", Route::SetWindowPosition),
-                (Get, "/session/{sessionId}/window/rect", Route::GetWindowRect),
-                (Post, "/session/{sessionId}/window/rect", Route::SetWindowRect),
-                (Post, "/session/{sessionId}/window/minimize", Route::MinimizeWindow),
-                (Post, "/session/{sessionId}/window/maximize", Route::MaximizeWindow),
-                (Post, "/session/{sessionId}/window/fullscreen", Route::FullscreenWindow),
-                (Post, "/session/{sessionId}/window", Route::SwitchToWindow),
-                (Post, "/session/{sessionId}/frame", Route::SwitchToFrame),
-                (Post, "/session/{sessionId}/frame/parent", Route::SwitchToParentFrame),
-                (Post, "/session/{sessionId}/element", Route::FindElement),
-                (Post, "/session/{sessionId}/elements", Route::FindElements),
-                (Post, "/session/{sessionId}/element/{elementId}/element", Route::FindElementElement),
-                (Post, "/session/{sessionId}/element/{elementId}/elements", Route::FindElementElements),
-                (Get, "/session/{sessionId}/element/active", Route::GetActiveElement),
-                (Get, "/session/{sessionId}/element/{elementId}/displayed", Route::IsDisplayed),
-                (Get, "/session/{sessionId}/element/{elementId}/selected", Route::IsSelected),
-                (Get, "/session/{sessionId}/element/{elementId}/attribute/{name}", Route::GetElementAttribute),
-                (Get, "/session/{sessionId}/element/{elementId}/property/{name}", Route::GetElementProperty),
-                (Get, "/session/{sessionId}/element/{elementId}/css/{propertyName}", Route::GetCSSValue),
-                (Get, "/session/{sessionId}/element/{elementId}/text", Route::GetElementText),
-                (Get, "/session/{sessionId}/element/{elementId}/name", Route::GetElementTagName),
-                (Get, "/session/{sessionId}/element/{elementId}/rect", Route::GetElementRect),
-                (Get, "/session/{sessionId}/element/{elementId}/enabled", Route::IsEnabled),
-                (Post, "/session/{sessionId}/execute/sync", Route::ExecuteScript),
-                (Post, "/session/{sessionId}/execute/async", Route::ExecuteAsyncScript),
-                (Get, "/session/{sessionId}/cookie", Route::GetCookies),
-                (Get, "/session/{sessionId}/cookie/{name}", Route::GetNamedCookie),
-                (Post, "/session/{sessionId}/cookie", Route::AddCookie),
-                (Delete, "/session/{sessionId}/cookie", Route::DeleteCookies),
-                (Delete, "/session/{sessionId}/cookie/{name}", Route::DeleteCookie),
-                (Get, "/session/{sessionId}/timeouts", Route::GetTimeouts),
-                (Post, "/session/{sessionId}/timeouts", Route::SetTimeouts),
-                (Post, "/session/{sessionId}/element/{elementId}/click", Route::ElementClick),
-                (Post, "/session/{sessionId}/element/{elementId}/tap", Route::ElementTap),
-                (Post, "/session/{sessionId}/element/{elementId}/clear", Route::ElementClear),
-                (Post, "/session/{sessionId}/element/{elementId}/value", Route::ElementSendKeys),
-                (Post, "/session/{sessionId}/alert/dismiss", Route::DismissAlert),
-                (Post, "/session/{sessionId}/alert/accept", Route::AcceptAlert),
-                (Get, "/session/{sessionId}/alert/text", Route::GetAlertText),
-                (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, Debug)]
-pub enum Route<U:WebDriverExtensionRoute> {
-    NewSession,
-    DeleteSession,
-    Get,
-    GetCurrentUrl,
-    GoBack,
-    GoForward,
-    Refresh,
-    GetTitle,
-    GetPageSource,
-    GetWindowHandle,
-    GetWindowHandles,
-    CloseWindow,
-    GetWindowSize,  // deprecated
-    SetWindowSize,  // deprecated
-    GetWindowPosition,  // deprecated
-    SetWindowPosition,  // deprecated
-    GetWindowRect,
-    SetWindowRect,
-    MinimizeWindow,
-    MaximizeWindow,
-    FullscreenWindow,
-    SwitchToWindow,
-    SwitchToFrame,
-    SwitchToParentFrame,
-    FindElement,
-    FindElements,
-    FindElementElement,
-    FindElementElements,
-    GetActiveElement,
-    IsDisplayed,
-    IsSelected,
-    GetElementAttribute,
-    GetElementProperty,
-    GetCSSValue,
-    GetElementText,
-    GetElementTagName,
-    GetElementRect,
-    IsEnabled,
-    ExecuteScript,
-    ExecuteAsyncScript,
-    GetCookies,
-    GetNamedCookie,
-    AddCookie,
-    DeleteCookies,
-    DeleteCookie,
-    GetTimeouts,
-    SetTimeouts,
-    ElementClick,
-    ElementTap,
-    ElementClear,
-    ElementSendKeys,
-    PerformActions,
-    ReleaseActions,
-    DismissAlert,
-    AcceptAlert,
-    GetAlertText,
-    SendAlertText,
-    TakeScreenshot,
-    TakeElementScreenshot,
-    Status,
-    Extension(U),
-}
-
-pub trait WebDriverExtensionRoute : Clone + Send + PartialEq {
-    type Command: WebDriverExtensionCommand + 'static;
-
-    fn command(&self, &Captures, &Json) -> WebDriverResult<WebDriverCommand<Self::Command>>;
-}
-
-#[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, 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> {
-        let path_regexp = RequestMatcher::<U>::compile_path(path);
-        RequestMatcher {
-            method: method,
-            path_regexp: path_regexp,
-            match_type: match_type
-        }
-    }
-
-    pub fn get_match<'t>(&'t self, method: Method, path: &'t str) -> (bool, Option<Captures>) {
-        let captures = self.path_regexp.captures(path);
-        (method == self.method, captures)
-    }
-
-    fn compile_path(path: &str) -> Regex {
-        let mut rv = String::new();
-        rv.push_str("^");
-        let components = path.split('/');
-        for component in components {
-            if component.starts_with("{") {
-                if !component.ends_with("}") {
-                    panic!("Invalid url pattern")
-                }
-                rv.push_str(&format!("(?P<{}>[^/]+)/", &component[1..component.len()-1])[..]);
-            } else {
-                rv.push_str(&format!("{}/", component)[..]);
-            }
-        }
-        //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![],
-        };
-        debug!("Creating routes");
-        for &(ref method, ref url, ref match_type) in standard_routes::<U>().iter() {
-            rv.add(method.clone(), *url, (*match_type).clone());
-        };
-        for &(ref method, ref url, ref extension_route) in extension_routes.iter() {
-            rv.add(method.clone(), *url, Route::Extension(extension_route.clone()));
-        };
-        rv
-    }
-
-    fn add(&mut self, method: Method, path: &str, match_type: Route<U>) {
-        let http_matcher = RequestMatcher::new(method.clone(), path, match_type);
-        self.routes.push((method, http_matcher));
-    }
-
-    pub fn decode_request(&self, method: Method, path: &str, body: &str) -> WebDriverResult<WebDriverMessage<U>> {
-        let mut error = ErrorStatus::UnknownPath;
-        for &(ref match_method, ref matcher) in self.routes.iter() {
-            if method == *match_method {
-                let (method_match, captures) = matcher.get_match(method.clone(), path);
-                if captures.is_some() {
-                    if method_match {
-                        return WebDriverMessage::from_http(matcher.match_type.clone(),
-                                                           &captures.unwrap(),
-                                                           body,
-                                                           method == Post)
-                    } else {
-                        error = ErrorStatus::UnknownMethod;
-                    }
-                }
-            }
-        }
-        Err(WebDriverError::new(error,
-                                format!("{} {} did not match a known command", method, path)))
-    }
-}
deleted file mode 100644
--- a/third_party/rust/webdriver/src/lib.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-#![allow(non_snake_case)]
-
-extern crate backtrace;
-#[macro_use]
-extern crate log;
-extern crate rustc_serialize;
-extern crate hyper;
-extern crate regex;
-extern crate cookie;
-extern crate time;
-extern crate url;
-
-#[macro_use] pub mod macros;
-pub mod httpapi;
-pub mod capabilities;
-pub mod command;
-pub mod common;
-pub mod error;
-pub mod server;
-pub mod response;
-
-#[cfg(test)]
-mod nullable_tests {
-    use super::common::Nullable;
-
-    #[test]
-    fn test_nullable_map() {
-        let mut test = Nullable::Value(21);
-
-        assert_eq!(test.map(|x| x << 1), Nullable::Value(42));
-
-        test = Nullable::Null;
-
-        assert_eq!(test.map(|x| x << 1), Nullable::Null);
-    }
-
-    #[test]
-    fn test_nullable_into() {
-        let test: Option<i32> = Nullable::Value(42).into();
-
-        assert_eq!(test, Some(42));
-    }
-}
deleted file mode 100644
--- a/third_party/rust/webdriver/src/macros.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-macro_rules! try_opt {
-    ($expr:expr, $err_type:expr, $err_msg:expr) => ({
-        match $expr {
-            Some(x) => x,
-            None => return Err(WebDriverError::new($err_type, $err_msg))
-        }
-    })
-}
deleted file mode 100644
--- a/third_party/rust/webdriver/src/response.rs
+++ /dev/null
@@ -1,336 +0,0 @@
-use common::{Date, Nullable, WindowState};
-use cookie;
-use rustc_serialize::json::{self, Json, ToJson};
-use std::collections::BTreeMap;
-use time;
-
-#[derive(Debug)]
-pub enum WebDriverResponse {
-    CloseWindow(CloseWindowResponse),
-    Cookie(CookieResponse),
-    Cookies(CookiesResponse),
-    DeleteSession,
-    ElementRect(ElementRectResponse),
-    Generic(ValueResponse),
-    NewSession(NewSessionResponse),
-    Timeouts(TimeoutsResponse),
-    Void,
-    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.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(Debug, RustcEncodable)]
-pub struct CloseWindowResponse {
-    pub window_handles: Vec<String>,
-}
-
-impl CloseWindowResponse {
-    pub fn new(handles: Vec<String>) -> CloseWindowResponse {
-        CloseWindowResponse { window_handles: handles }
-    }
-}
-
-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(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(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(Debug, RustcEncodable)]
-pub struct ValueResponse {
-    pub value: json::Json
-}
-
-impl ValueResponse {
-    pub fn new(value: json::Json) -> ValueResponse {
-        ValueResponse {
-            value: value
-        }
-    }
-}
-
-#[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,
-
-    /// Width of the element’s [bounding rectangle] in CSS reference
-    /// pixels.
-    ///
-    /// [bounding rectangle]: https://drafts.fxtf.org/geometry/#rectangle
-    pub height: f64,
-}
-
-#[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(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,
-}
-
-impl Into<cookie::Cookie<'static>> for Cookie {
-    fn into(self) -> cookie::Cookie<'static> {
-        let cookie = cookie::Cookie::build(self.name, self.value)
-            .secure(self.secure)
-            .http_only(self.httpOnly);
-        let cookie = match self.domain {
-            Nullable::Value(domain) => cookie.domain(domain),
-            Nullable::Null => cookie,
-        };
-        let cookie = match self.path {
-            Nullable::Value(path) => cookie.path(path),
-            Nullable::Null => cookie,
-        };
-        let cookie = match self.expiry {
-            Nullable::Value(Date(expiry)) => {
-                cookie.expires(time::at(time::Timespec::new(expiry as i64, 0)))
-            }
-            Nullable::Null => cookie,
-        };
-        cookie.finish()
-    }
-}
-
-#[derive(Debug, RustcEncodable)]
-pub struct CookieResponse {
-    pub value: Cookie,
-}
-
-#[derive(Debug, RustcEncodable)]
-pub struct CookiesResponse {
-    pub value: Vec<Cookie>,
-}
-
-#[cfg(test)]
-mod tests {
-    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);
-    }
-
-    #[test]
-    fn test_close_window() {
-        let resp = WebDriverResponse::CloseWindow(
-            CloseWindowResponse::new(vec!["test".into()]));
-        let expected = r#"{"value": ["test"]}"#;
-        test(resp, expected);
-    }
-
-    #[test]
-    fn test_cookie() {
-        let cookie = Cookie {
-            name: "name".into(),
-            value: "value".into(),
-            path: Nullable::Value("/".into()),
-            domain: Nullable::Null,
-            expiry: Nullable::Null,
-            secure: true,
-            httpOnly: false,
-        };
-        let resp = WebDriverResponse::Cookie(CookieResponse { value: cookie });
-        let expected = r#"{"value": {"name": "name", "expiry": null, "value": "value",
-"path": "/", "domain": null, "secure": true, "httpOnly": false}}"#;
-        test(resp, expected);
-    }
-
-    #[test]
-    fn test_cookies() {
-        let resp = WebDriverResponse::Cookies(CookiesResponse {
-            value: vec![
-                Cookie {
-                    name: "name".into(),
-                    value: "value".into(),
-                    path: Nullable::Value("/".into()),
-                    domain: Nullable::Null,
-                    expiry: Nullable::Null,
-                    secure: true,
-                    httpOnly: false,
-                }
-            ]});
-        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 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 rect = WindowRectResponse {
-            x: 0f64,
-            y: 1f64,
-            width: 2f64,
-            height: 3f64,
-            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())));
-        let expected = r#"{"value": {"sessionId": "test", "capabilities": {}}}"#;
-        test(resp, expected);
-    }
-
-    #[test]
-    fn test_timeouts() {
-         let resp = WebDriverResponse::Timeouts(TimeoutsResponse::new(
-            1, 2, 3));
-        let expected = r#"{"value": {"script": 1, "pageLoad": 2, "implicit": 3}}"#;
-        test(resp, expected);
-    }
-
-    #[test]
-    fn test_value() {
-        let mut value = BTreeMap::new();
-        value.insert("example".into(), Json::Array(vec![Json::String("test".into())]));
-        let resp = WebDriverResponse::Generic(ValueResponse::new(
-            Json::Object(value)));
-        let expected = r#"{"value": {"example": ["test"]}}"#;
-        test(resp, expected);
-    }
-}
deleted file mode 100644
--- a/third_party/rust/webdriver/src/server.rs
+++ /dev/null
@@ -1,263 +0,0 @@
-use std::io::Read;
-use std::marker::PhantomData;
-use std::net::SocketAddr;
-use std::sync::mpsc::{channel, Receiver, Sender};
-use std::sync::Mutex;
-use std::thread;
-
-use hyper::header::{ContentType, CacheControl, CacheDirective};
-use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
-use hyper::method::Method;
-use hyper::Result;
-use hyper::server::{Handler, Listening, Request, Response, Server};
-use hyper::status::StatusCode;
-use hyper::uri::RequestUri::AbsolutePath;
-
-use command::{WebDriverMessage, WebDriverCommand};
-use error::{WebDriverResult, WebDriverError, ErrorStatus};
-use httpapi::{WebDriverHttpApi, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
-use response::{CloseWindowResponse, WebDriverResponse};
-
-enum DispatchMessage<U: WebDriverExtensionRoute> {
-    HandleWebDriver(WebDriverMessage<U>, Sender<WebDriverResult<WebDriverResponse>>),
-    Quit
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub struct Session {
-    id: String
-}
-
-impl Session {
-    fn new(id: String) -> Session {
-        Session {
-            id: id
-        }
-    }
-}
-
-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> {
-    fn new(handler: T) -> Dispatcher<T, U> {
-        Dispatcher {
-            handler: handler,
-            session: None,
-            extension_type: PhantomData,
-        }
-    }
-
-    fn run(&mut self, msg_chan: Receiver<DispatchMessage<U>>) {
-        loop {
-            match msg_chan.recv() {
-                Ok(DispatchMessage::HandleWebDriver(msg, resp_chan)) => {
-                    let resp = match self.check_session(&msg) {
-                        Ok(_) => self.handler.handle_command(&self.session, msg),
-                        Err(e) => Err(e),
-                    };
-
-                    match resp {
-                        Ok(WebDriverResponse::NewSession(ref new_session)) => {
-                            self.session = Some(Session::new(new_session.sessionId.clone()));
-                        }
-                        Ok(WebDriverResponse::CloseWindow(CloseWindowResponse { ref window_handles })) => {
-                            if window_handles.len() == 0 {
-                                debug!("Last window was closed, deleting session");
-                                self.delete_session();
-                            }
-                        }
-                        Ok(WebDriverResponse::DeleteSession) => self.delete_session(),
-                        Err(ref x) if x.delete_session => self.delete_session(),
-                        _ => {}
-                    }
-
-                    if resp_chan.send(resp).is_err() {
-                        error!("Sending response to the main thread failed");
-                    };
-                }
-                Ok(DispatchMessage::Quit) => break,
-                Err(_) => panic!("Error receiving message in handler"),
-            }
-        }
-    }
-
-    fn delete_session(&mut self) {
-        debug!("Deleting session");
-        self.handler.delete_session(&self.session);
-        self.session = None;
-    }
-
-    fn check_session(&self, msg: &WebDriverMessage<U>) -> WebDriverResult<()> {
-        match msg.session_id {
-            Some(ref msg_session_id) => {
-                match self.session {
-                    Some(ref existing_session) => {
-                        if existing_session.id != *msg_session_id {
-                            Err(WebDriverError::new(
-                                ErrorStatus::InvalidSessionId,
-                                format!("Got unexpected session id {}",
-                                        msg_session_id)))
-                        } else {
-                            Ok(())
-                        }
-                    },
-                    None => Ok(())
-                }
-            },
-            None => {
-                match self.session {
-                    Some(_) => {
-                        match msg.command {
-                            WebDriverCommand::Status => Ok(()),
-                            WebDriverCommand::NewSession(_) => {
-                                Err(WebDriverError::new(
-                                    ErrorStatus::SessionNotCreated,
-                                    "Session is already started"))
-                            },
-                            _ => {
-                                //This should be impossible
-                                error!("Got a message with no session id");
-                                Err(WebDriverError::new(
-                                    ErrorStatus::UnknownError,
-                                    "Got a command with no session?!"))
-                            }
-                        }
-                    },
-                    None => {
-                        match msg.command {
-                            WebDriverCommand::NewSession(_) => Ok(()),
-                            WebDriverCommand::Status => Ok(()),
-                            _ => Err(WebDriverError::new(
-                                ErrorStatus::InvalidSessionId,
-                                "Tried to run a command before creating a session"))
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-#[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 {
-            chan: Mutex::new(chan),
-            api: Mutex::new(api)
-        }
-    }
-}
-
-impl<U: WebDriverExtensionRoute> Handler for HttpHandler<U> {
-    fn handle(&self, req: Request, res: Response) {
-        let mut req = req;
-        let mut res = res;
-
-        let mut body = String::new();
-        if let Method::Post = req.method {
-            req.read_to_string(&mut body).unwrap();
-        }
-
-        debug!("-> {} {} {}", req.method, req.uri, body);
-
-        match req.uri {
-            AbsolutePath(path) => {
-                let msg_result = {
-                    // The fact that this locks for basically the whole request doesn't
-                    // matter as long as we are only handling one request at a time.
-                    match self.api.lock() {
-                        Ok(ref api) => api.decode_request(req.method, &path[..], &body[..]),
-                        Err(_) => return,
-                    }
-                };
-                let (status, resp_body) = match msg_result {
-                    Ok(message) => {
-                        let (send_res, recv_res) = channel();
-                        match self.chan.lock() {
-                            Ok(ref c) => {
-                                let res =
-                                    c.send(DispatchMessage::HandleWebDriver(message, send_res));
-                                match res {
-                                    Ok(x) => x,
-                                    Err(_) => {
-                                        error!("Something terrible happened");
-                                        return;
-                                    }
-                                }
-                            }
-                            Err(_) => {
-                                error!("Something terrible happened");
-                                return;
-                            }
-                        }
-                        match recv_res.recv() {
-                            Ok(data) => {
-                                match data {
-                                    Ok(response) => (StatusCode::Ok, response.to_json_string()),
-                                    Err(err) => (err.http_status(), err.to_json_string()),
-                                }
-                            }
-                            Err(e) => panic!("Error reading response: {:?}", e),
-                        }
-                    }
-                    Err(err) => (err.http_status(), err.to_json_string()),
-                };
-
-                debug!("<- {} {}", status, resp_body);
-
-                {
-                    let resp_status = res.status_mut();
-                    *resp_status = status;
-                }
-                res.headers_mut()
-                    .set(ContentType(Mime(TopLevel::Application,
-                                          SubLevel::Json,
-                                          vec![(Attr::Charset, Value::Utf8)])));
-                res.headers_mut()
-                    .set(CacheControl(vec![CacheDirective::NoCache]));
-
-                res.send(&resp_body.as_bytes()).unwrap();
-            }
-            _ => {}
-        }
-    }
-}
-
-pub fn start<T, U>(address: SocketAddr,
-                   handler: T,
-                   extension_routes: &[(Method, &str, U)])
-                   -> Result<Listening>
-    where T: 'static + WebDriverHandler<U>,
-          U: 'static + WebDriverExtensionRoute
-{
-    let (msg_send, msg_recv) = channel();
-
-    let api = WebDriverHttpApi::new(extension_routes);
-    let http_handler = HttpHandler::new(api, msg_send);
-    let mut server = try!(Server::http(address));
-    server.keep_alive(None);
-
-    let builder = thread::Builder::new().name("webdriver dispatcher".to_string());
-    try!(builder.spawn(move || {
-        let mut dispatcher = Dispatcher::new(handler);
-        dispatcher.run(msg_recv);
-    }));
-
-    server.handle(http_handler)
-}