From 024b40b39d3848f1a1f7020bd7ed8c901817f09c Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Mon, 27 Aug 2018 18:36:52 +0200 Subject: [PATCH] Update hyper to 0.12 --- Cargo.lock | 845 +++++++++++++----- components/constellation/Cargo.toml | 2 +- components/constellation/lib.rs | 2 +- components/constellation/network_listener.rs | 4 +- components/devtools/Cargo.toml | 7 +- components/devtools/actors/network_event.rs | 109 +-- components/devtools/lib.rs | 3 + components/devtools_traits/Cargo.toml | 3 +- components/devtools_traits/lib.rs | 10 +- components/malloc_size_of/Cargo.toml | 4 +- components/malloc_size_of/lib.rs | 51 +- components/net/Cargo.toml | 27 +- components/net/blob_loader.rs | 44 +- components/net/connector.rs | 157 +++- components/net/cookie.rs | 8 +- components/net/cookie_storage.rs | 12 +- components/net/data_loader.rs | 5 +- components/net/fetch/cors_cache.rs | 17 +- components/net/fetch/methods.rs | 200 ++--- components/net/http_cache.rs | 336 ++++--- components/net/http_loader.rs | 692 +++++++------- components/net/lib.rs | 7 +- components/net/mime_classifier.rs | 244 +++-- components/net/resource_thread.rs | 11 +- components/net/subresource_integrity.rs | 5 +- components/net/tests/cookie.rs | 12 +- components/net/tests/cookie_http_state.rs | 12 +- components/net/tests/data_loader.rs | 37 +- components/net/tests/fetch.rs | 412 ++++----- components/net/tests/http_loader.rs | 626 ++++++------- components/net/tests/main.rs | 112 ++- components/net/tests/mime_classifier.rs | 305 +++---- components/net/websocket_loader.rs | 35 +- components/net_traits/Cargo.toml | 10 +- components/net_traits/lib.rs | 83 +- components/net_traits/quality.rs | 80 ++ components/net_traits/request.rs | 16 +- components/net_traits/response.rs | 48 +- components/profile/Cargo.toml | 3 +- components/profile/lib.rs | 1 + components/profile/time.rs | 8 +- components/script/Cargo.toml | 15 +- components/script/body.rs | 33 +- components/script/dom/bindings/trace.rs | 10 +- components/script/dom/document.rs | 35 +- components/script/dom/domimplementation.rs | 16 +- components/script/dom/eventsource.rs | 28 +- components/script/dom/filereader.rs | 11 +- components/script/dom/headers.rs | 63 +- components/script/dom/htmlformelement.rs | 71 +- components/script/dom/htmlimageelement.rs | 23 +- components/script/dom/htmlmediaelement.rs | 22 +- components/script/dom/request.rs | 41 +- components/script/dom/response.rs | 12 +- components/script/dom/servoparser/mod.rs | 31 +- components/script/dom/xmlhttprequest.rs | 238 ++--- components/script/lib.rs | 5 +- components/script/script_thread.rs | 92 +- components/script/stylesheet_loader.rs | 22 +- components/script/webdriver_handlers.rs | 6 +- components/script_traits/Cargo.toml | 7 +- components/script_traits/lib.rs | 11 +- components/webdriver_server/Cargo.toml | 11 +- components/webdriver_server/lib.rs | 463 +++++----- servo-tidy.toml | 6 +- tests/unit/metrics/paint_time.rs | 2 +- ...ntrol-expose-headers-parsing.window.js.ini | 1 - tests/wpt/metadata/cors/allow-headers.htm.ini | 15 + tests/wpt/metadata/cors/origin.htm.ini | 16 + .../wpt/metadata/cors/redirect-origin.htm.ini | 24 - .../metadata/cors/redirect-userinfo.htm.ini | 5 - .../wpt/metadata/cors/request-headers.htm.ini | 4 + tests/wpt/metadata/cors/status-async.htm.ini | 37 + .../metadata/cors/status-preflight.htm.ini | 7 + .../CSS2/backgrounds/background-043.xht.ini | 1 - .../CSS2/backgrounds/background-048.xht.ini | 4 +- .../cssom-view/elementFromPoint-001.html.ini | 1 + ...elementFromPoint-dynamic-anon-box.html.ini | 1 + .../format-mime-trailing-semicolon.htm.ini | 4 + .../fetch/api/abort/general.any.js.ini | 4 + .../api/cors/cors-cookies-redirect.any.js.ini | 4 - .../fetch/api/cors/cors-redirect.any.js.ini | 60 -- .../redirect-empty-location.any.js.ini | 6 - .../api/redirect/redirect-origin.any.js.ini | 33 - .../fetch/api/request/request-error.html.ini | 2 - .../api/response/response-consume.html.ini | 3 - .../fetch/data-urls/processing.any.js.ini | 84 +- .../fetch/nosniff/importscripts.html.ini | 5 + .../metadata/fetch/nosniff/script.html.ini | 4 + .../fetch/nosniff/stylesheet.html.ini | 6 + .../mime-types/canPlayType.html.ini | 46 +- .../update-the-source-set.html.ini | 3 + .../dynamic-imports-credentials.sub.html.ini | 4 + .../url/a-element-origin-xhtml.xhtml.ini | 3 - .../metadata/url/a-element-origin.html.ini | 4 - .../metadata/url/a-element-xhtml.xhtml.ini | 102 +-- tests/wpt/metadata/url/a-element.html.ini | 102 +-- tests/wpt/metadata/url/failure.html.ini | 115 ++- .../wpt/metadata/url/url-constructor.html.ini | 102 +-- tests/wpt/metadata/url/url-origin.html.ini | 2 +- tests/wpt/metadata/url/url-setters.html.ini | 162 +++- .../metadata/websockets/basic-auth.any.js.ini | 12 +- .../xhr/access-control-and-redirects.htm.ini | 5 - ...ess-control-origin-header-data-url.htm.ini | 5 - .../allow-lists-starting-with-comma.htm.ini | 4 + .../getresponseheader-chunked-trailer.htm.ini | 3 +- .../xhr/headers-normalize-response.htm.ini | 6 + .../xhr/overridemimetype-blob.html.ini | 42 + .../preserve-ua-header-on-redirect.htm.ini | 5 - .../xhr/responsexml-media-type.htm.ini | 4 + .../metadata/xhr/send-accept-language.htm.ini | 5 - .../xhr/send-content-type-charset.htm.ini | 12 - .../xhr/send-data-unexpected-tostring.htm.ini | 3 + .../xhr/send-redirect-no-location.htm.ini | 13 + ...setrequestheader-allow-empty-value.htm.ini | 11 - ...stheader-allow-whitespace-in-value.htm.ini | 14 - .../setrequestheader-case-insensitive.htm.ini | 3 + .../xhr/setrequestheader-content-type.htm.ini | 66 -- .../setrequestheader-header-allowed.htm.ini | 26 +- tests/wpt/metadata/xhr/status-async.htm.ini | 82 ++ tests/wpt/metadata/xhr/status-basic.htm.ini | 82 ++ tests/wpt/metadata/xhr/status-error.htm.ini | 13 + 122 files changed, 3829 insertions(+), 3442 deletions(-) create mode 100644 components/net_traits/quality.rs create mode 100644 tests/wpt/metadata/cors/origin.htm.ini delete mode 100644 tests/wpt/metadata/cors/redirect-userinfo.htm.ini create mode 100644 tests/wpt/metadata/cors/request-headers.htm.ini create mode 100644 tests/wpt/metadata/cors/status-async.htm.ini create mode 100644 tests/wpt/metadata/cors/status-preflight.htm.ini create mode 100644 tests/wpt/metadata/eventsource/format-mime-trailing-semicolon.htm.ini delete mode 100644 tests/wpt/metadata/fetch/api/redirect/redirect-origin.any.js.ini create mode 100644 tests/wpt/metadata/fetch/nosniff/importscripts.html.ini create mode 100644 tests/wpt/metadata/fetch/nosniff/script.html.ini create mode 100644 tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-credentials.sub.html.ini delete mode 100644 tests/wpt/metadata/xhr/access-control-and-redirects.htm.ini delete mode 100644 tests/wpt/metadata/xhr/access-control-basic-allow-access-control-origin-header-data-url.htm.ini create mode 100644 tests/wpt/metadata/xhr/allow-lists-starting-with-comma.htm.ini delete mode 100644 tests/wpt/metadata/xhr/preserve-ua-header-on-redirect.htm.ini create mode 100644 tests/wpt/metadata/xhr/responsexml-media-type.htm.ini delete mode 100644 tests/wpt/metadata/xhr/send-accept-language.htm.ini create mode 100644 tests/wpt/metadata/xhr/send-redirect-no-location.htm.ini delete mode 100644 tests/wpt/metadata/xhr/setrequestheader-allow-empty-value.htm.ini delete mode 100644 tests/wpt/metadata/xhr/setrequestheader-allow-whitespace-in-value.htm.ini create mode 100644 tests/wpt/metadata/xhr/status-async.htm.ini create mode 100644 tests/wpt/metadata/xhr/status-basic.htm.ini create mode 100644 tests/wpt/metadata/xhr/status-error.htm.ini diff --git a/Cargo.lock b/Cargo.lock index d785fe4ecff4..cabae5e8e811 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,7 +13,7 @@ dependencies = [ [[package]] name = "alloc-no-stdlib" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -68,6 +68,11 @@ dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" version = "0.4.6" @@ -132,7 +137,7 @@ dependencies = [ [[package]] name = "base64" -version = "0.6.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -173,11 +178,6 @@ dependencies = [ "which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "1.0.3" @@ -188,6 +188,15 @@ name = "block" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "block-buffer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bluetooth" version = "0.0.1" @@ -251,19 +260,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "brotli" -version = "1.1.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "brotli-decompressor 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "alloc-no-stdlib 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "brotli-decompressor 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "brotli-decompressor" -version = "1.1.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloc-no-stdlib 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -276,6 +285,11 @@ name = "byte-slice-cast" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byte-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.2.1" @@ -283,7 +297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -533,7 +547,7 @@ dependencies = [ "gaol 0.0.1 (git+https://github.com/servo/gaol)", "gfx 0.0.1", "gfx_traits 0.0.1", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "keyboard-types 0.4.2-servo (registry+https://github.com/rust-lang/crates.io-index)", "layout_traits 0.0.1", @@ -557,7 +571,7 @@ dependencies = [ [[package]] name = "cookie" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -639,6 +653,15 @@ dependencies = [ "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-deque" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-epoch" version = "0.3.1" @@ -653,6 +676,19 @@ dependencies = [ "scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-epoch" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-epoch" version = "0.6.0" @@ -688,7 +724,7 @@ dependencies = [ "dtoa-short 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -702,7 +738,7 @@ name = "cssparser-macros" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -754,7 +790,7 @@ version = "0.0.1" dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "servo_channel 0.0.1", - "ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -797,8 +833,11 @@ name = "devtools" version = "0.0.1" dependencies = [ "devtools_traits 0.0.1", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-core 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-ext 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -813,8 +852,7 @@ name = "devtools_traits" version = "0.0.1" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "malloc_size_of 0.0.1", "malloc_size_of_derive 0.0.1", @@ -824,6 +862,14 @@ dependencies = [ "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "digest" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dirs" version = "1.0.2" @@ -1014,6 +1060,11 @@ dependencies = [ "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fallible" version = "0.0.1" @@ -1097,6 +1148,20 @@ dependencies = [ "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "futures" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -1124,6 +1189,14 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "generic-array" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "getopts" version = "0.2.17" @@ -1452,6 +1525,23 @@ name = "gvr-sys" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "h2" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "half" version = "1.0.0" @@ -1475,6 +1565,41 @@ dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "headers-core" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "headers-derive" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "headers-ext" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-core 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-derive 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "heartbeats-simple" version = "0.4.0" @@ -1512,9 +1637,19 @@ dependencies = [ "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1527,40 +1662,56 @@ dependencies = [ [[package]] name = "hyper" -version = "0.10.13" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hyper-openssl" -version = "0.2.6" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-openssl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hyper_serde" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-ext 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1608,6 +1759,11 @@ dependencies = [ "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "indexmap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "inflate" version = "0.4.3" @@ -1618,10 +1774,16 @@ dependencies = [ [[package]] name = "influent" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1655,7 +1817,7 @@ dependencies = [ "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1743,11 +1905,6 @@ name = "khronos_api" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "layout" version = "0.0.1" @@ -1863,7 +2020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazycell" -version = "0.6.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1982,6 +2139,19 @@ dependencies = [ "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "linked-hash-map" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "linked_hash_set" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lock_api" version = "0.1.3" @@ -2033,8 +2203,8 @@ dependencies = [ "cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashglobe 0.1.0", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "keyboard-types 0.4.2-servo (registry+https://github.com/rust-lang/crates.io-index)", "mozjs 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "selectors 0.20.0", @@ -2047,7 +2217,7 @@ dependencies = [ "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_api 0.57.2 (git+https://github.com/servo/webrender)", "xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2075,8 +2245,8 @@ name = "markup5ever" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2146,21 +2316,21 @@ dependencies = [ [[package]] name = "mime" -version = "0.2.4" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mime_guess" -version = "1.8.1" +version = "2.0.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2194,14 +2364,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.15" +version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2210,6 +2380,27 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mio-extras" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio-uds" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "miow" version = "0.2.1" @@ -2288,15 +2479,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "net" version = "0.0.1" dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "brotli 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "brotli 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", "embedder_traits 0.0.1", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-openssl 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-core 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-ext 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-openssl 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "immeta 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2304,11 +2500,11 @@ dependencies = [ "malloc_size_of 0.0.1", "malloc_size_of_derive 0.0.1", "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", - "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)", "pixels 0.0.1", "profile_traits 0.0.1", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2321,11 +2517,13 @@ dependencies = [ "std_test_override 0.0.1", "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-openssl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_api 0.57.2 (git+https://github.com/servo/webrender)", - "ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2342,16 +2540,20 @@ dependencies = [ name = "net_traits" version = "0.0.1" dependencies = [ - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "embedder_traits 0.0.1", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-core 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-ext 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "malloc_size_of 0.0.1", "malloc_size_of_derive 0.0.1", + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "pixels 0.0.1", @@ -2360,7 +2562,7 @@ dependencies = [ "servo_config 0.0.1", "servo_url 0.0.1", "std_test_override 0.0.1", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_api 0.57.2 (git+https://github.com/servo/webrender)", ] @@ -2502,19 +2704,20 @@ dependencies = [ [[package]] name = "openssl" -version = "0.9.24" +version = "0.10.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-sys" -version = "0.9.27" +version = "0.9.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2612,37 +2815,37 @@ dependencies = [ [[package]] name = "phf" -version = "0.7.21" +version = "0.7.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_codegen" -version = "0.7.21" +version = "0.7.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_generator" -version = "0.7.21" +version = "0.7.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_shared" -version = "0.7.21" +version = "0.7.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2715,7 +2918,7 @@ name = "profile" version = "0.0.1" dependencies = [ "heartbeats-simple 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "influent 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "influent 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "jemalloc-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2727,6 +2930,7 @@ dependencies = [ "servo_config 0.0.1", "task_info 0.0.1", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2938,14 +3142,6 @@ name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc_version" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "safemem" version = "0.2.0" @@ -2975,7 +3171,7 @@ version = "0.0.1" dependencies = [ "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "bluetooth_traits 0.0.1", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2983,7 +3179,7 @@ dependencies = [ "caseless 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)", "deny_public_fields 0.0.1", "devtools_traits 0.0.1", @@ -2996,9 +3192,12 @@ dependencies = [ "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-core 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-ext 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3010,8 +3209,8 @@ dependencies = [ "malloc_size_of 0.0.1", "malloc_size_of_derive 0.0.1", "metrics 0.0.1", - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "mozjs 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3020,9 +3219,9 @@ dependencies = [ "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "offscreen_gl_context 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "pixels 0.0.1", "profile_traits 0.0.1", "ref_filter_map 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3051,7 +3250,7 @@ dependencies = [ "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_api 0.57.2 (git+https://github.com/servo/webrender)", @@ -3118,13 +3317,14 @@ version = "0.0.1" dependencies = [ "bluetooth_traits 0.0.1", "canvas_traits 0.0.1", - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", "embedder_traits 0.0.1", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "keyboard-types 0.4.2-servo (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3140,7 +3340,7 @@ dependencies = [ "servo_url 0.0.1", "style_traits 0.0.1", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_api 0.57.2 (git+https://github.com/servo/webrender)", "webvr_traits 0.0.1", ] @@ -3154,19 +3354,14 @@ dependencies = [ "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "servo_arc 0.1.1", "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "semver" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "serde" version = "1.0.66" @@ -3392,7 +3587,7 @@ dependencies = [ "servo_geometry 0.0.1", "servo_url 0.0.1", "std_test_override 0.0.1", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3442,14 +3637,25 @@ dependencies = [ "malloc_size_of_derive 0.0.1", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "servo_rand 0.0.1", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha-1" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sha1" -version = "0.2.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3480,11 +3686,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "size_of_test" version = "0.0.1" -[[package]] -name = "slab" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "slab" version = "0.4.1" @@ -3532,6 +3733,11 @@ dependencies = [ "embedder_traits 0.0.1", ] +[[package]] +name = "string" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "string_cache" version = "0.7.3" @@ -3539,7 +3745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3551,8 +3757,8 @@ name = "string_cache_codegen" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3702,6 +3908,16 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synstructure" version = "0.8.1" @@ -3813,17 +4029,170 @@ dependencies = [ ] [[package]] -name = "toml" -version = "0.4.5" +name = "tokio" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "traitobject" +name = "tokio-codec" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-executor" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-fs" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-io" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-openssl" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-timer" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-udp" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-uds" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "truetype" @@ -3831,8 +4200,13 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "typeable" -version = "0.1.2" +name = "try-lock" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "typenum" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3855,10 +4229,18 @@ dependencies = [ [[package]] name = "unicase" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3909,7 +4291,7 @@ dependencies = [ [[package]] name = "url" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3923,7 +4305,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3968,6 +4350,11 @@ name = "vec_map" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "void" version = "1.0.2" @@ -3982,6 +4369,16 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "want" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "wayland-client" version = "0.20.10" @@ -4034,27 +4431,33 @@ dependencies = [ [[package]] name = "webdriver" -version = "0.35.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webdriver_server" version = "0.0.1" dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "keyboard-types 0.4.2-servo (registry+https://github.com/rust-lang/crates.io-index)", @@ -4062,23 +4465,24 @@ dependencies = [ "msg 0.0.1", "net_traits 0.0.1", "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "script_traits 0.0.1", + "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "servo_channel 0.0.1", "servo_config 0.0.1", "servo_url 0.0.1", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webdriver 0.35.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webdriver 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webrender" version = "0.57.2" -source = "git+https://github.com/servo/webrender#923ee495bd9b0fda8a4a94c5a6cf42e2f0548731" +source = "git+https://github.com/servo/webrender#f0221fabc87c5b69a49689eeaa69bd5c380599f0" dependencies = [ "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4104,13 +4508,13 @@ dependencies = [ "thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_api 0.57.2 (git+https://github.com/servo/webrender)", - "ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webrender_api" version = "0.57.2" -source = "git+https://github.com/servo/webrender#923ee495bd9b0fda8a4a94c5a6cf42e2f0548731" +source = "git+https://github.com/servo/webrender#f0221fabc87c5b69a49689eeaa69bd5c380599f0" dependencies = [ "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4230,19 +4634,20 @@ dependencies = [ [[package]] name = "ws" -version = "0.7.3" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4329,7 +4734,7 @@ dependencies = [ [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0ba20154ea1f47ce2793322f049c5646cc6d0fa9759d5f333f286e507bf8080" -"checksum alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b21f6ad9c9957eb5d70c3dee16d31c092b3cab339628f821766b05e6833d72b8" +"checksum alloc-no-stdlib 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71877e174a5d78c969228d628c4f7f3b545d13452bd3d9393fa07aacfb7c6894" "checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" "checksum android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80b9e34fcbf29c0563547cb2ecce9b49504597cad6166769b1e4efb45c6c2951" "checksum android_log-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b8052e2d8aabbb8d556d6abbcce2a22b9590996c5f849b9c7ce4544a2e3b984e" @@ -4338,6 +4743,7 @@ dependencies = [ "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9dadc668390b373e73e4abbfc1f07238b09a25858f2f39c06cebc6d8e141d774" "checksum array-init 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3cc8456d0ae81a8c76f59e384683a601548c38949a4bfcb65dd31ded5c75ff3" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2" "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21" @@ -4345,24 +4751,25 @@ dependencies = [ "checksum azure 0.34.0 (git+https://github.com/servo/rust-azure)" = "" "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" -"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" +"checksum base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "85415d2594767338a74a30c1d370b2f3262ec1b4ed2d7bba5b3faf4de40467d9" "checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff" "checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0" "checksum bindgen 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eac4ed5f2de9efc3c87cb722468fa49d0763e98f999d539bfc5e452c13d85c91" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" "checksum blurdroid 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "19b23557dd27704797128f9db2816416bef20dad62d4a9768714eeb65f07d296" "checksum blurmac 0.1.0 (git+https://github.com/servo/devices)" = "" "checksum blurmock 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "68dd72da3a3bb40f3d3bdd366c4cf8e2b1d208c366304f382c80cef8126ca8da" "checksum blurz 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e73bda0f4c71c63a047351070097f3f507e6718e86b9ee525173371ef7b94b73" "checksum boxfnonce 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbec60c560f322d8e3cd403f91d8908cfd965fff53ba97154bd1b9d90149d98e" -"checksum brotli 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fe87b40996b84fdc56e57c165d93079f4b50cb806598118e692ddfaa3d3c57c0" -"checksum brotli-decompressor 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "313f4b6cc0b365d6b88eda5aa40175ee34ac6efa9a79e0b3b8202eca90247ba8" +"checksum brotli 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6236055e28bc092d6d370f3219e6939d8ba8352b397e290391bb8af0d94f25" +"checksum brotli-decompressor 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "471bf19486c9aaf5b817ed04c49ccc8acd8d28c70d5114e710e8b9f530df89cd" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byte-slice-cast 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28346c117b50270785fbc123bd6e4ecad20d0c6d5f43d081dc80a3abcc62be64" +"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" -"checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9" +"checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8" "checksum bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" "checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b" "checksum caseless 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "808dab3318747be122cb31d36de18d4d1c81277a76f8332a02b81a3d73463d7f" @@ -4381,7 +4788,7 @@ dependencies = [ "checksum cocoa 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cd1afb83b2de9c41e5dfedb2bcccb779d433b958404876009ae4b01746ff23" "checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d" "checksum combine 3.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54cedd8056314afe0d844a37a207007edf8a45f2cc452fd77629cd63c221740e" -"checksum cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "746858cae4eae40fff37e1998320068df317bc247dc91a67c6cfa053afdc2abb" +"checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf" "checksum core-foundation 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "58667b9a618a37ea8c4c4cb5298703e5dfadcd3698c79f54fc43e6a2e94733ea" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92801c908ea6301ae619ed842a72e01098085fc321b9c2f3f833dad555bba055" @@ -4390,7 +4797,9 @@ dependencies = [ "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crossbeam-channel 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a5716fadb87a5633db34c5e83ee6e036e6edc229f8a6bfb7c7c84ed340ba95df" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" +"checksum crossbeam-deque 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3486aefc4c0487b9cb52372c97df0a48b8c249514af1ee99703bf70d2f2ceda1" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" +"checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9" "checksum crossbeam-epoch 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c90f1474584f38e270b5b613e898c8c328aa4f3dea85e0a27ac2e642f009416" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" @@ -4402,6 +4811,7 @@ dependencies = [ "checksum dbus 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "acd824d45fad5ff0e178fcb3c040f13780e73f63a0a6d5cde59e7894f251ab0e" "checksum deflate 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebb02aaf4b775afc96684b8402510a338086974e38570a1f65bea8c202eb77a7" "checksum device 0.0.1 (git+https://github.com/servo/devices)" = "" +"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" "checksum dirs 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "37a76dd8b997af7107d0bb69d43903cf37153a18266f8b3fdb9911f28efb5444" "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" "checksum downcast-rs 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "18df8ce4470c189d18aa926022da57544f31e154631eb4cfe796aea97051fe6c" @@ -4421,6 +4831,7 @@ dependencies = [ "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70a2ebdf55fb9d6329046e026329a55ef8fbaae5ea833f56e170beb3125a8a5f" "checksum expat-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" @@ -4431,9 +4842,12 @@ dependencies = [ "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" +"checksum futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "884dbe32a6ae4cd7da5c6db9b78114449df9953b8d490c9d7e1b51720b922c62" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gaol 0.0.1 (git+https://github.com/servo/gaol)" = "" "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" +"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" "checksum gif 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3414b424657317e708489d2857d9575f4403698428b040b609b9d1c1a84a2c" "checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a" @@ -4457,23 +4871,29 @@ dependencies = [ "checksum gstreamer-video 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1f04816d7e183714830da26274f97e7aeff09ae6641058538d21443b4ec07d" "checksum gstreamer-video-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e2efb301a0b94fa4af503122faa04247085936dd888fd59fa4e21eab3cbd37" "checksum gvr-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1334b94d8ce67319ddc44663daef53d8c1538629a11562530c981dbd9085b9a" +"checksum h2 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a27e7ed946e8335bdf9a191bc1b9b14a03ba822d013d2f58437f4fabcbd7fc2c" "checksum half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63d68db75012a85555434ee079e7e6337931f87a087ab2988becbadf64673a7f" "checksum harfbuzz-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "87a29ce223fee4727c0c4810a1419a3412f65b29146339fb6a47ee39456c34ea" +"checksum headers-core 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7794c3bca3a5fb812a06d43f715cf857f7b037d52d6d8e054231d439dd839073" +"checksum headers-derive 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93b8509be5e3893b8c9c37805a05aa57e4561cf1f1a2aab30cec4931127f36ca" +"checksum headers-ext 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6657fda27978455d69652a0c817d5c73d6d3694d97027924477a1e1c66e33f61" "checksum heartbeats-simple 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad003ce233955e9d95f2c69cde84e68302ba9ba4a673d351c9bff93c738aadc" "checksum heartbeats-simple-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e1a408c0011427cc0e0049f7861c70377819aedfc006e8c901b1c70fd98fb1a4" "checksum histogram 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1bdcec4094c1ca961b685384ea7af76af5718230b3f34657d1a71fd2dcf4cc9d" "checksum html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b04478cf718862650a0bf66acaf8f2f8c906fbc703f35c916c1f4211b069a364" -"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d" +"checksum http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "24f58e8c2d8e886055c3ead7b28793e1455270b5fb39650984c224bc538ba581" +"checksum httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b6288d7db100340ca12873fd4d08ad1b8f206a9457798dfb17c018a33fee540" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" -"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" -"checksum hyper-openssl 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "85a372eb692590b3fe014c196c30f9f52d4c42f58cd49dd94caeee1593c9cc37" -"checksum hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0997ad463f64ce6ba02cf5af320622bb9782e4f8355b650a2cc7ccca69a7cc2e" +"checksum hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)" = "4aca412c241a2dd53af261efc7adf7736fdebd67dc0d1cc1ffdbcb9407e0e810" +"checksum hyper-openssl 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddca42b55aaf1755b417d286d5eaa1f435cd626b53ffbb53bb9cef4d8819ac86" +"checksum hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af6cd576f3bf6d7dabc34828c16a08c99e71dca01c87e4a5d754c6ea3995f3d9" "checksum ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9826188e666f2ed92071d2dadef6edc430b11b158b5b2b3f4babbcc891eaaa" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebdff791af04e30089bde8ad2a632b86af433b40c04db8d70ad4b21487db7a6a" "checksum immeta 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7371aa3c98fad60de2d9b517e2e1ed45593c32b0c77249310fa507749a2a318b" +"checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220" "checksum inflate 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6f53b811ee8e2057ccf9643ca6b4277de90efaf5e61e55fd5254576926bb4245" -"checksum influent 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9bc265d6f1f53ae16fd3c18cc737c8c91ec1381afc6a15bee35fecd16a83070e" +"checksum influent 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f06f65fa332019cbf57b927cd5a5da53cfce506109f38312fd597745a8a48c0" "checksum io-surface 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9a33981dff54baaff80f4decb487a65d148a3c00facc97820d0f09128f74dd" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd75debad4ffd295c00c6e3634d254df30050b0837a85e5cd039ac424365f24a" @@ -4486,15 +4906,16 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum keyboard-types 0.4.2-servo (registry+https://github.com/rust-lang/crates.io-index)" = "75082c134a78e0fc2232d2f30bf3dfdea1cd28591846b85a73b4b46cd776b482" "checksum khronos_api 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ef23fcc4059260c5936f638c9805ebfc87cb172fa6661d130cba7f97d58f55" -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" +"checksum lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d33a48d0365c96081958cc663eef834975cb1e8d8bea3378513fc72bdbf11e50" "checksum leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73" "checksum leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40a8225d44241fd324a8af2806ba635fc7c8a7e9a7de4d5cf3ef54e71f5926fc" "checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" "checksum libdbus-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8720f9274907052cb50313f91201597868da9d625f8dd125f2aca5bddb7e83a1" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" +"checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" +"checksum linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7c91c4c7bbeb4f2f7c4e5be11e6a05bd6830bc37249c47ce1ad86ad453ff9c" "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" @@ -4506,12 +4927,14 @@ dependencies = [ "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d69889cdc6336ed56b174514ce876c4c3dc564cc23dd872e7bca589bb2a36c8" -"checksum mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76da6df85047af8c0edfa53f48eb1073012ce1cc95c8fedc0a374f659a89dd65" +"checksum mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "0a907b83e7b9e987032439a387e187119cddafc92d5c2aaeb1d92580a793f630" +"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" "checksum miniz_oxide 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba430291c9d6cedae28bcd2d49d1c32fc57d60cd49086646c5dd5673a870eb5" "checksum miniz_oxide_c_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5a5b8234d6103ebfba71e29786da4608540f862de5ce980a1c94f86a40ca0d51" -"checksum mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4fcfcb32d63961fb6f367bfd5d21e4600b92cd310f71f9dca25acae196eb1560" +"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" +"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f" "checksum mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "45a8a18a41cfab0fde25cc2f43ea89064d211a0fbb33225b8ff93ab20406e0e7" @@ -4535,8 +4958,8 @@ dependencies = [ "checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" "checksum objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4730aa1c64d722db45f7ccc4113a3e2c465d018de6db4d3e7dfe031e8c8a297" "checksum offscreen_gl_context 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95f2e39e3b8c95495cfec835b6fefee3f1e7d63c6f81d99796b4f9926c02db3c" -"checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" -"checksum openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdc5c4a02e69ce65046f1763a0181107038e02176233acb0b3351d7cc588f9" +"checksum openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6c24d3508b4fb6da175c10baac54c578b33f09c89ae90c6fe9788b3b4768efdc" +"checksum openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)" = "912f301a749394e1025d9dcddef6106ddee9252620e6d0a0e5f8d0681de9b129" "checksum ordered-float 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9a3c8db0fca1fdb34404f0b1286db252f23930b9f7a481e376c16c0d5c309d4" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum osmesa-src 0.1.0 (git+https://github.com/servo/osmesa-src)" = "" @@ -4549,10 +4972,10 @@ dependencies = [ "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" -"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" -"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" -"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" -"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" +"checksum phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "cec29da322b242f4c3098852c77a0ca261c9c01b806cae85a5572a1eb94db9a6" +"checksum phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "7d187f00cd98d5afbcd8898f6cf181743a449162aeb329dcd2f3849009e605ad" +"checksum phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "03dc191feb9b08b0dc1330d6549b795b9d81aec19efe6b4a45aec8d4caee0c4b" +"checksum phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "b539898d22d4273ded07f64a05737649dc69095d92cb87c7097ec68e3f150b93" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum plane-split 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d252db71f3d2109c4936e87d9f29f3c737e89f9ac239999d78866bdd60b9deda" "checksum png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f54b9600d584d3b8a739e1662a595fab051329eff43f20e7d8cc22872962145b" @@ -4582,12 +5005,10 @@ dependencies = [ "checksum rust-webvr-api 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "712e22ba3c03a7075b40842ae91029a0ab96a81f95e97c0cf623800ec0cbac07" "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" "checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a" "checksum scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c79eb2c3ac4bc2507cda80e7f3ac5b88bd8eae4c0914d5663e6a8933994be918" -"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "e9a2d9a9ac5120e0f768801ca2b58ad6eec929dc9d1d616c162f208869c2ce95" "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" "checksum serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "0a90213fa7e0f5eac3f7afe2d5ff6b088af515052cc7303bd68c7e3b91a3fb79" @@ -4602,17 +5023,18 @@ dependencies = [ "checksum servo-media-player 0.1.0 (git+https://github.com/servo/media)" = "" "checksum servo-skia 0.30000019.1 (registry+https://github.com/rust-lang/crates.io-index)" = "82eddddcf9512dd7c60eccdb486e60e5bd4930afaa4da2d7d4afdff75950fb88" "checksum servo_media_derive 0.1.0 (git+https://github.com/servo/media)" = "" -"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" +"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded" +"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8254bf098ce4d8d7cc7cc6de438c5488adc5297e5b7ffef88816c0a91bd289c1" "checksum sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c6649e43c1a1e68d29ed56d0dc3b5b6cf3b901da77cf107c4066b9e3da036df5" "checksum signpost 0.1.0 (git+https://github.com/pcwalton/signpost.git)" = "" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" -"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" "checksum smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c63726029f0069f88467873e47f392575f28f9f16b72ac65465263db4b3a13c" "checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8" "checksum smithay-client-toolkit 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2051bffc6cbf271176e8ba1527f801b6444567daee15951ff5152aaaf7777b2f" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" +"checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" "checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" @@ -4620,6 +5042,7 @@ dependencies = [ "checksum swapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e454d048db5527d000bfddb77bd072bbf3a1e2ae785f16d9bd116e07c2ab45eb" "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" "checksum syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c67da57e61ebc7b7b6fff56bb34440ca3a83db037320b0507af4c10368deda7d" +"checksum syn 0.15.6 (registry+https://github.com/rust-lang/crates.io-index)" = "854b08a640fc8f54728fb95321e3ec485b365a97fe47609797c671addd1dde69" "checksum synstructure 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "98cad891cd238c98e1f0aec9f7c0f620aa696e4e5f7daba56ac67b5e86a6b049" "checksum tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47776f63b85777d984a50ce49d6b9e58826b6a3766a449fc95bc66cd5663c15b" "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" @@ -4632,14 +5055,28 @@ dependencies = [ "checksum threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59f6d3eff89920113dac9db44dde461d71d01e88a5b57b258a0466c32b5d7fe1" "checksum time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd7ccbf969a892bf83f1e441126968a07a3941c24ff522a26af9f9f4585d1a3" "checksum tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d79833ca2c493c726ea6a7b651ba0ff8a790add5156cd11bf3743f346005c0c8" +"checksum tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fbb6a6e9db2702097bfdfddcb09841211ad423b86c75b5ddaca1d62842ac492c" +"checksum tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "881e9645b81c2ce95fcb799ded2c29ffb9f25ef5bef909089a420e5961dd8ccb" +"checksum tokio-current-thread 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fdfb899688ac16f618076bd09215edbfda0fd5dfecb375b6942636cb31fa8a7" +"checksum tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "84823b932d566bc3c6aa644df4ca36cb38593c50b7db06011fd4e12e31e4047e" +"checksum tokio-fs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5cbe4ca6e71cb0b62a66e4e6f53a8c06a6eefe46cc5f665ad6f274c9906f135" +"checksum tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6cc2de7725863c86ac71b0b9068476fec50834f055a243558ef1655bbd34cb" +"checksum tokio-openssl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4646ae1fd623393de3d796ea53af75acd02938dd5579544fbd6d236d041978a6" +"checksum tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8703a5762ff6913510dc64272c714c4389ffd8c4b3cf602879b8bd14ff06b604" +"checksum tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5b4c329b47f071eb8a746040465fa751bd95e4716e98daef6a9b4e434c17d565" +"checksum tokio-threadpool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a5758cecb6e0633cea5d563ac07c975e04961690b946b04fd84e7d6445a8f6af" +"checksum tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d03fa701f9578a01b7014f106b47f0a363b4727a7f3f75d666e312ab7acbbf1c" +"checksum tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da941144b816d0dcda4db3a1ba87596e4df5e860a72b70783fe435891f80601c" +"checksum tokio-uds 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "424c1ed15a0132251813ccea50640b224c809d6ceafb88154c1a8775873a0e89" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" -"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec30350633d6dac9dc1a625786b6cbe9150664be941aac2c35ad7199eab877" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe4fa6e588762366f1eb4991ce59ad1b93651d0b769dfb4e4d1c5c4b943d1159" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum uluru 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2606e9192f308ddc4f0b3c5d1bf3400e28a70fff956e9d9f46d23b094746d9f" -"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" +"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +"checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" "checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" "checksum unicode-script 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e8bd7bbf020b2885113e6304f68bcc33881c5552657c58d4e9699cd1b6606e81" @@ -4647,7 +5084,7 @@ dependencies = [ "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum url 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23ef1b2df9b1541244318407f1ed96e754dab6efac4121dc1c4c16d38daf215e" +"checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" "checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" "checksum utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f923c601c7ac48ef1d66f7d5b5b2d9a7ba9c51333ab75a3ddf8d0309185a56" @@ -4655,14 +5092,16 @@ dependencies = [ "checksum uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4670e1e935f7edd193a413f802e2ee52274aed62a09ccaab1656515c9c53a66" "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" +"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369" +"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" "checksum wayland-client 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0f3ed65542a0be13ea0fdcc55c9a011fcc44c3882e6e1a9b4dfddb25182897dd" "checksum wayland-commons 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac5c79f1d050f4047a82ddce77acda026c142c0023e7b7e20eea5ad76fb7dbf" "checksum wayland-protocols 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)" = "be56e3d80559177a70bc78f9396fbe1705b7baed4951ae6e34d28bb59681b1a8" "checksum wayland-scanner 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)" = "93cf4ef48caedf3fc1a9b2bf0df64e6d425bd628b85830a08432dd25b61de17c" "checksum wayland-sys 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d2dbe7b51c16b8a8153806aaa21f346333074482bb57bc5cb059cc828f8c6842" -"checksum webdriver 0.35.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c6d14048509ec30805ee10b9d610d3d1987e560f5d3be5c599c2c812a34bbfe" +"checksum webdriver 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)" = "426afe4e337c88343569b65ed0d84c44655c1d66c5570f3e50da98b64c38298f" "checksum webrender 0.57.2 (git+https://github.com/servo/webrender)" = "" "checksum webrender_api 0.57.2 (git+https://github.com/servo/webrender)" = "" "checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb" @@ -4674,7 +5113,7 @@ dependencies = [ "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" "checksum winit 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51fe58cceab36bef11fcb57d0a86f4cdf0c8668ad51fdbc6d48efa6b2db0cddd" "checksum winres 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "27d9192d6356d7efe8405dec6c5506b67543cf64b6049968f39f4c4623b4f25d" -"checksum ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "89c48c53bf9dee34411a08993c10b879c36e105d609b46e25673befe3a5c1320" +"checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum x11 2.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5c4ac579b5d324dc4add02312b5d0e3e0218521e2d5779d526ac39ee4bb171" "checksum x11-clipboard 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d8617c6185c96e5fcf57ff156496d73c9c82b7f09a5fea21b518dd32c10e2e05" diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml index 7c1ee6b99af1..a036f0036d21 100644 --- a/components/constellation/Cargo.toml +++ b/components/constellation/Cargo.toml @@ -22,7 +22,7 @@ euclid = "0.19" embedder_traits = { path = "../embedder_traits" } gfx = {path = "../gfx"} gfx_traits = {path = "../gfx_traits"} -hyper = "0.10" +http = "0.1" ipc-channel = "0.11" layout_traits = {path = "../layout_traits"} keyboard-types = {version = "0.4.2-servo", features = ["serde"]} diff --git a/components/constellation/lib.rs b/components/constellation/lib.rs index f5e23ba3c097..57b59960eb38 100644 --- a/components/constellation/lib.rs +++ b/components/constellation/lib.rs @@ -20,7 +20,7 @@ extern crate euclid; extern crate gaol; extern crate gfx; extern crate gfx_traits; -extern crate hyper; +extern crate http; extern crate ipc_channel; extern crate keyboard_types; extern crate layout_traits; diff --git a/components/constellation/network_listener.rs b/components/constellation/network_listener.rs index 3f58d029acf8..457a2021cede 100644 --- a/components/constellation/network_listener.rs +++ b/components/constellation/network_listener.rs @@ -6,7 +6,7 @@ //! Any redirects that are encountered are followed. Whenever a non-redirect //! response is received, it is forwarded to the appropriate script thread. -use hyper::header::Location; +use http::header::LOCATION; use ipc_channel::ipc; use ipc_channel::router::ROUTER; use msg::constellation_msg::PipelineId; @@ -99,7 +99,7 @@ impl NetworkListener { }; match metadata.headers { - Some(ref headers) if headers.has::() => { + Some(ref headers) if headers.contains_key(LOCATION) => { if self.req_init.url_list.is_empty() { self.req_init.url_list.push(self.req_init.url.clone()); } diff --git a/components/devtools/Cargo.toml b/components/devtools/Cargo.toml index 1bcbc1290b20..ba0b4d172c68 100644 --- a/components/devtools/Cargo.toml +++ b/components/devtools/Cargo.toml @@ -11,8 +11,11 @@ path = "lib.rs" [dependencies] devtools_traits = {path = "../devtools_traits"} -hyper = "0.10" -hyper_serde = "0.8" +headers-core = "0.0.1" +headers-ext = "0.0.3" +http = "0.1" +hyper = "0.12" +hyper_serde = "0.9" ipc-channel = "0.11" log = "0.4" msg = {path = "../msg"} diff --git a/components/devtools/actors/network_event.rs b/components/devtools/actors/network_event.rs index 5e4fe01bcf32..8bc3cf9850aa 100644 --- a/components/devtools/actors/network_event.rs +++ b/components/devtools/actors/network_event.rs @@ -9,13 +9,12 @@ use actor::{Actor, ActorMessageStatus, ActorRegistry}; use devtools_traits::HttpRequest as DevtoolsHttpRequest; use devtools_traits::HttpResponse as DevtoolsHttpResponse; -use hyper::header::{ContentType, Cookie}; -use hyper::header::Headers; -use hyper::http::RawStatus; -use hyper::method::Method; +use headers_core::HeaderMapExt; +use headers_ext::{ContentType, Cookie}; +use http::{header, HeaderMap}; +use hyper::{Method, StatusCode}; use protocol::JsonPacketStream; use serde_json::{Map, Value}; -use std::borrow::Cow; use std::net::TcpStream; use time; use time::Tm; @@ -23,7 +22,7 @@ use time::Tm; struct HttpRequest { url: String, method: Method, - headers: Headers, + headers: HeaderMap, body: Option>, startedDateTime: Tm, timeStamp: i64, @@ -32,9 +31,9 @@ struct HttpRequest { } struct HttpResponse { - headers: Option, - status: Option, - body: Option>, + headers: Option, + status: Option<(StatusCode, String)>, + body: Option> } pub struct NetworkEventActor { @@ -189,15 +188,11 @@ impl Actor for NetworkEventActor { let mut headers = Vec::new(); let mut rawHeadersString = "".to_owned(); let mut headersSize = 0; - for item in self.request.headers.iter() { - let name = item.name(); - let value = item.value_string(); - rawHeadersString = rawHeadersString + name + ":" + &value + "\r\n"; - headersSize += name.len() + value.len(); - headers.push(Header { - name: name.to_owned(), - value: value.to_owned(), - }); + for (name, value) in self.request.headers.iter() { + let value = &value.to_str().unwrap().to_string(); + rawHeadersString = rawHeadersString + name.as_str() + ":" + &value + "\r\n"; + headersSize += name.as_str().len() + value.len(); + headers.push(Header { name: name.as_str().to_owned(), value: value.to_owned() }); } let msg = GetRequestHeadersReply { from: self.name(), @@ -210,11 +205,10 @@ impl Actor for NetworkEventActor { }, "getRequestCookies" => { let mut cookies = Vec::new(); - if let Some(req_cookies) = self.request.headers.get_raw("Cookie") { - for cookie in &*req_cookies { - if let Ok(cookie_value) = String::from_utf8(cookie.clone()) { - cookies = cookie_value.into_bytes(); - } + + for cookie in self.request.headers.get_all(header::COOKIE) { + if let Ok(cookie_value) = String::from_utf8(cookie.as_bytes().to_vec()) { + cookies = cookie_value.into_bytes(); } } @@ -239,17 +233,15 @@ impl Actor for NetworkEventActor { let mut headers = vec![]; let mut rawHeadersString = "".to_owned(); let mut headersSize = 0; - for item in response_headers.iter() { - let name = item.name(); - let value = item.value_string(); + for (name, value) in response_headers.iter() { headers.push(Header { - name: name.to_owned(), - value: value.clone(), + name: name.as_str().to_owned(), + value: value.to_str().unwrap().to_owned(), }); - headersSize += name.len() + value.len(); - rawHeadersString.push_str(name); + headersSize += name.as_str().len() + value.len(); + rawHeadersString.push_str(name.as_str()); rawHeadersString.push_str(":"); - rawHeadersString.push_str(&value); + rawHeadersString.push_str(value.to_str().unwrap()); rawHeadersString.push_str("\r\n"); } let msg = GetResponseHeadersReply { @@ -264,11 +256,10 @@ impl Actor for NetworkEventActor { }, "getResponseCookies" => { let mut cookies = Vec::new(); - if let Some(res_cookies) = self.request.headers.get_raw("set-cookie") { - for cookie in &*res_cookies { - if let Ok(cookie_value) = String::from_utf8(cookie.clone()) { - cookies = cookie_value.into_bytes(); - } + // TODO: This seems quite broken + for cookie in self.request.headers.get_all(header::SET_COOKIE) { + if let Ok(cookie_value) = String::from_utf8(cookie.as_bytes().to_vec()) { + cookies = cookie_value.into_bytes(); } } @@ -330,8 +321,8 @@ impl NetworkEventActor { name: name, request: HttpRequest { url: String::new(), - method: Method::Get, - headers: Headers::new(), + method: Method::GET, + headers: HeaderMap::new(), body: None, startedDateTime: time::now(), timeStamp: time::get_time().sec, @@ -363,7 +354,7 @@ impl NetworkEventActor { self.response.headers = response.headers.clone(); self.response.status = response.status.as_ref().map(|&(s, ref st)| { let status_text = String::from_utf8_lossy(st).into_owned(); - RawStatus(s, Cow::from(status_text)) + (StatusCode::from_u16(s).unwrap(), status_text) }); self.response.body = response.body.clone(); } @@ -385,13 +376,8 @@ impl NetworkEventActor { // TODO: Send the correct values for all these fields. let hSizeOption = self.response.headers.as_ref().map(|headers| headers.len()); let hSize = hSizeOption.unwrap_or(0); - let (status_code, status_message) = self - .response - .status - .as_ref() - .map_or((0, "".to_owned()), |&RawStatus(ref code, ref text)| { - (*code, text.clone().into_owned()) - }); + let (status_code, status_message) = self.response.status.as_ref() + .map_or((0, "".to_owned()), |(code, text)| (code.as_u16(), text.clone())); // TODO: Send the correct values for remoteAddress and remotePort and http_version. ResponseStartMsg { httpVersion: "HTTP/1.1".to_owned(), @@ -407,9 +393,9 @@ impl NetworkEventActor { pub fn response_content(&self) -> ResponseContentMsg { let mut mString = "".to_owned(); if let Some(ref headers) = self.response.headers { - mString = match headers.get() { - Some(&ContentType(ref mime)) => mime.to_string(), - None => "".to_owned(), + mString = match headers.typed_get::() { + Some(ct) => ct.to_string(), + _ => "".to_owned() }; } // TODO: Set correct values when response's body is sent to the devtools in http_loader. @@ -424,9 +410,9 @@ impl NetworkEventActor { pub fn response_cookies(&self) -> ResponseCookiesMsg { let mut cookies_size = 0; if let Some(ref headers) = self.response.headers { - cookies_size = match headers.get() { - Some(&Cookie(ref cookie)) => cookie.len(), - None => 0, + cookies_size = match headers.typed_get::() { + Some(ref cookie) => cookie.len(), + _ => 0, }; } ResponseCookiesMsg { @@ -439,8 +425,8 @@ impl NetworkEventActor { let mut headers_byte_count = 0; if let Some(ref headers) = self.response.headers { headers_size = headers.len(); - for item in headers.iter() { - headers_byte_count += item.name().len() + item.value_string().len(); + for (name, value) in headers.iter() { + headers_byte_count += name.as_str().len() + value.len(); } } ResponseHeadersMsg { @@ -450,11 +436,10 @@ impl NetworkEventActor { } pub fn request_headers(&self) -> RequestHeadersMsg { - let size = self - .request - .headers - .iter() - .fold(0, |acc, h| acc + h.name().len() + h.value_string().len()); + let size = self.request + .headers + .iter() + .fold(0, |acc, (name, value)| acc + name.as_str().len() + value.len()); RequestHeadersMsg { headers: self.request.headers.len(), headersSize: size, @@ -462,9 +447,9 @@ impl NetworkEventActor { } pub fn request_cookies(&self) -> RequestCookiesMsg { - let cookies_size = match self.request.headers.get() { - Some(&Cookie(ref cookie)) => cookie.len(), - None => 0, + let cookies_size = match self.request.headers.typed_get::() { + Some(ref cookie) => cookie.len(), + _ => 0 }; RequestCookiesMsg { cookies: cookies_size, diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs index 547f96bc4457..9541d553de38 100644 --- a/components/devtools/lib.rs +++ b/components/devtools/lib.rs @@ -13,6 +13,9 @@ #![deny(unsafe_code)] extern crate devtools_traits; +extern crate headers_core; +extern crate headers_ext; +extern crate http; extern crate hyper; extern crate ipc_channel; #[macro_use] diff --git a/components/devtools_traits/Cargo.toml b/components/devtools_traits/Cargo.toml index 34359dadf41f..26769dfba3dd 100644 --- a/components/devtools_traits/Cargo.toml +++ b/components/devtools_traits/Cargo.toml @@ -11,8 +11,7 @@ path = "lib.rs" [dependencies] bitflags = "1.0" -hyper = "0.10" -hyper_serde = "0.8" +http = "0.1" ipc-channel = "0.11" malloc_size_of = { path = "../malloc_size_of" } malloc_size_of_derive = { path = "../malloc_size_of_derive" } diff --git a/components/devtools_traits/lib.rs b/components/devtools_traits/lib.rs index 764af5da0a27..9d95adb3d26c 100644 --- a/components/devtools_traits/lib.rs +++ b/components/devtools_traits/lib.rs @@ -13,7 +13,7 @@ #[macro_use] extern crate bitflags; -extern crate hyper; +extern crate http; extern crate ipc_channel; extern crate malloc_size_of; #[macro_use] @@ -24,8 +24,8 @@ extern crate serde; extern crate servo_url; extern crate time; -use hyper::header::Headers; -use hyper::method::Method; +use http::HeaderMap; +use http::method::Method; use ipc_channel::ipc::IpcSender; use msg::constellation_msg::PipelineId; use servo_url::ServoUrl; @@ -301,7 +301,7 @@ pub enum CachedConsoleMessage { pub struct HttpRequest { pub url: ServoUrl, pub method: Method, - pub headers: Headers, + pub headers: HeaderMap, pub body: Option>, pub pipeline_id: PipelineId, pub startedDateTime: Tm, @@ -313,7 +313,7 @@ pub struct HttpRequest { #[derive(Debug, PartialEq)] pub struct HttpResponse { - pub headers: Option, + pub headers: Option, pub status: Option<(u16, Vec)>, pub body: Option>, pub pipeline_id: PipelineId, diff --git a/components/malloc_size_of/Cargo.toml b/components/malloc_size_of/Cargo.toml index 04df21fd628b..fff432e3fbcb 100644 --- a/components/malloc_size_of/Cargo.toml +++ b/components/malloc_size_of/Cargo.toml @@ -29,8 +29,8 @@ app_units = "0.7" cssparser = "0.24.0" euclid = "0.19" hashglobe = { path = "../hashglobe" } -hyper = { version = "0.10", optional = true } -hyper_serde = { version = "0.8", optional = true } +hyper = { version = "0.12", optional = true } +hyper_serde = { version = "0.9", optional = true } keyboard-types = {version = "0.4.2-servo", features = ["serde"], optional = true} mozjs = { version = "0.9.3", optional = true } selectors = { path = "../selectors" } diff --git a/components/malloc_size_of/lib.rs b/components/malloc_size_of/lib.rs index 52b8412f64e9..e0f638a843d2 100644 --- a/components/malloc_size_of/lib.rs +++ b/components/malloc_size_of/lib.rs @@ -977,48 +977,6 @@ impl MallocSizeOf for xml5ever::QualName { } } -#[cfg(feature = "servo")] -impl MallocSizeOf for hyper::header::Headers { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.iter().fold(0, |acc, x| { - let name = x.name(); - let raw = self.get_raw(name); - acc + raw.size_of(ops) - }) - } -} - -#[cfg(feature = "servo")] -impl MallocSizeOf for hyper::header::ContentType { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.0.size_of(ops) - } -} - -#[cfg(feature = "servo")] -impl MallocSizeOf for hyper::mime::Mime { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops) - } -} - -#[cfg(feature = "servo")] -impl MallocSizeOf for hyper::mime::Attr { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - match *self { - hyper::mime::Attr::Ext(ref s) => s.size_of(ops), - _ => 0, - } - } -} - -#[cfg(feature = "servo")] -impl MallocSizeOf for hyper::mime::Value { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { - self.len() // Length of string value in bytes (not the char length of a string)! - } -} - #[cfg(feature = "servo")] malloc_size_of_is_0!(time::Duration); #[cfg(feature = "servo")] @@ -1046,12 +1004,9 @@ impl MallocSizeOf for servo_channel::Sender { } #[cfg(feature = "servo")] -impl MallocSizeOf for hyper::status::StatusCode { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - match *self { - hyper::status::StatusCode::Unregistered(u) => u.size_of(ops), - _ => 0, - } +impl MallocSizeOf for hyper::StatusCode { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + 0 } } diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index 402044c1ecd0..099f2c17f71a 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -13,15 +13,19 @@ test = false doctest = false [dependencies] -base64 = "0.6" -brotli = "1.0.6" -cookie = "0.10" +base64 = "0.9" +brotli = "2.5" +bytes = "0.4" +cookie = "0.11" devtools_traits = {path = "../devtools_traits"} embedder_traits = { path = "../embedder_traits" } flate2 = "1" -hyper = "0.10" -hyper_serde = "0.8" -hyper-openssl = "0.2.2" +headers-core = "0.0.1" +headers-ext = "0.0.3" +http = "0.1" +hyper = "0.12" +hyper_serde = "0.9" +hyper-openssl = "0.6" immeta = "0.4" ipc-channel = "0.11" lazy_static = "1" @@ -29,11 +33,11 @@ log = "0.4" malloc_size_of = { path = "../malloc_size_of" } malloc_size_of_derive = { path = "../malloc_size_of_derive" } matches = "0.1" -mime = "0.2.1" -mime_guess = "1.8.0" +mime = "0.3" +mime_guess = "2.0.0-alpha.6" msg = {path = "../msg"} net_traits = {path = "../net_traits"} -openssl = "0.9" +openssl = "0.10" pixels = {path = "../pixels"} profile_traits = {path = "../profile_traits"} serde = "1.0" @@ -43,9 +47,10 @@ servo_arc = {path = "../servo_arc"} servo_channel = {path = "../channel"} servo_config = {path = "../config"} servo_url = {path = "../url"} +tokio = "0.1" +tokio-timer = "0.2" threadpool = "1.0" time = "0.1.17" -unicase = "1.4.0" url = "1.2" uuid = {version = "0.6", features = ["v4"]} webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} @@ -53,6 +58,8 @@ ws = { version = "0.7", features = ["ssl"] } [dev-dependencies] std_test_override = { path = "../std_test_override" } +futures = "0.1" +tokio-openssl = "0.2" [[test]] name = "main" diff --git a/components/net/blob_loader.rs b/components/net/blob_loader.rs index 1fe05cc1c20b..3af4d531549e 100644 --- a/components/net/blob_loader.rs +++ b/components/net/blob_loader.rs @@ -3,11 +3,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use filemanager_thread::FileManager; -use hyper::header::{Charset, ContentLength, ContentType, Headers}; -use hyper::header::{ContentDisposition, DispositionParam, DispositionType}; +use headers_core::HeaderMapExt; +use headers_ext::{ContentLength, ContentType}; +use http::HeaderMap; +use http::header::{self, HeaderValue}; use ipc_channel::ipc; -use mime::{Attr, Mime}; -use net_traits::NetworkError; +use mime::{self, Mime}; +use net_traits::{http_percent_encode, NetworkError}; use net_traits::blob_url_store::parse_blob_url; use net_traits::filemanager_thread::ReadFileProgress; use servo_url::ServoUrl; @@ -20,7 +22,7 @@ use servo_url::ServoUrl; pub fn load_blob_sync (url: ServoUrl, filemanager: FileManager) - -> Result<(Headers, Vec), NetworkError> { + -> Result<(HeaderMap, Vec), NetworkError> { let (id, origin) = match parse_blob_url(&url) { Ok((id, origin)) => (id, origin), Err(()) => { @@ -43,26 +45,32 @@ pub fn load_blob_sync } }; - let content_type: Mime = blob_buf.type_string.parse().unwrap_or(mime!(Text / Plain)); - let charset = content_type.get_param(Attr::Charset); + let content_type: Mime = blob_buf.type_string.parse().unwrap_or(mime::TEXT_PLAIN); + let charset = content_type.get_param(mime::CHARSET); - let mut headers = Headers::new(); + let mut headers = HeaderMap::new(); if let Some(name) = blob_buf.filename { - let charset = charset.and_then(|c| c.as_str().parse().ok()); - headers.set(ContentDisposition { - disposition: DispositionType::Inline, - parameters: vec![ - DispositionParam::Filename(charset.unwrap_or(Charset::Us_Ascii), - None, name.as_bytes().to_vec()) - ] - }); + let charset = charset.map(|c| c.as_ref().into()).unwrap_or("us-ascii".to_owned()); + // TODO(eijebong): Replace this once the typed header is there + headers.insert( + header::CONTENT_DISPOSITION, + HeaderValue::from_bytes( + format!("inline; {}", + if charset.to_lowercase() == "utf-8" { + format!("filename=\"{}\"", String::from_utf8(name.as_bytes().into()).unwrap()) + } else { + format!("filename*=\"{}\"''{}", charset, http_percent_encode(name.as_bytes())) + } + ).as_bytes() + ).unwrap() + ); } // Basic fetch, Step 4. - headers.set(ContentLength(blob_buf.size as u64)); + headers.typed_insert(ContentLength(blob_buf.size as u64)); // Basic fetch, Step 5. - headers.set(ContentType(content_type.clone())); + headers.typed_insert(ContentType::from(content_type.clone())); let mut bytes = blob_buf.bytes; loop { diff --git a/components/net/connector.rs b/components/net/connector.rs index 03ee7e5459d3..0311b05b1256 100644 --- a/components/net/connector.rs +++ b/components/net/connector.rs @@ -2,60 +2,132 @@ * 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/. */ +use flate2::read::GzDecoder; use hosts::replace_host; -use hyper::client::Pool; -use hyper::error::{Result as HyperResult, Error as HyperError}; -use hyper::net::{NetworkConnector, HttpsStream, HttpStream, SslClient}; -use hyper_openssl::OpensslClient; -use openssl::ssl::{SSL_OP_NO_COMPRESSION, SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3}; -use openssl::ssl::{SslConnector, SslConnectorBuilder, SslMethod}; +use http_loader::Decoder; +use hyper::{Body, Client}; +use hyper::body::Payload; +use hyper::client::HttpConnector as HyperHttpConnector; +use hyper::client::connect::{Connect, Destination}; +use hyper::rt::Future; +use hyper_openssl::HttpsConnector; +use openssl::ssl::{SslConnector, SslConnectorBuilder, SslMethod, SslOptions}; use openssl::x509; -use std::io; -use std::net::TcpStream; +use std::io::{Cursor, Read}; +use tokio::prelude::{Async, Stream}; +use tokio::prelude::future::Executor; -pub struct HttpsConnector { - ssl: OpensslClient, +pub const BUF_SIZE: usize = 32768; + +pub struct HttpConnector { + inner: HyperHttpConnector } -impl HttpsConnector { - fn new(ssl: OpensslClient) -> HttpsConnector { - HttpsConnector { - ssl: ssl, +impl HttpConnector { + fn new() -> HttpConnector { + let mut inner = HyperHttpConnector::new(4); + inner.enforce_http(false); + inner.set_happy_eyeballs_timeout(None); + HttpConnector { + inner } } } -impl NetworkConnector for HttpsConnector { - type Stream = HttpsStream<::Stream>; - - fn connect(&self, host: &str, port: u16, scheme: &str) -> HyperResult { - if scheme != "http" && scheme != "https" { - return Err(HyperError::Io(io::Error::new(io::ErrorKind::InvalidInput, - "Invalid scheme for Http"))); - } +impl Connect for HttpConnector { + type Transport = ::Transport; + type Error = ::Error; + type Future = ::Future; + fn connect(&self, dest: Destination) -> Self::Future { // Perform host replacement when making the actual TCP connection. - let addr = &(&*replace_host(host), port); - let stream = HttpStream(TcpStream::connect(addr)?); + let mut new_dest = dest.clone(); + let addr = replace_host(dest.host()); + new_dest.set_host(&*addr).unwrap(); + self.inner.connect(new_dest) + } +} - if scheme == "http" { - Ok(HttpsStream::Http(stream)) - } else { - // Do not perform host replacement on the host that is used - // for verifying any SSL certificate encountered. - self.ssl.wrap_client(stream, host).map(HttpsStream::Https) +pub type Connector = HttpsConnector; +pub struct WrappedBody { + pub body: Body, + pub decoder: Decoder, +} + +impl WrappedBody { + pub fn new(body: Body) -> Self { + Self::new_with_decoder(body, Decoder::Plain) + } + + pub fn new_with_decoder(body: Body, decoder: Decoder) -> Self { + WrappedBody { + body, + decoder, } } } -pub type Connector = HttpsConnector; +impl Payload for WrappedBody { + type Data = ::Data; + type Error = ::Error; + fn poll_data(&mut self) -> Result>, Self::Error> { + self.body.poll_data() + } +} -pub fn create_ssl_connector(certs: &str) -> SslConnector { +impl Stream for WrappedBody { + type Item = ::Item; + type Error = ::Error; + fn poll(&mut self) -> Result>, Self::Error> { + self.body.poll().map(|res| { + res.map(|maybe_chunk| { + if let Some(chunk) = maybe_chunk { + match self.decoder { + Decoder::Plain => Some(chunk), + Decoder::Gzip(Some(ref mut decoder)) => { + let mut buf = vec![0; BUF_SIZE]; + *decoder.get_mut() = Cursor::new(chunk.into_bytes()); + let len = decoder.read(&mut buf).ok()?; + buf.truncate(len); + Some(buf.into()) + } + Decoder::Gzip(None) => { + let mut buf = vec![0; BUF_SIZE]; + let mut decoder = GzDecoder::new(Cursor::new(chunk.into_bytes())); + let len = decoder.read(&mut buf).ok()?; + buf.truncate(len); + self.decoder = Decoder::Gzip(Some(decoder)); + Some(buf.into()) + } + Decoder::Deflate(ref mut decoder) => { + let mut buf = vec![0; BUF_SIZE]; + *decoder.get_mut() = Cursor::new(chunk.into_bytes()); + let len = decoder.read(&mut buf).ok()?; + buf.truncate(len); + Some(buf.into()) + } + Decoder::Brotli(ref mut decoder) => { + let mut buf = vec![0; BUF_SIZE]; + decoder.get_mut().get_mut().extend(&chunk.into_bytes()); + let len = decoder.read(&mut buf).ok()?; + buf.truncate(len); + Some(buf.into()) + } + } + } else { + None + } + }) + }) + } +} + +pub fn create_ssl_connector_builder(certs: &str) -> SslConnectorBuilder { // certs include multiple certificates. We could add all of them at once, // but if any of them were already added, openssl would fail to insert all // of them. let mut certs = certs; - let mut ssl_connector_builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); + let mut ssl_connector_builder = SslConnector::builder(SslMethod::tls()).unwrap(); loop { let token = "-----END CERTIFICATE-----"; if let Some(index) = certs.find(token) { @@ -78,18 +150,17 @@ pub fn create_ssl_connector(certs: &str) -> SslConnector { } } ssl_connector_builder.set_cipher_list(DEFAULT_CIPHERS).expect("could not set ciphers"); - ssl_connector_builder.set_options(SSL_OP_NO_SSLV2 | SSL_OP_NO_SSLV3 | SSL_OP_NO_COMPRESSION); - ssl_connector_builder.build() -} - -pub fn create_ssl_client(certs: &str) -> OpensslClient { - let ssl_connector = create_ssl_connector(certs); - OpensslClient::from(ssl_connector) + ssl_connector_builder.set_options(SslOptions::NO_SSLV2 | SslOptions::NO_SSLV3 | SslOptions::NO_COMPRESSION); + ssl_connector_builder } -pub fn create_http_connector(ssl_client: OpensslClient) -> Pool { - let https_connector = HttpsConnector::new(ssl_client); - Pool::with_connector(Default::default(), https_connector) +pub fn create_http_client(ssl_connector_builder: SslConnectorBuilder, executor: E) + -> Client + where + E: Executor + Send + 'static>> + Sync + Send + 'static +{ + let connector = HttpsConnector::with_connector(HttpConnector::new(), ssl_connector_builder).unwrap(); + Client::builder().http1_title_case_headers(true).executor(executor).build(connector) } // The basic logic here is to prefer ciphers with ECDSA certificates, Forward diff --git a/components/net/cookie.rs b/components/net/cookie.rs index e8e7be6733dd..fb4036281079 100644 --- a/components/net/cookie.rs +++ b/components/net/cookie.rs @@ -94,14 +94,14 @@ impl Cookie { // Step 10 - if cookie.http_only() && source == CookieSource::NonHTTP { + if cookie.http_only().unwrap_or(false) && source == CookieSource::NonHTTP { return None; } // https://tools.ietf.org/html/draft-west-cookie-prefixes-04#section-4 // Step 1 of cookie prefixes if (cookie.name().starts_with("__Secure-") || cookie.name().starts_with("__Host-")) && - !(cookie.secure() && request.is_secure_scheme()) + !(cookie.secure().unwrap_or(false) && request.is_secure_scheme()) { return None; } @@ -197,10 +197,10 @@ impl Cookie { } } - if self.cookie.secure() && !url.is_secure_scheme() { + if self.cookie.secure().unwrap_or(false) && !url.is_secure_scheme() { return false; } - if self.cookie.http_only() && source == CookieSource::NonHTTP { + if self.cookie.http_only().unwrap_or(false) && source == CookieSource::NonHTTP { return false; } diff --git a/components/net/cookie_storage.rs b/components/net/cookie_storage.rs index 4dc7075a9fd0..cb066d416fec 100644 --- a/components/net/cookie_storage.rs +++ b/components/net/cookie_storage.rs @@ -38,7 +38,7 @@ impl CookieStorage { let cookies = self.cookies_map.entry(domain).or_insert(vec![]); // https://www.ietf.org/id/draft-ietf-httpbis-cookie-alone-01.txt Step 2 - if !cookie.cookie.secure() && !url.is_secure_scheme() { + if !cookie.cookie.secure().unwrap_or(false) && !url.is_secure_scheme() { let new_domain = cookie.cookie.domain().as_ref().unwrap().to_owned(); let new_path = cookie.cookie.path().as_ref().unwrap().to_owned(); @@ -47,7 +47,7 @@ impl CookieStorage { let existing_path = c.cookie.path().as_ref().unwrap().to_owned(); c.cookie.name() == cookie.cookie.name() && - c.cookie.secure() && + c.cookie.secure().unwrap_or(false) && (Cookie::domain_match(new_domain, existing_domain) || Cookie::domain_match(existing_domain, new_domain)) && Cookie::path_match(new_path, existing_path) @@ -70,7 +70,7 @@ impl CookieStorage { let c = cookies.remove(ind); // http://tools.ietf.org/html/rfc6265#section-5.3 step 11.2 - if c.cookie.http_only() && source == CookieSource::NonHTTP { + if c.cookie.http_only().unwrap_or(false) && source == CookieSource::NonHTTP { // Undo the removal. cookies.push(c); Err(()) @@ -85,7 +85,7 @@ impl CookieStorage { // http://tools.ietf.org/html/rfc6265#section-5.3 pub fn push(&mut self, mut cookie: Cookie, url: &ServoUrl, source: CookieSource) { // https://www.ietf.org/id/draft-ietf-httpbis-cookie-alone-01.txt Step 1 - if cookie.cookie.secure() && !url.is_secure_scheme() { + if cookie.cookie.secure().unwrap_or(false) && !url.is_secure_scheme() { return; } @@ -111,7 +111,7 @@ impl CookieStorage { let new_len = cookies.len(); // https://www.ietf.org/id/draft-ietf-httpbis-cookie-alone-01.txt - if new_len == old_len && !evict_one_cookie(cookie.cookie.secure(), cookies) { + if new_len == old_len && !evict_one_cookie(cookie.cookie.secure().unwrap_or(false), cookies) { return; } } @@ -219,7 +219,7 @@ fn evict_one_cookie(is_secure_cookie: bool, cookies: &mut Vec) -> bool { fn get_oldest_accessed(is_secure_cookie: bool, cookies: &mut Vec) -> Option<(usize, Tm)> { let mut oldest_accessed: Option<(usize, Tm)> = None; for (i, c) in cookies.iter().enumerate() { - if (c.cookie.secure() == is_secure_cookie) && + if (c.cookie.secure().unwrap_or(false) == is_secure_cookie) && oldest_accessed.as_ref().map_or(true, |a| c.last_access < a.1) { oldest_accessed = Some((i, c.last_access)); } diff --git a/components/net/data_loader.rs b/components/net/data_loader.rs index b95a2ab34123..16ffb75a323a 100644 --- a/components/net/data_loader.rs +++ b/components/net/data_loader.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use base64; -use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value}; +use mime::Mime; use servo_url::ServoUrl; use url::Position; use url::percent_encoding::percent_decode; @@ -37,8 +37,7 @@ pub fn decode(url: &ServoUrl) -> Result { }; let content_type = ct_str.parse().unwrap_or_else(|_| { - Mime(TopLevel::Text, SubLevel::Plain, - vec![(Attr::Charset, Value::Ext("US-ASCII".to_owned()))]) + "text/plain; charset=US-ASCII".parse().unwrap() }); let mut bytes = percent_decode(parts[1].as_bytes()).collect::>(); diff --git a/components/net/fetch/cors_cache.rs b/components/net/fetch/cors_cache.rs index 8962dd2c9985..95e070cfc8e8 100644 --- a/components/net/fetch/cors_cache.rs +++ b/components/net/fetch/cors_cache.rs @@ -9,7 +9,8 @@ //! This library will eventually become the core of the Fetch crate //! with CORSRequest being expanded into FetchRequest (etc) -use hyper::method::Method; +use http::header::HeaderName; +use hyper::Method; use net_traits::request::{CredentialsMode, Origin, Request}; use servo_url::ServoUrl; use time::{self, Timespec}; @@ -19,14 +20,14 @@ use time::{self, Timespec}; /// Each entry might pertain to a header or method #[derive(Clone, Debug)] pub enum HeaderOrMethod { - HeaderData(String), + HeaderData(HeaderName), MethodData(Method) } impl HeaderOrMethod { - fn match_header(&self, header_name: &str) -> bool { + fn match_header(&self, header_name: &HeaderName) -> bool { match *self { - HeaderOrMethod::HeaderData(ref s) => (&**s).eq_ignore_ascii_case(header_name), + HeaderOrMethod::HeaderData(ref n) => n == header_name, _ => false } } @@ -80,7 +81,7 @@ impl CorsCache { } fn find_entry_by_header<'a>(&'a mut self, request: &Request, - header_name: &str) -> Option<&'a mut CorsCacheEntry> { + header_name: &HeaderName) -> Option<&'a mut CorsCacheEntry> { self.cleanup(); self.0.iter_mut().find(|e| match_headers(e, request) && e.header_or_method.match_header(header_name)) } @@ -113,7 +114,7 @@ impl CorsCache { /// Returns true if an entry with a /// [matching header](https://fetch.spec.whatwg.org/#concept-cache-match-header) is found - pub fn match_header(&mut self, request: &Request, header_name: &str) -> bool { + pub fn match_header(&mut self, request: &Request, header_name: &HeaderName) -> bool { self.find_entry_by_header(&request, header_name).is_some() } @@ -122,13 +123,13 @@ impl CorsCache { /// /// If not, it will insert an equivalent entry pub fn match_header_and_update(&mut self, request: &Request, - header_name: &str, new_max_age: u32) -> bool { + header_name: &HeaderName, new_max_age: u32) -> bool { match self.find_entry_by_header(&request, header_name).map(|e| e.max_age = new_max_age) { Some(_) => true, None => { self.insert(CorsCacheEntry::new(request.origin.clone(), request.current_url(), new_max_age, request.credentials_mode == CredentialsMode::Include, - HeaderOrMethod::HeaderData(header_name.to_owned()))); + HeaderOrMethod::HeaderData(header_name.clone()))); false } } diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index bec31fe81a21..edc6e3be45a3 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -7,16 +7,15 @@ use data_loader::decode; use devtools_traits::DevtoolsControlMsg; use fetch::cors_cache::CorsCache; use filemanager_thread::FileManager; +use headers_core::HeaderMapExt; +use headers_ext::{AccessControlExposeHeaders, ContentType, Range}; +use http::header::{self, HeaderMap, HeaderName, HeaderValue}; use http_loader::{HttpState, determine_request_referrer, http_fetch}; use http_loader::{set_default_accept, set_default_accept_language}; -use hyper::{Error, Result as HyperResult}; -use hyper::header; -use hyper::header::{Accept, AcceptLanguage, AccessControlExposeHeaders, ContentLanguage, ContentType}; -use hyper::header::{Header, HeaderFormat, HeaderView, Headers, Referer as RefererHeader}; -use hyper::method::Method; -use hyper::mime::{Mime, SubLevel, TopLevel}; -use hyper::status::StatusCode; +use hyper::Method; +use hyper::StatusCode; use ipc_channel::ipc::IpcReceiver; +use mime::{self, Mime}; use mime_guess::guess_mime_type; use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy}; use net_traits::request::{CredentialsMode, Destination, Referrer, Request, RequestMode}; @@ -25,16 +24,20 @@ use net_traits::response::{Response, ResponseBody, ResponseType}; use servo_channel::{channel, Sender, Receiver}; use servo_url::ServoUrl; use std::borrow::Cow; -use std::fmt; use std::fs::File; use std::io::{BufReader, BufRead, Seek, SeekFrom}; use std::mem; +use std::ops::Bound; use std::str; use std::sync::{Arc, Mutex}; use std::sync::atomic::Ordering; use std::thread; use subresource_integrity::is_response_integrity_valid; +lazy_static! { + static ref X_CONTENT_TYPE_OPTIONS: HeaderName = HeaderName::from_static("x-content-type-options"); +} + const FILE_CHUNK_SIZE: usize = 32768; //32 KB pub type Target<'a> = &'a mut (FetchTaskTarget + Send); @@ -173,11 +176,11 @@ pub fn main_fetch(request: &mut Request, Referrer::Client => { // FIXME(#14507): We should never get this value here; it should // already have been handled in the script thread. - request.headers.remove::(); + request.headers.remove(header::REFERER); None }, Referrer::ReferrerUrl(url) => { - request.headers.remove::(); + request.headers.remove(header::REFERER); let current_url = request.current_url().clone(); determine_request_referrer(&mut request.headers, request.referrer_policy.unwrap(), @@ -238,7 +241,7 @@ pub fn main_fetch(request: &mut Request, } else if request.use_cors_preflight || (request.unsafe_request && (!is_cors_safelisted_method(&request.method) || - request.headers.iter().any(|h| !is_cors_safelisted_request_header(&h)))) { + request.headers.iter().any(|(name, value)| !is_cors_safelisted_request_header(&name, &value)))) { // Substep 1. request.response_tainting = ResponseTainting::CorsTainting; // Substep 2. @@ -269,18 +272,19 @@ pub fn main_fetch(request: &mut Request, // Substep 1. if request.response_tainting == ResponseTainting::CorsTainting { // Subsubstep 1. - let header_names = response.headers.get::(); + let header_names: Option> = response.headers.typed_get::() + .map(|v| v.iter().collect()); match header_names { // Subsubstep 2. - Some(list) if request.credentials_mode != CredentialsMode::Include => { + Some(ref list) if request.credentials_mode != CredentialsMode::Include => { if list.len() == 1 && list[0] == "*" { response.cors_exposed_header_name_list = - response.headers.iter().map(|h| h.name().to_owned()).collect(); + response.headers.iter().map(|(name, _)| name.as_str().to_owned()).collect(); } }, // Subsubstep 3. Some(list) => { - response.cors_exposed_header_name_list = list.iter().map(|h| (**h).clone()).collect(); + response.cors_exposed_header_name_list = list.iter().map(|h| h.as_str().to_owned()).collect(); }, _ => (), } @@ -341,7 +345,7 @@ pub fn main_fetch(request: &mut Request, let not_network_error = !response_is_network_error && !internal_response.is_network_error(); if not_network_error && (is_null_body_status(&internal_response.status) || match request.method { - Method::Head | Method::Connect => true, + Method::HEAD | Method::CONNECT => true, _ => false }) { // when Fetch is used only asynchronously, we will need to make sure // that nothing tries to write to the body at this point @@ -463,7 +467,7 @@ fn scheme_fetch(request: &mut Request, match url.scheme() { "about" if url.path() == "blank" => { let mut response = Response::new(url); - response.headers.set(ContentType(mime!(Text / Html; Charset = Utf8))); + response.headers.typed_insert(ContentType::from(mime::TEXT_HTML_UTF_8)); *response.body.lock().unwrap() = ResponseBody::Done(vec![]); response }, @@ -477,7 +481,7 @@ fn scheme_fetch(request: &mut Request, Ok((mime, bytes)) => { let mut response = Response::new(url); *response.body.lock().unwrap() = ResponseBody::Done(bytes); - response.headers.set(ContentType(mime)); + response.headers.typed_insert(ContentType::from(mime)); response }, Err(_) => Response::network_error(NetworkError::Internal("Decoding data URL failed".into())) @@ -485,7 +489,7 @@ fn scheme_fetch(request: &mut Request, }, "file" => { - if request.method == Method::Get { + if request.method == Method::GET { match url.to_file_path() { Ok(file_path) => { match File::open(file_path.clone()) { @@ -493,7 +497,7 @@ fn scheme_fetch(request: &mut Request, let mime = guess_mime_type(file_path); let mut response = Response::new(url); - response.headers.set(ContentType(mime)); + response.headers.typed_insert(ContentType::from(mime)); let (done_sender, done_receiver) = channel(); *done_chan = Some((done_sender.clone(), done_receiver)); @@ -503,22 +507,22 @@ fn scheme_fetch(request: &mut Request, let cancellation_listener = context.cancellation_listener.clone(); - let range = request.headers.get::(); - let (start, end) = if let Some(&header::Range::Bytes(ref range)) = range { - match range.first().unwrap() { - &header::ByteRangeSpec::AllFrom(start) => (start, None), - &header::ByteRangeSpec::FromTo(start, end) => { + let (start, end) = if let Some(ref range) = request.headers.typed_get::() { + match range.iter().collect::, Bound)>>().first() { + Some(&(Bound::Included(start), Bound::Unbounded)) => (start, None), + Some(&(Bound::Included(start), Bound::Included(end))) => { // `end` should be less or equal to `start`. (start, Some(u64::max(start, end))) }, - &header::ByteRangeSpec::Last(offset) => { + Some(&(Bound::Unbounded, Bound::Included(offset))) => { if let Ok(metadata) = file.metadata() { // `offset` cannot be bigger than the file size. (metadata.len() - u64::min(metadata.len(), offset), None) } else { (0, None) } - } + }, + _ => (0, None) } } else { (0, None) @@ -591,7 +595,7 @@ fn scheme_fetch(request: &mut Request, "blob" => { println!("Loading blob {}", url.as_str()); // Step 2. - if request.method != Method::Get { + if request.method != Method::GET { return Response::network_error(NetworkError::Internal("Unexpected method for blob".into())); } @@ -619,33 +623,33 @@ fn scheme_fetch(request: &mut Request, } /// -pub fn is_cors_safelisted_request_header(h: &HeaderView) -> bool { - if h.is::() { - match h.value() { - Some(&ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) | - Some(&ContentType(Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, _))) | - Some(&ContentType(Mime(TopLevel::Multipart, SubLevel::FormData, _))) => true, - _ => false - +pub fn is_cors_safelisted_request_header(name: &HeaderName, value: &HeaderValue) -> bool { + if name == header::CONTENT_TYPE { + if let Some(m) = value.to_str().ok().and_then(|s| s.parse::().ok()) { + m.type_() == mime::TEXT && m.subtype() == mime::PLAIN || + m.type_() == mime::APPLICATION && m.subtype() == mime::WWW_FORM_URLENCODED || + m.type_() == mime::MULTIPART && m.subtype() == mime::FORM_DATA + } else { + false } } else { - h.is::() || h.is::() || h.is::() + name == header::ACCEPT || name == header::ACCEPT_LANGUAGE || name == header::CONTENT_LANGUAGE } } /// pub fn is_cors_safelisted_method(m: &Method) -> bool { match *m { - Method::Get | Method::Head | Method::Post => true, + Method::GET | Method::HEAD | Method::POST => true, _ => false } } -fn is_null_body_status(status: &Option) -> bool { +fn is_null_body_status(status: &Option<(StatusCode, String)>) -> bool { match *status { - Some(status) => match status { - StatusCode::SwitchingProtocols | StatusCode::NoContent | - StatusCode::ResetContent | StatusCode::NotModified => true, + Some((status, _)) => match status { + StatusCode::SWITCHING_PROTOCOLS | StatusCode::NO_CONTENT | + StatusCode::RESET_CONTENT | StatusCode::NOT_MODIFIED => true, _ => false }, _ => false @@ -653,84 +657,56 @@ fn is_null_body_status(status: &Option) -> bool { } /// -pub fn should_be_blocked_due_to_nosniff(destination: Destination, response_headers: &Headers) -> bool { - /// - /// This is needed to parse `X-Content-Type-Options` according to spec, - /// which requires that we inspect only the first value. - /// - /// A [unit-like struct](https://doc.rust-lang.org/book/structs.html#unit-like-structs) - /// is sufficient since a valid header implies that we use `nosniff`. - #[derive(Clone, Copy, Debug)] - struct XContentTypeOptions; - - impl Header for XContentTypeOptions { - fn header_name() -> &'static str { - "X-Content-Type-Options" - } - - /// https://fetch.spec.whatwg.org/#should-response-to-request-be-blocked-due-to-nosniff%3F #2 - fn parse_header(raw: &[Vec]) -> HyperResult { - raw.first() - .and_then(|v| str::from_utf8(v).ok()) - .and_then(|s| if s.trim().eq_ignore_ascii_case("nosniff") { - Some(XContentTypeOptions) - } else { - None - }) - .ok_or(Error::Header) - } - } - - impl HeaderFormat for XContentTypeOptions { - fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("nosniff") - } - } - +pub fn should_be_blocked_due_to_nosniff(destination: Destination, response_headers: &HeaderMap) -> bool { // Steps 1-3. - if response_headers.get::().is_none() { + // TODO(eijebong): Replace this once typed headers allow custom ones... + if response_headers.get("x-content-type-options") + .map_or(true, |val| val.to_str().unwrap_or("").to_lowercase() != "nosniff") + { return false; } // Step 4 // Note: an invalid MIME type will produce a `None`. - let content_type_header = response_headers.get::(); + let content_type_header = response_headers.typed_get::(); /// #[inline] fn is_javascript_mime_type(mime_type: &Mime) -> bool { let javascript_mime_types: [Mime; 16] = [ - mime!(Application / ("ecmascript")), - mime!(Application / ("javascript")), - mime!(Application / ("x-ecmascript")), - mime!(Application / ("x-javascript")), - mime!(Text / ("ecmascript")), - mime!(Text / ("javascript")), - mime!(Text / ("javascript1.0")), - mime!(Text / ("javascript1.1")), - mime!(Text / ("javascript1.2")), - mime!(Text / ("javascript1.3")), - mime!(Text / ("javascript1.4")), - mime!(Text / ("javascript1.5")), - mime!(Text / ("jscript")), - mime!(Text / ("livescript")), - mime!(Text / ("x-ecmascript")), - mime!(Text / ("x-javascript")), + "application/ecmascript".parse().unwrap(), + "application/javascript".parse().unwrap(), + "application/x-ecmascript".parse().unwrap(), + "application/x-javascript".parse().unwrap(), + "text/ecmascript".parse().unwrap(), + "text/javascript".parse().unwrap(), + "text/javascript1.0".parse().unwrap(), + "text/javascript1.1".parse().unwrap(), + "text/javascript1.2".parse().unwrap(), + "text/javascript1.3".parse().unwrap(), + "text/javascript1.4".parse().unwrap(), + "text/javascript1.5".parse().unwrap(), + "text/jscript".parse().unwrap(), + "text/livescript".parse().unwrap(), + "text/x-ecmascript".parse().unwrap(), + "text/x-javascript".parse().unwrap(), ]; javascript_mime_types.iter() - .any(|mime| mime.0 == mime_type.0 && mime.1 == mime_type.1) + .any(|mime| mime.type_() == mime_type.type_() && mime.subtype() == mime_type.subtype()) } - // Assumes str::starts_with is equivalent to mime::TopLevel match content_type_header { // Step 6 - Some(&ContentType(ref mime_type)) if destination.is_script_like() - => !is_javascript_mime_type(mime_type), + Some(ref ct) if destination.is_script_like() + => !is_javascript_mime_type(&ct.clone().into()), // Step 7 - Some(&ContentType(Mime(ref tl, ref sl, _))) if destination == Destination::Style - => *tl != TopLevel::Text && *sl != SubLevel::Css, + Some(ref ct) if destination == Destination::Style + => { + let m: mime::Mime = ct.clone().into(); + m.type_() != mime::TEXT && m.subtype() != mime::CSS + }, None if destination == Destination::Style || destination.is_script_like() => true, // Step 8 @@ -739,23 +715,23 @@ pub fn should_be_blocked_due_to_nosniff(destination: Destination, response_heade } /// -fn should_be_blocked_due_to_mime_type(destination: Destination, response_headers: &Headers) -> bool { +fn should_be_blocked_due_to_mime_type(destination: Destination, response_headers: &HeaderMap) -> bool { // Step 1 - let mime_type = match response_headers.get::() { - Some(header) => header, + let mime_type: mime::Mime = match response_headers.typed_get::() { + Some(header) => header.into(), None => return false, }; // Step 2-3 - destination.is_script_like() && match *mime_type { - ContentType(Mime(TopLevel::Audio, _, _)) | - ContentType(Mime(TopLevel::Video, _, _)) | - ContentType(Mime(TopLevel::Image, _, _)) => true, - ContentType(Mime(TopLevel::Text, SubLevel::Ext(ref ext), _)) => ext == "csv", - - // Step 4 - _ => false, - } + destination.is_script_like() && + match mime_type.type_() { + mime::AUDIO | + mime::VIDEO | + mime::IMAGE => true, + mime::TEXT if mime_type.subtype() == mime::CSV => true, + // Step 4 + _ => false + } } /// diff --git a/components/net/http_cache.rs b/components/net/http_cache.rs index 1fcafc929528..dbb777eb1034 100644 --- a/components/net/http_cache.rs +++ b/components/net/http_cache.rs @@ -8,12 +8,11 @@ //! and . use fetch::methods::{Data, DoneChannel}; -use hyper::header; -use hyper::header::ContentType; -use hyper::header::Headers; -use hyper::method::Method; -use hyper::status::StatusCode; -use hyper_serde::Serde; +use headers_core::HeaderMapExt; +use headers_ext::{CacheControl, ContentRange, Expires, LastModified, Pragma, Range, Vary}; +use http::{header, HeaderMap}; +use http::header::HeaderValue; +use hyper::{Method, StatusCode}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf, MallocUnconditionalShallowSizeOf}; use malloc_size_of::Measurable; use net_traits::{Metadata, FetchMetadata}; @@ -24,11 +23,12 @@ use servo_channel::{Sender, channel}; use servo_config::prefs::PREFS; use servo_url::ServoUrl; use std::collections::HashMap; -use std::str; +use std::ops::Bound; use std::sync::Mutex; use std::sync::atomic::{AtomicBool, Ordering}; +use std::time::SystemTime; use time; -use time::{Duration, Tm}; +use time::{Duration, Timespec, Tm}; /// The key used to differentiate requests in the cache. @@ -59,7 +59,7 @@ impl CacheKey { /// A complete cached resource. #[derive(Clone)] struct CachedResource { - request_headers: Arc>, + request_headers: Arc>, body: Arc>, aborted: Arc, awaiting_body: Arc>>>, @@ -71,7 +71,7 @@ struct MeasurableCachedResource { metadata: CachedMetadata, location_url: Option>, https_state: HttpsState, - status: Option, + status: Option<(StatusCode, String)>, raw_status: Option<(u16, Vec)>, url_list: Vec, expires: Duration, @@ -80,7 +80,7 @@ struct MeasurableCachedResource { impl MallocSizeOf for CachedResource { fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.request_headers.unconditional_size_of(ops) + + // TODO: self.request_headers.unconditional_size_of(ops) + self.body.unconditional_size_of(ops) + self.aborted.unconditional_size_of(ops) + self.awaiting_body.unconditional_size_of(ops) + @@ -92,7 +92,7 @@ impl MallocSizeOf for CachedResource { #[derive(Clone)] struct CachedMetadata { /// Headers - pub headers: Arc>, + pub headers: Arc>, /// Fields that implement MallocSizeOf pub data: Measurable } @@ -102,7 +102,7 @@ struct MeasurableCachedMetadata { /// Final URL after redirects. pub final_url: ServoUrl, /// MIME type / subtype. - pub content_type: Option>, + pub content_type: Option, /// Character set. pub charset: Option, /// HTTP Status @@ -112,7 +112,7 @@ struct MeasurableCachedMetadata { impl MallocSizeOf for CachedMetadata { fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { self.headers.unconditional_shallow_size_of(ops) + - self.headers.size_of(ops) + + // TODO: self.headers.size_of(ops) + self.data.size_of(ops) } } @@ -141,23 +141,25 @@ fn response_is_cacheable(metadata: &Metadata) -> bool { // 2. check for absence of the Authorization header field. let mut is_cacheable = false; let headers = metadata.headers.as_ref().unwrap(); - if headers.has::() || - headers.has::() || - headers.has::() { + if headers.contains_key(header::EXPIRES) || + headers.contains_key(header::LAST_MODIFIED) || + headers.contains_key(header::ETAG) { is_cacheable = true; } - if let Some(&header::CacheControl(ref directive)) = headers.get::() { - for directive in directive.iter() { - match *directive { - header::CacheDirective::NoStore => return false, - header::CacheDirective::Public | header::CacheDirective::SMaxAge(_) - | header::CacheDirective::MaxAge(_) | header::CacheDirective::NoCache => is_cacheable = true, - _ => {}, - } + if let Some(ref directive) = headers.typed_get::() { + if directive.no_store() { + return false + } + if directive.public() || directive.s_max_age().is_some() || + directive.max_age().is_some() || directive.no_cache() + { + is_cacheable = true; } } - if let Some(&header::Pragma::NoCache) = headers.get::() { - return false; + if let Some(pragma) = headers.typed_get::() { + if pragma.is_no_cache() { + return false; + } } is_cacheable } @@ -166,10 +168,11 @@ fn response_is_cacheable(metadata: &Metadata) -> bool { /// fn calculate_response_age(response: &Response) -> Duration { // TODO: follow the spec more closely (Date headers, request/response lag, ...) - if let Some(secs) = response.headers.get_raw("Age") { - let seconds_string = String::from_utf8_lossy(&secs[0]); - if let Ok(secs) = seconds_string.parse::() { - return Duration::seconds(secs); + if let Some(secs) = response.headers.get(header::AGE) { + if let Ok(seconds_string) = secs.to_str() { + if let Ok(secs) = seconds_string.parse::() { + return Duration::seconds(secs); + } } } Duration::seconds(0i64) @@ -180,42 +183,37 @@ fn calculate_response_age(response: &Response) -> Duration { fn get_response_expiry(response: &Response) -> Duration { // Calculating Freshness Lifetime let age = calculate_response_age(&response); - if let Some(&header::CacheControl(ref directives)) = response.headers.get::() { - let has_no_cache_directive = directives.iter().any(|directive| { - header::CacheDirective::NoCache == *directive - }); - if has_no_cache_directive { + if let Some(directives) = response.headers.typed_get::() { + if directives.no_cache() { // Requires validation on first use. return Duration::seconds(0i64); } else { - for directive in directives { - match *directive { - header::CacheDirective::SMaxAge(secs) | header::CacheDirective::MaxAge(secs) => { - let max_age = Duration::seconds(secs as i64); - if max_age < age { - return Duration::seconds(0i64); - } - return max_age - age; - }, - _ => (), + if let Some(secs) = directives.max_age().or(directives.s_max_age()) { + let max_age = Duration::from_std(secs).unwrap(); + if max_age < age { + return Duration::seconds(0i64); } + return max_age - age; } } } - if let Some(&header::Expires(header::HttpDate(t))) = response.headers.get::() { - // store the period of time from now until expiry - let desired = t.to_timespec(); - let current = time::now().to_timespec(); - if desired > current { - return desired - current; - } else { - return Duration::seconds(0i64); - } - } else { - if let Some(_) = response.headers.get_raw("Expires") { - // Malformed Expires header, shouldn't be used to construct a valid response. - return Duration::seconds(0i64); - } + match response.headers.typed_get::() { + Some(t) => { + // store the period of time from now until expiry + let t: SystemTime = t.into(); + let t = t.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let desired = Timespec::new(t.as_secs() as i64, 0); + let current = time::now().to_timespec(); + + if desired > current { + return desired - current; + } else { + return Duration::seconds(0i64); + } + }, + // Malformed Expires header, shouldn't be used to construct a valid response. + None if response.headers.contains_key(header::EXPIRES) => return Duration::seconds(0i64), + _ => {}, } // Calculating Heuristic Freshness // @@ -224,13 +222,15 @@ fn get_response_expiry(response: &Response) -> Duration { // Since presently we do not generate a Warning header field with a 113 warn-code, // 24 hours minus response age is the max for heuristic calculation. let max_heuristic = Duration::hours(24) - age; - let heuristic_freshness = if let Some(&header::LastModified(header::HttpDate(t))) = + let heuristic_freshness = if let Some(last_modified) = // If the response has a Last-Modified header field, // caches are encouraged to use a heuristic expiration value // that is no more than some fraction of the interval since that time. - response.headers.get::() { - let last_modified = t.to_timespec(); + response.headers.typed_get::() { let current = time::now().to_timespec(); + let last_modified: SystemTime = last_modified.into(); + let last_modified = last_modified.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let last_modified = Timespec::new(last_modified.as_secs() as i64, 0); // A typical setting of this fraction might be 10%. let raw_heuristic_calc = (current - last_modified) / 10; let result = if raw_heuristic_calc < max_heuristic { @@ -249,11 +249,9 @@ fn get_response_expiry(response: &Response) -> Duration { }, _ => { // Other status codes can only use heuristic freshness if the public cache directive is present. - if let Some(&header::CacheControl(ref directives)) = response.headers.get::() { - let has_public_directive = directives.iter().any(|directive| { - header::CacheDirective::Public == *directive - }); - if has_public_directive { + if let Some(ref directives) = response.headers.typed_get::() + { + if directives.public() { return heuristic_freshness; } } @@ -267,48 +265,39 @@ fn get_response_expiry(response: &Response) -> Duration { /// Request Cache-Control Directives /// fn get_expiry_adjustment_from_request_headers(request: &Request, expires: Duration) -> Duration { - let directive_data = match request.headers.get_raw("cache-control") { + let directive = match request.headers.typed_get::() { Some(data) => data, None => return expires, }; - let directives_string = String::from_utf8_lossy(&directive_data[0]); - for directive in directives_string.split(",") { - let mut directive_info = directive.split("="); - match (directive_info.next(), directive_info.next()) { - (Some("max-stale"), Some(sec_str)) => { - if let Ok(secs) = sec_str.parse::() { - return expires + Duration::seconds(secs); - } - }, - (Some("max-age"), Some(sec_str)) => { - if let Ok(secs) = sec_str.parse::() { - let max_age = Duration::seconds(secs); - if expires > max_age { - return Duration::min_value(); - } - return expires - max_age; - } - }, - (Some("min-fresh"), Some(sec_str)) => { - if let Ok(secs) = sec_str.parse::() { - let min_fresh = Duration::seconds(secs); - if expires < min_fresh { - return Duration::min_value(); - } - return expires - min_fresh; - } - }, - (Some("no-cache"), _) | (Some("no-store"), _) => return Duration::min_value(), - _ => {} + + if let Some(max_age) = directive.max_stale() { + return expires + Duration::from_std(max_age).unwrap(); + } + if let Some(max_age) = directive.max_age() { + let max_age = Duration::from_std(max_age).unwrap(); + if expires > max_age { + return Duration::min_value(); } + return expires - max_age; } + if let Some(min_fresh) = directive.min_fresh() { + let min_fresh = Duration::from_std(min_fresh).unwrap(); + if expires < min_fresh { + return Duration::min_value(); + } + return expires - min_fresh; + } + if directive.no_cache() || directive.no_store() { + return Duration::min_value() + } + expires } /// Create a CachedResponse from a request and a CachedResource. fn create_cached_response(request: &Request, cached_resource: &CachedResource, - cached_headers: &Headers, + cached_headers: &HeaderMap, done_chan: &mut DoneChannel) -> CachedResponse { let mut response = Response::new(cached_resource.data.metadata.data.final_url.clone()); @@ -353,7 +342,7 @@ fn create_resource_with_bytes_from_resource(bytes: &[u8], resource: &CachedResou metadata: resource.data.metadata.clone(), location_url: resource.data.location_url.clone(), https_state: resource.data.https_state.clone(), - status: Some(StatusCode::PartialContent), + status: Some((StatusCode::PARTIAL_CONTENT, "Partial Content".into())), raw_status: Some((206, b"Partial Content".to_vec())), url_list: resource.data.url_list.clone(), expires: resource.data.expires.clone(), @@ -365,7 +354,7 @@ fn create_resource_with_bytes_from_resource(bytes: &[u8], resource: &CachedResou /// Support for range requests . fn handle_range_request(request: &Request, candidates: Vec<&CachedResource>, - range_spec: &[header::ByteRangeSpec], + range_spec: Vec<(Bound, Bound)>, done_chan: &mut DoneChannel) -> Option { let mut complete_cached_resources = candidates.iter().filter(|resource| { @@ -389,7 +378,7 @@ fn handle_range_request(request: &Request, // see . // TODO: add support for complete and partial resources, // whose body is in the ResponseBody::Receiving state. - (&header::ByteRangeSpec::FromTo(beginning, end), Some(ref complete_resource)) => { + (&(Bound::Included(beginning), Bound::Included(end)), Some(ref complete_resource)) => { if let ResponseBody::Done(ref body) = *complete_resource.body.lock().unwrap() { let b = beginning as usize; let e = end as usize + 1; @@ -402,14 +391,18 @@ fn handle_range_request(request: &Request, } } }, - (&header::ByteRangeSpec::FromTo(beginning, end), None) => { + (&(Bound::Included(beginning), Bound::Included(end)), None) => { for partial_resource in partial_cached_resources { let headers = partial_resource.data.metadata.headers.lock().unwrap(); - let content_range = headers.get::(); + let content_range = headers.typed_get::(); let (res_beginning, res_end) = match content_range { - Some(&header::ContentRange( - header::ContentRangeSpec::Bytes { - range: Some((res_beginning, res_end)), .. })) => (res_beginning, res_end), + Some(range) => { + if let Some(bytes_range) = range.bytes_range() { + bytes_range + } else { + continue + } + } _ => continue, }; if res_beginning - 1 < beginning && res_end + 1 > end { @@ -430,7 +423,7 @@ fn handle_range_request(request: &Request, } } }, - (&header::ByteRangeSpec::AllFrom(beginning), Some(ref complete_resource)) => { + (&(Bound::Included(beginning), Bound::Unbounded), Some(ref complete_resource)) => { if let ResponseBody::Done(ref body) = *complete_resource.body.lock().unwrap() { let b = beginning as usize; let requested = body.get(b..); @@ -442,16 +435,17 @@ fn handle_range_request(request: &Request, } } }, - (&header::ByteRangeSpec::AllFrom(beginning), None) => { + (&(Bound::Included(beginning), Bound::Unbounded), None) => { for partial_resource in partial_cached_resources { let headers = partial_resource.data.metadata.headers.lock().unwrap(); - let content_range = headers.get::(); - let (res_beginning, res_end, total) = match content_range { - Some(&header::ContentRange( - header::ContentRangeSpec::Bytes { - range: Some((res_beginning, res_end)), - instance_length: Some(total) })) => (res_beginning, res_end, total), - _ => continue, + let content_range = headers.typed_get::(); + let (res_beginning, res_end, total) = if let Some(range) = content_range { + match (range.bytes_range(), range.bytes_len()) { + (Some(bytes_range), Some(total)) => (bytes_range.0, bytes_range.1, total), + _ => continue, + } + } else { + continue; }; if res_beginning < beginning && res_end == total - 1 { let resource_body = &*partial_resource.body.lock().unwrap(); @@ -470,7 +464,7 @@ fn handle_range_request(request: &Request, } } }, - (&header::ByteRangeSpec::Last(offset), Some(ref complete_resource)) => { + (&(Bound::Unbounded, Bound::Included(offset)), Some(ref complete_resource)) => { if let ResponseBody::Done(ref body) = *complete_resource.body.lock().unwrap() { let from_byte = body.len() - offset as usize; let requested = body.get(from_byte..); @@ -482,16 +476,17 @@ fn handle_range_request(request: &Request, } } }, - (&header::ByteRangeSpec::Last(offset), None) => { + (&(Bound::Unbounded, Bound::Included(offset)), None) => { for partial_resource in partial_cached_resources { let headers = partial_resource.data.metadata.headers.lock().unwrap(); - let content_range = headers.get::(); - let (res_beginning, res_end, total) = match content_range { - Some(&header::ContentRange( - header::ContentRangeSpec::Bytes { - range: Some((res_beginning, res_end)), - instance_length: Some(total) })) => (res_beginning, res_end, total), - _ => continue, + let content_range = headers.typed_get::(); + let (res_beginning, res_end, total) = if let Some(range) = content_range { + match (range.bytes_range(), range.bytes_len()) { + (Some(bytes_range), Some(total)) => (bytes_range.0, bytes_range.1, total), + _ => continue, + } + } else { + continue; }; if (total - res_beginning) > (offset - 1 ) && (total - res_end) < offset + 1 { let resource_body = &*partial_resource.body.lock().unwrap(); @@ -509,7 +504,9 @@ fn handle_range_request(request: &Request, } } } - } + }, + // All the cases with Bound::Excluded should be unreachable anyway + _ => return None } None } @@ -527,7 +524,7 @@ impl HttpCache { /// pub fn construct_response(&self, request: &Request, done_chan: &mut DoneChannel) -> Option { // TODO: generate warning headers as appropriate - if request.method != Method::Get { + if request.method != Method::GET { // Only Get requests are cached, avoid a url based match for others. return None; } @@ -538,41 +535,35 @@ impl HttpCache { let mut can_be_constructed = true; let cached_headers = cached_resource.data.metadata.headers.lock().unwrap(); let original_request_headers = cached_resource.request_headers.lock().unwrap(); - if let Some(vary_data) = cached_headers.get_raw("Vary") { - // Calculating Secondary Keys with Vary - let vary_data_string = String::from_utf8_lossy(&vary_data[0]); - let vary_values = vary_data_string.split(",").map(|val| val.trim()); - for vary_val in vary_values { + if let Some(vary_value) = cached_headers.typed_get::() { + if vary_value.is_any() { + can_be_constructed = false + } else { // For every header name found in the Vary header of the stored response. - if vary_val == "*" { - // A Vary header field-value of "*" always fails to match. - can_be_constructed = false; - break; - } - match request.headers.get_raw(vary_val) { - Some(header_data) => { - // If the header is present in the request. - let request_header_data_string = String::from_utf8_lossy(&header_data[0]); - if let Some(original_header_data) = original_request_headers.get_raw(vary_val) { - // Check that the value of the nominated header field, - // in the original request, matches the value in the current request. - let original_request_header_data_string = - String::from_utf8_lossy(&original_header_data[0]); - if original_request_header_data_string != request_header_data_string { - can_be_constructed = false; - break; + // Calculating Secondary Keys with Vary + for vary_val in vary_value.iter_strs() { + match request.headers.get(vary_val) { + Some(header_data) => { + // If the header is present in the request. + if let Some(original_header_data) = original_request_headers.get(vary_val) { + // Check that the value of the nominated header field, + // in the original request, matches the value in the current request. + if original_header_data != header_data { + can_be_constructed = false; + break; + } } - } - }, - None => { - // If a header field is absent from a request, - // it can only match a stored response if those headers, - // were also absent in the original request. - can_be_constructed = original_request_headers.get_raw(vary_val).is_none(); - }, - } - if !can_be_constructed { - break; + }, + None => { + // If a header field is absent from a request, + // it can only match a stored response if those headers, + // were also absent in the original request. + can_be_constructed = original_request_headers.get(vary_val).is_none(); + }, + } + if !can_be_constructed { + break; + } } } } @@ -581,8 +572,8 @@ impl HttpCache { } } // Support for range requests - if let Some(&header::Range::Bytes(ref range_spec)) = request.headers.get::() { - return handle_range_request(request, candidates, &range_spec, done_chan); + if let Some(range_spec) = request.headers.typed_get::() { + return handle_range_request(request, candidates, range_spec.iter().collect(), done_chan); } else { // Not a Range request. if let Some(ref cached_resource) = candidates.first() { @@ -620,7 +611,7 @@ impl HttpCache { /// Freshening Stored Responses upon Validation. /// pub fn refresh(&mut self, request: &Request, response: Response, done_chan: &mut DoneChannel) -> Option { - assert_eq!(response.status, Some(StatusCode::NotModified)); + assert_eq!(response.status.map(|s| s.0), Some(StatusCode::NOT_MODIFIED)); let entry_key = CacheKey::new(request.clone()); if let Some(cached_resources) = self.entries.get_mut(&entry_key) { for cached_resource in cached_resources.iter_mut() { @@ -654,7 +645,7 @@ impl HttpCache { constructed_response.url_list = cached_resource.data.url_list.clone(); cached_resource.data.expires = get_response_expiry(&constructed_response); let mut stored_headers = cached_resource.data.metadata.headers.lock().unwrap(); - stored_headers.extend(response.headers.iter()); + stored_headers.extend(response.headers); constructed_response.headers = stored_headers.clone(); return Some(constructed_response); } @@ -674,17 +665,16 @@ impl HttpCache { /// Invalidation. /// pub fn invalidate(&mut self, request: &Request, response: &Response) { - if let Some(&header::Location(ref location)) = response.headers.get::() { + // TODO(eijebong): Once headers support typed_get, update this to use them + if let Some(Ok(location)) = response.headers.get(header::LOCATION).map(HeaderValue::to_str) { if let Ok(url) = request.current_url().join(location) { self.invalidate_for_url(&url); } } - // TODO: update hyper to use typed getter. - if let Some(url_data) = response.headers.get_raw("Content-Location") { - if let Ok(content_location) = str::from_utf8(&url_data[0]) { - if let Ok(url) = request.current_url().join(content_location) { - self.invalidate_for_url(&url); - } + if let Some(Ok(ref content_location)) = response.headers.get(header::CONTENT_LOCATION).map(HeaderValue::to_str) + { + if let Ok(url) = request.current_url().join(&content_location) { + self.invalidate_for_url(&url); } } self.invalidate_for_url(&request.url()); @@ -696,7 +686,7 @@ impl HttpCache { if PREFS.get("network.http-cache.disabled").as_boolean().unwrap_or(false) { return } - if request.method != Method::Get { + if request.method != Method::GET { // Only Get requests are cached. return } @@ -716,7 +706,7 @@ impl HttpCache { headers: Arc::new(Mutex::new(response.headers.clone())), data: Measurable(MeasurableCachedMetadata { final_url: metadata.final_url, - content_type: metadata.content_type, + content_type: metadata.content_type.map(|v| v.0.to_string()), charset: metadata.charset, status: metadata.status }) diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index fe85fc5a6f73..20aaaffc2375 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -3,7 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use brotli::Decompressor; -use connector::{Connector, create_http_connector}; +use bytes::Bytes; +use connector::{BUF_SIZE, Connector, create_http_client, WrappedBody}; use cookie; use cookie_storage::CookieStorage; use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, HttpRequest as DevtoolsHttpRequest}; @@ -12,60 +13,51 @@ use fetch::cors_cache::CorsCache; use fetch::methods::{Data, DoneChannel, FetchContext, Target}; use fetch::methods::{is_cors_safelisted_request_header, is_cors_safelisted_method, main_fetch}; use flate2::read::{DeflateDecoder, GzDecoder}; +use headers_core::HeaderMapExt; +use headers_ext::{AccessControlAllowCredentials, AccessControlAllowHeaders}; +use headers_ext::{AccessControlAllowMethods, AccessControlRequestHeaders, AccessControlRequestMethod, Authorization}; +use headers_ext::{AccessControlAllowOrigin, AccessControlMaxAge, Basic}; +use headers_ext::{CacheControl, ContentEncoding, ContentLength}; +use headers_ext::{Host, IfModifiedSince, LastModified, Origin as HyperOrigin, Pragma, Referer, UserAgent}; use hsts::HstsList; +use http::{HeaderMap, Request as HyperRequest}; +use http::header::{self, HeaderName, HeaderValue}; +use http::uri::Authority; use http_cache::HttpCache; -use hyper::Error as HttpError; -use hyper::LanguageTag; -use hyper::client::{Pool, Request as HyperRequest, Response as HyperResponse}; -use hyper::header::{Accept, AccessControlAllowCredentials, AccessControlAllowHeaders}; -use hyper::header::{AccessControlAllowMethods, AccessControlAllowOrigin}; -use hyper::header::{AccessControlMaxAge, AccessControlRequestHeaders}; -use hyper::header::{AccessControlRequestMethod, AcceptEncoding, AcceptLanguage}; -use hyper::header::{Authorization, Basic, CacheControl, CacheDirective}; -use hyper::header::{ContentEncoding, ContentLength, Encoding, Header, Headers}; -use hyper::header::{Host, HttpDate, Origin as HyperOrigin, IfMatch, IfRange}; -use hyper::header::{IfUnmodifiedSince, IfModifiedSince, IfNoneMatch, Location}; -use hyper::header::{Pragma, Quality, QualityItem, Referer, SetCookie}; -use hyper::header::{UserAgent, q, qitem}; -use hyper::method::Method; -use hyper::status::StatusCode; -use hyper_openssl::OpensslClient; +use hyper::{Body, Client, Method, StatusCode, Response as HyperResponse}; use hyper_serde::Serde; use log; +use mime; use msg::constellation_msg::{HistoryStateId, PipelineId}; use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy}; +use net_traits::quality::{quality_to_value, Quality, QualityItem}; use net_traits::request::{CacheMode, CredentialsMode, Destination, Origin}; use net_traits::request::{RedirectMode, Referrer, Request, RequestMode}; use net_traits::request::{ResponseTainting, ServiceWorkersMode}; use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType}; +use openssl::ssl::SslConnectorBuilder; use resource_thread::AuthCache; use servo_channel::{channel, Sender}; use servo_url::{ImmutableOrigin, ServoUrl}; use std::collections::{HashMap, HashSet}; use std::error::Error; -use std::io::{self, Read, Write}; +use std::io::Cursor; use std::iter::FromIterator; use std::mem; use std::ops::Deref; use std::str::FromStr; +use std::sync::Mutex; use std::sync::RwLock; -use std::thread; -use time; -use time::Tm; -use unicase::UniCase; +use std::time::{Duration, SystemTime}; +use time::{self, Tm}; +use tokio::prelude::{Future, future, Stream}; +use tokio::runtime::Runtime; use uuid; -fn read_block(reader: &mut R) -> Result { - let mut buf = vec![0; 32768]; - - match reader.read(&mut buf) { - Ok(len) if len > 0 => { - buf.truncate(len); - Ok(Data::Payload(buf)) - } - Ok(_) => Ok(Data::Done), - Err(_) => Err(()), - } +lazy_static! { + pub static ref HANDLE: Mutex = { + Mutex::new(Runtime::new().unwrap()) + }; } pub struct HttpState { @@ -74,20 +66,18 @@ pub struct HttpState { pub http_cache: RwLock, pub auth_cache: RwLock, pub history_states: RwLock>>, - pub ssl_client: OpensslClient, - pub connector: Pool, + pub client: Client, } impl HttpState { - pub fn new(ssl_client: OpensslClient) -> HttpState { + pub fn new(ssl_connector_builder: SslConnectorBuilder) -> HttpState { HttpState { hsts_list: RwLock::new(HstsList::new()), cookie_jar: RwLock::new(CookieStorage::new(150)), auth_cache: RwLock::new(AuthCache::new()), history_states: RwLock::new(HashMap::new()), http_cache: RwLock::new(HttpCache::new()), - ssl_client: ssl_client.clone(), - connector: create_http_connector(ssl_client), + client: create_http_client(ssl_connector_builder, HANDLE.lock().unwrap().executor()), } } } @@ -97,72 +87,63 @@ fn precise_time_ms() -> u64 { } // Step 3 of https://fetch.spec.whatwg.org/#concept-fetch. -pub fn set_default_accept(destination: Destination, headers: &mut Headers) { - if headers.has::() { +pub fn set_default_accept(destination: Destination, headers: &mut HeaderMap) { + if headers.contains_key(header::ACCEPT) { return; } let value = match destination { // Step 3.2. Destination::Document => { vec![ - qitem(mime!(Text / Html)), - qitem(mime!(Application / ("xhtml+xml"))), - QualityItem::new(mime!(Application / Xml), q(0.9)), - QualityItem::new(mime!(_ / _), q(0.8)), + QualityItem::new(mime::TEXT_HTML, Quality::from_u16(1000)), + QualityItem::new("application/xhtml+xml".parse().unwrap(), Quality::from_u16(1000)), + QualityItem::new("application/xml".parse().unwrap(), Quality::from_u16(900)), + QualityItem::new(mime::STAR_STAR, Quality::from_u16(800)) ] }, // Step 3.3. Destination::Image => { vec![ - qitem(mime!(Image / Png)), - qitem(mime!(Image / ("svg+xml") )), - QualityItem::new(mime!(Image / _), q(0.8)), - QualityItem::new(mime!(_ / _), q(0.5)), + QualityItem::new(mime::IMAGE_PNG, Quality::from_u16(1000)), + QualityItem::new(mime::IMAGE_SVG, Quality::from_u16(1000)), + QualityItem::new(mime::IMAGE_STAR, Quality::from_u16(800)), + QualityItem::new(mime::STAR_STAR, Quality::from_u16(500)) ] }, // Step 3.3. Destination::Style => { vec![ - qitem(mime!(Text / Css)), - QualityItem::new(mime!(_ / _), q(0.1)) + QualityItem::new(mime::TEXT_CSS, Quality::from_u16(1000)), + QualityItem::new(mime::STAR_STAR, Quality::from_u16(100)) ] }, // Step 3.1. _ => { - vec![qitem(mime!(_ / _))] + vec![QualityItem::new(mime::STAR_STAR, Quality::from_u16(1000))] }, }; // Step 3.4. - headers.set(Accept(value)); + // TODO(eijebong): Change this once typed headers are done + headers.insert(header::ACCEPT, quality_to_value(value)); } -fn set_default_accept_encoding(headers: &mut Headers) { - if headers.has::() { +fn set_default_accept_encoding(headers: &mut HeaderMap) { + if headers.contains_key(header::ACCEPT_ENCODING) { return } - headers.set(AcceptEncoding(vec![ - qitem(Encoding::Gzip), - qitem(Encoding::Deflate), - qitem(Encoding::EncodingExt("br".to_owned())) - ])); + // TODO(eijebong): Change this once typed headers are done + headers.insert(header::ACCEPT_ENCODING, HeaderValue::from_static("gzip, deflate, br")); } -pub fn set_default_accept_language(headers: &mut Headers) { - if headers.has::() { +pub fn set_default_accept_language(headers: &mut HeaderMap) { + if headers.contains_key(header::ACCEPT_LANGUAGE) { return; } - let mut en_us: LanguageTag = Default::default(); - en_us.language = Some("en".to_owned()); - en_us.region = Some("US".to_owned()); - let mut en: LanguageTag = Default::default(); - en.language = Some("en".to_owned()); - headers.set(AcceptLanguage(vec![ - qitem(en_us), - QualityItem::new(en, Quality(500)), - ])); + // TODO(eijebong): Change this once typed headers are done + headers.insert(header::ACCEPT_LANGUAGE, HeaderValue::from_static("en-US, en; q=0.5")); } /// @@ -210,12 +191,12 @@ fn strip_url(mut referrer_url: ServoUrl, origin_only: bool) -> Option /// /// Steps 4-6. -pub fn determine_request_referrer(headers: &mut Headers, +pub fn determine_request_referrer(headers: &mut HeaderMap, referrer_policy: ReferrerPolicy, referrer_source: ServoUrl, current_url: ServoUrl) -> Option { - assert!(!headers.has::()); + assert!(!headers.contains_key(header::REFERER)); // FIXME(#14505): this does not seem to be the correct way of checking for // same-origin requests. let cross_origin = referrer_source.origin() != current_url.origin(); @@ -233,94 +214,65 @@ pub fn determine_request_referrer(headers: &mut Headers, } } -pub fn set_request_cookies(url: &ServoUrl, headers: &mut Headers, cookie_jar: &RwLock) { +pub fn set_request_cookies(url: &ServoUrl, headers: &mut HeaderMap, cookie_jar: &RwLock) { let mut cookie_jar = cookie_jar.write().unwrap(); if let Some(cookie_list) = cookie_jar.cookies_for_url(url, CookieSource::HTTP) { - let mut v = Vec::new(); - v.push(cookie_list.into_bytes()); - headers.set_raw("Cookie".to_owned(), v); + headers.insert(header::COOKIE, HeaderValue::from_bytes(cookie_list.as_bytes()).unwrap()); } } fn set_cookie_for_url(cookie_jar: &RwLock, request: &ServoUrl, - cookie_val: String) { + cookie_val: &str) { let mut cookie_jar = cookie_jar.write().unwrap(); let source = CookieSource::HTTP; - let header = Header::parse_header(&[cookie_val.into_bytes()]); - if let Ok(SetCookie(cookies)) = header { - for cookie in cookies { - if let Some(cookie) = cookie::Cookie::from_cookie_string(cookie, request, source) { - cookie_jar.push(cookie, request, source); - } - } + if let Some(cookie) = cookie::Cookie::from_cookie_string(cookie_val.into(), request, source) { + cookie_jar.push(cookie, request, source); } } -fn set_cookies_from_headers(url: &ServoUrl, headers: &Headers, cookie_jar: &RwLock) { - if let Some(cookies) = headers.get_raw("set-cookie") { - for cookie in cookies.iter() { - if let Ok(cookie_value) = String::from_utf8(cookie.clone()) { - set_cookie_for_url(&cookie_jar, - &url, - cookie_value); - } +fn set_cookies_from_headers(url: &ServoUrl, headers: &HeaderMap, cookie_jar: &RwLock) { + for cookie in headers.get_all(header::SET_COOKIE) { + if let Ok(cookie_str) = cookie.to_str() { + set_cookie_for_url(&cookie_jar, + &url, + &cookie_str); } } } -struct StreamedResponse { - decoder: Decoder, -} - - -impl Read for StreamedResponse { - #[inline] - fn read(&mut self, buf: &mut [u8]) -> io::Result { - match self.decoder { - Decoder::Gzip(ref mut d) => d.read(buf), - Decoder::Deflate(ref mut d) => d.read(buf), - Decoder::Brotli(ref mut d) => d.read(buf), - Decoder::Plain(ref mut d) => d.read(buf) - } - } -} - -impl StreamedResponse { - fn from_http_response(response: HyperResponse) -> io::Result { - let decoder = { - if let Some(ref encoding) = response.headers.get::().cloned() { - if encoding.contains(&Encoding::Gzip) { - Decoder::Gzip(GzDecoder::new(response)) - } - else if encoding.contains(&Encoding::Deflate) { - Decoder::Deflate(DeflateDecoder::new(response)) - } - else if encoding.contains(&Encoding::EncodingExt("br".to_owned())) { - Decoder::Brotli(Decompressor::new(response, 1024)) - } else { - Decoder::Plain(response) - } +impl Decoder { + fn from_http_response(response: &HyperResponse) -> Decoder { + if let Some(encoding) = response.headers().typed_get::() { + if encoding.contains("gzip") { + Decoder::Gzip(None) + } + else if encoding.contains("deflate") { + Decoder::Deflate(DeflateDecoder::new(Cursor::new(Bytes::new()))) + } + else if encoding.contains("br") { + Decoder::Brotli(Decompressor::new(Cursor::new(Bytes::new()), BUF_SIZE)) } else { - Decoder::Plain(response) + Decoder::Plain } - }; - Ok(StreamedResponse { decoder: decoder }) + } else { + Decoder::Plain + } } } -enum Decoder { - Gzip(GzDecoder), - Deflate(DeflateDecoder), - Brotli(Decompressor), - Plain(HyperResponse) +pub enum Decoder { + Gzip(Option>>), + Deflate(DeflateDecoder>), + Brotli(Decompressor>), + Plain, } fn prepare_devtools_request(request_id: String, url: ServoUrl, method: Method, - headers: Headers, + headers: HeaderMap, body: Option>, pipeline_id: PipelineId, now: Tm, @@ -351,7 +303,7 @@ fn send_request_to_devtools(msg: ChromeToDevtoolsControlMsg, fn send_response_to_devtools(devtools_chan: &Sender, request_id: String, - headers: Option, + headers: Option, status: Option<(u16, Vec)>, pipeline_id: PipelineId) { let response = DevtoolsHttpResponse { headers: headers, status: status, body: None, pipeline_id: pipeline_id }; @@ -361,111 +313,93 @@ fn send_response_to_devtools(devtools_chan: &Sender, let _ = devtools_chan.send(DevtoolsControlMsg::FromChrome(msg)); } -fn auth_from_cache(auth_cache: &RwLock, origin: &ImmutableOrigin) -> Option { +fn auth_from_cache(auth_cache: &RwLock, origin: &ImmutableOrigin) -> Option> { if let Some(ref auth_entry) = auth_cache.read().unwrap().entries.get(&origin.ascii_serialization()) { - let user_name = auth_entry.user_name.clone(); - let password = Some(auth_entry.password.clone()); - Some(Basic { username: user_name, password: password }) + let user_name = &auth_entry.user_name; + let password = &auth_entry.password; + Some(Authorization::basic(user_name, password)) } else { None } } -fn obtain_response(connector: &Pool, +fn obtain_response(client: &Client, url: &ServoUrl, method: &Method, - request_headers: &Headers, + request_headers: &HeaderMap, data: &Option>, load_data_method: &Method, pipeline_id: &Option, iters: u32, request_id: Option<&str>, is_xhr: bool) - -> Result<(HyperResponse, Option), NetworkError> { - let null_data = None; - - // loop trying connections in connection pool - // they may have grown stale (disconnected), in which case we'll get - // a ConnectionAborted error. this loop tries again with a new - // connection. - loop { - let mut headers = request_headers.clone(); - - // Avoid automatically sending request body if a redirect has occurred. - // - // TODO - This is the wrong behaviour according to the RFC. However, I'm not - // sure how much "correctness" vs. real-world is important in this case. - // - // https://tools.ietf.org/html/rfc7231#section-6.4 - let is_redirected_request = iters != 1; - let request_body; - match data { - &Some(ref d) if !is_redirected_request => { - headers.set(ContentLength(d.len() as u64)); - request_body = data; - } - _ => { - if *load_data_method != Method::Get && *load_data_method != Method::Head { - headers.set(ContentLength(0)) - } - request_body = &null_data; - } + -> Box, Option), + Error = NetworkError>> { + let mut headers = request_headers.clone(); + + // Avoid automatically sending request body if a redirect has occurred. + // + // TODO - This is the wrong behaviour according to the RFC. However, I'm not + // sure how much "correctness" vs. real-world is important in this case. + // + // https://tools.ietf.org/html/rfc7231#section-6.4 + let is_redirected_request = iters != 1; + let request_body; + match data { + &Some(ref d) if !is_redirected_request => { + headers.typed_insert(ContentLength(d.len() as u64)); + request_body = d.clone(); } - - if log_enabled!(log::Level::Info) { - info!("{} {}", method, url); - for header in headers.iter() { - info!(" - {}", header); + _ => { + if *load_data_method != Method::GET && *load_data_method != Method::HEAD { + headers.typed_insert(ContentLength(0)) } - info!("{:?}", data); + request_body = vec![]; } + } - let connect_start = precise_time_ms(); - - let request = HyperRequest::with_connector(method.clone(), - url.clone().into_url(), - &*connector); - let mut request = match request { - Ok(request) => request, - Err(e) => return Err(NetworkError::from_hyper_error(&url, e)), - }; - *request.headers_mut() = headers.clone(); - - let connect_end = precise_time_ms(); - - let send_start = precise_time_ms(); + if log_enabled!(log::Level::Info) { + info!("{} {}", method, url); + for header in headers.iter() { + info!(" - {:?}", header); + } + info!("{:?}", data); + } - let mut request_writer = match request.start() { - Ok(streaming) => streaming, - Err(e) => return Err(NetworkError::Internal(e.description().to_owned())), - }; + let connect_start = precise_time_ms(); + // https://url.spec.whatwg.org/#percent-encoded-bytes + let request = HyperRequest::builder() + .method(method) + .uri(url.clone().into_url().as_ref().replace("|", "%7C").replace("{", "%7B").replace("}", "%7D")) + .body(WrappedBody::new(request_body.clone().into())); - if let Some(ref data) = *request_body { - if let Err(e) = request_writer.write_all(&data) { - return Err(NetworkError::Internal(e.description().to_owned())) - } - } + let mut request = match request { + Ok(request) => request, + Err(e) => return Box::new(future::result(Err(NetworkError::from_http_error(&e)))), + }; + *request.headers_mut() = headers.clone(); + let connect_end = precise_time_ms(); - let response = match request_writer.send() { - Ok(w) => w, - Err(HttpError::Io(ref io_error)) - if io_error.kind() == io::ErrorKind::ConnectionAborted || - io_error.kind() == io::ErrorKind::ConnectionReset => { - debug!("connection aborted ({:?}), possibly stale, trying new connection", io_error.description()); - continue; - }, - Err(e) => return Err(NetworkError::Internal(e.description().to_owned())), - }; + let request_id = request_id.map(|v| v.to_owned()); + let pipeline_id = pipeline_id.clone(); + let closure_url = url.clone(); + let method = method.clone(); + let send_start = precise_time_ms(); + Box::new(client.request(request).and_then(move |res| { let send_end = precise_time_ms(); let msg = if let Some(request_id) = request_id { - if let Some(pipeline_id) = *pipeline_id { + if let Some(pipeline_id) = pipeline_id { Some(prepare_devtools_request( - request_id.into(), - url.clone(), method.clone(), headers, - request_body.clone(), pipeline_id, time::now(), + request_id, + closure_url, method.clone(), headers, + Some(request_body.clone()), pipeline_id, time::now(), connect_end - connect_start, send_end - send_start, is_xhr)) + // TODO: ^This is not right, connect_start is taken before contructing the + // request and connect_end at the end of it. send_start is takend before the + // connection too. I'm not sure it's currently possible to get the time at the + // point between the connection and the start of a request. } else { debug!("Not notifying devtools (no pipeline_id)"); None @@ -474,8 +408,9 @@ fn obtain_response(connector: &Pool, debug!("Not notifying devtools (no request_id)"); None }; - return Ok((response, msg)); - } + let decoder = Decoder::from_http_response(&res); + Ok((res.map(move |r| WrappedBody::new_with_decoder(r, decoder)), msg)) + }).map_err(move |e| NetworkError::from_hyper_error(&e))) } /// [HTTP fetch](https://fetch.spec.whatwg.org#http-fetch) @@ -543,8 +478,8 @@ pub fn http_fetch(request: &mut Request, let method_mismatch = !method_cache_match && (!is_cors_safelisted_method(&request.method) || request.use_cors_preflight); - let header_mismatch = request.headers.iter().any(|view| - !cache.match_header(&*request, view.name()) && !is_cors_safelisted_request_header(&view) + let header_mismatch = request.headers.iter().any(|(name, value)| + !cache.match_header(&*request, &name) && !is_cors_safelisted_request_header(&name, &value) ); // Sub-substep 1 @@ -579,16 +514,19 @@ pub fn http_fetch(request: &mut Request, let mut response = response.unwrap(); // Step 5 - if response.actual_response().status.map_or(false, is_redirect_status) { + if response.actual_response().status.as_ref().map_or(false, is_redirect_status) { // Substep 1. - if response.actual_response().status.map_or(true, |s| s != StatusCode::SeeOther) { + if response.actual_response().status.as_ref().map_or(true, |s| s.0 != StatusCode::SEE_OTHER) { // TODO: send RST_STREAM frame } // Substep 2-3. - let location = response.actual_response().headers.get::().map( - |l| ServoUrl::parse_with_base(response.actual_response().url(), l) - .map_err(|err| err.description().into())); + let location = response.actual_response().headers.get(header::LOCATION) + .and_then(|v| HeaderValue::to_str(v).map(|l| { + ServoUrl::parse_with_base(response.actual_response().url(), &l) + .map_err(|err| err.description().into()) + }).ok() + ); // Substep 4. response.actual_response_mut().location_url = location; @@ -664,7 +602,7 @@ pub fn http_redirect_fetch(request: &mut Request, } // Step 9 - if response.actual_response().status.map_or(true, |s| s != StatusCode::SeeOther) && + if response.actual_response().status.as_ref().map_or(true, |s| s.0 != StatusCode::SEE_OTHER) && request.body.as_ref().map_or(false, |b| b.is_empty()) { return Response::network_error(NetworkError::Internal("Request body is not done".into())); } @@ -675,10 +613,10 @@ pub fn http_redirect_fetch(request: &mut Request, } // Step 11 - if response.actual_response().status.map_or(false, |code| - ((code == StatusCode::MovedPermanently || code == StatusCode::Found) && request.method == Method::Post) || - (code == StatusCode::SeeOther && request.method != Method::Head)) { - request.method = Method::Get; + if response.actual_response().status.as_ref().map_or(false, |(code, _)| + ((*code == StatusCode::MOVED_PERMANENTLY || *code == StatusCode::FOUND) && request.method == Method::POST) || + (*code == StatusCode::SEE_OTHER && request.method != Method::HEAD)) { + request.method = Method::GET; request.body = None; } @@ -701,10 +639,9 @@ pub fn http_redirect_fetch(request: &mut Request, fn try_immutable_origin_to_hyper_origin(url_origin: &ImmutableOrigin) -> Option { match *url_origin { - // TODO (servo/servo#15569) Set "Origin: null" when hyper supports it - ImmutableOrigin::Opaque(_) => None, + ImmutableOrigin::Opaque(_) => Some(HyperOrigin::NULL), ImmutableOrigin::Tuple(ref scheme, ref host, ref port) => - Some(HyperOrigin::new(scheme.clone(), host.to_string(), Some(port.clone()))) + HyperOrigin::try_from_parts(&scheme, &host.to_string(), Some(port.clone())).ok() } } @@ -742,7 +679,7 @@ fn http_network_or_cache_fetch(request: &mut Request, None => match http_request.method { // Step 6 - Method::Post | Method::Put => + Method::POST | Method::PUT => Some(0), // Step 5 _ => None @@ -753,7 +690,7 @@ fn http_network_or_cache_fetch(request: &mut Request, // Step 8 if let Some(content_length_value) = content_length_value { - http_request.headers.set(ContentLength(content_length_value)); + http_request.headers.typed_insert(ContentLength(content_length_value)); if http_request.keep_alive { // Step 9 TODO: needs request's client object } @@ -764,7 +701,7 @@ fn http_network_or_cache_fetch(request: &mut Request, match http_request.referrer { Referrer::NoReferrer => (), Referrer::ReferrerUrl(ref http_request_referrer) => - http_request.headers.set(Referer(http_request_referrer.to_string())), + http_request.headers.typed_insert::(http_request_referrer.to_string().parse().unwrap()), Referrer::Client => // it should be impossible for referrer to be anything else during fetching // https://fetch.spec.whatwg.org/#concept-request-referrer @@ -772,19 +709,19 @@ fn http_network_or_cache_fetch(request: &mut Request, }; // Step 11 - if cors_flag || (http_request.method != Method::Get && http_request.method != Method::Head) { + if cors_flag || (http_request.method != Method::GET && http_request.method != Method::HEAD) { debug_assert_ne!(http_request.origin, Origin::Client); if let Origin::Origin(ref url_origin) = http_request.origin { if let Some(hyper_origin) = try_immutable_origin_to_hyper_origin(url_origin) { - http_request.headers.set(hyper_origin) + http_request.headers.typed_insert(hyper_origin) } } } // Step 12 - if !http_request.headers.has::() { + if !http_request.headers.contains_key(header::USER_AGENT) { let user_agent = context.user_agent.clone().into_owned(); - http_request.headers.set(UserAgent(user_agent)); + http_request.headers.typed_insert::(user_agent.parse().unwrap()); } match http_request.cache_mode { @@ -794,20 +731,20 @@ fn http_network_or_cache_fetch(request: &mut Request, }, // Step 14 - CacheMode::NoCache if !http_request.headers.has::() => { - http_request.headers.set(CacheControl(vec![CacheDirective::MaxAge(0)])); + CacheMode::NoCache if !http_request.headers.contains_key(header::CACHE_CONTROL) => { + http_request.headers.typed_insert(CacheControl::new().with_max_age(Duration::from_secs(0))); }, // Step 15 CacheMode::Reload | CacheMode::NoStore => { // Substep 1 - if !http_request.headers.has::() { - http_request.headers.set(Pragma::NoCache); + if !http_request.headers.contains_key(header::PRAGMA) { + http_request.headers.typed_insert(Pragma::no_cache()); } // Substep 2 - if !http_request.headers.has::() { - http_request.headers.set(CacheControl(vec![CacheDirective::NoCache])); + if !http_request.headers.contains_key(header::CACHE_CONTROL) { + http_request.headers.typed_insert(CacheControl::new().with_no_cache()); } }, @@ -816,11 +753,13 @@ fn http_network_or_cache_fetch(request: &mut Request, // Step 16 let current_url = http_request.current_url(); - let host = Host { - hostname: current_url.host_str().unwrap().to_owned(), - port: current_url.port() - }; - http_request.headers.set(host); + let host = Host::from( + format!("{}{}", current_url.host_str().unwrap(), + current_url.port().map(|v| format!(":{}", v)).unwrap_or("".into()) + ).parse::().unwrap() + ); + + http_request.headers.typed_insert(host); // unlike http_loader, we should not set the accept header // here, according to the fetch spec set_default_accept_encoding(&mut http_request.headers); @@ -835,7 +774,7 @@ fn http_network_or_cache_fetch(request: &mut Request, &mut http_request.headers, &context.state.cookie_jar); // Substep 2 - if !http_request.headers.has::>() { + if !http_request.headers.contains_key(header::AUTHORIZATION) { // Substep 3 let mut authorization_value = None; @@ -849,16 +788,16 @@ fn http_network_or_cache_fetch(request: &mut Request, // Substep 5 if authentication_fetch_flag && authorization_value.is_none() { if has_credentials(¤t_url) { - authorization_value = Some(Basic { - username: current_url.username().to_owned(), - password: current_url.password().map(str::to_owned) - }) + authorization_value = Some(Authorization::basic( + current_url.username(), + current_url.password().unwrap_or("") + )); } } // Substep 6 if let Some(basic) = authorization_value { - http_request.headers.set(Authorization(basic)); + http_request.headers.typed_insert(basic); } } } @@ -886,17 +825,12 @@ fn http_network_or_cache_fetch(request: &mut Request, if needs_revalidation { revalidating_flag = true; // Substep 5 - // TODO: find out why the typed header getter return None from the headers of cached responses. - if let Some(date_slice) = response_headers.get_raw("Last-Modified") { - let date_string = String::from_utf8_lossy(&date_slice[0]); - if let Ok(http_date) = HttpDate::from_str(&date_string) { - http_request.headers.set(IfModifiedSince(http_date)); - } + if let Some(http_date) = response_headers.typed_get::() { + let http_date: SystemTime = http_date.into(); + http_request.headers.typed_insert(IfModifiedSince::from(http_date)); } - if let Some(entity_tag) = - response_headers.get_raw("ETag") { - http_request.headers.set_raw("If-None-Match", entity_tag.to_vec()); - + if let Some(entity_tag) = response_headers.get(header::ETAG) { + http_request.headers.insert(header::IF_NONE_MATCH, entity_tag.clone()); } } else { // Substep 6 @@ -945,14 +879,14 @@ fn http_network_or_cache_fetch(request: &mut Request, done_chan, context); // Substep 3 if let Some((200...399, _)) = forward_response.raw_status { - if !http_request.method.safe() { + if !http_request.method.is_safe() { if let Ok(mut http_cache) = context.state.http_cache.write() { http_cache.invalidate(&http_request, &forward_response); } } } // Substep 4 - if revalidating_flag && forward_response.status.map_or(false, |s| s == StatusCode::NotModified) { + if revalidating_flag && forward_response.status.as_ref().map_or(false, |s| s.0 == StatusCode::NOT_MODIFIED) { if let Ok(mut http_cache) = context.state.http_cache.write() { response = http_cache.refresh(&http_request, forward_response.clone(), done_chan); wait_for_cached_response(done_chan, &mut response); @@ -976,7 +910,9 @@ fn http_network_or_cache_fetch(request: &mut Request, // Step 23 // FIXME: Figure out what to do with request window objects - if let (Some(StatusCode::Unauthorized), false, true) = (response.status, cors_flag, credentials_flag) { + if let (Some((StatusCode::UNAUTHORIZED, _)), false, true) = + (response.status.as_ref(), cors_flag, credentials_flag) + { // Substep 1 // TODO: Spec says requires testing on multiple WWW-Authenticate headers @@ -1002,7 +938,7 @@ fn http_network_or_cache_fetch(request: &mut Request, } // Step 24 - if let Some(StatusCode::ProxyAuthenticationRequired) = response.status { + if let Some((StatusCode::PROXY_AUTHENTICATION_REQUIRED, _)) = response.status.as_ref() { // Step 1 if request_has_no_window { return Response::network_error(NetworkError::Internal("Can't find Window object".into())); @@ -1062,38 +998,38 @@ fn http_network_fetch(request: &Request, // do not. Once we support other kinds of fetches we'll need to be more fine grained here // since things like image fetches are classified differently by devtools let is_xhr = request.destination == Destination::None; - let wrapped_response = obtain_response(&context.state.connector, - &url, - &request.method, - &request.headers, - &request.body, &request.method, - &request.pipeline_id, request.redirect_count + 1, - request_id.as_ref().map(Deref::deref), is_xhr); + let response_future = obtain_response(&context.state.client, + &url, + &request.method, + &request.headers, + &request.body, &request.method, + &request.pipeline_id, request.redirect_count + 1, + request_id.as_ref().map(Deref::deref), is_xhr); let pipeline_id = request.pipeline_id; - let (res, msg) = match wrapped_response { + // This will only get the headers, the body is read later + let (res, msg) = match response_future.wait() { Ok(wrapped_response) => wrapped_response, Err(error) => return Response::network_error(error), }; if log_enabled!(log::Level::Info) { info!("response for {}", url); - for header in res.headers.iter() { - info!(" - {}", header); + for header in res.headers().iter() { + info!(" - {:?}", header); } } let mut response = Response::new(url.clone()); - response.status = Some(res.status); - response.raw_status = Some((res.status_raw().0, - res.status_raw().1.as_bytes().to_vec())); - response.headers = res.headers.clone(); + response.status = Some((res.status(), res.status().canonical_reason().unwrap_or("").into())); + response.raw_status = Some((res.status().as_u16(), res.status().canonical_reason().unwrap_or("").into())); + response.headers = res.headers().clone(); response.referrer = request.referrer.to_url().cloned(); response.referrer_policy = request.referrer_policy.clone(); let res_body = response.body.clone(); - // We're about to spawn a thread to be waited on here + // We're about to spawn a future to be waited on here let (done_sender, done_receiver) = channel(); *done_chan = Some((done_sender.clone(), done_receiver)); let meta = match response.metadata().expect("Response metadata should exist at this stage") { @@ -1107,68 +1043,56 @@ fn http_network_fetch(request: &Request, if cancellation_listener.lock().unwrap().cancelled() { return Response::network_error(NetworkError::Internal("Fetch aborted".into())) } - thread::Builder::new().name(format!("fetch worker thread")).spawn(move || { - match StreamedResponse::from_http_response(res) { - Ok(mut res) => { - *res_body.lock().unwrap() = ResponseBody::Receiving(vec![]); - - if let Some(ref sender) = devtools_sender { - if let Some(m) = msg { - send_request_to_devtools(m, &sender); - } - // --- Tell devtools that we got a response - // Send an HttpResponse message to devtools with the corresponding request_id - if let Some(pipeline_id) = pipeline_id { - send_response_to_devtools( - &sender, request_id.unwrap(), - meta_headers.map(Serde::into_inner), - meta_status, - pipeline_id); - } - } + *res_body.lock().unwrap() = ResponseBody::Receiving(vec![]); - loop { - if cancellation_listener.lock().unwrap().cancelled() { - *res_body.lock().unwrap() = ResponseBody::Done(vec![]); - let _ = done_sender.send(Data::Cancelled); - return; - } - match read_block(&mut res) { - Ok(Data::Payload(chunk)) => { - if let ResponseBody::Receiving(ref mut body) = *res_body.lock().unwrap() { - body.extend_from_slice(&chunk); - let _ = done_sender.send(Data::Payload(chunk)); - } - }, - Ok(Data::Done) | Err(_) => { - let mut body = res_body.lock().unwrap(); - let completed_body = match *body { - ResponseBody::Receiving(ref mut body) => { - mem::replace(body, vec![]) - }, - _ => vec![], - }; - *body = ResponseBody::Done(completed_body); - let _ = done_sender.send(Data::Done); - break; - } - Ok(Data::Cancelled) => unreachable!() // read_block doesn't return Data::Cancelled - } - } - } - Err(_) => { - // XXXManishearth we should propagate this error somehow - *res_body.lock().unwrap() = ResponseBody::Done(vec![]); - let _ = done_sender.send(Data::Done); - } + if let Some(ref sender) = devtools_sender { + if let Some(m) = msg { + send_request_to_devtools(m, &sender); } - }).expect("Thread spawning failed"); - // TODO these substeps aren't possible yet - // Substep 1 + // --- Tell devtools that we got a response + // Send an HttpResponse message to devtools with the corresponding request_id + if let Some(pipeline_id) = pipeline_id { + send_response_to_devtools( + &sender, request_id.unwrap(), + meta_headers.map(Serde::into_inner), + meta_status, + pipeline_id); + } + } - // Substep 2 + let done_sender = done_sender.clone(); + let done_sender2 = done_sender.clone(); + HANDLE.lock().unwrap().spawn(res.into_body().map_err(|_|()).fold(res_body, move |res_body, chunk| { + if cancellation_listener.lock().unwrap().cancelled() { + *res_body.lock().unwrap() = ResponseBody::Done(vec![]); + let _ = done_sender.send(Data::Cancelled); + return future::failed(()); + } + if let ResponseBody::Receiving(ref mut body) = *res_body.lock().unwrap() { + let bytes = chunk.into_bytes(); + body.extend_from_slice(&*bytes); + let _ = done_sender.send(Data::Payload(bytes.to_vec())); + } + future::ok(res_body) + }).and_then(move |res_body| { + let mut body = res_body.lock().unwrap(); + let completed_body = match *body { + ResponseBody::Receiving(ref mut body) => { + mem::replace(body, vec![]) + }, + _ => vec![], + }; + *body = ResponseBody::Done(completed_body); + let _ = done_sender2.send(Data::Done); + future::ok(()) + }).map_err(|_| ())); + + // TODO these substeps aren't possible yet + // Substep 1 + + // Substep 2 // TODO Determine if response was retrieved over HTTPS // TODO Servo needs to decide what ciphers are to be treated as "deprecated" @@ -1183,11 +1107,11 @@ fn http_network_fetch(request: &Request, // TODO when https://bugzilla.mozilla.org/show_bug.cgi?id=1030660 // is resolved, this step will become uneccesary // TODO this step - if let Some(encoding) = response.headers.get::() { - if encoding.contains(&Encoding::Gzip) { + if let Some(encoding) = response.headers.typed_get::() { + if encoding.contains("gzip") { } - else if encoding.contains(&Encoding::Compress) { + else if encoding.contains("compress") { } }; @@ -1228,7 +1152,7 @@ fn cors_preflight_fetch(request: &Request, -> Response { // Step 1 let mut preflight = Request::new(request.current_url(), Some(request.origin.clone()), request.pipeline_id); - preflight.method = Method::Options; + preflight.method = Method::OPTIONS; preflight.initiator = request.initiator.clone(); preflight.destination = request.destination.clone(); preflight.origin = request.origin.clone(); @@ -1236,20 +1160,24 @@ fn cors_preflight_fetch(request: &Request, preflight.referrer_policy = request.referrer_policy; // Step 2 - preflight.headers.set::( - AccessControlRequestMethod(request.method.clone())); + preflight.headers.typed_insert::( + AccessControlRequestMethod::from(request.method.clone())); // Step 3 let mut headers = request.headers .iter() - .filter(|view| !is_cors_safelisted_request_header(view)) - .map(|view| UniCase(view.name().to_ascii_lowercase().to_owned())) - .collect::>>(); + .filter(|(name, value)| !is_cors_safelisted_request_header(&name, &value)) + .map(|(name, _)| name.as_str()) + .collect::>(); headers.sort(); + let headers = headers + .iter() + .map(|name| HeaderName::from_str(name).unwrap()) + .collect::>(); // Step 4 if !headers.is_empty() { - preflight.headers.set::(AccessControlRequestHeaders(headers)); + preflight.headers.typed_insert(AccessControlRequestHeaders::from_iter(headers)); } // Step 5 @@ -1257,11 +1185,11 @@ fn cors_preflight_fetch(request: &Request, // Step 6 if cors_check(&request, &response).is_ok() && - response.status.map_or(false, |status| status.is_success()) { + response.status.as_ref().map_or(false, |(status, _)| status.is_success()) { // Substep 1, 2 - let mut methods = if response.headers.has::() { - match response.headers.get::() { - Some(&AccessControlAllowMethods(ref m)) => m.clone(), + let mut methods = if response.headers.contains_key(header::ACCESS_CONTROL_ALLOW_METHODS) { + match response.headers.typed_get::() { + Some(methods) => methods.iter().collect(), // Substep 4 None => return Response::network_error(NetworkError::Internal("CORS ACAM check failed".into())) } @@ -1270,9 +1198,9 @@ fn cors_preflight_fetch(request: &Request, }; // Substep 3 - let header_names = if response.headers.has::() { - match response.headers.get::() { - Some(&AccessControlAllowHeaders(ref hn)) => hn.clone(), + let header_names = if response.headers.contains_key(header::ACCESS_CONTROL_ALLOW_HEADERS) { + match response.headers.typed_get::() { + Some(names) => names.iter().collect(), // Substep 4 None => return Response::network_error(NetworkError::Internal("CORS ACAH check failed".into())) } @@ -1282,7 +1210,7 @@ fn cors_preflight_fetch(request: &Request, // Substep 5 if (methods.iter().any(|m| m.as_ref() == "*") || - header_names.iter().any(|hn| &**hn == "*")) && + header_names.iter().any(|hn| hn.as_str() == "*")) && request.credentials_mode == CredentialsMode::Include { return Response::network_error( NetworkError::Internal("CORS ACAH/ACAM and request credentials mode mismatch".into())); @@ -1304,22 +1232,24 @@ fn cors_preflight_fetch(request: &Request, // Substep 8 if request.headers.iter().any( - |header| header.name() == "authorization" && - header_names.iter().all(|hn| *hn != UniCase(header.name()))) { + |(name, _)| name == header::AUTHORIZATION && + header_names.iter().all(|hn| hn != name)) { return Response::network_error(NetworkError::Internal("CORS authorization check failed".into())); } // Substep 9 debug!("CORS check: Allowed headers: {:?}, current headers: {:?}", header_names, request.headers); - let set: HashSet<&UniCase> = HashSet::from_iter(header_names.iter()); + let set: HashSet<&HeaderName> = HashSet::from_iter(header_names.iter()); if request.headers.iter().any( - |ref hv| !set.contains(&UniCase(hv.name().to_owned())) && !is_cors_safelisted_request_header(hv)) { + |(name, value)| !set.contains(name) && !is_cors_safelisted_request_header(&name, &value)) { return Response::network_error(NetworkError::Internal("CORS headers check failed".into())); } // Substep 10, 11 - let max_age = response.headers.get::().map(|acma| acma.0).unwrap_or(0); - + let max_age: Duration = response.headers.typed_get::() + .map(|acma| acma.into()) + .unwrap_or(Duration::from_secs(0)); + let max_age = max_age.as_secs() as u32; // Substep 12 // TODO: Need to define what an imposed limit on max-age is @@ -1346,26 +1276,26 @@ fn cors_preflight_fetch(request: &Request, /// [CORS check](https://fetch.spec.whatwg.org#concept-cors-check) fn cors_check(request: &Request, response: &Response) -> Result<(), ()> { // Step 1 - let origin = response.headers.get::().cloned(); + let origin = response.headers.typed_get::(); // Step 2 let origin = origin.ok_or(())?; // Step 3 if request.credentials_mode != CredentialsMode::Include && - origin == AccessControlAllowOrigin::Any { + origin == AccessControlAllowOrigin::ANY { return Ok(()); } // Step 4 - let origin = match origin { - AccessControlAllowOrigin::Value(origin) => origin, + let origin = match origin.origin() { + Some(origin) => origin, // if it's Any or Null at this point, there's nothing to do but return Err(()) - _ => return Err(()) + None => return Err(()) }; match request.origin { - Origin::Origin(ref o) if o.ascii_serialization() == origin.trim() => {}, + Origin::Origin(ref o) if o.ascii_serialization() == origin.to_string().trim() => {}, _ => return Err(()) } @@ -1375,7 +1305,7 @@ fn cors_check(request: &Request, response: &Response) -> Result<(), ()> { } // Step 6 - let credentials = response.headers.get::().cloned(); + let credentials = response.headers.typed_get::(); // Step 7 if credentials.is_some() { @@ -1390,20 +1320,20 @@ fn has_credentials(url: &ServoUrl) -> bool { !url.username().is_empty() || url.password().is_some() } -fn is_no_store_cache(headers: &Headers) -> bool { - headers.has::() | headers.has::() | - headers.has::() | headers.has::() | - headers.has::() +fn is_no_store_cache(headers: &HeaderMap) -> bool { + headers.contains_key(header::IF_MODIFIED_SINCE) | headers.contains_key(header::IF_NONE_MATCH) | + headers.contains_key(header::IF_UNMODIFIED_SINCE) | headers.contains_key(header::IF_MATCH) | + headers.contains_key(header::IF_RANGE) } /// -pub fn is_redirect_status(status: StatusCode) -> bool { - match status { - StatusCode::MovedPermanently | - StatusCode::Found | - StatusCode::SeeOther | - StatusCode::TemporaryRedirect | - StatusCode::PermanentRedirect => true, +pub fn is_redirect_status(status: &(StatusCode, String)) -> bool { + match status.0 { + StatusCode::MOVED_PERMANENTLY | + StatusCode::FOUND | + StatusCode::SEE_OTHER | + StatusCode::TEMPORARY_REDIRECT | + StatusCode::PERMANENT_REDIRECT => true, _ => false, } } diff --git a/components/net/lib.rs b/components/net/lib.rs index 285a755a9e9a..cebeb447aef2 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -6,10 +6,14 @@ extern crate base64; extern crate brotli; +extern crate bytes; extern crate cookie as cookie_rs; extern crate devtools_traits; extern crate embedder_traits; extern crate flate2; +extern crate headers_core; +extern crate headers_ext; +extern crate http; extern crate hyper; extern crate hyper_openssl; extern crate hyper_serde; @@ -21,7 +25,6 @@ extern crate lazy_static; extern crate malloc_size_of; #[macro_use] extern crate malloc_size_of_derive; #[macro_use] #[no_link] extern crate matches; -#[macro_use] extern crate mime; extern crate mime_guess; extern crate msg; @@ -38,7 +41,7 @@ extern crate servo_channel; extern crate servo_config; extern crate servo_url; extern crate time; -extern crate unicase; +extern crate tokio; extern crate url; extern crate uuid; extern crate webrender_api; diff --git a/components/net/mime_classifier.rs b/components/net/mime_classifier.rs index f59dc2b925d6..801f5bce9b39 100644 --- a/components/net/mime_classifier.rs +++ b/components/net/mime_classifier.rs @@ -2,9 +2,8 @@ * 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/. */ -use hyper::mime::TopLevel; +use mime::{self, Mime}; use net_traits::LoadContext; -use std::borrow::ToOwned; pub struct MimeClassifier { image_classifier: GroupedClassifier, @@ -49,34 +48,28 @@ pub enum NoSniffFlag { Off } -pub type MimeType = (TopLevel, String); - impl MimeClassifier { //Performs MIME Type Sniffing Algorithm (sections 7 and 8) - pub fn classify(&self, + pub fn classify<'a>(&'a self, context: LoadContext, no_sniff_flag: NoSniffFlag, apache_bug_flag: ApacheBugFlag, - supplied_type: &Option, - data: &[u8]) -> MimeType { - let supplied_type_or_octet_stream = supplied_type.clone() - .unwrap_or((TopLevel::Application, - "octet-stream".to_owned())); + supplied_type: &Option, + data: &'a [u8]) -> Mime { + let supplied_type_or_octet_stream = supplied_type.clone().unwrap_or(mime::APPLICATION_OCTET_STREAM); match context { LoadContext::Browsing => match *supplied_type { None => self.sniff_unknown_type(no_sniff_flag, data), Some(ref supplied_type) => { - let &(ref media_type, ref media_subtype) = supplied_type; - if MimeClassifier::is_explicit_unknown(media_type, media_subtype) { + if MimeClassifier::is_explicit_unknown(supplied_type) { self.sniff_unknown_type(no_sniff_flag, data) } else { match no_sniff_flag { NoSniffFlag::On => supplied_type.clone(), NoSniffFlag::Off => match apache_bug_flag { ApacheBugFlag::On => self.sniff_text_or_data(data), - ApacheBugFlag::Off => match MimeClassifier::get_media_type(media_type, - media_subtype) { + ApacheBugFlag::Off => match MimeClassifier::get_media_type(supplied_type) { Some(MediaType::Html) => self.feeds_classifier.classify(data), Some(MediaType::Image) => self.image_classifier.classify(data), Some(MediaType::AudioVideo) => self.audio_video_classifier.classify(data), @@ -107,7 +100,7 @@ impl MimeClassifier { // This section was *not* finalized in the specs at the time // of this implementation. match *supplied_type { - None => (TopLevel::Application, "octet-stream".to_owned()), + None => mime::APPLICATION_OCTET_STREAM, _ => supplied_type_or_octet_stream, } }, @@ -117,7 +110,7 @@ impl MimeClassifier { // This section was *not* finalized in the specs at the time // of this implementation. match *supplied_type { - None => (TopLevel::Text, "css".to_owned()), + None => mime::TEXT_CSS, _ => supplied_type_or_octet_stream, } }, @@ -127,7 +120,7 @@ impl MimeClassifier { // This section was *not* finalized in the specs at the time // of this implementation. match *supplied_type { - None => (TopLevel::Text, "javascript".to_owned()), + None => mime::TEXT_JAVASCRIPT, _ => supplied_type_or_octet_stream, } }, @@ -143,14 +136,14 @@ impl MimeClassifier { // // This section was *not* finalized in the specs at the time // of this implementation. - (TopLevel::Text, "vtt".to_owned()) + "text/vtt".parse().unwrap() }, LoadContext::CacheManifest => { // 8.9 Sniffing in a cache manifest context // // This section was *not* finalized in the specs at the time // of this implementation. - (TopLevel::Text, "cache-manifest".to_owned()) + "text/cache-manifest".parse().unwrap() }, } } @@ -181,7 +174,7 @@ impl MimeClassifier { } //some sort of iterator over the classifiers might be better? - fn sniff_unknown_type(&self, no_sniff_flag: NoSniffFlag, data: &[u8]) -> MimeType { + fn sniff_unknown_type(&self, no_sniff_flag: NoSniffFlag, data: &[u8]) -> Mime { let should_sniff_scriptable = no_sniff_flag == NoSniffFlag::Off; let sniffed = if should_sniff_scriptable { self.scriptable_classifier.classify(data) @@ -197,72 +190,60 @@ impl MimeClassifier { .expect("BinaryOrPlaintextClassifier always succeeds") } - fn sniff_text_or_data(&self, data: &[u8]) -> MimeType { + fn sniff_text_or_data<'a>(&'a self, data: &'a [u8]) -> Mime { self.binary_or_plaintext.classify(data).expect("BinaryOrPlaintextClassifier always succeeds") } - fn is_xml(tp: &TopLevel, sub_tp: &str) -> bool { - sub_tp.ends_with("+xml") || - match (tp, sub_tp) { - (&TopLevel::Application, "xml") | (&TopLevel::Text, "xml") => true, - _ => false - } + fn is_xml(mt: &Mime) -> bool { + mt.suffix() == Some(mime::XML) || + (mt.type_() == mime::APPLICATION && mt.subtype() == mime::XML) || + (mt.type_() == mime::TEXT && mt.subtype() == mime::XML) } - fn is_html(tp: &TopLevel, sub_tp: &str) -> bool { - *tp == TopLevel::Text && sub_tp == "html" + fn is_html(mt: &Mime) -> bool { + mt.type_() == mime::TEXT && mt.subtype() == mime::HTML } - fn is_image(tp: &TopLevel) -> bool { - *tp == TopLevel::Image + fn is_image(mt: &Mime) -> bool { + mt.type_() == mime::IMAGE } - fn is_audio_video(tp: &TopLevel, sub_tp: &str) -> bool { - *tp == TopLevel::Audio || - *tp == TopLevel::Video || - (*tp == TopLevel::Application && sub_tp == "ogg") + fn is_audio_video(mt: &Mime) -> bool { + mt.type_() == mime::AUDIO || + mt.type_() == mime::VIDEO || + mt.type_() == mime::APPLICATION && mt.subtype() == mime::OGG } - fn is_explicit_unknown(tp: &TopLevel, sub_tp: &str) -> bool { - if let TopLevel::Ext(ref e) = *tp { - return e == "unknown" && sub_tp == "unknown"; - } - match (tp, sub_tp) { - (&TopLevel::Application, "unknown") | - (&TopLevel::Star, "*") => true, - _ => false - } + fn is_explicit_unknown(mt: &Mime) -> bool { + mt.type_().as_str() == "unknown" && mt.subtype().as_str() == "unknown" || + mt.type_() == mime::APPLICATION && mt.subtype().as_str() == "unknown" || + mt.type_() == mime::STAR && mt.subtype() == mime::STAR } - fn get_media_type(media_type: &TopLevel, - media_subtype: &str) -> Option { - if MimeClassifier::is_xml(media_type, media_subtype) { + fn get_media_type(mime: &Mime) -> Option { + if MimeClassifier::is_xml(&mime) { Some(MediaType::Xml) - } else if MimeClassifier::is_html(media_type, media_subtype) { + } else if MimeClassifier::is_html(&mime) { Some(MediaType::Html) - } else if MimeClassifier::is_image(media_type) { + } else if MimeClassifier::is_image(&mime) { Some(MediaType::Image) - } else if MimeClassifier::is_audio_video(media_type, media_subtype) { + } else if MimeClassifier::is_audio_video(&mime) { Some(MediaType::AudioVideo) } else { None } } - fn maybe_get_media_type(supplied_type: &Option) -> Option { - supplied_type.as_ref().and_then(|&(ref media_type, ref media_subtype)| { - MimeClassifier::get_media_type(media_type, media_subtype) + fn maybe_get_media_type(supplied_type: &Option) -> Option { + supplied_type.as_ref().and_then(|ref mime| { + MimeClassifier::get_media_type(mime) }) } } -pub fn as_string_option(tup: Option<(TopLevel, &'static str)>) -> Option { - tup.map(|(a, b)| (a.to_owned(), b.to_owned())) -} - //Interface used for composite types trait MIMEChecker { - fn classify(&self, data: &[u8]) -> Option; + fn classify(&self, data: &[u8]) -> Option; /// Validate the MIME checker configuration fn validate(&self) -> Result<(), String>; } @@ -303,7 +284,7 @@ struct ByteMatcher { pattern: &'static [u8], mask: &'static [u8], leading_ignore: &'static [u8], - content_type: (TopLevel, &'static str) + content_type: Mime, } impl ByteMatcher { @@ -328,31 +309,31 @@ impl ByteMatcher { } impl MIMEChecker for ByteMatcher { - fn classify(&self, data: &[u8]) -> Option { + fn classify(&self, data: &[u8]) -> Option { self.matches(data).map(|_| { - (self.content_type.0.to_owned(), self.content_type.1.to_owned()) + self.content_type.clone() }) } fn validate(&self) -> Result<(), String> { if self.pattern.len() == 0 { return Err(format!( - "Zero length pattern for {}/{}", - self.content_type.0, self.content_type.1 + "Zero length pattern for {:?}", + self.content_type )) } if self.pattern.len() != self.mask.len() { return Err(format!( - "Unequal pattern and mask length for {}/{}", - self.content_type.0, self.content_type.1 + "Unequal pattern and mask length for {:?}", + self.content_type )) } if self.pattern.iter().zip(self.mask.iter()).any( |(&pattern, &mask)| pattern & mask != pattern ) { return Err(format!( - "Pattern not pre-masked for {}/{}", - self.content_type.0, self.content_type.1 + "Pattern not pre-masked for {:?}", + self.content_type )) } Ok(()) @@ -364,11 +345,10 @@ struct TagTerminatedByteMatcher { } impl MIMEChecker for TagTerminatedByteMatcher { - fn classify(&self, data: &[u8]) -> Option { + fn classify(&self, data: &[u8]) -> Option { self.matcher.matches(data).and_then(|j| if j < data.len() && (data[j] == b' ' || data[j] == b'>') { - Some((self.matcher.content_type.0.to_owned(), - self.matcher.content_type.1.to_owned())) + Some(self.matcher.content_type.clone()) } else { None }) @@ -405,9 +385,9 @@ impl Mp4Matcher { } impl MIMEChecker for Mp4Matcher { - fn classify(&self, data: &[u8]) -> Option { + fn classify(&self, data: &[u8]) -> Option { if self.matches(data) { - Some((TopLevel::Video, "mp4".to_owned())) + Some("video/mp4".parse().unwrap()) } else { None } @@ -421,25 +401,25 @@ impl MIMEChecker for Mp4Matcher { struct BinaryOrPlaintextClassifier; impl BinaryOrPlaintextClassifier { - fn classify_impl(&self, data: &[u8]) -> (TopLevel, &'static str) { + fn classify_impl(&self, data: &[u8]) -> Mime { if data.starts_with(&[0xFFu8, 0xFEu8]) || data.starts_with(&[0xFEu8, 0xFFu8]) || data.starts_with(&[0xEFu8, 0xBBu8, 0xBFu8]) { - (TopLevel::Text, "plain") + mime::TEXT_PLAIN } else if data.iter().any(|&x| x <= 0x08u8 || x == 0x0Bu8 || (x >= 0x0Eu8 && x <= 0x1Au8) || (x >= 0x1Cu8 && x <= 0x1Fu8)) { - (TopLevel::Application, "octet-stream") + mime::APPLICATION_OCTET_STREAM } else { - (TopLevel::Text, "plain") + mime::TEXT_PLAIN } } } impl MIMEChecker for BinaryOrPlaintextClassifier { - fn classify(&self, data: &[u8]) -> Option { - as_string_option(Some(self.classify_impl(data))) + fn classify(&self, data: &[u8]) -> Option { + Some(self.classify_impl(data)) } fn validate(&self) -> Result<(), String> { @@ -538,7 +518,7 @@ impl GroupedClassifier { } } impl MIMEChecker for GroupedClassifier { - fn classify(&self, data: &[u8]) -> Option { + fn classify(&self, data: &[u8]) -> Option { self.byte_matchers .iter() .filter_map(|matcher| matcher.classify(data)) @@ -591,7 +571,7 @@ where T: Iterator + Clone { struct FeedsClassifier; impl FeedsClassifier { // Implements sniffing for mislabeled feeds (https://mimesniff.spec.whatwg.org/#sniffing-a-mislabeled-feed) - fn classify_impl(&self, data: &[u8]) -> Option<(TopLevel, &'static str)> { + fn classify_impl(&self, data: &[u8]) -> Option { // Step 4: can not be feed unless length is > 3 if data.len() < 3 { return None; @@ -622,11 +602,11 @@ impl FeedsClassifier { // Step 5.2.5 if matcher.matches(b"rss") { - return Some((TopLevel::Application, "rss+xml")); + return Some("application/rss+xml".parse().unwrap()); } // Step 5.2.6 if matcher.matches(b"feed") { - return Some((TopLevel::Application, "atom+xml")); + return Some("application/atom+xml".parse().unwrap()); } // Step 5.2.7 if matcher.matches(b"rdf:RDF") { @@ -637,7 +617,7 @@ impl FeedsClassifier { .chain(|| eats_until(&mut matcher, b"http://www.w3.org/1999/02/22-rdf-syntax-ns#", b"http://purl.org/rss/1.0/")) { - Match::StartAndEnd => return Some((TopLevel::Application, "rss+xml")), + Match::StartAndEnd => return Some("application/rss+xml".parse().unwrap()), Match::DidNotMatch => {}, Match::Start => return None } @@ -649,8 +629,8 @@ impl FeedsClassifier { } impl MIMEChecker for FeedsClassifier { - fn classify(&self, data: &[u8]) -> Option { - as_string_option(self.classify_impl(data)) + fn classify(&self, data: &[u8]) -> Option { + self.classify_impl(data) } fn validate(&self) -> Result<(), String> { @@ -666,7 +646,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"\x00\x00\x01\x00", mask: b"\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Image, "x-icon"), + content_type: "image/x-icon".parse().unwrap(), leading_ignore: &[] } } @@ -675,7 +655,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"\x00\x00\x02\x00", mask: b"\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Image, "x-icon"), + content_type: "image/x-icon".parse().unwrap(), leading_ignore: &[] } } @@ -684,7 +664,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"BM", mask: b"\xFF\xFF", - content_type: (TopLevel::Image, "bmp"), + content_type: mime::IMAGE_BMP, leading_ignore: &[] } } @@ -693,7 +673,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"GIF89a", mask: b"\xFF\xFF\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Image, "gif"), + content_type: mime::IMAGE_GIF, leading_ignore: &[] } } @@ -702,7 +682,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"GIF87a", mask: b"\xFF\xFF\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Image, "gif"), + content_type: mime::IMAGE_GIF, leading_ignore: &[] } } @@ -711,7 +691,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"RIFF\x00\x00\x00\x00WEBPVP", mask: b"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Image, "webp"), + content_type: "image/webp".parse().unwrap(), leading_ignore: &[] } } @@ -721,7 +701,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"\x89PNG\r\n\x1A\n", mask: b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Image, "png"), + content_type: mime::IMAGE_PNG, leading_ignore: &[] } } @@ -730,7 +710,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"\xFF\xD8\xFF", mask: b"\xFF\xFF\xFF", - content_type: (TopLevel::Image, "jpeg"), + content_type: mime::IMAGE_JPEG, leading_ignore: &[] } } @@ -739,7 +719,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"\x1A\x45\xDF\xA3", mask: b"\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Video, "webm"), + content_type: "video/webm".parse().unwrap(), leading_ignore: &[] } } @@ -748,7 +728,7 @@ impl ByteMatcher { ByteMatcher { pattern: b".snd", mask: b"\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Audio, "basic"), + content_type: "audio/basic".parse().unwrap(), leading_ignore: &[] } } @@ -757,7 +737,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"FORM\x00\x00\x00\x00AIFF", mask: b"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Audio, "aiff"), + content_type: "audio/aiff".parse().unwrap(), leading_ignore: &[] } } @@ -766,7 +746,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"ID3", mask: b"\xFF\xFF\xFF", - content_type: (TopLevel::Audio, "mpeg"), + content_type: "audio/mpeg".parse().unwrap(), leading_ignore: &[] } } @@ -775,7 +755,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"OggS\x00", mask: b"\xFF\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Application, "ogg"), + content_type: "application/ogg".parse().unwrap(), leading_ignore: &[] } } @@ -785,7 +765,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"MThd\x00\x00\x00\x06", mask: b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Audio, "midi"), + content_type: "audio/midi".parse().unwrap(), leading_ignore: &[] } } @@ -794,7 +774,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"RIFF\x00\x00\x00\x00AVI ", mask: b"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Video, "avi"), + content_type: "video/avi".parse().unwrap(), leading_ignore: &[] } } @@ -803,7 +783,7 @@ impl ByteMatcher { ByteMatcher { pattern: b"RIFF\x00\x00\x00\x00WAVE", mask: b"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", - content_type: (TopLevel::Audio, "wave"), + content_type: "audio/wave".parse().unwrap(), leading_ignore: &[] } } @@ -813,7 +793,7 @@ impl ByteMatcher { matcher: ByteMatcher { pattern: b") -> (Arc, Arc, message_digest: MessageDigest) -> String { if let ResponseBody::Done(ref vec) = *body { - let response_digest = hash2(message_digest, vec).unwrap(); //Now hash2 + let response_digest = hash(message_digest, vec).unwrap(); //Now hash base64::encode(&response_digest) } else { unreachable!("Tried to calculate digest of incomplete response body") diff --git a/components/net/tests/cookie.rs b/components/net/tests/cookie.rs index 68149736680c..3702f93fee2a 100644 --- a/components/net/tests/cookie.rs +++ b/components/net/tests/cookie.rs @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use cookie_rs; -use hyper::header::{Header, SetCookie}; use net::cookie::Cookie; use net::cookie_storage::CookieStorage; use net_traits::CookieSource; @@ -90,7 +89,7 @@ fn fn_cookie_constructor() { let cookie = Cookie::new_wrapped(cookie, url, CookieSource::HTTP).unwrap(); assert_eq!(cookie.cookie.value(), "bar"); assert_eq!(cookie.cookie.name(), "baz"); - assert!(cookie.cookie.secure()); + assert!(cookie.cookie.secure().unwrap_or(false)); assert_eq!(&cookie.cookie.path().as_ref().unwrap()[..], "/foo/bar/"); assert_eq!(&cookie.cookie.domain().as_ref().unwrap()[..], "example.com"); assert!(cookie.host_only); @@ -324,13 +323,8 @@ fn add_retrieve_cookies(set_location: &str, // Add all cookies to the store for str_cookie in set_cookies { - let bytes = str_cookie.to_string().into_bytes(); - let header = Header::parse_header(&[bytes]).unwrap(); - let SetCookie(cookies) = header; - for bare_cookie in cookies { - let cookie = Cookie::from_cookie_string(bare_cookie, &url, source).unwrap(); - storage.push(cookie, &url, source); - } + let cookie = Cookie::from_cookie_string(str_cookie.to_owned(), &url, source).unwrap(); + storage.push(cookie, &url, source); } // Get cookies for the test location diff --git a/components/net/tests/cookie_http_state.rs b/components/net/tests/cookie_http_state.rs index 30cec8b26b2d..ab310f6a35ee 100644 --- a/components/net/tests/cookie_http_state.rs +++ b/components/net/tests/cookie_http_state.rs @@ -2,13 +2,11 @@ * 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/. */ -use hyper::header::{Header, SetCookie}; use net::cookie::Cookie; use net::cookie_storage::CookieStorage; use net_traits::CookieSource; use servo_url::ServoUrl; - fn run(set_location: &str, set_cookies: &[&str], final_location: &str) -> String { let mut storage = CookieStorage::new(150); let url = ServoUrl::parse(set_location).unwrap(); @@ -16,14 +14,8 @@ fn run(set_location: &str, set_cookies: &[&str], final_location: &str) -> String // Add all cookies to the store for str_cookie in set_cookies { - let bytes = str_cookie.to_string().into_bytes(); - let header = Header::parse_header(&[bytes]); - if let Ok(SetCookie(cookies)) = header { - for bare_cookie in cookies { - if let Some(cookie) = Cookie::from_cookie_string(bare_cookie, &url, source) { - storage.push(cookie, &url, source); - } - } + if let Some(cookie) = Cookie::from_cookie_string(str_cookie.to_owned().into(), &url, source) { + storage.push(cookie, &url, source); } } diff --git a/components/net/tests/data_loader.rs b/components/net/tests/data_loader.rs index 4ad73dee080a..56b70af9e99f 100644 --- a/components/net/tests/data_loader.rs +++ b/components/net/tests/data_loader.rs @@ -3,9 +3,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use fetch; -use hyper::header::ContentType; -use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value}; +use headers_core::HeaderMapExt; +use headers_ext::ContentType; use hyper_serde::Serde; +use mime::{self, Mime}; use net_traits::{FetchMetadata, FilteredMetadata, NetworkError}; use net_traits::request::{Origin, Request}; use net_traits::response::ResponseBody; @@ -28,8 +29,8 @@ fn assert_parse(url: &'static str, assert!(!response.is_network_error()); assert_eq!(response.headers.len(), 1); - let header_content_type = response.headers.get::(); - assert_eq!(header_content_type, content_type.as_ref()); + let header_content_type = response.headers.typed_get::(); + assert_eq!(header_content_type, content_type); let metadata = match response.metadata() { Ok(FetchMetadata::Filtered { filtered: FilteredMetadata::Basic(m), .. }) => m, @@ -62,9 +63,8 @@ fn empty_invalid() { fn plain() { assert_parse( "data:,hello%20world", - Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, - vec!((Attr::Charset, Value::Ext("US-ASCII".to_owned())))))), - Some("US-ASCII"), + Some(ContentType::from("text/plain; charset=US-ASCII".parse::().unwrap())), + Some("us-ascii"), Some(b"hello world")); } @@ -72,7 +72,7 @@ fn plain() { fn plain_ct() { assert_parse( "data:text/plain,hello", - Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, vec!()))), + Some(ContentType::from(mime::TEXT_PLAIN)), None, Some(b"hello")); } @@ -81,7 +81,7 @@ fn plain_ct() { fn plain_html() { assert_parse( "data:text/html,

Servo

", - Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec!()))), + Some(ContentType::from(mime::TEXT_HTML)), None, Some(b"

Servo

")); } @@ -90,9 +90,7 @@ fn plain_html() { fn plain_charset() { assert_parse( "data:text/plain;charset=latin1,hello", - Some(ContentType(Mime(TopLevel::Text, - SubLevel::Plain, - vec!((Attr::Charset, Value::Ext("latin1".to_owned())))))), + Some(ContentType::from("text/plain; charset=latin1".parse::().unwrap())), Some("latin1"), Some(b"hello")); } @@ -101,9 +99,7 @@ fn plain_charset() { fn plain_only_charset() { assert_parse( "data:;charset=utf-8,hello", - Some(ContentType(Mime(TopLevel::Text, - SubLevel::Plain, - vec!((Attr::Charset, Value::Utf8))))), + Some(ContentType::from(mime::TEXT_PLAIN_UTF_8)), Some("utf-8"), Some(b"hello")); } @@ -112,10 +108,8 @@ fn plain_only_charset() { fn base64() { assert_parse( "data:;base64,C62+7w==", - Some(ContentType(Mime(TopLevel::Text, - SubLevel::Plain, - vec!((Attr::Charset, Value::Ext("US-ASCII".to_owned())))))), - Some("US-ASCII"), + Some(ContentType::from("text/plain; charset=US-ASCII".parse::().unwrap())), + Some("us-ascii"), Some(&[0x0B, 0xAD, 0xBE, 0xEF])); } @@ -123,7 +117,7 @@ fn base64() { fn base64_ct() { assert_parse( "data:application/octet-stream;base64,C62+7w==", - Some(ContentType(Mime(TopLevel::Application, SubLevel::Ext("octet-stream".to_owned()), vec!()))), + Some(ContentType::from(mime::APPLICATION_OCTET_STREAM)), None, Some(&[0x0B, 0xAD, 0xBE, 0xEF])); } @@ -132,8 +126,7 @@ fn base64_ct() { fn base64_charset() { assert_parse( "data:text/plain;charset=koi8-r;base64,8PLl9+XkIO3l5Pfl5A==", - Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, - vec!((Attr::Charset, Value::Ext("koi8-r".to_owned())))))), + Some(ContentType::from("text/plain; charset=koi8-r".parse::().unwrap())), Some("koi8-r"), Some(&[0xF0, 0xF2, 0xE5, 0xF7, 0xE5, 0xE4, 0x20, 0xED, 0xE5, 0xE4, 0xF7, 0xE5, 0xE4])); } diff --git a/components/net/tests/fetch.rs b/components/net/tests/fetch.rs index 2e33727e37f8..d0d472614f9b 100644 --- a/components/net/tests/fetch.rs +++ b/components/net/tests/fetch.rs @@ -2,27 +2,24 @@ * 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/. */ -use {DEFAULT_USER_AGENT, new_fetch_context, create_embedder_proxy, fetch, make_server}; +use {DEFAULT_USER_AGENT, new_fetch_context, create_embedder_proxy, fetch, make_server, make_ssl_server}; use devtools_traits::HttpRequest as DevtoolsHttpRequest; use devtools_traits::HttpResponse as DevtoolsHttpResponse; use fetch_with_context; use fetch_with_cors_cache; +use headers_core::HeaderMapExt; +use headers_ext::{AccessControlAllowCredentials, AccessControlAllowHeaders, AccessControlAllowOrigin}; +use headers_ext::{AccessControlAllowMethods, AccessControlMaxAge}; +use headers_ext::{CacheControl, ContentLength, ContentType, Expires, Host, LastModified, Pragma, UserAgent}; +use http::{Method, StatusCode}; +use http::header::{self, HeaderMap, HeaderName, HeaderValue}; +use http::uri::Authority; use http_loader::{expect_devtools_http_request, expect_devtools_http_response}; -use hyper::LanguageTag; -use hyper::header::{Accept, AccessControlAllowCredentials, AccessControlAllowHeaders, AccessControlAllowOrigin}; -use hyper::header::{AcceptEncoding, AcceptLanguage, AccessControlAllowMethods, AccessControlMaxAge}; -use hyper::header::{AccessControlRequestHeaders, AccessControlRequestMethod, Date, UserAgent}; -use hyper::header::{CacheControl, ContentLanguage, ContentLength, ContentType, Expires, LastModified}; -use hyper::header::{Encoding, Location, Pragma, Quality, QualityItem, SetCookie, qitem}; -use hyper::header::{Headers, Host, HttpDate, Referer as HyperReferer}; -use hyper::method::Method; -use hyper::mime::{Mime, SubLevel, TopLevel}; -use hyper::server::{Request as HyperRequest, Response as HyperResponse, Server}; -use hyper::status::StatusCode; -use hyper::uri::RequestUri; -use hyper_openssl; +use hyper::{Request as HyperRequest, Response as HyperResponse}; +use hyper::body::Body; +use mime::{self, Mime}; use msg::constellation_msg::TEST_PIPELINE_ID; -use net::connector::create_ssl_client; +use net::connector::create_ssl_connector_builder; use net::fetch::cors_cache::CorsCache; use net::fetch::methods::{CancellationListener, FetchContext}; use net::filemanager_thread::FileManager; @@ -37,21 +34,21 @@ use servo_channel::{channel, Sender}; use servo_url::{ImmutableOrigin, ServoUrl}; use std::fs::File; use std::io::Read; +use std::iter::FromIterator; use std::path::Path; use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicUsize, Ordering}; -use time::{self, Duration}; -use unicase::UniCase; +use std::time::{SystemTime, Duration}; // TODO write a struct that impls Handler for storing test values #[test] fn test_fetch_response_is_not_network_error() { static MESSAGE: &'static [u8] = b""; - let handler = move |_: HyperRequest, response: HyperResponse| { - response.send(MESSAGE).unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -79,10 +76,10 @@ fn test_fetch_on_bad_port_is_network_error() { #[test] fn test_fetch_response_body_matches_const_message() { static MESSAGE: &'static [u8] = b"Hello World!"; - let handler = move |_: HyperRequest, response: HyperResponse| { - response.send(MESSAGE).unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -142,11 +139,11 @@ fn test_fetch_blob() { assert_eq!(fetch_response.headers.len(), 2); - let content_type: &ContentType = fetch_response.headers.get().unwrap(); - assert_eq!(**content_type, Mime(TopLevel::Text, SubLevel::Plain, vec![])); + let content_type: Mime = fetch_response.headers.typed_get::().unwrap().into(); + assert_eq!(content_type, mime::TEXT_PLAIN); - let content_length: &ContentLength = fetch_response.headers.get().unwrap(); - assert_eq!(**content_length, bytes.len() as u64); + let content_length: ContentLength = fetch_response.headers.typed_get().unwrap(); + assert_eq!(content_length.0, bytes.len() as u64); assert_eq!(*fetch_response.body.lock().unwrap(), ResponseBody::Done(bytes.to_vec())); @@ -162,8 +159,8 @@ fn test_fetch_file() { let fetch_response = fetch(&mut request, None); assert!(!fetch_response.is_network_error()); assert_eq!(fetch_response.headers.len(), 1); - let content_type: &ContentType = fetch_response.headers.get().unwrap(); - assert_eq!(**content_type, Mime(TopLevel::Text, SubLevel::Css, vec![])); + let content_type: Mime = fetch_response.headers.typed_get::().unwrap().into(); + assert_eq!(content_type, mime::TEXT_CSS); let resp_body = fetch_response.body.lock().unwrap(); let mut file = File::open(path).unwrap(); @@ -202,20 +199,20 @@ fn test_fetch_bogus_scheme() { fn test_cors_preflight_fetch() { static ACK: &'static [u8] = b"ACK"; let state = Arc::new(AtomicUsize::new(0)); - let handler = move |request: HyperRequest, mut response: HyperResponse| { - if request.method == Method::Options && state.clone().fetch_add(1, Ordering::SeqCst) == 0 { - assert!(request.headers.has::()); - assert!(!request.headers.has::()); - assert!(!request.headers.get::().unwrap().contains("a.html")); - response.headers_mut().set(AccessControlAllowOrigin::Any); - response.headers_mut().set(AccessControlAllowCredentials); - response.headers_mut().set(AccessControlAllowMethods(vec![Method::Get])); + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + if request.method() == Method::OPTIONS && state.clone().fetch_add(1, Ordering::SeqCst) == 0 { + assert!(request.headers().contains_key(header::ACCESS_CONTROL_REQUEST_METHOD)); + assert!(!request.headers().contains_key(header::ACCESS_CONTROL_REQUEST_HEADERS)); + assert!(!request.headers().get(header::REFERER).unwrap().to_str().unwrap().contains("a.html")); + response.headers_mut().typed_insert(AccessControlAllowOrigin::ANY); + response.headers_mut().typed_insert(AccessControlAllowCredentials); + response.headers_mut().typed_insert(AccessControlAllowMethods::from_iter(vec![Method::GET])); } else { - response.headers_mut().set(AccessControlAllowOrigin::Any); - response.send(ACK).unwrap(); + response.headers_mut().typed_insert(AccessControlAllowOrigin::ANY); + *response.body_mut() = ACK.to_vec().into(); } }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let target_url = url.clone().join("a.html").unwrap(); @@ -241,20 +238,20 @@ fn test_cors_preflight_cache_fetch() { let state = Arc::new(AtomicUsize::new(0)); let counter = state.clone(); let mut cache = CorsCache::new(); - let handler = move |request: HyperRequest, mut response: HyperResponse| { - if request.method == Method::Options && state.clone().fetch_add(1, Ordering::SeqCst) == 0 { - assert!(request.headers.has::()); - assert!(!request.headers.has::()); - response.headers_mut().set(AccessControlAllowOrigin::Any); - response.headers_mut().set(AccessControlAllowCredentials); - response.headers_mut().set(AccessControlAllowMethods(vec![Method::Get])); - response.headers_mut().set(AccessControlMaxAge(6000)); + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + if request.method() == Method::OPTIONS && state.clone().fetch_add(1, Ordering::SeqCst) == 0 { + assert!(request.headers().contains_key(header::ACCESS_CONTROL_REQUEST_METHOD)); + assert!(!request.headers().contains_key(header::ACCESS_CONTROL_REQUEST_HEADERS)); + response.headers_mut().typed_insert(AccessControlAllowOrigin::ANY); + response.headers_mut().typed_insert(AccessControlAllowCredentials); + response.headers_mut().typed_insert(AccessControlAllowMethods::from_iter(vec![Method::GET])); + response.headers_mut().typed_insert(AccessControlMaxAge::from(Duration::new(6000, 0))); } else { - response.headers_mut().set(AccessControlAllowOrigin::Any); - response.send(ACK).unwrap(); + response.headers_mut().typed_insert(AccessControlAllowOrigin::ANY); + *response.body_mut() = ACK.to_vec().into(); } }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let mut request = Request::new(url.clone(), Some(origin.clone()), None); @@ -274,8 +271,8 @@ fn test_cors_preflight_cache_fetch() { assert_eq!(1, counter.load(Ordering::SeqCst)); // The entry exists in the CORS-preflight cache - assert_eq!(true, cache.match_method(&wrapped_request0, Method::Get)); - assert_eq!(true, cache.match_method(&wrapped_request1, Method::Get)); + assert_eq!(true, cache.match_method(&wrapped_request0, Method::GET)); + assert_eq!(true, cache.match_method(&wrapped_request1, Method::GET)); match *fetch_response0.body.lock().unwrap() { ResponseBody::Done(ref body) => assert_eq!(&**body, ACK), @@ -291,23 +288,23 @@ fn test_cors_preflight_cache_fetch() { fn test_cors_preflight_fetch_network_error() { static ACK: &'static [u8] = b"ACK"; let state = Arc::new(AtomicUsize::new(0)); - let handler = move |request: HyperRequest, mut response: HyperResponse| { - if request.method == Method::Options && state.clone().fetch_add(1, Ordering::SeqCst) == 0 { - assert!(request.headers.has::()); - assert!(!request.headers.has::()); - response.headers_mut().set(AccessControlAllowOrigin::Any); - response.headers_mut().set(AccessControlAllowCredentials); - response.headers_mut().set(AccessControlAllowMethods(vec![Method::Get])); + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + if request.method() == Method::OPTIONS && state.clone().fetch_add(1, Ordering::SeqCst) == 0 { + assert!(request.headers().contains_key(header::ACCESS_CONTROL_REQUEST_METHOD)); + assert!(!request.headers().contains_key(header::ACCESS_CONTROL_REQUEST_HEADERS)); + response.headers_mut().typed_insert(AccessControlAllowOrigin::ANY); + response.headers_mut().typed_insert(AccessControlAllowCredentials); + response.headers_mut().typed_insert(AccessControlAllowMethods::from_iter(vec![Method::GET])); } else { - response.headers_mut().set(AccessControlAllowOrigin::Any); - response.send(ACK).unwrap(); + response.headers_mut().typed_insert(AccessControlAllowOrigin::ANY); + *response.body_mut() = ACK.to_vec().into(); } }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let mut request = Request::new(url, Some(origin), None); - request.method = Method::Extension("CHICKEN".to_owned()); + request.method = Method::from_bytes(b"CHICKEN").unwrap(); request.referrer = Referrer::NoReferrer; request.use_cors_preflight = true; request.mode = RequestMode::CorsMode; @@ -320,14 +317,17 @@ fn test_cors_preflight_fetch_network_error() { #[test] fn test_fetch_response_is_basic_filtered() { static MESSAGE: &'static [u8] = b""; - let handler = move |_: HyperRequest, mut response: HyperResponse| { - response.headers_mut().set(SetCookie(vec![])); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().insert(header::SET_COOKIE, HeaderValue::from_static("")); // this header is obsoleted, so hyper doesn't implement it, but it's still covered by the spec - response.headers_mut().set_raw("Set-Cookie2", vec![]); + response.headers_mut().insert( + HeaderName::from_static("set-cookie2"), + HeaderValue::from_bytes(&vec![]).unwrap() + ); - response.send(MESSAGE).unwrap(); + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -339,39 +339,42 @@ fn test_fetch_response_is_basic_filtered() { assert_eq!(fetch_response.response_type, ResponseType::Basic); let headers = fetch_response.headers; - assert!(!headers.has::()); - assert!(headers.get_raw("Set-Cookie2").is_none()); + assert!(!headers.contains_key(header::SET_COOKIE)); + assert!(headers.get(HeaderName::from_static("set-cookie2")).is_none()); } #[test] fn test_fetch_response_is_cors_filtered() { static MESSAGE: &'static [u8] = b""; - let handler = move |_: HyperRequest, mut response: HyperResponse| { + let handler = move |_: HyperRequest, response: &mut HyperResponse| { // this is mandatory for the Cors Check to pass // TODO test using different url encodings with this value ie. punycode - response.headers_mut().set(AccessControlAllowOrigin::Any); + response.headers_mut().typed_insert(AccessControlAllowOrigin::ANY); // these are the headers that should be kept after filtering - response.headers_mut().set(CacheControl(vec![])); - response.headers_mut().set(ContentLanguage(vec![])); - response.headers_mut().set(ContentType::html()); - response.headers_mut().set(Expires(HttpDate(time::now() + Duration::days(1)))); - response.headers_mut().set(LastModified(HttpDate(time::now()))); - response.headers_mut().set(Pragma::NoCache); + response.headers_mut().typed_insert(CacheControl::new()); + response.headers_mut().insert(header::CONTENT_LANGUAGE, HeaderValue::from_bytes(&vec![]).unwrap()); + response.headers_mut().typed_insert(ContentType::from(mime::TEXT_HTML)); + response.headers_mut().typed_insert(Expires::from(SystemTime::now() + Duration::new(86400, 0))); + response.headers_mut().typed_insert(LastModified::from(SystemTime::now())); + response.headers_mut().typed_insert(Pragma::no_cache()); // these headers should not be kept after filtering, even though they are given a pass - response.headers_mut().set(SetCookie(vec![])); - response.headers_mut().set_raw("Set-Cookie2", vec![]); - response.headers_mut().set( - AccessControlAllowHeaders(vec![ - UniCase("set-cookie".to_owned()), - UniCase("set-cookie2".to_owned()) + response.headers_mut().insert(header::SET_COOKIE, HeaderValue::from_static("")); + response.headers_mut().insert( + HeaderName::from_static("set-cookie2"), + HeaderValue::from_bytes(&vec![]).unwrap() + ); + response.headers_mut().typed_insert( + AccessControlAllowHeaders::from_iter(vec![ + HeaderName::from_static("set-cookie"), + HeaderName::from_static("set-cookie2") ]) ); - response.send(MESSAGE).unwrap(); + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); // an origin mis-match will stop it from defaulting to a basic filtered response let origin = Origin::Origin(ImmutableOrigin::new_opaque()); @@ -385,25 +388,25 @@ fn test_fetch_response_is_cors_filtered() { assert_eq!(fetch_response.response_type, ResponseType::Cors); let headers = fetch_response.headers; - assert!(headers.has::()); - assert!(headers.has::()); - assert!(headers.has::()); - assert!(headers.has::()); - assert!(headers.has::()); - assert!(headers.has::()); - - assert!(!headers.has::()); - assert!(!headers.has::()); - assert!(headers.get_raw("Set-Cookie2").is_none()); + assert!(headers.contains_key(header::CACHE_CONTROL)); + assert!(headers.contains_key(header::CONTENT_LANGUAGE)); + assert!(headers.contains_key(header::CONTENT_TYPE)); + assert!(headers.contains_key(header::EXPIRES)); + assert!(headers.contains_key(header::LAST_MODIFIED)); + assert!(headers.contains_key(header::PRAGMA)); + + assert!(!headers.contains_key(header::ACCESS_CONTROL_ALLOW_ORIGIN)); + assert!(!headers.contains_key(header::SET_COOKIE)); + assert!(headers.get(HeaderName::from_static("set-cookie2")).is_none()); } #[test] fn test_fetch_response_is_opaque_filtered() { static MESSAGE: &'static [u8] = b""; - let handler = move |_: HyperRequest, response: HyperResponse| { - response.send(MESSAGE).unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); // an origin mis-match will fall through to an Opaque filtered response let origin = Origin::Origin(ImmutableOrigin::new_opaque()); @@ -419,7 +422,7 @@ fn test_fetch_response_is_opaque_filtered() { assert!(fetch_response.url_list.is_empty()); // this also asserts that status message is "the empty byte sequence" assert!(fetch_response.status.is_none()); - assert_eq!(fetch_response.headers, Headers::new()); + assert_eq!(fetch_response.headers, HeaderMap::new()); match *fetch_response.body.lock().unwrap() { ResponseBody::Empty => { }, _ => panic!() @@ -433,25 +436,18 @@ fn test_fetch_response_is_opaque_filtered() { #[test] fn test_fetch_response_is_opaque_redirect_filtered() { static MESSAGE: &'static [u8] = b""; - let handler = move |request: HyperRequest, mut response: HyperResponse| { - let redirects = match request.uri { - RequestUri::AbsolutePath(url) => - url.split("/").collect::().parse::().unwrap_or(0), - RequestUri::AbsoluteUri(url) => - url.path_segments().unwrap().next_back().unwrap().parse::().unwrap_or(0), - _ => panic!() - }; + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + let redirects = request.uri().path().split("/").collect::().parse::().unwrap_or(0); if redirects == 1 { - response.send(MESSAGE).unwrap(); + *response.body_mut() = MESSAGE.to_vec().into(); } else { - *response.status_mut() = StatusCode::Found; - let url = format!("{}", 1); - response.headers_mut().set(Location(url.to_owned())); + *response.status_mut() = StatusCode::FOUND; + response.headers_mut().insert(header::LOCATION, HeaderValue::from_static("1")); } }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -465,7 +461,7 @@ fn test_fetch_response_is_opaque_redirect_filtered() { // this also asserts that status message is "the empty byte sequence" assert!(fetch_response.status.is_none()); - assert_eq!(fetch_response.headers, Headers::new()); + assert_eq!(fetch_response.headers, HeaderMap::new()); match *fetch_response.body.lock().unwrap() { ResponseBody::Empty => { }, _ => panic!() @@ -481,10 +477,10 @@ fn test_fetch_with_local_urls_only() { // If flag `local_urls_only` is set, fetching a non-local URL must result in network error. static MESSAGE: &'static [u8] = b""; - let handler = move |_: HyperRequest, response: HyperResponse| { - response.send(MESSAGE).unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, server_url) = make_server(handler); + let (server, server_url) = make_server(handler); let do_fetch = |url: ServoUrl| { let origin = Origin::Origin(url.origin()); @@ -506,7 +502,6 @@ fn test_fetch_with_local_urls_only() { assert!(!local_response.is_network_error()); assert!(server_response.is_network_error()); } - // NOTE(emilio): If this test starts failing: // // openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ @@ -517,22 +512,17 @@ fn test_fetch_with_local_urls_only() { #[test] fn test_fetch_with_hsts() { static MESSAGE: &'static [u8] = b""; - let handler = move |_: HyperRequest, response: HyperResponse| { - response.send(MESSAGE).unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.body_mut() = MESSAGE.to_vec().into(); }; let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt").canonicalize().unwrap(); let key_path = Path::new("../../resources/privatekey_for_testing.key").canonicalize().unwrap(); - - let ssl = hyper_openssl::OpensslServer::from_files(key_path, cert_path.clone()) - .unwrap(); - - //takes an address and something that implements hyper::net::Ssl - let mut server = Server::https("0.0.0.0:0", ssl).unwrap().handle_threads(handler, 1).unwrap(); + let (server, url) = make_ssl_server(handler, cert_path.clone(), key_path.clone()); let mut ca_content = String::new(); File::open(cert_path).unwrap().read_to_string(&mut ca_content).unwrap(); - let ssl_client = create_ssl_client(&ca_content); + let ssl_client = create_ssl_connector_builder(&ca_content); let context = FetchContext { state: Arc::new(HttpState::new(ssl_client)), @@ -547,15 +537,13 @@ fn test_fetch_with_hsts() { list.push(HstsEntry::new("localhost".to_owned(), IncludeSubdomains::NotIncluded, None) .unwrap()); } - let url_string = format!("http://localhost:{}", server.socket.port()); - let url = ServoUrl::parse(&url_string).unwrap(); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); request.referrer = Referrer::NoReferrer; // Set the flag. request.local_urls_only = false; let response = fetch_with_context(&mut request, &context); - let _ = server.close(); + server.close(); assert_eq!(response.internal_response.unwrap().url().unwrap().scheme(), "https"); } @@ -563,10 +551,10 @@ fn test_fetch_with_hsts() { #[test] fn test_fetch_with_sri_network_error() { static MESSAGE: &'static [u8] = b"alert('Hello, Network Error');"; - let handler = move |_: HyperRequest, response: HyperResponse| { - response.send(MESSAGE).unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -587,10 +575,10 @@ fn test_fetch_with_sri_network_error() { #[test] fn test_fetch_with_sri_sucess() { static MESSAGE: &'static [u8] = b"alert('Hello, world.');"; - let handler = move |_: HyperRequest, response: HyperResponse| { - response.send(MESSAGE).unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -616,20 +604,20 @@ fn test_fetch_blocked_nosniff() { mime: Mime, should_error: bool) { const MESSAGE: &'static [u8] = b""; - const HEADER: &'static str = "X-Content-Type-Options"; + const HEADER: &'static str = "x-content-type-options"; const VALUE: &'static [u8] = b"nosniff"; - let handler = move |_: HyperRequest, mut response: HyperResponse| { - let mime_header = ContentType(mime.clone()); - response.headers_mut().set(mime_header); - assert!(response.headers().has::()); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + let mime_header = ContentType::from(mime.clone()); + response.headers_mut().typed_insert(mime_header); + assert!(response.headers().contains_key(header::CONTENT_TYPE)); // Add the nosniff header - response.headers_mut().set_raw(HEADER, vec![VALUE.to_vec()]); + response.headers_mut().insert(HeaderName::from_static(HEADER), HeaderValue::from_bytes(VALUE).unwrap()); - response.send(MESSAGE).unwrap(); + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -641,9 +629,9 @@ fn test_fetch_blocked_nosniff() { } let tests = vec![ - (Destination::Script, Mime(TopLevel::Text, SubLevel::Javascript, vec![]), false), - (Destination::Script, Mime(TopLevel::Text, SubLevel::Css, vec![]), true), - (Destination::Style, Mime(TopLevel::Text, SubLevel::Css, vec![]), false), + (Destination::Script, mime::TEXT_JAVASCRIPT, false), + (Destination::Script, mime::TEXT_CSS, true), + (Destination::Style, mime::TEXT_CSS, false), ]; for test in tests { @@ -653,25 +641,19 @@ fn test_fetch_blocked_nosniff() { } fn setup_server_and_fetch(message: &'static [u8], redirect_cap: u32) -> Response { - let handler = move |request: HyperRequest, mut response: HyperResponse| { - let redirects = match request.uri { - RequestUri::AbsolutePath(url) => - url.split("/").collect::().parse::().unwrap_or(0), - RequestUri::AbsoluteUri(url) => - url.path_segments().unwrap().next_back().unwrap().parse::().unwrap_or(0), - _ => panic!() - }; + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + let redirects = request.uri().path().split("/").collect::().parse::().unwrap_or(0); if redirects >= redirect_cap { - response.send(message).unwrap(); + *response.body_mut() = message.to_vec().into(); } else { - *response.status_mut() = StatusCode::Found; + *response.status_mut() = StatusCode::FOUND; let url = format!("{redirects}", redirects = redirects + 1); - response.headers_mut().set(Location(url.to_owned())); + response.headers_mut().insert(header::LOCATION, HeaderValue::from_str(&url).unwrap()); } }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -720,30 +702,24 @@ fn test_fetch_redirect_updates_method_runner(tx: Sender, status_code: Stat let handler_method = method.clone(); let handler_tx = Arc::new(Mutex::new(tx)); - let handler = move |request: HyperRequest, mut response: HyperResponse| { - let redirects = match request.uri { - RequestUri::AbsolutePath(url) => - url.split("/").collect::().parse::().unwrap_or(0), - RequestUri::AbsoluteUri(url) => - url.path_segments().unwrap().next_back().unwrap().parse::().unwrap_or(0), - _ => panic!() - }; + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + let redirects = request.uri().path().split("/").collect::().parse::().unwrap_or(0); let mut test_pass = true; if redirects == 0 { - *response.status_mut() = StatusCode::TemporaryRedirect; - response.headers_mut().set(Location("1".to_owned())); + *response.status_mut() = StatusCode::TEMPORARY_REDIRECT; + response.headers_mut().insert(header::LOCATION, HeaderValue::from_static("1")); } else if redirects == 1 { // this makes sure that the request method does't change from the wrong status code - if handler_method != Method::Get && request.method == Method::Get { + if handler_method != Method::GET && request.method() == Method::GET { test_pass = false; } *response.status_mut() = status_code; - response.headers_mut().set(Location("2".to_owned())); + response.headers_mut().insert(header::LOCATION, HeaderValue::from_static("2")); - } else if request.method != Method::Get { + } else if request.method() != Method::GET { test_pass = false; } @@ -754,7 +730,7 @@ fn test_fetch_redirect_updates_method_runner(tx: Sender, status_code: Stat }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -769,36 +745,36 @@ fn test_fetch_redirect_updates_method_runner(tx: Sender, status_code: Stat fn test_fetch_redirect_updates_method() { let (tx, rx) = channel(); - test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::MovedPermanently, Method::Post); + test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::MOVED_PERMANENTLY, Method::POST); assert_eq!(rx.recv().unwrap(), true); assert_eq!(rx.recv().unwrap(), true); // make sure the test doesn't send more data than expected assert_eq!(rx.try_recv().is_none(), true); - test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::Found, Method::Post); + test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::FOUND, Method::POST); assert_eq!(rx.recv().unwrap(), true); assert_eq!(rx.recv().unwrap(), true); assert_eq!(rx.try_recv().is_none(), true); - test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::SeeOther, Method::Get); + test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::SEE_OTHER, Method::GET); assert_eq!(rx.recv().unwrap(), true); assert_eq!(rx.recv().unwrap(), true); assert_eq!(rx.try_recv().is_none(), true); - let extension = Method::Extension("FOO".to_owned()); + let extension = Method::from_bytes(b"FOO").unwrap(); - test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::MovedPermanently, extension.clone()); + test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::MOVED_PERMANENTLY, extension.clone()); assert_eq!(rx.recv().unwrap(), true); // for MovedPermanently and Found, Method should only be changed if it was Post assert_eq!(rx.recv().unwrap(), false); assert_eq!(rx.try_recv().is_none(), true); - test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::Found, extension.clone()); + test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::FOUND, extension.clone()); assert_eq!(rx.recv().unwrap(), true); assert_eq!(rx.recv().unwrap(), false); assert_eq!(rx.try_recv().is_none(), true); - test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::SeeOther, extension.clone()); + test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::SEE_OTHER, extension.clone()); assert_eq!(rx.recv().unwrap(), true); // for SeeOther, Method should always be changed, so this should be true assert_eq!(rx.recv().unwrap(), true); @@ -826,10 +802,10 @@ fn response_is_done(response: &Response) -> bool { #[test] fn test_fetch_async_returns_complete_response() { static MESSAGE: &'static [u8] = b"this message should be retrieved in full"; - let handler = move |_: HyperRequest, response: HyperResponse| { - response.send(MESSAGE).unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -844,10 +820,10 @@ fn test_fetch_async_returns_complete_response() { #[test] fn test_opaque_filtered_fetch_async_returns_complete_response() { static MESSAGE: &'static [u8] = b""; - let handler = move |_: HyperRequest, response: HyperResponse| { - response.send(MESSAGE).unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); // an origin mis-match will fall through to an Opaque filtered response let origin = Origin::Origin(ImmutableOrigin::new_opaque()); @@ -865,25 +841,18 @@ fn test_opaque_filtered_fetch_async_returns_complete_response() { #[test] fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() { static MESSAGE: &'static [u8] = b""; - let handler = move |request: HyperRequest, mut response: HyperResponse| { - let redirects = match request.uri { - RequestUri::AbsolutePath(url) => - url.split("/").collect::().parse::().unwrap_or(0), - RequestUri::AbsoluteUri(url) => - url.path_segments().unwrap().last().unwrap().parse::().unwrap_or(0), - _ => panic!() - }; + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + let redirects = request.uri().path().split("/").collect::().parse::().unwrap_or(0); if redirects == 1 { - response.send(MESSAGE).unwrap(); + *response.body_mut() = MESSAGE.to_vec().into(); } else { - *response.status_mut() = StatusCode::Found; - let url = format!("{}", 1); - response.headers_mut().set(Location(url.to_owned())); + *response.status_mut() = StatusCode::FOUND; + response.headers_mut().insert(header::LOCATION, HeaderValue::from_static("1")); } }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), None); @@ -901,11 +870,11 @@ fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() { #[test] fn test_fetch_with_devtools() { static MESSAGE: &'static [u8] = b"Yay!"; - let handler = move |_: HyperRequest, response: HyperResponse| { - response.send(MESSAGE).unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.body_mut() = MESSAGE.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url.clone(), Some(origin), Some(TEST_PIPELINE_ID)); @@ -921,36 +890,23 @@ fn test_fetch_with_devtools() { let mut devhttpresponse = expect_devtools_http_response(&devtools_port); //Creating default headers for request - let mut headers = Headers::new(); - - headers.set(AcceptEncoding(vec![ - qitem(Encoding::Gzip), - qitem(Encoding::Deflate), - qitem(Encoding::EncodingExt("br".to_owned())) - ])); + let mut headers = HeaderMap::new(); - headers.set(Host { hostname: url.host_str().unwrap().to_owned() , port: url.port().to_owned() }); + headers.insert(header::ACCEPT_ENCODING, HeaderValue::from_static("gzip, deflate, br")); + headers.typed_insert( + Host::from(format!("{}:{}", url.host_str().unwrap(), url.port().unwrap()).parse::().unwrap())); - let accept = Accept(vec![qitem(Mime(TopLevel::Star, SubLevel::Star, vec![]))]); - headers.set(accept); + headers.insert(header::ACCEPT, HeaderValue::from_static("*/*")); - let mut en_us: LanguageTag = Default::default(); - en_us.language = Some("en".to_owned()); - en_us.region = Some("US".to_owned()); - let mut en: LanguageTag = Default::default(); - en.language = Some("en".to_owned()); - headers.set(AcceptLanguage(vec![ - qitem(en_us), - QualityItem::new(en, Quality(500)), - ])); + headers.insert(header::ACCEPT_LANGUAGE, HeaderValue::from_static("en-US, en; q=0.5")); - headers.set(UserAgent(DEFAULT_USER_AGENT.to_owned())); + headers.typed_insert::(DEFAULT_USER_AGENT.parse().unwrap()); let httprequest = DevtoolsHttpRequest { url: url, - method: Method::Get, + method: Method::GET, headers: headers, - body: None, + body: Some(vec![]), pipeline_id: TEST_PIPELINE_ID, startedDateTime: devhttprequest.startedDateTime, timeStamp: devhttprequest.timeStamp, @@ -960,9 +916,9 @@ fn test_fetch_with_devtools() { }; let content = "Yay!"; - let mut response_headers = Headers::new(); - response_headers.set(ContentLength(content.len() as u64)); - devhttpresponse.headers.as_mut().unwrap().remove::(); + let mut response_headers = HeaderMap::new(); + response_headers.typed_insert(ContentLength(content.len() as u64)); + devhttpresponse.headers.as_mut().unwrap().remove(header::DATE); let httpresponse = DevtoolsHttpResponse { headers: Some(response_headers), diff --git a/components/net/tests/http_loader.rs b/components/net/tests/http_loader.rs index 96c424469d1e..4d327029ccd5 100644 --- a/components/net/tests/http_loader.rs +++ b/components/net/tests/http_loader.rs @@ -10,16 +10,15 @@ use fetch; use fetch_with_context; use flate2::Compression; use flate2::write::{DeflateEncoder, GzEncoder}; -use hyper::LanguageTag; -use hyper::header::{Accept, AcceptEncoding, ContentEncoding, ContentLength, Cookie as CookieHeader}; -use hyper::header::{AcceptLanguage, AccessControlAllowOrigin, Authorization, Basic, Date}; -use hyper::header::{Encoding, Headers, Host, Location, Origin, Quality, QualityItem, SetCookie, qitem}; -use hyper::header::{StrictTransportSecurity, UserAgent}; -use hyper::method::Method; -use hyper::mime::{Mime, SubLevel, TopLevel}; -use hyper::server::{Request as HyperRequest, Response as HyperResponse}; -use hyper::status::StatusCode; -use hyper::uri::RequestUri; +use futures::{self, Future, Stream}; +use headers_core::HeaderMapExt; +use headers_ext::{Authorization, Basic, AccessControlAllowOrigin, ContentLength, Date, Host, Origin}; +use headers_ext::{StrictTransportSecurity, UserAgent}; +use http::{Method, StatusCode}; +use http::header::{self, HeaderMap, HeaderValue}; +use http::uri::Authority; +use hyper::{Request as HyperRequest, Response as HyperResponse}; +use hyper::body::Body; use make_server; use msg::constellation_msg::TEST_PIPELINE_ID; use net::cookie::Cookie; @@ -33,25 +32,21 @@ use new_fetch_context; use servo_channel::{channel, Receiver}; use servo_url::{ServoUrl, ImmutableOrigin}; use std::collections::HashMap; -use std::io::{Read, Write}; -use std::str::FromStr; +use std::io::Write; +use std::str; use std::sync::{Arc, Mutex, RwLock}; use std::sync::atomic::{AtomicBool, Ordering}; +use std::time::Duration; fn mock_origin() -> ImmutableOrigin { ServoUrl::parse("http://servo.org").unwrap().origin() } -fn read_response(reader: &mut Read) -> String { - let mut buf = vec![0; 1024]; - match reader.read(&mut buf) { - Ok(len) if len > 0 => { - unsafe { buf.set_len(len); } - String::from_utf8(buf).unwrap() - }, - Ok(_) => "".to_owned(), - Err(e) => panic!("problem reading response {}", e) - } +fn read_response(req: HyperRequest) -> impl Future { + req.into_body() + .concat2() + .and_then(|body| futures::future::ok(str::from_utf8(&body).unwrap().to_owned())) + .map_err(|_| ()) } fn assert_cookie_for_domain(cookie_jar: &RwLock, domain: &str, cookie: Option<&str>) { @@ -97,90 +92,71 @@ pub fn expect_devtools_http_response(devtools_port: &Receiver, _: &mut HyperResponse| { + assert_eq!(request.headers().clone(), expected_headers_clone.lock().unwrap().take().unwrap()); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); - let mut headers = Headers::new(); + let mut headers = HeaderMap::new(); - headers.set(AcceptEncoding(vec![qitem(Encoding::Gzip), - qitem(Encoding::Deflate), - qitem(Encoding::EncodingExt("br".to_owned()))])); - - let hostname = match url.host_str() { - Some(hostname) => hostname.to_owned(), - _ => panic!() - }; + headers.insert(header::ACCEPT_ENCODING, HeaderValue::from_static("gzip, deflate, br")); - headers.set(Host { hostname: hostname, port: url.port() }); + headers.typed_insert( + Host::from(format!("{}:{}", url.host_str().unwrap(), url.port().unwrap()).parse::().unwrap())); - let accept = Accept(vec![ - qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])), - qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_owned()), vec![])), - QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900u16)), - QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800u16)), - ]); - headers.set(accept); + headers.insert(header::ACCEPT, + HeaderValue::from_static("text/html, application/xhtml+xml, application/xml; q=0.9, */*; q=0.8")); - let mut en_us: LanguageTag = Default::default(); - en_us.language = Some("en".to_owned()); - en_us.region = Some("US".to_owned()); - let mut en: LanguageTag = Default::default(); - en.language = Some("en".to_owned()); - headers.set(AcceptLanguage(vec![ - qitem(en_us), - QualityItem::new(en, Quality(500)), - ])); + headers.insert(header::ACCEPT_LANGUAGE, HeaderValue::from_static("en-US, en; q=0.5")); - headers.set(UserAgent(::DEFAULT_USER_AGENT.to_owned())); + headers.typed_insert::(::DEFAULT_USER_AGENT.parse().unwrap()); *expected_headers.lock().unwrap() = Some(headers.clone()); // Testing for method.GET let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, destination: Destination::Document, origin: url.clone().origin(), pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); let response = fetch(&mut request, None); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); // Testing for method.POST let mut post_headers = headers.clone(); - post_headers.set(ContentLength(0 as u64)); + post_headers.typed_insert(ContentLength(0 as u64)); let url_str = url.as_str(); // request gets header "Origin: http://example.com" but expected_headers has // "Origin: http://example.com/" which do not match for equality so strip trailing '/' - post_headers.set(Origin::from_str(&url_str[..url_str.len()-1]).unwrap()); + post_headers.insert(header::ORIGIN, HeaderValue::from_str(&url_str[..url_str.len()-1]).unwrap()); *expected_headers.lock().unwrap() = Some(post_headers); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Post, + method: Method::POST, destination: Destination::Document, origin: url.clone().origin(), pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); let response = fetch(&mut request, None); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); let _ = server.close(); } #[test] fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length_should_be_set_to_0() { - let handler = move |request: HyperRequest, _: HyperResponse| { - assert_eq!(request.headers.get::(), Some(&ContentLength(0))); + let handler = move |request: HyperRequest, _: &mut HyperResponse| { + assert_eq!(request.headers().typed_get::(), Some(ContentLength(0))); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Post, + method: Method::POST, body: None, destination: Destination::Document, origin: mock_origin(), @@ -188,24 +164,24 @@ fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length .. RequestInit::default() }); let response = fetch(&mut request, None); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); let _ = server.close(); } #[test] fn test_request_and_response_data_with_network_messages() { - let handler = move |_: HyperRequest, mut response: HyperResponse| { - response.headers_mut().set(Host { hostname: "foo.bar".to_owned(), port: None }); - response.send(b"Yay!").unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().typed_insert(Host::from("foo.bar".parse::().unwrap())); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); - let mut request_headers = Headers::new(); - request_headers.set(Host { hostname: "bar.foo".to_owned(), port: None }); + let mut request_headers = HeaderMap::new(); + request_headers.typed_insert(Host::from("bar.foo".parse::().unwrap())); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, headers: request_headers, body: None, destination: Destination::Document, @@ -215,7 +191,7 @@ fn test_request_and_response_data_with_network_messages() { }); let (devtools_chan, devtools_port) = channel(); let response = fetch(&mut request, Some(devtools_chan)); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); let _ = server.close(); @@ -224,41 +200,23 @@ fn test_request_and_response_data_with_network_messages() { let devhttpresponse = expect_devtools_http_response(&devtools_port); //Creating default headers for request - let mut headers = Headers::new(); - - headers.set(AcceptEncoding(vec![ - qitem(Encoding::Gzip), - qitem(Encoding::Deflate), - qitem(Encoding::EncodingExt("br".to_owned())) - ])); - - headers.set(Host { hostname: url.host_str().unwrap().to_owned() , port: url.port() }); - - let accept = Accept(vec![ - qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])), - qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_owned()), vec![])), - QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900u16)), - QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800u16)), - ]); - headers.set(accept); - - let mut en_us: LanguageTag = Default::default(); - en_us.language = Some("en".to_owned()); - en_us.region = Some("US".to_owned()); - let mut en: LanguageTag = Default::default(); - en.language = Some("en".to_owned()); - headers.set(AcceptLanguage(vec![ - qitem(en_us), - QualityItem::new(en, Quality(500)), - ])); - - headers.set(UserAgent(::DEFAULT_USER_AGENT.to_owned())); + let mut headers = HeaderMap::new(); + + headers.insert(header::ACCEPT_ENCODING, HeaderValue::from_static("gzip, deflate, br")); + headers.typed_insert( + Host::from(format!("{}:{}", url.host_str().unwrap(), url.port().unwrap()).parse::().unwrap())); + + headers.insert(header::ACCEPT, + HeaderValue::from_static("text/html, application/xhtml+xml, application/xml; q=0.9, */*; q=0.8")); + + headers.insert(header::ACCEPT_LANGUAGE, HeaderValue::from_static("en-US, en; q=0.5")); + headers.typed_insert::(::DEFAULT_USER_AGENT.parse().unwrap()); let httprequest = DevtoolsHttpRequest { url: url, - method: Method::Get, + method: Method::GET, headers: headers, - body: None, + body: Some(b"".to_vec()), pipeline_id: TEST_PIPELINE_ID, startedDateTime: devhttprequest.startedDateTime, timeStamp: devhttprequest.timeStamp, @@ -268,10 +226,10 @@ fn test_request_and_response_data_with_network_messages() { }; let content = "Yay!"; - let mut response_headers = Headers::new(); - response_headers.set(ContentLength(content.len() as u64)); - response_headers.set(Host { hostname: "foo.bar".to_owned(), port: None }); - response_headers.set(devhttpresponse.headers.as_ref().unwrap().get::().unwrap().clone()); + let mut response_headers = HeaderMap::new(); + response_headers.typed_insert(ContentLength(content.len() as u64)); + response_headers.typed_insert(Host::from("foo.bar".parse::().unwrap())); + response_headers.typed_insert(devhttpresponse.headers.as_ref().unwrap().typed_get::().unwrap().clone()); let httpresponse = DevtoolsHttpResponse { headers: Some(response_headers), @@ -286,15 +244,15 @@ fn test_request_and_response_data_with_network_messages() { #[test] fn test_request_and_response_message_from_devtool_without_pipeline_id() { - let handler = move |_: HyperRequest, mut response: HyperResponse| { - response.headers_mut().set(Host { hostname: "foo.bar".to_owned(), port: None }); - response.send(b"Yay!").unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().typed_insert(Host::from("foo.bar".parse::().unwrap())); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, destination: Destination::Document, origin: mock_origin(), pipeline_id: None, @@ -302,7 +260,7 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() { }); let (devtools_chan, devtools_port) = channel(); let response = fetch(&mut request, Some(devtools_chan)); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); let _ = server.close(); @@ -312,24 +270,23 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() { #[test] fn test_redirected_request_to_devtools() { - let post_handler = move |request: HyperRequest, response: HyperResponse| { - assert_eq!(request.method, Method::Get); - response.send(b"Yay!").unwrap(); + let post_handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.method(), Method::GET); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut post_server, post_url) = make_server(post_handler); + let (post_server, post_url) = make_server(post_handler); let post_redirect_url = post_url.clone(); - let pre_handler = move |request: HyperRequest, mut response: HyperResponse| { - assert_eq!(request.method, Method::Post); - response.headers_mut().set(Location(post_redirect_url.to_string())); - *response.status_mut() = StatusCode::MovedPermanently; - response.send(b"").unwrap(); + let pre_handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.method(), Method::POST); + response.headers_mut().insert(header::LOCATION, HeaderValue::from_str(&post_redirect_url.to_string()).unwrap()); + *response.status_mut() = StatusCode::MOVED_PERMANENTLY; }; - let (mut pre_server, pre_url) = make_server(pre_handler); + let (pre_server, pre_url) = make_server(pre_handler); let mut request = Request::from_init(RequestInit { url: pre_url.clone(), - method: Method::Post, + method: Method::POST, destination: Destination::Document, pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() @@ -343,14 +300,14 @@ fn test_redirected_request_to_devtools() { let devhttprequest = expect_devtools_http_request(&devtools_port); let devhttpresponse = expect_devtools_http_response(&devtools_port); - assert_eq!(devhttprequest.method, Method::Post); + assert_eq!(devhttprequest.method, Method::POST); assert_eq!(devhttprequest.url, pre_url); assert_eq!(devhttpresponse.status, Some((301, b"Moved Permanently".to_vec()))); let devhttprequest = expect_devtools_http_request(&devtools_port); let devhttpresponse = expect_devtools_http_response(&devtools_port); - assert_eq!(devhttprequest.method, Method::Get); + assert_eq!(devhttprequest.method, Method::GET); assert_eq!(devhttprequest.url, post_url); assert_eq!(devhttpresponse.status, Some((200, b"OK".to_vec()))); } @@ -359,24 +316,23 @@ fn test_redirected_request_to_devtools() { #[test] fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() { - let post_handler = move |request: HyperRequest, response: HyperResponse| { - assert_eq!(request.method, Method::Get); - response.send(b"Yay!").unwrap(); + let post_handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.method(), Method::GET); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut post_server, post_url) = make_server(post_handler); + let (post_server, post_url) = make_server(post_handler); let post_redirect_url = post_url.clone(); - let pre_handler = move |request: HyperRequest, mut response: HyperResponse| { - assert_eq!(request.method, Method::Post); - response.headers_mut().set(Location(post_redirect_url.to_string())); - *response.status_mut() = StatusCode::MovedPermanently; - response.send(b"").unwrap(); + let pre_handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.method(), Method::POST); + response.headers_mut().insert(header::LOCATION, HeaderValue::from_str(&post_redirect_url.to_string()).unwrap()); + *response.status_mut() = StatusCode::MOVED_PERMANENTLY; }; - let (mut pre_server, pre_url) = make_server(pre_handler); + let (pre_server, pre_url) = make_server(pre_handler); let mut request = Request::from_init(RequestInit { url: pre_url.clone(), - method: Method::Post, + method: Method::POST, destination: Destination::Document, origin: mock_origin(), pipeline_id: Some(TEST_PIPELINE_ID), @@ -387,23 +343,23 @@ fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() { let _ = pre_server.close(); let _ = post_server.close(); - assert!(response.to_actual().status.unwrap().is_success()); + assert!(response.to_actual().status.unwrap().0.is_success()); } #[test] fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_content_encoding_deflate() { - let handler = move |_: HyperRequest, mut response: HyperResponse| { - response.headers_mut().set(ContentEncoding(vec![Encoding::Deflate])); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().insert(header::CONTENT_ENCODING, HeaderValue::from_static("deflate")); let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); e.write(b"Yay!").unwrap(); let encoded_content = e.finish().unwrap(); - response.send(&encoded_content).unwrap(); + *response.body_mut() = encoded_content.into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, body: None, destination: Destination::Document, origin: mock_origin(), @@ -415,25 +371,25 @@ fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_co let _ = server.close(); let internal_response = response.internal_response.unwrap(); - assert!(internal_response.status.unwrap().is_success()); + assert!(internal_response.status.clone().unwrap().0.is_success()); assert_eq!(*internal_response.body.lock().unwrap(), ResponseBody::Done(b"Yay!".to_vec())); } #[test] fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_content_encoding_gzip() { - let handler = move |_: HyperRequest, mut response: HyperResponse| { - response.headers_mut().set(ContentEncoding(vec![Encoding::Gzip])); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().insert(header::CONTENT_ENCODING, HeaderValue::from_static("gzip")); let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write(b"Yay!").unwrap(); let encoded_content = e.finish().unwrap(); - response.send(&encoded_content).unwrap(); + *response.body_mut() = encoded_content.into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, body: None, destination: Destination::Document, origin: mock_origin(), @@ -445,35 +401,36 @@ fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_conte let _ = server.close(); let internal_response = response.internal_response.unwrap(); - assert!(internal_response.status.unwrap().is_success()); + assert!(internal_response.status.clone().unwrap().0.is_success()); assert_eq!(*internal_response.body.lock().unwrap(), ResponseBody::Done(b"Yay!".to_vec())); } #[test] fn test_load_doesnt_send_request_body_on_any_redirect() { - let post_handler = move |mut request: HyperRequest, response: HyperResponse| { - assert_eq!(request.method, Method::Get); - let data = read_response(&mut request); - assert_eq!(data, ""); - response.send(b"Yay!").unwrap(); + let post_handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.method(), Method::GET); + read_response(request).and_then(|data| { + assert_eq!(data, ""); futures::future::ok(()) + }).poll().unwrap(); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut post_server, post_url) = make_server(post_handler); + let (post_server, post_url) = make_server(post_handler); let post_redirect_url = post_url.clone(); - let pre_handler = move |mut request: HyperRequest, mut response: HyperResponse| { - let data = read_response(&mut request); - assert_eq!(data, "Body on POST!"); - response.headers_mut().set(Location(post_redirect_url.to_string())); - *response.status_mut() = StatusCode::MovedPermanently; - response.send(b"").unwrap(); + let pre_handler = move |request: HyperRequest, response: &mut HyperResponse| { + read_response(request).and_then(|data| { + assert_eq!(data, "Body on POST"); futures::future::ok(()) + }).poll().unwrap(); + response.headers_mut().insert(header::LOCATION, HeaderValue::from_str(&post_redirect_url.to_string()).unwrap()); + *response.status_mut() = StatusCode::MOVED_PERMANENTLY; }; - let (mut pre_server, pre_url) = make_server(pre_handler); + let (pre_server, pre_url) = make_server(pre_handler); let mut request = Request::from_init(RequestInit { url: pre_url.clone(), body: Some(b"Body on POST!".to_vec()), - method: Method::Post, + method: Method::POST, destination: Destination::Document, origin: mock_origin(), pipeline_id: Some(TEST_PIPELINE_ID), @@ -484,20 +441,21 @@ fn test_load_doesnt_send_request_body_on_any_redirect() { let _ = pre_server.close(); let _ = post_server.close(); - assert!(response.to_actual().status.unwrap().is_success()); + assert!(response.to_actual().status.unwrap().0.is_success()); } #[test] fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_are_present() { - let handler = move |_: HyperRequest, mut response: HyperResponse| { - response.headers_mut().set(StrictTransportSecurity::excluding_subdomains(31536000)); - response.send(b"Yay!").unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().typed_insert( + StrictTransportSecurity::excluding_subdomains(Duration::from_secs(31536000))); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, body: None, destination: Destination::Document, origin: mock_origin(), @@ -509,17 +467,17 @@ fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_ar let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); assert_eq!(context.state.hsts_list.read().unwrap().is_host_secure(url.host_str().unwrap()), false); } #[test] fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_in_response() { - let handler = move |_: HyperRequest, mut response: HyperResponse| { - response.headers_mut().set(SetCookie(vec!["mozillaIs=theBest".to_owned()])); - response.send(b"Yay!").unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().insert(header::SET_COOKIE, HeaderValue::from_static("mozillaIs=theBest")); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let context = new_fetch_context(None, None); @@ -527,7 +485,7 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_ let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, body: None, destination: Destination::Document, origin: mock_origin(), @@ -539,19 +497,18 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_ let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), Some("mozillaIs=theBest")); } #[test] fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_resource_manager() { - let handler = move |request: HyperRequest, response: HyperResponse| { - assert_eq!(request.headers.get::(), - Some(&CookieHeader(vec!["mozillaIs=theBest".to_owned()]))); - response.send(b"Yay!").unwrap(); + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.headers().get(header::COOKIE).unwrap().as_bytes(), b"mozillaIs=theBest"); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let context = new_fetch_context(None, None); @@ -567,7 +524,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, body: None, destination: Destination::Document, origin: mock_origin(), @@ -579,17 +536,16 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); } #[test] fn test_load_sends_cookie_if_nonhttp() { - let handler = move |request: HyperRequest, response: HyperResponse| { - assert_eq!(request.headers.get::(), - Some(&CookieHeader(vec!["mozillaIs=theBest".to_owned()]))); - response.send(b"Yay!").unwrap(); + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.headers().get(header::COOKIE).unwrap().as_bytes(), b"mozillaIs=theBest"); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let context = new_fetch_context(None, None); @@ -605,7 +561,7 @@ fn test_load_sends_cookie_if_nonhttp() { let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, body: None, destination: Destination::Document, origin: mock_origin(), @@ -617,17 +573,16 @@ fn test_load_sends_cookie_if_nonhttp() { let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); } #[test] fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl() { - let handler = move |_: HyperRequest, mut response: HyperResponse| { - let pair = vec!["mozillaIs=theBest; HttpOnly".to_owned()]; - response.headers_mut().set(SetCookie(pair)); - response.send(b"Yay!").unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().insert(header::SET_COOKIE, HeaderValue::from_static("mozillaIs=theBest; HttpOnly")); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let context = new_fetch_context(None, None); @@ -635,7 +590,7 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl( let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, body: None, destination: Destination::Document, origin: mock_origin(), @@ -647,7 +602,7 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl( let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), Some("mozillaIs=theBest")); let mut cookie_jar = context.state.cookie_jar.write().unwrap(); @@ -656,12 +611,11 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl( #[test] fn test_when_cookie_received_marked_secure_is_ignored_for_http() { - let handler = move |_: HyperRequest, mut response: HyperResponse| { - let pair = vec!["mozillaIs=theBest; Secure".to_owned()]; - response.headers_mut().set(SetCookie(pair)); - response.send(b"Yay!").unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().insert(header::SET_COOKIE, HeaderValue::from_static("mozillaIs=theBest; Secure")); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let context = new_fetch_context(None, None); @@ -669,7 +623,7 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() { let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, body: None, destination: Destination::Document, origin: mock_origin(), @@ -681,7 +635,7 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() { let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None); } @@ -689,16 +643,16 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() { #[test] fn test_load_sets_content_length_to_length_of_request_body() { let content = b"This is a request body"; - let content_length = ContentLength(content.len() as u64); - let handler = move |request: HyperRequest, response: HyperResponse| { - assert_eq!(request.headers.get::(), Some(&content_length)); - response.send(content).unwrap(); + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + let content_length = ContentLength(content.len() as u64); + assert_eq!(request.headers().typed_get::(), Some(content_length)); + *response.body_mut() = content.to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Post, + method: Method::POST, body: Some(content.to_vec()), destination: Destination::Document, origin: mock_origin(), @@ -709,24 +663,22 @@ fn test_load_sets_content_length_to_length_of_request_body() { let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); } #[test] fn test_load_uses_explicit_accept_from_headers_in_load_data() { - let accept = Accept(vec![qitem(Mime(TopLevel::Text, SubLevel::Html, vec![]))]); - let expected_accept = accept.clone(); - let handler = move |request: HyperRequest, response: HyperResponse| { - assert_eq!(request.headers.get::(), Some(&expected_accept)); - response.send(b"Yay!").unwrap(); + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.headers().get(header::ACCEPT).unwrap().to_str().unwrap(), "text/html"); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); - let mut accept_headers = Headers::new(); - accept_headers.set(accept); + let mut accept_headers = HeaderMap::new(); + accept_headers.insert(header::ACCEPT, HeaderValue::from_static("text/html")); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, headers: accept_headers, destination: Destination::Document, origin: mock_origin(), @@ -737,25 +689,21 @@ fn test_load_uses_explicit_accept_from_headers_in_load_data() { let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); } #[test] fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() { - let handler = move |request: HyperRequest, response: HyperResponse| { - assert_eq!(request.headers.get::(), Some(&Accept(vec![ - qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])), - qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_owned()), vec![])), - QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900)), - QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800)), - ]))); - response.send(b"Yay!").unwrap(); + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.headers().get(header::ACCEPT).unwrap().to_str().unwrap(), + "text/html, application/xhtml+xml, application/xml; q=0.9, */*; q=0.8"); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, destination: Destination::Document, origin: mock_origin(), pipeline_id: Some(TEST_PIPELINE_ID), @@ -765,24 +713,22 @@ fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() { let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); } #[test] fn test_load_uses_explicit_accept_encoding_from_load_data_headers() { - let accept_encoding = AcceptEncoding(vec![qitem(Encoding::Chunked)]); - let expected_accept_encoding = accept_encoding.clone(); - let handler = move |request: HyperRequest, response: HyperResponse| { - assert_eq!(request.headers.get::(), Some(&expected_accept_encoding)); - response.send(b"Yay!").unwrap(); + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.headers().get(header::ACCEPT_ENCODING).unwrap().to_str().unwrap(), "chunked"); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); - let mut accept_encoding_headers = Headers::new(); - accept_encoding_headers.set(accept_encoding); + let mut accept_encoding_headers = HeaderMap::new(); + accept_encoding_headers.insert(header::ACCEPT_ENCODING, HeaderValue::from_static("chunked")); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, headers: accept_encoding_headers, destination: Destination::Document, origin: mock_origin(), @@ -793,24 +739,20 @@ fn test_load_uses_explicit_accept_encoding_from_load_data_headers() { let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); } #[test] fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() { - let handler = move |request: HyperRequest, response: HyperResponse| { - assert_eq!(request.headers.get::(), Some(&AcceptEncoding(vec![ - qitem(Encoding::Gzip), - qitem(Encoding::Deflate), - qitem(Encoding::EncodingExt("br".to_owned())) - ]))); - response.send(b"Yay!").unwrap(); + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.headers().get(header::ACCEPT_ENCODING).unwrap().to_str().unwrap(), "gzip, deflate, br"); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, destination: Destination::Document, origin: mock_origin(), pipeline_id: Some(TEST_PIPELINE_ID), @@ -820,33 +762,32 @@ fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() { let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); } #[test] fn test_load_errors_when_there_a_redirect_loop() { let url_b_for_a = Arc::new(Mutex::new(None::)); let url_b_for_a_clone = url_b_for_a.clone(); - let handler_a = move |_: HyperRequest, mut response: HyperResponse| { - response.headers_mut().set(Location(url_b_for_a_clone.lock().unwrap().as_ref().unwrap().to_string())); - *response.status_mut() = StatusCode::MovedPermanently; - response.send(b"").unwrap(); + let handler_a = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().insert(header::LOCATION, + HeaderValue::from_str(&url_b_for_a_clone.lock().unwrap().as_ref().unwrap().to_string()).unwrap()); + *response.status_mut() = StatusCode::MOVED_PERMANENTLY; }; - let (mut server_a, url_a) = make_server(handler_a); + let (server_a, url_a) = make_server(handler_a); let url_a_for_b = url_a.clone(); - let handler_b = move |_: HyperRequest, mut response: HyperResponse| { - response.headers_mut().set(Location(url_a_for_b.to_string())); - *response.status_mut() = StatusCode::MovedPermanently; - response.send(b"").unwrap(); + let handler_b = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().insert(header::LOCATION, HeaderValue::from_str(&url_a_for_b.to_string()).unwrap()); + *response.status_mut() = StatusCode::MOVED_PERMANENTLY; }; - let (mut server_b, url_b) = make_server(handler_b); + let (server_b, url_b) = make_server(handler_b); *url_b_for_a.lock().unwrap() = Some(url_b.clone()); let mut request = Request::from_init(RequestInit { url: url_a.clone(), - method: Method::Get, + method: Method::GET, destination: Destination::Document, origin: mock_origin(), pipeline_id: Some(TEST_PIPELINE_ID), @@ -866,30 +807,29 @@ fn test_load_succeeds_with_a_redirect_loop() { let url_b_for_a = Arc::new(Mutex::new(None::)); let url_b_for_a_clone = url_b_for_a.clone(); let handled_a = AtomicBool::new(false); - let handler_a = move |_: HyperRequest, mut response: HyperResponse| { + let handler_a = move |_: HyperRequest, response: &mut HyperResponse| { if !handled_a.swap(true, Ordering::SeqCst) { - response.headers_mut().set(Location(url_b_for_a_clone.lock().unwrap().as_ref().unwrap().to_string())); - *response.status_mut() = StatusCode::MovedPermanently; - response.send(b"").unwrap(); + response.headers_mut().insert(header::LOCATION, + HeaderValue::from_str(&url_b_for_a_clone.lock().unwrap().as_ref().unwrap().to_string()).unwrap()); + *response.status_mut() = StatusCode::MOVED_PERMANENTLY; } else { - response.send(b"Success").unwrap(); + *response.body_mut() = b"Success".to_vec().into() } }; - let (mut server_a, url_a) = make_server(handler_a); + let (server_a, url_a) = make_server(handler_a); let url_a_for_b = url_a.clone(); - let handler_b = move |_: HyperRequest, mut response: HyperResponse| { - response.headers_mut().set(Location(url_a_for_b.to_string())); - *response.status_mut() = StatusCode::MovedPermanently; - response.send(b"").unwrap(); + let handler_b = move |_: HyperRequest, response: &mut HyperResponse| { + response.headers_mut().insert(header::LOCATION, HeaderValue::from_str(&url_a_for_b.to_string()).unwrap()); + *response.status_mut() = StatusCode::MOVED_PERMANENTLY; }; - let (mut server_b, url_b) = make_server(handler_b); + let (server_b, url_b) = make_server(handler_b); *url_b_for_a.lock().unwrap() = Some(url_b.clone()); let mut request = Request::from_init(RequestInit { url: url_a.clone(), - method: Method::Get, + method: Method::GET, destination: Destination::Document, origin: mock_origin(), pipeline_id: Some(TEST_PIPELINE_ID), @@ -908,24 +848,23 @@ fn test_load_succeeds_with_a_redirect_loop() { #[test] fn test_load_follows_a_redirect() { - let post_handler = move |request: HyperRequest, response: HyperResponse| { - assert_eq!(request.method, Method::Get); - response.send(b"Yay!").unwrap(); + let post_handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.method(), Method::GET); + *response.body_mut() = b"Yay!".to_vec().into(); }; - let (mut post_server, post_url) = make_server(post_handler); + let (post_server, post_url) = make_server(post_handler); let post_redirect_url = post_url.clone(); - let pre_handler = move |request: HyperRequest, mut response: HyperResponse| { - assert_eq!(request.method, Method::Get); - response.headers_mut().set(Location(post_redirect_url.to_string())); - *response.status_mut() = StatusCode::MovedPermanently; - response.send(b"").unwrap(); + let pre_handler = move |request: HyperRequest, response: &mut HyperResponse| { + assert_eq!(request.method(), Method::GET); + response.headers_mut().insert(header::LOCATION, HeaderValue::from_str(&post_redirect_url.to_string()).unwrap()); + *response.status_mut() = StatusCode::MOVED_PERMANENTLY; }; - let (mut pre_server, pre_url) = make_server(pre_handler); + let (pre_server, pre_url) = make_server(pre_handler); let mut request = Request::from_init(RequestInit { url: pre_url.clone(), - method: Method::Get, + method: Method::GET, destination: Destination::Document, origin: mock_origin(), pipeline_id: Some(TEST_PIPELINE_ID), @@ -937,7 +876,7 @@ fn test_load_follows_a_redirect() { let _ = post_server.close(); let internal_response = response.internal_response.unwrap(); - assert!(internal_response.status.unwrap().is_success()); + assert!(internal_response.status.clone().unwrap().0.is_success()); assert_eq!(*internal_response.body.lock().unwrap(), ResponseBody::Done(b"Yay!".to_vec())); } @@ -946,27 +885,21 @@ fn test_load_follows_a_redirect() { fn test_redirect_from_x_to_y_provides_y_cookies_from_y() { let shared_url_y = Arc::new(Mutex::new(None::)); let shared_url_y_clone = shared_url_y.clone(); - let handler = move |request: HyperRequest, mut response: HyperResponse| { - let path = match request.uri { - RequestUri::AbsolutePath(path) => path, - uri => panic!("Unexpected uri: {:?}", uri), - }; + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + let path = request.uri().path(); if path == "/com/" { - assert_eq!(request.headers.get(), - Some(&CookieHeader(vec!["mozillaIsNot=dotOrg".to_owned()]))); + assert_eq!(request.headers().get(header::COOKIE).unwrap().as_bytes(), b"mozillaIsNot=dotOrg"); let location = shared_url_y.lock().unwrap().as_ref().unwrap().to_string(); - response.headers_mut().set(Location(location)); - *response.status_mut() = StatusCode::MovedPermanently; - response.send(b"").unwrap(); + response.headers_mut().insert(header::LOCATION, HeaderValue::from_str(&location.to_string()).unwrap()); + *response.status_mut() = StatusCode::MOVED_PERMANENTLY; } else if path == "/org/" { - assert_eq!(request.headers.get(), - Some(&CookieHeader(vec!["mozillaIs=theBest".to_owned()]))); - response.send(b"Yay!").unwrap(); + assert_eq!(request.headers().get(header::COOKIE).unwrap().as_bytes(), b"mozillaIs=theBest"); + *response.body_mut() = b"Yay!".to_vec().into(); } else { panic!("unexpected path {:?}", path) } }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let port = url.port().unwrap(); assert_eq!(url.host_str(), Some("localhost")); @@ -1002,7 +935,7 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() { let mut request = Request::from_init(RequestInit { url: url_x.clone(), - method: Method::Get, + method: Method::GET, destination: Destination::Document, origin: mock_origin(), pipeline_id: Some(TEST_PIPELINE_ID), @@ -1014,39 +947,34 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() { let _ = server.close(); let internal_response = response.internal_response.unwrap(); - assert!(internal_response.status.unwrap().is_success()); + assert!(internal_response.status.clone().unwrap().0.is_success()); assert_eq!(*internal_response.body.lock().unwrap(), ResponseBody::Done(b"Yay!".to_vec())); } #[test] fn test_redirect_from_x_to_x_provides_x_with_cookie_from_first_response() { - let handler = move |request: HyperRequest, mut response: HyperResponse| { - let path = match request.uri { - ::hyper::uri::RequestUri::AbsolutePath(path) => path, - uri => panic!("Unexpected uri: {:?}", uri), - }; + let handler = move |request: HyperRequest, response: &mut HyperResponse| { + let path = request.uri().path(); if path == "/initial/" { - response.headers_mut().set_raw("set-cookie", vec![b"mozillaIs=theBest; path=/;".to_vec()]); + response.headers_mut().insert(header::SET_COOKIE, HeaderValue::from_static("mozillaIs=theBest; path=/;")); let location = "/subsequent/".to_string(); - response.headers_mut().set(Location(location)); - *response.status_mut() = StatusCode::MovedPermanently; - response.send(b"").unwrap(); + response.headers_mut().insert(header::LOCATION, HeaderValue::from_str(&location.to_string()).unwrap()); + *response.status_mut() = StatusCode::MOVED_PERMANENTLY; } else if path == "/subsequent/" { - assert_eq!(request.headers.get(), - Some(&CookieHeader(vec!["mozillaIs=theBest".to_owned()]))); - response.send(b"Yay!").unwrap(); + assert_eq!(request.headers().get(header::COOKIE).unwrap().as_bytes(), b"mozillaIs=theBest"); + *response.body_mut() = b"Yay!".to_vec().into(); } else { panic!("unexpected path {:?}", path) } }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let url = url.join("/initial/").unwrap(); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, destination: Destination::Document, origin: mock_origin(), pipeline_id: Some(TEST_PIPELINE_ID), @@ -1058,26 +986,22 @@ fn test_redirect_from_x_to_x_provides_x_with_cookie_from_first_response() { let _ = server.close(); let internal_response = response.internal_response.unwrap(); - assert!(internal_response.status.unwrap().is_success()); + assert!(internal_response.status.clone().unwrap().0.is_success()); assert_eq!(*internal_response.body.lock().unwrap(), ResponseBody::Done(b"Yay!".to_vec())); } #[test] fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() { - let handler = move |request: HyperRequest, response: HyperResponse| { - let expected = Authorization(Basic { - username: "username".to_owned(), - password: Some("test".to_owned()) - }); - assert_eq!(request.headers.get(), Some(&expected)); - response.send(b"").unwrap(); + let handler = move |request: HyperRequest, _response: &mut HyperResponse| { + let expected = Authorization::basic("username", "test"); + assert_eq!(request.headers().typed_get::>(), Some(expected)); }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, body: None, destination: Destination::Document, origin: mock_origin(), @@ -1098,20 +1022,19 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() { let _ = server.close(); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); } #[test] fn test_auth_ui_needs_www_auth() { - let handler = move |_: HyperRequest, mut response: HyperResponse| { - *response.status_mut() = StatusCode::Unauthorized; - response.send(b"").unwrap(); + let handler = move |_: HyperRequest, response: &mut HyperResponse| { + *response.status_mut() = StatusCode::UNAUTHORIZED; }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, body: None, destination: Destination::Document, origin: mock_origin(), @@ -1124,41 +1047,50 @@ fn test_auth_ui_needs_www_auth() { let _ = server.close(); - assert_eq!(response.internal_response.unwrap().status.unwrap(), StatusCode::Unauthorized); + assert_eq!(response.internal_response.unwrap().status.unwrap().0, StatusCode::UNAUTHORIZED); } #[test] fn test_origin_set() { let origin_header = Arc::new(Mutex::new(None)); let origin_header_clone = origin_header.clone(); - let handler = move |request: HyperRequest, mut resp: HyperResponse| { + let handler = move |request: HyperRequest, resp: &mut HyperResponse| { let origin_header_clone = origin_header.clone(); - resp.headers_mut().set(AccessControlAllowOrigin::Any); - match request.headers.get::() { + resp.headers_mut().typed_insert(AccessControlAllowOrigin::ANY); + match request.headers().typed_get::() { None => assert_eq!(origin_header_clone.lock().unwrap().take(), None), - Some(h) => assert_eq!(*h, origin_header_clone.lock().unwrap().take().unwrap()), + Some(h) => assert_eq!(h, origin_header_clone.lock().unwrap().take().unwrap()), } }; - let (mut server, url) = make_server(handler); + let (server, url) = make_server(handler); - let mut origin = Origin::new(url.scheme(), url.host_str().unwrap(), url.port()); + let mut origin = Origin::try_from_parts( + url.scheme(), + url.host_str().unwrap(), + url.port() + ).unwrap(); *origin_header_clone.lock().unwrap() = Some(origin.clone()); let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Post, + method: Method::POST, body: None, origin: url.clone().origin(), .. RequestInit::default() }); let response = fetch(&mut request, None); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); let origin_url = ServoUrl::parse("http://example.com").unwrap(); - origin = Origin::new(origin_url.scheme(), origin_url.host_str().unwrap(), origin_url.port()); + // XXX: Not sure about the Some(80) here. origin_url.origin() returns 80 for the port but origin_url returns None. + origin = Origin::try_from_parts( + origin_url.scheme(), + origin_url.host_str().unwrap(), + Some(80) + ).unwrap(); // Test Origin header is set on Get request with CORS mode let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Get, + method: Method::GET, mode: RequestMode::CorsMode, body: None, origin: origin_url.clone().origin(), @@ -1167,12 +1099,12 @@ fn test_origin_set() { *origin_header_clone.lock().unwrap() = Some(origin.clone()); let response = fetch(&mut request, None); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); // Test Origin header is not set on method Head let mut request = Request::from_init(RequestInit { url: url.clone(), - method: Method::Head, + method: Method::HEAD, body: None, origin: url.clone().origin(), .. RequestInit::default() @@ -1180,7 +1112,7 @@ fn test_origin_set() { *origin_header_clone.lock().unwrap() = None; let response = fetch(&mut request, None); - assert!(response.internal_response.unwrap().status.unwrap().is_success()); + assert!(response.internal_response.unwrap().status.unwrap().0.is_success()); let _ = server.close(); } diff --git a/components/net/tests/main.rs b/components/net/tests/main.rs index aeddb5105d12..ad666198a076 100644 --- a/components/net/tests/main.rs +++ b/components/net/tests/main.rs @@ -8,19 +8,27 @@ extern crate cookie as cookie_rs; extern crate devtools_traits; extern crate embedder_traits; extern crate flate2; +extern crate futures; +extern crate headers_core; +extern crate headers_ext; +extern crate http; extern crate hyper; -extern crate hyper_openssl; extern crate hyper_serde; extern crate ipc_channel; +#[macro_use] +extern crate lazy_static; +extern crate mime; extern crate msg; extern crate net; extern crate net_traits; +extern crate openssl; extern crate profile_traits; extern crate servo_channel; extern crate servo_config; extern crate servo_url; extern crate time; -extern crate unicase; +extern crate tokio; +extern crate tokio_openssl; extern crate url; mod cookie; @@ -38,8 +46,12 @@ mod subresource_integrity; use devtools_traits::DevtoolsControlMsg; use embedder_traits::{EmbedderProxy, EventLoopWaker}; use embedder_traits::resources::{self, Resource}; -use hyper::server::{Handler, Listening, Server}; -use net::connector::create_ssl_client; +use futures::{Future, Stream}; +use hyper::{Body, Request as HyperRequest, Response as HyperResponse}; +use hyper::server::Server as HyperServer; +use hyper::server::conn::Http; +use hyper::service::service_fn_ok; +use net::connector::create_ssl_connector_builder; use net::fetch::cors_cache::CorsCache; use net::fetch::methods::{self, CancellationListener, FetchContext}; use net::filemanager_thread::FileManager; @@ -47,9 +59,21 @@ use net::test::HttpState; use net_traits::FetchTaskTarget; use net_traits::request::Request; use net_traits::response::Response; +use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; use servo_channel::{channel, Sender}; use servo_url::ServoUrl; +use std::net::TcpListener as StdTcpListener; +use std::path::PathBuf; use std::sync::{Arc, Mutex}; +use tokio::net::TcpListener; +use tokio::runtime::Runtime; +use tokio_openssl::SslAcceptorExt; + +lazy_static! { + pub static ref HANDLE: Mutex = { + Mutex::new(Runtime::new().unwrap()) + }; +} const DEFAULT_USER_AGENT: &'static str = "Such Browser. Very Layout. Wow."; @@ -84,10 +108,10 @@ fn create_embedder_proxy() -> EmbedderProxy { } fn new_fetch_context(dc: Option>, fc: Option) -> FetchContext { - let ssl_client = create_ssl_client(&resources::read_string(Resource::SSLCertificates)); + let ssl_connector = create_ssl_connector_builder(&resources::read_string(Resource::SSLCertificates)); let sender = fc.unwrap_or_else(|| create_embedder_proxy()); FetchContext { - state: Arc::new(HttpState::new(ssl_client)), + state: Arc::new(HttpState::new(ssl_connector)), user_agent: DEFAULT_USER_AGENT.into(), devtools_chan: dc, filemanager: FileManager::new(sender), @@ -131,10 +155,78 @@ fn fetch_with_cors_cache(request: &mut Request, cache: &mut CorsCache) -> Respon receiver.recv().unwrap() } -fn make_server(handler: H) -> (Listening, ServoUrl) { - // this is a Listening server because of handle_threads() - let server = Server::http("0.0.0.0:0").unwrap().handle_threads(handler, 2).unwrap(); - let url_string = format!("http://localhost:{}", server.socket.port()); +pub(crate) struct Server { + pub close_channel: futures::sync::oneshot::Sender<()>, +} + +impl Server { + fn close(self) { + self.close_channel.send(()).unwrap(); + } +} + +fn make_server(handler: H) -> (Server, ServoUrl) + where + H: Fn(HyperRequest, &mut HyperResponse) + Send + Sync + 'static, +{ + let handler = Arc::new(handler); + let listener = StdTcpListener::bind("0.0.0.0:0").unwrap(); + let url_string = format!("http://localhost:{}", listener.local_addr().unwrap().port()); let url = ServoUrl::parse(&url_string).unwrap(); + let (tx, rx) = futures::sync::oneshot::channel::<()>(); + let server = HyperServer::from_tcp(listener).unwrap().serve( + move || { + let handler = handler.clone(); + service_fn_ok(move |req: HyperRequest| { + let mut response = HyperResponse::new(Vec::::new().into()); + handler(req, &mut response); + response + }) + } + ) + .with_graceful_shutdown(rx) + .map_err(|_|()); + + HANDLE.lock().unwrap().spawn(server); + let server = Server { close_channel: tx }; + (server, url) +} + +fn make_ssl_server(handler: H, cert_path: PathBuf, key_path: PathBuf) -> (Server, ServoUrl) + where + H: Fn(HyperRequest, &mut HyperResponse) + Send + Sync + 'static, +{ + let handler = Arc::new(handler); + let listener = StdTcpListener::bind("[::0]:0").unwrap(); + let listener = TcpListener::from_std(listener, &HANDLE.lock().unwrap().reactor()).unwrap(); + let url_string = format!("http://localhost:{}", listener.local_addr().unwrap().port()); + let url = ServoUrl::parse(&url_string).unwrap(); + + let server = listener.incoming() + .map_err(|_| ()) + .for_each(move |sock| { + let mut ssl_builder = SslAcceptor::mozilla_modern(SslMethod::tls()).unwrap(); + ssl_builder.set_certificate_file(&cert_path, SslFiletype::PEM).unwrap(); + ssl_builder.set_private_key_file(&key_path, SslFiletype::PEM).unwrap(); + + let handler = handler.clone(); + ssl_builder.build().accept_async(sock).map_err(|_| ()).and_then(move |ssl| { + Http::new().serve_connection(ssl, + service_fn_ok(move |req: HyperRequest| { + let mut response = HyperResponse::new(Vec::::new().into()); + handler(req, &mut response); + response + }) + ) + .map_err(|_|()) + }) + }); + + let (tx, rx) = futures::sync::oneshot::channel::<()>(); + let server = server.select(rx.map_err(|_| ())).map(|_| ()).map_err(|_| ()); + + HANDLE.lock().unwrap().spawn(server); + + let server = Server { close_channel: tx }; (server, url) } diff --git a/components/net/tests/mime_classifier.rs b/components/net/tests/mime_classifier.rs index 1a4757ded5f2..593017c7f2ca 100644 --- a/components/net/tests/mime_classifier.rs +++ b/components/net/tests/mime_classifier.rs @@ -2,8 +2,8 @@ * 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/. */ +use mime::{self, Mime}; use net::mime_classifier::{ApacheBugFlag, MimeClassifier, Mp4Matcher, NoSniffFlag}; -use net::mime_classifier::as_string_option; use net_traits::LoadContext; use std::env; use std::fs::File; @@ -58,11 +58,10 @@ fn test_validate_classifier() { #[cfg(test)] fn test_sniff_with_flags(filename_orig: &path::Path, - type_string: &str, - subtype_string: &str, - supplied_type: Option<(&'static str, &'static str)>, - no_sniff_flag: NoSniffFlag, - apache_bug_flag: ApacheBugFlag) { + expected_mime: Mime, + supplied_type: Option, + no_sniff_flag: NoSniffFlag, + apache_bug_flag: ApacheBugFlag) { let current_working_directory = env::current_dir().unwrap(); println!("The current directory is {}", current_working_directory.display()); @@ -75,17 +74,15 @@ fn test_sniff_with_flags(filename_orig: &path::Path, match read_result { Ok(data) => { - let supplied_type = supplied_type.map(|(x, y)| (x.parse().unwrap(), y)); - let (parsed_type, parsed_subtp) = classifier.classify(LoadContext::Browsing, - no_sniff_flag, - apache_bug_flag, - &as_string_option(supplied_type), - &data); - if (&parsed_type[..] != type_string) || - (&parsed_subtp[..] != subtype_string) { - panic!("File {:?} parsed incorrectly should be {}/{}, parsed as {}/{}", - filename, type_string, subtype_string, - parsed_type, parsed_subtp); + let parsed_mime = classifier.classify(LoadContext::Browsing, + no_sniff_flag, + apache_bug_flag, + &supplied_type, + &data); + if (parsed_mime.type_() != expected_mime.type_()) || + (parsed_mime.subtype() != expected_mime.subtype()) { + panic!("File {:?} parsed incorrectly should be {:?}, parsed as {:?}", + filename, expected_mime, parsed_mime); } } Err(e) => panic!("Couldn't read from file {:?} with error {}", @@ -94,407 +91,407 @@ fn test_sniff_with_flags(filename_orig: &path::Path, } #[cfg(test)] -fn test_sniff_full(filename_orig: &path::Path, type_string: &str, subtype_string: &str, - supplied_type: Option<(&'static str, &'static str)>) { +fn test_sniff_full(filename_orig: &path::Path, expected_mime: Mime, + supplied_type: Option) { test_sniff_with_flags(filename_orig, - type_string, - subtype_string, + expected_mime, supplied_type, NoSniffFlag::Off, ApacheBugFlag::Off) } #[cfg(test)] -fn test_sniff_classification(file: &str, type_string: &str, subtype_string: &str, - supplied_type: Option<(&'static str, &'static str)>) { +fn test_sniff_classification(file: &str, expected_mime: Mime, supplied_type: Option) { let mut x = PathBuf::from("./"); - x.push(type_string); - x.push(subtype_string); + x.push(expected_mime.type_().as_str()); + x.push(expected_mime.subtype().as_str()); x.push(file); - test_sniff_full(&x, type_string, subtype_string, supplied_type); + test_sniff_full(&x, expected_mime, supplied_type); } #[cfg(test)] -fn test_sniff_classification_sup(file: &str, type_string: &'static str, subtype_string: &str) { - test_sniff_classification(file, type_string, subtype_string, None); - let class_type = Some((type_string, "")); - test_sniff_classification(file, type_string, subtype_string, class_type); +fn test_sniff_classification_sup(file: &str, expected_mime: Mime) { + test_sniff_classification(file, expected_mime.clone(), None); + let no_sub = format!("{}/", expected_mime.type_()).parse().unwrap(); + test_sniff_classification(file, expected_mime, Some(no_sub)); } #[test] fn test_sniff_x_icon() { - test_sniff_classification_sup("test.ico", "image", "x-icon"); + test_sniff_classification_sup("test.ico", "image/x-icon".parse().unwrap()); } #[test] fn test_sniff_x_icon_cursor() { - test_sniff_classification_sup("test_cursor.ico", "image", "x-icon"); + test_sniff_classification_sup("test_cursor.ico", "image/x-icon".parse().unwrap()); } #[test] fn test_sniff_bmp() { - test_sniff_classification_sup("test.bmp", "image", "bmp"); + test_sniff_classification_sup("test.bmp", mime::IMAGE_BMP); } #[test] fn test_sniff_gif87a() { - test_sniff_classification_sup("test87a", "image", "gif"); + test_sniff_classification_sup("test87a", mime::IMAGE_GIF); } #[test] fn test_sniff_gif89a() { - test_sniff_classification_sup("test89a.gif", "image", "gif"); + test_sniff_classification_sup("test89a.gif", mime::IMAGE_GIF); } #[test] fn test_sniff_webp() { - test_sniff_classification_sup("test.webp", "image", "webp"); + test_sniff_classification_sup("test.webp", "image/webp".parse().unwrap()); } #[test] fn test_sniff_png() { - test_sniff_classification_sup("test.png", "image", "png"); + test_sniff_classification_sup("test.png", mime::IMAGE_PNG); } #[test] fn test_sniff_jpg() { - test_sniff_classification_sup("test.jpg", "image", "jpeg"); + test_sniff_classification_sup("test.jpg", mime::IMAGE_JPEG); } #[test] fn test_sniff_webm() { - test_sniff_classification_sup("test.webm", "video", "webm"); + test_sniff_classification_sup("test.webm", "video/webm".parse().unwrap()); } #[test] fn test_sniff_mp4() { - test_sniff_classification_sup("test.mp4", "video", "mp4"); + test_sniff_classification_sup("test.mp4", "video/mp4".parse().unwrap()); } #[test] fn test_sniff_avi() { - test_sniff_classification_sup("test.avi", "video", "avi"); + test_sniff_classification_sup("test.avi", "video/avi".parse().unwrap()); } #[test] fn test_sniff_basic() { - test_sniff_classification_sup("test.au", "audio", "basic"); + test_sniff_classification_sup("test.au", "audio/basic".parse().unwrap()); } #[test] fn test_sniff_aiff() { - test_sniff_classification_sup("test.aif", "audio", "aiff"); + test_sniff_classification_sup("test.aif", "audio/aiff".parse().unwrap()); } #[test] fn test_sniff_mpeg() { - test_sniff_classification_sup("test.mp3", "audio", "mpeg"); + test_sniff_classification_sup("test.mp3", "audio/mpeg".parse().unwrap()); } #[test] fn test_sniff_midi() { - test_sniff_classification_sup("test.mid", "audio", "midi"); + test_sniff_classification_sup("test.mid", "audio/midi".parse().unwrap()); } #[test] fn test_sniff_wave() { - test_sniff_classification_sup("test.wav", "audio", "wave"); + test_sniff_classification_sup("test.wav", "audio/wave".parse().unwrap()); } #[test] fn test_sniff_ogg() { - test_sniff_classification("small.ogg", "application", "ogg", None); - test_sniff_classification("small.ogg", "application", "ogg", Some(("audio", ""))); + test_sniff_classification("small.ogg", "application/ogg".parse().unwrap(), None); + test_sniff_classification("small.ogg", "application/ogg".parse().unwrap(), Some("audio/".parse().unwrap())); } #[test] #[should_panic] fn test_sniff_vsn_ms_fontobject() { - test_sniff_classification_sup("vnd.ms-fontobject", "application", "vnd.ms-fontobject"); + test_sniff_classification_sup("vnd.ms-fontobject", "application/vnd.ms-fontobject".parse().unwrap()); } #[test] #[should_panic] fn test_sniff_true_type() { - test_sniff_full(&PathBuf::from("unknown/true_type.ttf"), "(TrueType)", "", None); + test_sniff_full(&PathBuf::from("unknown/true_type.ttf"), "(TrueType)/".parse().unwrap(), None); } #[test] #[should_panic] fn test_sniff_open_type() { - test_sniff_full(&PathBuf::from("unknown/open_type"), "(OpenType)", "", None); + test_sniff_full(&PathBuf::from("unknown/open_type"), "(OpenType)/".parse().unwrap(), None); } #[test] #[should_panic] fn test_sniff_true_type_collection() { - test_sniff_full(&PathBuf::from("unknown/true_type_collection.ttc"), "(TrueType Collection)", "", None); + test_sniff_full(&PathBuf::from("unknown/true_type_collection.ttc"), "(TrueType Collection)/".parse().unwrap(), + None); } #[test] #[should_panic] fn test_sniff_woff() { - test_sniff_classification_sup("test.wof", "application", "font-woff"); + test_sniff_classification_sup("test.wof", "application/font-woff".parse().unwrap()); } #[test] fn test_sniff_gzip() { - test_sniff_classification("test.gz", "application", "x-gzip", None); + test_sniff_classification("test.gz", "application/x-gzip".parse().unwrap(), None); } #[test] fn test_sniff_zip() { - test_sniff_classification("test.zip", "application", "zip", None); + test_sniff_classification("test.zip", "application/zip".parse().unwrap(), None); } #[test] fn test_sniff_rar() { - test_sniff_classification("test.rar", "application", "x-rar-compressed", None); + test_sniff_classification("test.rar", "application/x-rar-compressed".parse().unwrap(), None); } #[test] fn test_sniff_text_html_doctype_20() { - test_sniff_classification("text_html_doctype_20.html", "text", "html", None); - test_sniff_classification("text_html_doctype_20_u.html", "text", "html", None); + test_sniff_classification("text_html_doctype_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_doctype_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_doctype_3e() { - test_sniff_classification("text_html_doctype_3e.html", "text", "html", None); - test_sniff_classification("text_html_doctype_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_doctype_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_doctype_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_page_20() { - test_sniff_classification("text_html_page_20.html", "text", "html", None); - test_sniff_classification("text_html_page_20_u.html", "text", "html", None); + test_sniff_classification("text_html_page_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_page_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_page_3e() { - test_sniff_classification("text_html_page_3e.html", "text", "html", None); - test_sniff_classification("text_html_page_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_page_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_page_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_head_20() { - test_sniff_classification("text_html_head_20.html", "text", "html", None); - test_sniff_classification("text_html_head_20_u.html", "text", "html", None); + test_sniff_classification("text_html_head_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_head_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_head_3e() { - test_sniff_classification("text_html_head_3e.html", "text", "html", None); - test_sniff_classification("text_html_head_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_head_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_head_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_script_20() { - test_sniff_classification("text_html_script_20.html", "text", "html", None); - test_sniff_classification("text_html_script_20_u.html", "text", "html", None); + test_sniff_classification("text_html_script_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_script_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_script_3e() { - test_sniff_classification("text_html_script_3e.html", "text", "html", None); - test_sniff_classification("text_html_script_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_script_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_script_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_iframe_20() { - test_sniff_classification("text_html_iframe_20.html", "text", "html", None); - test_sniff_classification("text_html_iframe_20_u.html", "text", "html", None); + test_sniff_classification("text_html_iframe_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_iframe_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_iframe_3e() { - test_sniff_classification("text_html_iframe_3e.html", "text", "html", None); - test_sniff_classification("text_html_iframe_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_iframe_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_iframe_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_h1_20() { - test_sniff_classification("text_html_h1_20.html", "text", "html", None); - test_sniff_classification("text_html_h1_20_u.html", "text", "html", None); + test_sniff_classification("text_html_h1_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_h1_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_h1_3e() { - test_sniff_classification("text_html_h1_3e.html", "text", "html", None); - test_sniff_classification("text_html_h1_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_h1_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_h1_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_div_20() { - test_sniff_classification("text_html_div_20.html", "text", "html", None); - test_sniff_classification("text_html_div_20_u.html", "text", "html", None); + test_sniff_classification("text_html_div_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_div_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_div_3e() { - test_sniff_classification("text_html_div_3e.html", "text", "html", None); - test_sniff_classification("text_html_div_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_div_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_div_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_font_20() { - test_sniff_classification("text_html_font_20.html", "text", "html", None); - test_sniff_classification("text_html_font_20_u.html", "text", "html", None); + test_sniff_classification("text_html_font_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_font_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_font_3e() { - test_sniff_classification("text_html_font_3e.html", "text", "html", None); - test_sniff_classification("text_html_font_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_font_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_font_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_table_20() { - test_sniff_classification("text_html_table_20.html", "text", "html", None); - test_sniff_classification("text_html_table_20_u.html", "text", "html", None); + test_sniff_classification("text_html_table_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_table_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_table_3e() { - test_sniff_classification("text_html_table_3e.html", "text", "html", None); - test_sniff_classification("text_html_table_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_table_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_table_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_a_20() { - test_sniff_classification("text_html_a_20.html", "text", "html", None); - test_sniff_classification("text_html_a_20_u.html", "text", "html", None); + test_sniff_classification("text_html_a_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_a_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_a_3e() { - test_sniff_classification("text_html_a_3e.html", "text", "html", None); - test_sniff_classification("text_html_a_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_a_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_a_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_style_20() { - test_sniff_classification("text_html_style_20.html", "text", "html", None); - test_sniff_classification("text_html_style_20_u.html", "text", "html", None); + test_sniff_classification("text_html_style_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_style_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_style_3e() { - test_sniff_classification("text_html_style_3e.html", "text", "html", None); - test_sniff_classification("text_html_style_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_style_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_style_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_title_20() { - test_sniff_classification("text_html_title_20.html", "text", "html", None); - test_sniff_classification("text_html_title_20_u.html", "text", "html", None); + test_sniff_classification("text_html_title_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_title_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_title_3e() { - test_sniff_classification("text_html_title_3e.html", "text", "html", None); - test_sniff_classification("text_html_title_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_title_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_title_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_b_20() { - test_sniff_classification("text_html_b_20.html", "text", "html", None); - test_sniff_classification("text_html_b_20_u.html", "text", "html", None); + test_sniff_classification("text_html_b_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_b_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_b_3e() { - test_sniff_classification("text_html_b_3e.html", "text", "html", None); - test_sniff_classification("text_html_b_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_b_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_b_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_body_20() { - test_sniff_classification("text_html_body_20.html", "text", "html", None); - test_sniff_classification("text_html_body_20_u.html", "text", "html", None); + test_sniff_classification("text_html_body_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_body_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_body_3e() { - test_sniff_classification("text_html_body_3e.html", "text", "html", None); - test_sniff_classification("text_html_body_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_body_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_body_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_br_20() { - test_sniff_classification("text_html_br_20.html", "text", "html", None); - test_sniff_classification("text_html_br_20_u.html", "text", "html", None); + test_sniff_classification("text_html_br_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_br_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_br_3e() { - test_sniff_classification("text_html_br_3e.html", "text", "html", None); - test_sniff_classification("text_html_br_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_br_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_br_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_p_20() { - test_sniff_classification("text_html_p_20.html", "text", "html", None); - test_sniff_classification("text_html_p_20_u.html", "text", "html", None); + test_sniff_classification("text_html_p_20.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_p_20_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_p_3e() { - test_sniff_classification("text_html_p_3e.html", "text", "html", None); - test_sniff_classification("text_html_p_3e_u.html", "text", "html", None); + test_sniff_classification("text_html_p_3e.html", mime::TEXT_HTML, None); + test_sniff_classification("text_html_p_3e_u.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_comment_20() { - test_sniff_classification("text_html_comment_20.html", "text", "html", None); + test_sniff_classification("text_html_comment_20.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_text_html_comment_3e() { - test_sniff_classification("text_html_comment_3e.html", "text", "html", None); + test_sniff_classification("text_html_comment_3e.html", mime::TEXT_HTML, None); } #[test] fn test_sniff_xml() { - test_sniff_classification("test.xml", "text", "xml", None); + test_sniff_classification("test.xml", mime::TEXT_XML, None); } #[test] fn test_sniff_pdf() { - test_sniff_classification("test.pdf", "application", "pdf", None); + test_sniff_classification("test.pdf", mime::APPLICATION_PDF, None); } #[test] fn test_sniff_postscript() { - test_sniff_classification("test.ps", "application", "postscript", None); + test_sniff_classification("test.ps", "application/postscript".parse().unwrap(), None); } #[test] fn test_sniff_utf_16be_bom() { - test_sniff_classification("utf16bebom.txt", "text", "plain", None); + test_sniff_classification("utf16bebom.txt", mime::TEXT_PLAIN, None); } #[test] fn test_sniff_utf_16le_bom() { - test_sniff_classification("utf16lebom.txt", "text", "plain", None); + test_sniff_classification("utf16lebom.txt", mime::TEXT_PLAIN, None); } #[test] fn test_sniff_utf_8_bom() { - test_sniff_classification("utf8bom.txt", "text", "plain", None); + test_sniff_classification("utf8bom.txt", mime::TEXT_PLAIN, None); } #[test] fn test_sniff_rss_feed() { // RSS feeds - test_sniff_full(&PathBuf::from("text/xml/feed.rss"), "application", "rss+xml", Some(("text", "html"))); - test_sniff_full(&PathBuf::from("text/xml/rdf_rss.xml"), "application", "rss+xml", Some(("text", "html"))); + test_sniff_full(&PathBuf::from("text/xml/feed.rss"), "application/rss+xml".parse().unwrap(), Some(mime::TEXT_HTML)); + test_sniff_full(&PathBuf::from("text/xml/rdf_rss.xml"), "application/rss+xml".parse().unwrap(), + Some(mime::TEXT_HTML)); // Not RSS feeds - test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_1.xml"), "text", "html", Some(("text", "html"))); - test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_2.xml"), "text", "html", Some(("text", "html"))); - test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_3.xml"), "text", "html", Some(("text", "html"))); - test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_4.xml"), "text", "html", Some(("text", "html"))); + test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_1.xml"), mime::TEXT_HTML, Some(mime::TEXT_HTML)); + test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_2.xml"), mime::TEXT_HTML, Some(mime::TEXT_HTML)); + test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_3.xml"), mime::TEXT_HTML, Some(mime::TEXT_HTML)); + test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_4.xml"), mime::TEXT_HTML, Some(mime::TEXT_HTML)); } #[test] fn test_sniff_atom_feed() { - test_sniff_full(&PathBuf::from("text/xml/feed.atom"), "application", "atom+xml", Some(("text", "html"))); + test_sniff_full(&PathBuf::from("text/xml/feed.atom"), "application/atom+xml".parse().unwrap(), + Some(mime::TEXT_HTML)); } #[test] fn test_sniff_binary_file() { - test_sniff_full(&PathBuf::from("unknown/binary_file"), "application", "octet-stream", None); + test_sniff_full(&PathBuf::from("unknown/binary_file"), mime::APPLICATION_OCTET_STREAM, None); } #[test] fn test_sniff_atom_feed_with_no_sniff_flag_on() { test_sniff_with_flags(&PathBuf::from("text/xml/feed.atom"), - "text", - "html", - Some(("text", "html")), + mime::TEXT_HTML, + Some(mime::TEXT_HTML), NoSniffFlag::On, ApacheBugFlag::Off); } @@ -502,9 +499,8 @@ fn test_sniff_atom_feed_with_no_sniff_flag_on() { #[test] fn test_sniff_with_no_sniff_flag_on_and_apache_flag_on() { test_sniff_with_flags(&PathBuf::from("text/xml/feed.atom"), - "text", - "html", - Some(("text", "html")), + mime::TEXT_HTML, + Some(mime::TEXT_HTML), NoSniffFlag::On, ApacheBugFlag::On); } @@ -512,9 +508,8 @@ fn test_sniff_with_no_sniff_flag_on_and_apache_flag_on() { #[test] fn test_sniff_utf_8_bom_with_apache_flag_on() { test_sniff_with_flags(&PathBuf::from("text/plain/utf8bom.txt"), - "text", - "plain", - Some(("dummy", "text")), + mime::TEXT_PLAIN, + Some("dummy/text".parse().unwrap()), NoSniffFlag::Off, ApacheBugFlag::On); } @@ -522,9 +517,8 @@ fn test_sniff_utf_8_bom_with_apache_flag_on() { #[test] fn test_sniff_utf_16be_bom_with_apache_flag_on() { test_sniff_with_flags(&PathBuf::from("text/plain/utf16bebom.txt"), - "text", - "plain", - Some(("dummy", "text")), + mime::TEXT_PLAIN, + Some("dummy/text".parse().unwrap()), NoSniffFlag::Off, ApacheBugFlag::On); } @@ -532,9 +526,8 @@ fn test_sniff_utf_16be_bom_with_apache_flag_on() { #[test] fn test_sniff_utf_16le_bom_with_apache_flag_on() { test_sniff_with_flags(&PathBuf::from("text/plain/utf16lebom.txt"), - "text", - "plain", - Some(("dummy", "text")), + mime::TEXT_PLAIN, + Some("dummy/text".parse().unwrap()), NoSniffFlag::Off, ApacheBugFlag::On); } @@ -542,9 +535,8 @@ fn test_sniff_utf_16le_bom_with_apache_flag_on() { #[test] fn test_sniff_octet_stream_apache_flag_on() { test_sniff_with_flags(&PathBuf::from("unknown/binary_file"), - "application", - "octet-stream", - Some(("dummy", "binary")), + mime::APPLICATION_OCTET_STREAM, + Some("dummy/binary".parse().unwrap()), NoSniffFlag::Off, ApacheBugFlag::On); } @@ -552,9 +544,8 @@ fn test_sniff_octet_stream_apache_flag_on() { #[test] fn test_sniff_mp4_video_apache_flag_on() { test_sniff_with_flags(&PathBuf::from("video/mp4/test.mp4"), - "application", - "octet-stream", - Some(("video", "mp4")), + mime::APPLICATION_OCTET_STREAM, + Some("video/mp4".parse().unwrap()), NoSniffFlag::Off, ApacheBugFlag::On); } diff --git a/components/net/websocket_loader.rs b/components/net/websocket_loader.rs index 5a676c904ad0..8440e0b3c634 100644 --- a/components/net/websocket_loader.rs +++ b/components/net/websocket_loader.rs @@ -2,13 +2,15 @@ * 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/. */ -use connector::create_ssl_connector; +use connector::create_ssl_connector_builder; use cookie::Cookie; use embedder_traits::resources::{self, Resource}; use fetch::methods::should_be_blocked_due_to_bad_port; +use headers_ext::Host; use hosts::replace_host; +use http::header::{self, HeaderMap, HeaderName, HeaderValue}; +use http::uri::Authority; use http_loader::HttpState; -use hyper::header::{Headers, Host, SetCookie}; use ipc_channel::ipc::{IpcReceiver, IpcSender}; use net_traits::{CookieSource, MessageData}; use net_traits::{WebSocketDomAction, WebSocketNetworkEvent}; @@ -69,17 +71,19 @@ impl<'a> Handler for Client<'a> { } fn on_open(&mut self, shake: Handshake) -> WebSocketResult<()> { - let mut headers = Headers::new(); + let mut headers = HeaderMap::new(); for &(ref name, ref value) in shake.response.headers().iter() { - headers.set_raw(name.clone(), vec![value.clone()]); + let name = HeaderName::from_bytes(name.as_bytes()).unwrap(); + let value = HeaderValue::from_bytes(&value).unwrap(); + + headers.insert(name, value); } - if let Some(cookies) = headers.get::() { - let mut jar = self.http_state.cookie_jar.write().unwrap(); - for cookie in &**cookies { - if let Some(cookie) = - Cookie::from_cookie_string(cookie.clone(), self.resource_url, CookieSource::HTTP) - { + let mut jar = self.http_state.cookie_jar.write().unwrap(); + // TODO(eijebong): Replace thise once typed headers settled on a cookie impl + for cookie in headers.get_all(header::SET_COOKIE) { + if let Ok(s) = cookie.to_str() { + if let Some(cookie) = Cookie::from_cookie_string(s.into(), self.resource_url, CookieSource::HTTP) { jar.push(cookie, self.resource_url, CookieSource::HTTP); } } @@ -144,7 +148,7 @@ impl<'a> Handler for Client<'a> { WebSocketErrorKind::Protocol, format!("Unable to parse domain from {}. Needed for SSL.", url), ))?; - let connector = create_ssl_connector(&certs); + let connector = create_ssl_connector_builder(&certs).build(); connector.connect(domain, stream).map_err(WebSocketError::from) } @@ -180,10 +184,11 @@ pub fn init( let mut net_url = req_init.url.clone().into_url(); net_url.set_host(Some(&host)).unwrap(); - let host = Host { - hostname: req_init.url.host_str().unwrap().to_owned(), - port: req_init.url.port_or_known_default(), - }; + let host = Host::from( + format!("{}{}", req_init.url.host_str().unwrap(), + req_init.url.port_or_known_default().map(|v| format!(":{}", v)).unwrap_or("".into()) + ).parse::().unwrap() + ); let client = Client { origin: &req_init.origin.ascii_serialization(), diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml index f2046b9cfebf..4d89992ff11f 100644 --- a/components/net_traits/Cargo.toml +++ b/components/net_traits/Cargo.toml @@ -12,16 +12,20 @@ test = false doctest = false [dependencies] -cookie = "0.10" +cookie = "0.11" embedder_traits = { path = "../embedder_traits" } -hyper = "0.10" -hyper_serde = "0.8" +headers-core = "0.0.1" +headers-ext = "0.0.3" +http = "0.1" +hyper = "0.12" +hyper_serde = "0.9" image = "0.19" ipc-channel = "0.11" lazy_static = "1" log = "0.4" malloc_size_of = { path = "../malloc_size_of" } malloc_size_of_derive = { path = "../malloc_size_of_derive" } +mime = "0.3" msg = {path = "../msg"} num-traits = "0.2" pixels = {path = "../pixels"} diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 85862b99a116..5a6a1364fbf9 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -7,6 +7,9 @@ extern crate cookie as cookie_rs; extern crate embedder_traits; +extern crate headers_core; +extern crate headers_ext; +extern crate http; extern crate hyper; extern crate hyper_serde; extern crate image as piston_image; @@ -15,38 +18,43 @@ extern crate ipc_channel; #[macro_use] extern crate log; #[macro_use] extern crate malloc_size_of; #[macro_use] extern crate malloc_size_of_derive; +extern crate mime; extern crate msg; extern crate num_traits; extern crate pixels; #[macro_use] extern crate serde; extern crate servo_arc; extern crate servo_url; -extern crate url; +#[macro_use] extern crate url; extern crate uuid; extern crate webrender_api; use cookie_rs::Cookie; use filemanager_thread::FileManagerThreadMsg; +use headers_core::HeaderMapExt; +use headers_ext::{ContentType, ReferrerPolicy as ReferrerPolicyHeader}; +use http::{Error as HttpError, HeaderMap}; use hyper::Error as HyperError; -use hyper::header::{ContentType, Headers, ReferrerPolicy as ReferrerPolicyHeader}; -use hyper::http::RawStatus; -use hyper::mime::{Attr, Mime}; +use hyper::StatusCode; use hyper_serde::Serde; use ipc_channel::Error as IpcError; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; +use mime::Mime; use msg::constellation_msg::HistoryStateId; use request::{Request, RequestInit}; use response::{HttpsState, Response, ResponseInit}; use servo_url::ServoUrl; use std::error::Error; use storage_thread::StorageThreadMsg; +use url::percent_encoding; pub mod blob_url_store; pub mod filemanager_thread; pub mod image_cache; pub mod net_error_list; pub mod pub_domains; +pub mod quality; pub mod request; pub mod response; pub mod storage_thread; @@ -80,16 +88,16 @@ pub struct CustomResponse { #[ignore_malloc_size_of = "Defined in hyper"] #[serde(deserialize_with = "::hyper_serde::deserialize", serialize_with = "::hyper_serde::serialize")] - pub headers: Headers, + pub headers: HeaderMap, #[ignore_malloc_size_of = "Defined in hyper"] #[serde(deserialize_with = "::hyper_serde::deserialize", serialize_with = "::hyper_serde::serialize")] - pub raw_status: RawStatus, + pub raw_status: (StatusCode, String), pub body: Vec, } impl CustomResponse { - pub fn new(headers: Headers, raw_status: RawStatus, body: Vec) -> CustomResponse { + pub fn new(headers: HeaderMap, raw_status: (StatusCode, String), body: Vec) -> CustomResponse { CustomResponse { headers: headers, raw_status: raw_status, @@ -126,24 +134,24 @@ pub enum ReferrerPolicy { StrictOriginWhenCrossOrigin, } -impl<'a> From<&'a ReferrerPolicyHeader> for ReferrerPolicy { - fn from(policy: &'a ReferrerPolicyHeader) -> Self { - match *policy { - ReferrerPolicyHeader::NoReferrer => +impl From for ReferrerPolicy { + fn from(policy: ReferrerPolicyHeader) -> Self { + match policy { + ReferrerPolicyHeader::NO_REFERRER => ReferrerPolicy::NoReferrer, - ReferrerPolicyHeader::NoReferrerWhenDowngrade => + ReferrerPolicyHeader::NO_REFERRER_WHEN_DOWNGRADE => ReferrerPolicy::NoReferrerWhenDowngrade, - ReferrerPolicyHeader::SameOrigin => + ReferrerPolicyHeader::SAME_ORIGIN => ReferrerPolicy::SameOrigin, - ReferrerPolicyHeader::Origin => + ReferrerPolicyHeader::ORIGIN => ReferrerPolicy::Origin, - ReferrerPolicyHeader::OriginWhenCrossOrigin => + ReferrerPolicyHeader::ORIGIN_WHEN_CROSS_ORIGIN => ReferrerPolicy::OriginWhenCrossOrigin, - ReferrerPolicyHeader::UnsafeUrl => + ReferrerPolicyHeader::UNSAFE_URL => ReferrerPolicy::UnsafeUrl, - ReferrerPolicyHeader::StrictOrigin => + ReferrerPolicyHeader::STRICT_ORIGIN => ReferrerPolicy::StrictOrigin, - ReferrerPolicyHeader::StrictOriginWhenCrossOrigin => + ReferrerPolicyHeader::STRICT_ORIGIN_WHEN_CROSS_ORIGIN => ReferrerPolicy::StrictOriginWhenCrossOrigin, } } @@ -419,7 +427,7 @@ pub struct Metadata { #[ignore_malloc_size_of = "Defined in hyper"] /// Headers - pub headers: Option>, + pub headers: Option>, /// HTTP Status pub status: Option<(u16, Vec)>, @@ -454,16 +462,15 @@ impl Metadata { /// Extract the parts of a Mime that we care about. pub fn set_content_type(&mut self, content_type: Option<&Mime>) { if self.headers.is_none() { - self.headers = Some(Serde(Headers::new())); + self.headers = Some(Serde(HeaderMap::new())); } if let Some(mime) = content_type { - self.headers.as_mut().unwrap().set(ContentType(mime.clone())); - self.content_type = Some(Serde(ContentType(mime.clone()))); - let Mime(_, _, ref parameters) = *mime; - for &(ref k, ref v) in parameters { - if Attr::Charset == *k { - self.charset = Some(v.to_string()); + self.headers.as_mut().unwrap().typed_insert(ContentType::from(mime.clone())); + self.content_type = Some(Serde(ContentType::from(mime.clone()))); + for (name, value) in mime.params() { + if mime::CHARSET == name { + self.charset = Some(value.to_string()); } } } @@ -518,18 +525,16 @@ pub enum NetworkError { } impl NetworkError { - pub fn from_hyper_error(url: &ServoUrl, error: HyperError) -> Self { - if let HyperError::Ssl(ref ssl_error) = error { - return NetworkError::from_ssl_error(url, &**ssl_error); - } + pub fn from_hyper_error(error: &HyperError) -> Self { NetworkError::Internal(error.description().to_owned()) } - pub fn from_ssl_error(url: &ServoUrl, error: &Error) -> Self { - NetworkError::SslValidation(url.clone(), error.description().to_owned()) + pub fn from_http_error(error: &HttpError) -> Self { + NetworkError::Internal(error.description().to_owned()) } } + /// Normalize `slice`, as defined by /// [the Fetch Spec](https://fetch.spec.whatwg.org/#concept-header-value-normalize). pub fn trim_http_whitespace(mut slice: &[u8]) -> &[u8] { @@ -551,3 +556,17 @@ pub fn trim_http_whitespace(mut slice: &[u8]) -> &[u8] { slice } + +pub fn http_percent_encode(bytes: &[u8]) -> String { + define_encode_set! { + // This encode set is used for HTTP header values and is defined at + // https://tools.ietf.org/html/rfc5987#section-3.2 + pub HTTP_VALUE = [percent_encoding::SIMPLE_ENCODE_SET] | { + ' ', '"', '%', '\'', '(', ')', '*', ',', '/', ':', ';', '<', '-', '>', '?', + '[', '\\', ']', '{', '}' + } + } + + url::percent_encoding::percent_encode(bytes, HTTP_VALUE).to_string() +} + diff --git a/components/net_traits/quality.rs b/components/net_traits/quality.rs new file mode 100644 index 000000000000..72fed2304ca9 --- /dev/null +++ b/components/net_traits/quality.rs @@ -0,0 +1,80 @@ +/* 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/. */ + +//TODO(eijebong): Remove this once typed headers figure out quality +// This is copy pasted from the old hyper headers to avoid hardcoding everything +// (I would probably also make some silly mistakes while migrating...) + +use http::header::HeaderValue; +use mime::Mime; +use std::{fmt, str}; + +/// A quality value, as specified in [RFC7231]. +/// +/// Quality values are decimal numbers between 0 and 1 (inclusive) with up to 3 fractional digits of precision. +/// +/// [RFC7231]: https://tools.ietf.org/html/rfc7231#section-5.3.1 +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct Quality(u16); + +impl Quality { + /// Creates a quality value from a value between 0 and 1000 inclusive. + /// + /// This is semantically divided by 1000 to produce a value between 0 and 1. + /// + /// # Panics + /// + /// Panics if the value is greater than 1000. + pub fn from_u16(quality: u16) -> Quality { + assert!(quality <= 1000); + Quality(quality) + } +} + +/// A value paired with its "quality" as defined in [RFC7231]. +/// +/// Quality items are used in content negotiation headers such as `Accept` and `Accept-Encoding`. +/// +/// [RFC7231]: https://tools.ietf.org/html/rfc7231#section-5.3 +#[derive(Clone, Debug, PartialEq)] +pub struct QualityItem { + pub item: T, + pub quality: Quality, +} + +impl QualityItem { + /// Creates a new quality item. + pub fn new(item: T, quality: Quality) -> QualityItem { + QualityItem { item, quality } + } +} + +impl fmt::Display for QualityItem +where + T: fmt::Display, +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.item, fmt)?; + match self.quality.0 { + 1000 => Ok(()), + 0 => fmt.write_str("; q=0"), + mut x => { + fmt.write_str("; q=0.")?; + let mut digits = *b"000"; + digits[2] = (x % 10) as u8 + b'0'; + x /= 10; + digits[1] = (x % 10) as u8 + b'0'; + x /= 10; + digits[0] = (x % 10) as u8 + b'0'; + + let s = str::from_utf8(&digits[..]).unwrap(); + fmt.write_str(s.trim_right_matches('0')) + } + } + } +} + +pub fn quality_to_value(q: Vec>) -> HeaderValue { + HeaderValue::from_str(&q.iter().map(|q| q.to_string()).collect::>().join(", ")).unwrap() +} diff --git a/components/net_traits/request.rs b/components/net_traits/request.rs index 822a39ee324c..4113037a6725 100644 --- a/components/net_traits/request.rs +++ b/components/net_traits/request.rs @@ -3,8 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use ReferrerPolicy; -use hyper::header::Headers; -use hyper::method::Method; +use http::HeaderMap; +use hyper::Method; use msg::constellation_msg::PipelineId; use servo_url::{ImmutableOrigin, ServoUrl}; use std::default::Default; @@ -145,7 +145,7 @@ pub struct RequestInit { #[serde(deserialize_with = "::hyper_serde::deserialize", serialize_with = "::hyper_serde::serialize")] #[ignore_malloc_size_of = "Defined in hyper"] - pub headers: Headers, + pub headers: HeaderMap, pub unsafe_request: bool, pub body: Option>, pub service_workers_mode: ServiceWorkersMode, @@ -171,9 +171,9 @@ pub struct RequestInit { impl Default for RequestInit { fn default() -> RequestInit { RequestInit { - method: Method::Get, + method: Method::GET, url: ServoUrl::parse("about:blank").unwrap(), - headers: Headers::new(), + headers: HeaderMap::new(), unsafe_request: false, body: None, service_workers_mode: ServiceWorkersMode::All, @@ -208,7 +208,7 @@ pub struct Request { pub sandboxed_storage_area_urls: bool, /// #[ignore_malloc_size_of = "Defined in hyper"] - pub headers: Headers, + pub headers: HeaderMap, /// pub unsafe_request: bool, /// @@ -264,10 +264,10 @@ impl Request { pipeline_id: Option) -> Request { Request { - method: Method::Get, + method: Method::GET, local_urls_only: false, sandboxed_storage_area_urls: false, - headers: Headers::new(), + headers: HeaderMap::new(), unsafe_request: false, body: None, window: Window::Client, diff --git a/components/net_traits/response.rs b/components/net_traits/response.rs index 4b0a64460ce1..e7f39358c5a6 100644 --- a/components/net_traits/response.rs +++ b/components/net_traits/response.rs @@ -5,8 +5,9 @@ //! The [Response](https://fetch.spec.whatwg.org/#responses) object //! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch) use {FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy}; -use hyper::header::{AccessControlExposeHeaders, ContentType, Headers}; -use hyper::status::StatusCode; +use headers_core::HeaderMapExt; +use headers_ext::{AccessControlExposeHeaders, ContentType}; +use http::{HeaderMap, StatusCode}; use hyper_serde::Serde; use servo_arc::Arc; use servo_url::ServoUrl; @@ -81,7 +82,7 @@ pub struct ResponseInit { #[serde(deserialize_with = "::hyper_serde::deserialize", serialize_with = "::hyper_serde::serialize")] #[ignore_malloc_size_of = "Defined in hyper"] - pub headers: Headers, + pub headers: HeaderMap, pub status_code: u16, pub referrer: Option, pub location_url: Option>, @@ -96,10 +97,10 @@ pub struct Response { pub url_list: Vec, /// `None` can be considered a StatusCode of `0`. #[ignore_malloc_size_of = "Defined in hyper"] - pub status: Option, + pub status: Option<(StatusCode, String)>, pub raw_status: Option<(u16, Vec)>, #[ignore_malloc_size_of = "Defined in hyper"] - pub headers: Headers, + pub headers: HeaderMap, #[ignore_malloc_size_of = "Mutex heap size undefined"] pub body: Arc>, pub cache_state: CacheState, @@ -127,9 +128,9 @@ impl Response { termination_reason: None, url: Some(url), url_list: vec![], - status: Some(StatusCode::Ok), + status: Some((StatusCode::OK, "OK".to_string())), raw_status: Some((200, b"OK".to_vec())), - headers: Headers::new(), + headers: HeaderMap::new(), body: Arc::new(Mutex::new(ResponseBody::Empty)), cache_state: CacheState::None, https_state: HttpsState::None, @@ -148,7 +149,7 @@ impl Response { res.location_url = init.location_url; res.headers = init.headers; res.referrer = init.referrer; - res.status = Some(StatusCode::from_u16(init.status_code)); + res.status = StatusCode::from_u16(init.status_code).map(|s| (s, s.to_string())).ok(); res } @@ -160,7 +161,7 @@ impl Response { url_list: vec![], status: None, raw_status: None, - headers: Headers::new(), + headers: HeaderMap::new(), body: Arc::new(Mutex::new(ResponseBody::Empty)), cache_state: CacheState::None, https_state: HttpsState::None, @@ -242,45 +243,43 @@ impl Response { ResponseType::Error(..) => unreachable!(), ResponseType::Basic => { - let headers = old_headers.iter().filter(|header| { - match &*header.name().to_ascii_lowercase() { + let headers = old_headers.iter().filter(|(name, _)| { + match &*name.as_str().to_ascii_lowercase() { "set-cookie" | "set-cookie2" => false, _ => true } - }).collect(); + }).map(|(n, v)| (n.clone(), v.clone())).collect(); response.headers = headers; }, ResponseType::Cors => { - let access = old_headers.get::(); - let allowed_headers = access.as_ref().map(|v| &v[..]).unwrap_or(&[]); - - let headers = old_headers.iter().filter(|header| { - match &*header.name().to_ascii_lowercase() { + let headers = old_headers.iter().filter(|(name, _)| { + match &*name.as_str().to_ascii_lowercase() { "cache-control" | "content-language" | "content-type" | "expires" | "last-modified" | "pragma" => true, "set-cookie" | "set-cookie2" => false, header => { - let result = - allowed_headers.iter().find(|h| *header == *h.to_ascii_lowercase()); + let access = old_headers.typed_get::(); + let result = access + .and_then(|v| v.iter().find(|h| *header == h.as_str().to_ascii_lowercase())); result.is_some() } } - }).collect(); + }).map(|(n, v)| (n.clone(), v.clone())).collect(); response.headers = headers; }, ResponseType::Opaque => { response.url_list = vec![]; response.url = None; - response.headers = Headers::new(); + response.headers = HeaderMap::new(); response.status = None; response.body = Arc::new(Mutex::new(ResponseBody::Empty)); response.cache_state = CacheState::None; }, ResponseType::OpaqueRedirect => { - response.headers = Headers::new(); + response.headers = HeaderMap::new(); response.status = None; response.body = Arc::new(Mutex::new(ResponseBody::Empty)); response.cache_state = CacheState::None; @@ -293,10 +292,7 @@ impl Response { pub fn metadata(&self) -> Result { fn init_metadata(response: &Response, url: &ServoUrl) -> Metadata { let mut metadata = Metadata::default(url.clone()); - metadata.set_content_type(match response.headers.get() { - Some(&ContentType(ref mime)) => Some(mime), - None => None, - }); + metadata.set_content_type(response.headers.typed_get::().map(|v| v.into()).as_ref()); metadata.location_url = response.location_url.clone(); metadata.headers = Some(Serde(response.headers.clone())); metadata.status = response.raw_status.clone(); diff --git a/components/profile/Cargo.toml b/components/profile/Cargo.toml index 7b9d79a7a8f0..890a9aa93368 100644 --- a/components/profile/Cargo.toml +++ b/components/profile/Cargo.toml @@ -14,7 +14,7 @@ unstable = ["jemalloc-sys"] [dependencies] profile_traits = {path = "../profile_traits"} -influent = "0.4" +influent = "0.5" ipc-channel = "0.11" heartbeats-simple = "0.4" log = "0.4" @@ -22,6 +22,7 @@ serde = "1.0" serde_json = "1.0" servo_config = {path = "../config"} time = "0.1.12" +tokio = "0.1" [target.'cfg(target_os = "macos")'.dependencies] task_info = {path = "../../support/rust-task_info"} diff --git a/components/profile/lib.rs b/components/profile/lib.rs index d01aad61cd05..248fd0ab19bb 100644 --- a/components/profile/lib.rs +++ b/components/profile/lib.rs @@ -25,6 +25,7 @@ extern crate servo_config; #[cfg(target_os = "macos")] extern crate task_info; extern crate time as std_time; +extern crate tokio; #[allow(unsafe_code)] mod heartbeats; diff --git a/components/profile/time.rs b/components/profile/time.rs index 780a6e9da2fd..e2d12ad57010 100644 --- a/components/profile/time.rs +++ b/components/profile/time.rs @@ -23,6 +23,8 @@ use std::io::{self, Write}; use std::path::Path; use std::time::Duration; use std_time::precise_time_ns; +use tokio; +use tokio::prelude::Future; use trace_dump::TraceDump; pub trait Formattable { @@ -470,9 +472,9 @@ impl Profiler { if let Some(ref meta) = *meta { measurement.add_tag("host", meta.url.as_str()); }; - if client.write_one(measurement, None).is_err() { - warn!("Could not write measurement to profiler db"); - } + + tokio::run(client.write_one(measurement, None) + .map_err(|e| warn!("Could not write measurement to profiler db: {:?}", e))); } } }, diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 12cb7c6c6674..614f9fcded15 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -31,13 +31,13 @@ tinyfiledialogs = "3.0" [dependencies] app_units = "0.7" backtrace = {version = "0.3", optional = true} -base64 = "0.6" +base64 = "0.9" bitflags = "1.0" bluetooth_traits = {path = "../bluetooth_traits"} byteorder = "1.0" canvas_traits = {path = "../canvas_traits"} caseless = "0.2" -cookie = "0.10" +cookie = "0.11" chrono = "0.4" cssparser = "0.24" deny_public_fields = {path = "../deny_public_fields"} @@ -51,9 +51,12 @@ euclid = "0.19" fnv = "1.0" gleam = "0.6" half = "1.0" +headers-core = "0.0.1" +headers-ext = "0.0.3" html5ever = "0.22" -hyper = "0.10" -hyper_serde = "0.8" +http = "0.1" +hyper = "0.12" +hyper_serde = "0.9" image = "0.19" ipc-channel = "0.11" itertools = "0.7.6" @@ -66,8 +69,8 @@ malloc_size_of = { path = "../malloc_size_of" } malloc_size_of_derive = { path = "../malloc_size_of_derive" } metrics = {path = "../metrics"} mitochondria = "1.1.2" -mime = "0.2.1" -mime_guess = "1.8.0" +mime = "0.3" +mime_guess = "2.0.0-alpha.6" mozjs = "0.9.3" msg = {path = "../msg"} net_traits = {path = "../net_traits"} diff --git a/components/script/body.rs b/components/script/body.rs index 9709043912b4..cfc167d25b42 100644 --- a/components/script/body.rs +++ b/components/script/body.rs @@ -22,7 +22,7 @@ use js::jsval::UndefinedValue; use js::rust::wrappers::JS_GetPendingException; use js::rust::wrappers::JS_ParseJSON; use js::typedarray::{ArrayBuffer, CreateWith}; -use mime::{Mime, TopLevel, SubLevel}; +use mime::{self, Mime}; use std::cell::Ref; use std::ptr; use std::rc::Rc; @@ -175,23 +175,22 @@ fn run_form_data_algorithm( } else { "" }; - let mime: Mime = mime_str - .parse() - .map_err(|_| Error::Type("Inappropriate MIME-type for Body".to_string()))?; - match mime { - // TODO - // ... Parser for Mime(TopLevel::Multipart, SubLevel::FormData, _) - // ... is not fully determined yet. - Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, _) => { - let entries = form_urlencoded::parse(&bytes); - let formdata = FormData::new(None, root); - for (k, e) in entries { - formdata.Append(USVString(k.into_owned()), USVString(e.into_owned())); - } - return Ok(FetchedData::FormData(formdata)); - }, - _ => return Err(Error::Type("Inappropriate MIME-type for Body".to_string())), + let mime: Mime = mime_str.parse().map_err( + |_| Error::Type("Inappropriate MIME-type for Body".to_string()))?; + + // TODO + // ... Parser for Mime(TopLevel::Multipart, SubLevel::FormData, _) + // ... is not fully determined yet. + if mime.type_() == mime::APPLICATION && mime.subtype() == mime::WWW_FORM_URLENCODED { + let entries = form_urlencoded::parse(&bytes); + let formdata = FormData::new(None, root); + for (k, e) in entries { + formdata.Append(USVString(k.into_owned()), USVString(e.into_owned())); + } + return Ok(FetchedData::FormData(formdata)); } + + Err(Error::Type("Inappropriate MIME-type for Body".to_string())) } #[allow(unsafe_code)] diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 8e720f28e255..75fcfb42c161 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -55,10 +55,9 @@ use euclid::Length as EuclidLength; use html5ever::{Prefix, LocalName, Namespace, QualName}; use html5ever::buffer_queue::BufferQueue; use html5ever::tendril::IncompleteUtf8; -use hyper::header::Headers; -use hyper::method::Method; -use hyper::mime::Mime; -use hyper::status::StatusCode; +use http::header::HeaderMap; +use hyper::Method; +use hyper::StatusCode; use ipc_channel::ipc::{IpcReceiver, IpcSender}; use js::glue::{CallObjectTracer, CallValueTracer}; use js::jsapi::{GCTraceKindToAscii, Heap, JSObject, JSTracer, TraceKind}; @@ -67,6 +66,7 @@ use js::rust::{GCMethods, Handle, Runtime}; use js::typedarray::TypedArray; use js::typedarray::TypedArrayElement; use metrics::{InteractiveMetrics, InteractiveWindow}; +use mime::Mime; use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId, TopLevelBrowsingContextId}; use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads}; use net_traits::filemanager_thread::RelativePos; @@ -391,7 +391,7 @@ unsafe_no_jsmanaged_fields!(TimelineMarkerType); unsafe_no_jsmanaged_fields!(WorkerId); unsafe_no_jsmanaged_fields!(BufferQueue, QuirksMode, IncompleteUtf8); unsafe_no_jsmanaged_fields!(Runtime); -unsafe_no_jsmanaged_fields!(Headers, Method); +unsafe_no_jsmanaged_fields!(HeaderMap, Method); unsafe_no_jsmanaged_fields!(WindowProxyHandler); unsafe_no_jsmanaged_fields!(UntrustedNodeAddress); unsafe_no_jsmanaged_fields!(LengthOrPercentageOrAuto); diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 9b52ea86b085..75527a90efcf 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -95,14 +95,13 @@ use encoding_rs::{Encoding, UTF_8}; use euclid::Point2D; use fetch::FetchCanceller; use html5ever::{LocalName, Namespace, QualName}; -use hyper::header::{Header, SetCookie}; use hyper_serde::Serde; use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::{JSContext, JSObject, JSRuntime}; use js::jsapi::JS_GetRuntime; use keyboard_types::{Key, KeyState, Modifiers}; use metrics::{InteractiveFlag, InteractiveMetrics, InteractiveWindow, ProfilerMetadataFactory, ProgressiveWebMetric}; -use mime::{Mime, TopLevel, SubLevel}; +use mime::{self, Mime}; use msg::constellation_msg::BrowsingContextId; use net_traits::{FetchResponseMsg, IpcSend, ReferrerPolicy}; use net_traits::CookieSource::NonHTTP; @@ -2530,14 +2529,12 @@ impl Document { implementation: Default::default(), content_type: match content_type { Some(mime_data) => mime_data, - None => Mime::from(match is_html_document { + None => match is_html_document { // https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument - IsHTMLDocument::HTMLDocument => Mime(TopLevel::Text, SubLevel::Html, vec![]), + IsHTMLDocument::HTMLDocument => mime::TEXT_HTML, // https://dom.spec.whatwg.org/#concept-document-content-type - IsHTMLDocument::NonHTMLDocument => { - Mime(TopLevel::Application, SubLevel::Xml, vec![]) - }, - }), + IsHTMLDocument::NonHTMLDocument => "application/xml".parse().unwrap(), + }, }, last_modified: last_modified, url: DomRefCell::new(url), @@ -3345,8 +3342,10 @@ impl DocumentMethods for Document { local_name.make_ascii_lowercase(); } - let is_xhtml = self.content_type.0 == TopLevel::Application && - self.content_type.1.as_str() == "xhtml+xml"; + let is_xhtml = self.content_type.type_() == mime::APPLICATION && + self.content_type.subtype().as_str() == "xhtml" && + self.content_type.suffix() == Some(mime::XML); + let ns = if self.is_html_document || is_xhtml { ns!(html) } else { @@ -3947,18 +3946,16 @@ impl DocumentMethods for Document { return Err(Error::Security); } - if let Ok(cookie_header) = SetCookie::parse_header(&vec![cookie.to_string().into_bytes()]) { - let cookies = cookie_header - .0 - .into_iter() - .filter_map(|cookie| cookie_rs::Cookie::parse(cookie).ok().map(Serde)) - .collect(); - let _ = self - .window + let cookies = if let Some(cookie) = cookie_rs::Cookie::parse(cookie.to_string()).ok().map(Serde) { + vec![cookie] + } else { + vec![] + }; + + let _ = self.window .upcast::() .resource_threads() .send(SetCookiesForUrl(self.url(), cookies, NonHTTP)); - } Ok(()) } diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs index f20cc61f3dfb..8936cc8b3916 100644 --- a/components/script/dom/domimplementation.rs +++ b/components/script/dom/domimplementation.rs @@ -24,7 +24,7 @@ use dom::node::Node; use dom::text::Text; use dom::xmldocument::XMLDocument; use dom_struct::dom_struct; -use mime::{Mime, TopLevel, SubLevel}; +use mime; use script_traits::DocumentActivity; // https://dom.spec.whatwg.org/#domimplementation @@ -82,17 +82,9 @@ impl DOMImplementationMethods for DOMImplementation { let namespace = namespace_from_domstring(maybe_namespace.to_owned()); let content_type = match namespace { - ns!(html) => Mime( - TopLevel::Application, - SubLevel::Ext("xhtml+xml".to_string()), - vec![], - ), - ns!(svg) => Mime( - TopLevel::Image, - SubLevel::Ext("svg+xml".to_string()), - vec![], - ), - _ => Mime(TopLevel::Application, SubLevel::Xml, vec![]), + ns!(html) => "application/xhtml+xml".parse().unwrap(), + ns!(svg) => mime::IMAGE_SVG, + _ => "application/xml".parse().unwrap(), }; // Step 1. diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index 7aad98406a4c..208d8aee8ed4 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -17,13 +17,14 @@ use dom::messageevent::MessageEvent; use dom_struct::dom_struct; use euclid::Length; use fetch::FetchCanceller; -use hyper::header::{Accept, qitem}; +use headers_ext::ContentType; +use http::header::{self, HeaderName, HeaderValue}; use ipc_channel::ipc; use ipc_channel::router::ROUTER; use js::conversions::ToJSValConvertible; use js::jsapi::JSAutoCompartment; use js::jsval::UndefinedValue; -use mime::{Mime, TopLevel, SubLevel}; +use mime::{self, Mime}; use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata}; use net_traits::{FetchResponseMsg, FetchResponseListener, NetworkError}; use net_traits::request::{CacheMode, CorsSettings, CredentialsMode}; @@ -39,7 +40,6 @@ use task_source::{TaskSource, TaskSourceName}; use timers::OneshotTimerCallback; use utf8; -header! { (LastEventId, "Last-Event-ID") => [String] } const DEFAULT_RECONNECTION_TIME: u64 = 5000; @@ -338,13 +338,14 @@ impl FetchResponseListener for EventSourceContext { }; match meta.content_type { None => self.fail_the_connection(), - Some(ct) => match ct.into_inner().0 { - Mime(TopLevel::Text, SubLevel::EventStream, _) => { + Some(ct) => { + if >::into(ct.into_inner()) == mime::TEXT_EVENT_STREAM { self.origin = meta.final_url.origin().ascii_serialization(); self.announce_the_connection(); - }, - _ => self.fail_the_connection(), - }, + } else { + self.fail_the_connection() + } + } } }, Err(_) => { @@ -501,9 +502,8 @@ impl EventSource { ..RequestInit::default() }; // Step 10 - request - .headers - .set(Accept(vec![qitem(mime!(Text / EventStream))])); + // TODO(eijebong): Replace once typed headers allow it + request.headers.insert(header::ACCEPT, HeaderValue::from_static("text/event-stream")); // Step 11 request.cache_mode = CacheMode::NoStore; // Step 12 @@ -613,9 +613,9 @@ impl EventSourceTimeoutCallback { let mut request = event_source.request(); // Step 5.3 if !event_source.last_event_id.borrow().is_empty() { - request.headers.set(LastEventId(String::from( - event_source.last_event_id.borrow().clone(), - ))); + //TODO(eijebong): Change this once typed header support custom values + request.headers.insert(HeaderName::from_static("last-event-id"), + HeaderValue::from_str(&String::from(event_source.last_event_id.borrow().clone())).unwrap()); } // Step 5.4 global diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs index c816c9433039..69ca537a75b8 100644 --- a/components/script/dom/filereader.rs +++ b/components/script/dom/filereader.rs @@ -22,13 +22,13 @@ use dom::globalscope::GlobalScope; use dom::progressevent::ProgressEvent; use dom_struct::dom_struct; use encoding_rs::{Encoding, UTF_8}; -use hyper::mime::{Attr, Mime}; use js::jsapi::Heap; use js::jsapi::JSAutoCompartment; use js::jsapi::JSContext; use js::jsapi::JSObject; use js::jsval::{self, JSVal}; use js::typedarray::{ArrayBuffer, CreateWith}; +use mime::{self, Mime}; use servo_atoms::Atom; use std::cell::Cell; use std::ptr; @@ -115,11 +115,10 @@ impl FileReaderSharedFunctionality { // Step 4 & 5 encoding = encoding.or_else(|| { let resultmime = blob_type.parse::().ok(); - resultmime.and_then(|Mime(_, _, ref parameters)| { - parameters - .iter() - .find(|&&(ref k, _)| &Attr::Charset == k) - .and_then(|&(_, ref v)| Encoding::for_label(v.as_str().as_bytes())) + resultmime.and_then(|mime| { + mime.params() + .find(|(ref k, _)| &mime::CHARSET == k) + .and_then(|(_, ref v)| Encoding::for_label(v.as_ref().as_bytes())) }) }); diff --git a/components/script/dom/headers.rs b/components/script/dom/headers.rs index 9ff08e7c07ab..2cdb955b43fd 100644 --- a/components/script/dom/headers.rs +++ b/components/script/dom/headers.rs @@ -11,11 +11,11 @@ use dom::bindings::root::DomRoot; use dom::bindings::str::{ByteString, is_token}; use dom::globalscope::GlobalScope; use dom_struct::dom_struct; -use hyper::header::Headers as HyperHeaders; -use mime::{Mime, TopLevel, SubLevel}; +use http::header::{self, HeaderMap as HyperHeaders, HeaderName, HeaderValue}; +use mime::{self, Mime}; use std::cell::Cell; use std::result::Result; -use std::str; +use std::str::{self, FromStr}; #[dom_struct] pub struct Headers { @@ -87,14 +87,14 @@ impl HeadersMethods for Headers { } // Step 7 let mut combined_value: Vec = vec![]; - if let Some(v) = self.header_list.borrow().get_raw(&valid_name) { - combined_value = v[0].clone(); + if let Some(v) = self.header_list.borrow().get(HeaderName::from_str(&valid_name).unwrap()) { + combined_value = v.as_bytes().to_vec(); combined_value.push(b','); } combined_value.extend(valid_value.iter().cloned()); self.header_list .borrow_mut() - .set_raw(valid_name, vec![combined_value]); + .insert(HeaderName::from_str(&valid_name).unwrap(), HeaderValue::from_bytes(&combined_value).unwrap()); Ok(()) } @@ -121,19 +121,17 @@ impl HeadersMethods for Headers { return Ok(()); } // Step 6 - self.header_list.borrow_mut().remove_raw(&valid_name); + self.header_list.borrow_mut().remove(&valid_name); Ok(()) } // https://fetch.spec.whatwg.org/#dom-headers-get fn Get(&self, name: ByteString) -> Fallible> { // Step 1 - let valid_name = &validate_name(name)?; - Ok(self - .header_list - .borrow() - .get_raw(&valid_name) - .map(|v| ByteString::new(v[0].clone()))) + let valid_name = validate_name(name)?; + Ok(self.header_list.borrow().get(HeaderName::from_str(&valid_name).unwrap()).map(|v| { + ByteString::new(v.as_bytes().to_vec()) + })) } // https://fetch.spec.whatwg.org/#dom-headers-has @@ -141,7 +139,7 @@ impl HeadersMethods for Headers { // Step 1 let valid_name = validate_name(name)?; // Step 2 - Ok(self.header_list.borrow_mut().get_raw(&valid_name).is_some()) + Ok(self.header_list.borrow_mut().get(&valid_name).is_some()) } // https://fetch.spec.whatwg.org/#dom-headers-set @@ -173,7 +171,7 @@ impl HeadersMethods for Headers { // https://fetch.spec.whatwg.org/#concept-header-list-set self.header_list .borrow_mut() - .set_raw(valid_name, vec![valid_value]); + .insert(HeaderName::from_str(&valid_name).unwrap(), HeaderValue::from_bytes(&valid_value).unwrap()); Ok(()) } } @@ -184,10 +182,10 @@ impl Headers { match filler { // Step 1 Some(HeadersInit::Headers(h)) => { - for header in h.header_list.borrow().iter() { + for (name, value) in h.header_list.borrow().iter() { self.Append( - ByteString::new(Vec::from(header.name())), - ByteString::new(Vec::from(header.value_string().into_bytes())), + ByteString::new(Vec::from(name.as_str())), + ByteString::new(Vec::from(value.to_str().unwrap().as_bytes())) )?; } Ok(()) @@ -248,26 +246,21 @@ impl Headers { } pub fn get_headers_list(&self) -> HyperHeaders { - let mut headers = HyperHeaders::new(); - headers.extend(self.header_list.borrow_mut().iter()); - headers + self.header_list.borrow_mut().clone() } // https://fetch.spec.whatwg.org/#concept-header-extract-mime-type pub fn extract_mime_type(&self) -> Vec { - self.header_list - .borrow() - .get_raw("content-type") - .map_or(vec![], |v| v[0].clone()) + self.header_list.borrow().get(header::CONTENT_TYPE).map_or(vec![], |v| v.as_bytes().to_owned()) } pub fn sort_header_list(&self) -> Vec<(String, String)> { let borrowed_header_list = self.header_list.borrow(); let headers_iter = borrowed_header_list.iter(); let mut header_vec = vec![]; - for header in headers_iter { - let name = header.name().to_string(); - let value = header.value_string(); + for (name, value) in headers_iter { + let name = name.as_str().to_owned(); + let value = value.to_str().unwrap().to_owned(); let name_value = (name, value); header_vec.push(name_value); } @@ -306,12 +299,14 @@ fn is_cors_safelisted_request_content_type(value: &[u8]) -> bool { let value_mime_result: Result = value_string.parse(); match value_mime_result { Err(_) => false, - Ok(value_mime) => match value_mime { - Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, _) | - Mime(TopLevel::Multipart, SubLevel::FormData, _) | - Mime(TopLevel::Text, SubLevel::Plain, _) => true, - _ => false, - }, + Ok(value_mime) => { + match (value_mime.type_(), value_mime.subtype()) { + (mime::APPLICATION, mime::WWW_FORM_URLENCODED) | + (mime::MULTIPART, mime::FORM_DATA) | + (mime::TEXT, mime::PLAIN) => true, + _ => false, + } + } } } diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 96f011bbb8e7..c1c3e0e4446e 100755 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -44,9 +44,12 @@ use dom::virtualmethods::VirtualMethods; use dom::window::Window; use dom_struct::dom_struct; use encoding_rs::{Encoding, UTF_8}; +use headers_core::HeaderMapExt; +use headers_ext::ContentType; use html5ever::{LocalName, Prefix}; -use hyper::header::{Charset, ContentDisposition, ContentType, DispositionParam, DispositionType}; -use hyper::method::Method; +use hyper::Method; +use mime::{self, Mime}; +use net_traits::http_percent_encode; use script_thread::MainThreadScriptMsg; use script_traits::LoadData; use servo_rand::random; @@ -379,23 +382,15 @@ impl HTMLFormElement { // https://html.spec.whatwg.org/multipage/#submit-dialog }, // https://html.spec.whatwg.org/multipage/#submit-mutate-action - ("http", FormMethod::FormGet) | - ("https", FormMethod::FormGet) | - ("data", FormMethod::FormGet) => { - load_data.headers.set(ContentType::form_url_encoded()); + ("http", FormMethod::FormGet) | ("https", FormMethod::FormGet) | ("data", FormMethod::FormGet) => { + load_data.headers.typed_insert(ContentType::from(mime::APPLICATION_WWW_FORM_URLENCODED)); self.mutate_action_url(&mut form_data, load_data, encoding, &target_window); }, // https://html.spec.whatwg.org/multipage/#submit-body ("http", FormMethod::FormPost) | ("https", FormMethod::FormPost) => { - load_data.method = Method::Post; - self.submit_entity_body( - &mut form_data, - load_data, - enctype, - encoding, - &target_window, - ); - }, + load_data.method = Method::POST; + self.submit_entity_body(&mut form_data, load_data, enctype, encoding, &target_window); + } // https://html.spec.whatwg.org/multipage/#submit-get-action ("file", _) | ("about", _) | @@ -450,7 +445,7 @@ impl HTMLFormElement { let bytes = match enctype { FormEncType::UrlEncoded => { let charset = encoding.name(); - load_data.headers.set(ContentType::form_url_encoded()); + load_data.headers.typed_insert(ContentType::from(mime::APPLICATION_WWW_FORM_URLENCODED)); self.set_encoding_override(load_data.url.as_mut_url().query_pairs_mut()) .clear() @@ -463,12 +458,12 @@ impl HTMLFormElement { load_data.url.query().unwrap_or("").to_string().into_bytes() }, FormEncType::FormDataEncoded => { - let mime = mime!(Multipart / FormData; Boundary =(&boundary)); - load_data.headers.set(ContentType(mime)); + let mime: Mime = format!("multipart/form-data; boundary={}", boundary).parse().unwrap(); + load_data.headers.typed_insert(ContentType::from(mime)); encode_multipart_form_data(form_data, boundary, encoding) }, FormEncType::TextPlainEncoded => { - load_data.headers.set(ContentType(mime!(Text / Plain))); + load_data.headers.typed_insert(ContentType::from(mime::TEXT_PLAIN)); self.encode_plaintext(form_data).into_bytes() }, }; @@ -1231,40 +1226,30 @@ pub fn encode_multipart_form_data( // what spec says (that it should start with a '\r\n'). let mut boundary_bytes = format!("--{}\r\n", boundary).into_bytes(); result.append(&mut boundary_bytes); - let mut content_disposition = ContentDisposition { - disposition: DispositionType::Ext("form-data".to_owned()), - parameters: vec![DispositionParam::Ext( - "name".to_owned(), - String::from(entry.name.clone()), - )], - }; + // TODO(eijebong): Everthing related to content-disposition it to redo once typed headers + // are capable of it. match entry.value { FormDatumValue::String(ref s) => { + let content_disposition = format!("form-data; name=\"{}\"", entry.name); let mut bytes = format!("Content-Disposition: {}\r\n\r\n{}", content_disposition, s) .into_bytes(); result.append(&mut bytes); }, FormDatumValue::File(ref f) => { - content_disposition - .parameters - .push(DispositionParam::Filename( - Charset::Ext(String::from(charset.clone())), - None, - f.name().clone().into(), - )); + let extra = if charset.to_lowercase() == "utf-8" { + format!("filename=\"{}\"", String::from_utf8(f.name().as_bytes().into()).unwrap()) + } else { + format!("filename*=\"{}\"''{}", charset, http_percent_encode(f.name().as_bytes())) + }; + + let content_disposition = format!("form-data; name=\"{}\"; {}", entry.name, extra); // https://tools.ietf.org/html/rfc7578#section-4.4 - let content_type = ContentType( - f.upcast::() - .Type() - .parse() - .unwrap_or(mime!(Text / Plain)), - ); - let mut type_bytes = format!( - "Content-Disposition: {}\r\ncontent-type: {}\r\n\r\n", - content_disposition, content_type - ).into_bytes(); + let content_type: Mime = f.upcast::().Type().parse().unwrap_or(mime::TEXT_PLAIN); + let mut type_bytes = format!("Content-Disposition: {}\r\ncontent-type: {}\r\n\r\n", + content_disposition, + content_type).into_bytes(); result.append(&mut type_bytes); let mut bytes = f.upcast::().get_bytes().unwrap_or(vec![]); diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index b31c5e886afd..c9de19952302 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -44,7 +44,7 @@ use html5ever::{LocalName, Prefix}; use ipc_channel::ipc; use ipc_channel::router::ROUTER; use microtask::{Microtask, MicrotaskRunnable}; -use mime::{Mime, TopLevel, SubLevel}; +use mime::{self, Mime}; use net_traits::{FetchResponseListener, FetchMetadata, NetworkError, FetchResponseMsg}; use net_traits::image::base::{Image, ImageMetadata}; use net_traits::image_cache::{CanRequestImages, ImageCache, ImageOrMetadataAvailable}; @@ -180,13 +180,9 @@ impl FetchResponseListener for ImageContext { // Step 14.5 of https://html.spec.whatwg.org/multipage/#img-environment-changes if let Some(metadata) = metadata.as_ref() { if let Some(ref content_type) = metadata.content_type { - match content_type.clone().into_inner().0 { - Mime(TopLevel::Multipart, SubLevel::Ext(s), _) => { - if s == "x-mixed-replace" { - self.aborted.set(true); - } - }, - _ => (), + let mime: Mime = content_type.clone().into_inner().into(); + if mime.type_() == mime::MULTIPART && mime.subtype().as_str() == "x-mixed-replace" { + self.aborted.set(true); } } } @@ -570,11 +566,12 @@ impl HTMLImageElement { // TODO Handle unsupported mime type let mime = x.value().parse::(); match mime { - Ok(m) => match m { - Mime(TopLevel::Image, _, _) => (), - _ => continue, - }, - _ => continue, + Ok(m) => + match m.type_() { + mime::IMAGE => (), + _ => continue + }, + _ => continue } } diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 047547128877..1cd0b5e825ab 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -34,12 +34,14 @@ use dom::promise::Promise; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; use fetch::FetchCanceller; +use headers_core::HeaderMapExt; +use headers_ext::ContentLength; use html5ever::{LocalName, Prefix}; -use hyper::header::{ByteRangeSpec, ContentLength, Headers, Range as HyperRange}; +use http::header::{self, HeaderMap, HeaderValue}; use ipc_channel::ipc; use ipc_channel::router::ROUTER; use microtask::{Microtask, MicrotaskRunnable}; -use mime::{Mime, SubLevel, TopLevel}; +use mime::{self, Mime}; use net_traits::{CoreResourceMsg, FetchChannels, FetchResponseListener, FetchMetadata, Metadata}; use net_traits::NetworkError; use net_traits::request::{CredentialsMode, Destination, RequestInit}; @@ -686,10 +688,9 @@ impl HTMLMediaElement { HTMLMediaElementTypeId::HTMLAudioElement => Destination::Audio, HTMLMediaElementTypeId::HTMLVideoElement => Destination::Video, }; - let mut headers = Headers::new(); - headers.set(HyperRange::Bytes(vec![ByteRangeSpec::AllFrom( - offset.unwrap_or(0), - )])); + let mut headers = HeaderMap::new(); + // FIXME(eijebong): Use typed headers once we have a constructor for the range header + headers.insert(header::RANGE, HeaderValue::from_str(&format!("bytes={}-", offset.unwrap_or(0))).unwrap()); let request = RequestInit { url: self.resource_url.borrow().as_ref().unwrap().clone(), headers, @@ -1271,7 +1272,10 @@ impl HTMLMediaElementMethods for HTMLMediaElement { // https://html.spec.whatwg.org/multipage/#dom-navigator-canplaytype fn CanPlayType(&self, type_: DOMString) -> CanPlayTypeResult { match type_.parse::() { - Ok(Mime(TopLevel::Application, SubLevel::OctetStream, _)) | Err(_) => { + Ok(ref mime) if (mime.type_() == mime::APPLICATION && mime.subtype() == mime::OCTET_STREAM) => { + CanPlayTypeResult::_empty + }, + Err(_) => { CanPlayTypeResult::_empty }, _ => CanPlayTypeResult::Maybe, @@ -1464,8 +1468,8 @@ impl FetchResponseListener for HTMLMediaElementContext { if let Some(metadata) = self.metadata.as_ref() { if let Some(headers) = metadata.headers.as_ref() { - if let Some(content_length) = headers.get::() { - if let Err(e) = self.elem.root().player.set_input_size(**content_length) { + if let Some(content_length) = headers.typed_get::() { + if let Err(e) = self.elem.root().player.set_input_size(content_length.0) { eprintln!("Could not set player input size {:?}", e); } } diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs index 0415aba9203e..ceb64ec45ce5 100644 --- a/components/script/dom/request.rs +++ b/components/script/dom/request.rs @@ -25,7 +25,8 @@ use dom::headers::{Guard, Headers}; use dom::promise::Promise; use dom::xmlhttprequest::Extractable; use dom_struct::dom_struct; -use hyper::method::Method as HttpMethod; +use http::Method as HttpMethod; +use http::method::InvalidMethod; use net_traits::ReferrerPolicy as MsgReferrerPolicy; use net_traits::request::{Origin, Window}; use net_traits::request::CacheMode as NetTraitsRequestCache; @@ -38,6 +39,7 @@ use net_traits::request::RequestMode as NetTraitsRequestMode; use servo_url::ServoUrl; use std::cell::{Cell, Ref}; use std::rc::Rc; +use std::str::FromStr; #[dom_struct] pub struct Request { @@ -283,7 +285,7 @@ impl Request { } // Step 25.2 let method = match init_method.as_str() { - Some(s) => normalize_method(s), + Some(s) => normalize_method(s).map_err(|e| Error::Type(format!("Method is not valid: {:?}", e)))?, None => return Err(Error::Type("Method is not a valid UTF8".to_string())), }; // Step 25.3 @@ -373,16 +375,10 @@ impl Request { let req = r.request.borrow(); let req_method = &req.method; match *req_method { - HttpMethod::Get => { - return Err(Error::Type( - "Init's body is non-null, and request method is GET".to_string(), - )) - }, - HttpMethod::Head => { - return Err(Error::Type( - "Init's body is non-null, and request method is HEAD".to_string(), - )) - }, + HttpMethod::GET => return Err(Error::Type( + "Init's body is non-null, and request method is GET".to_string())), + HttpMethod::HEAD => return Err(Error::Type( + "Init's body is non-null, and request method is HEAD".to_string())), _ => {}, } } @@ -473,17 +469,18 @@ fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequ } // https://fetch.spec.whatwg.org/#concept-method-normalize -fn normalize_method(m: &str) -> HttpMethod { +fn normalize_method(m: &str) -> Result { match_ignore_ascii_case! { m, - "delete" => return HttpMethod::Delete, - "get" => return HttpMethod::Get, - "head" => return HttpMethod::Head, - "options" => return HttpMethod::Options, - "post" => return HttpMethod::Post, - "put" => return HttpMethod::Put, + "delete" => return Ok(HttpMethod::DELETE), + "get" => return Ok(HttpMethod::GET), + "head" => return Ok(HttpMethod::HEAD), + "options" => return Ok(HttpMethod::OPTIONS), + "post" => return Ok(HttpMethod::POST), + "put" => return Ok(HttpMethod::PUT), _ => (), } - HttpMethod::Extension(m.to_string()) + debug!("Method: {:?}", m); + HttpMethod::from_str(m) } // https://fetch.spec.whatwg.org/#concept-method @@ -503,7 +500,9 @@ fn is_forbidden_method(m: &ByteString) -> bool { // https://fetch.spec.whatwg.org/#cors-safelisted-method fn is_cors_safelisted_method(m: &HttpMethod) -> bool { - m == &HttpMethod::Get || m == &HttpMethod::Head || m == &HttpMethod::Post + m == &HttpMethod::GET || + m == &HttpMethod::HEAD || + m == &HttpMethod::POST } // https://url.spec.whatwg.org/#include-credentials diff --git a/components/script/dom/response.rs b/components/script/dom/response.rs index 613145a370a6..828dfc565152 100644 --- a/components/script/dom/response.rs +++ b/components/script/dom/response.rs @@ -18,8 +18,8 @@ use dom::headers::{is_vchar, is_obs_text}; use dom::promise::Promise; use dom::xmlhttprequest::Extractable; use dom_struct::dom_struct; -use hyper::header::Headers as HyperHeaders; -use hyper::status::StatusCode; +use http::header::HeaderMap as HyperHeaders; +use hyper::StatusCode; use hyper_serde::Serde; use net_traits::response::{ResponseBody as NetTraitsResponseBody}; use servo_url::ServoUrl; @@ -55,7 +55,7 @@ impl Response { headers_reflector: Default::default(), mime_type: DomRefCell::new("".to_string().into_bytes()), body_used: Cell::new(false), - status: DomRefCell::new(Some(StatusCode::Ok)), + status: DomRefCell::new(Some(StatusCode::OK)), raw_status: DomRefCell::new(Some((200, b"OK".to_vec()))), response_type: DomRefCell::new(DOMResponseType::Default), url: DomRefCell::new(None), @@ -99,7 +99,7 @@ impl Response { let r = Response::new(global); // Step 4 - *r.status.borrow_mut() = Some(StatusCode::from_u16(init.status)); + *r.status.borrow_mut() = Some(StatusCode::from_u16(init.status).unwrap()); // Step 5 *r.raw_status.borrow_mut() = Some((init.status, init.statusText.clone().into())); @@ -189,7 +189,7 @@ impl Response { let r = Response::new(global); // Step 5 - *r.status.borrow_mut() = Some(StatusCode::from_u16(status)); + *r.status.borrow_mut() = Some(StatusCode::from_u16(status).unwrap()); *r.raw_status.borrow_mut() = Some((status, b"".to_vec())); // Step 6 @@ -300,7 +300,7 @@ impl ResponseMethods for Response { fn Ok(&self) -> bool { match *self.status.borrow() { Some(s) => { - let status_num = s.to_u16(); + let status_num = s.as_u16(); return status_num >= 200 && status_num <= 299; }, None => false, diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index e64580f68c1c..cacd54d2f1ac 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -35,9 +35,8 @@ use html5ever::{Attribute, ExpandedName, LocalName, QualName}; use html5ever::buffer_queue::BufferQueue; use html5ever::tendril::{StrTendril, ByteTendril, IncompleteUtf8}; use html5ever::tree_builder::{NodeOrText, TreeSink, NextParserState, QuirksMode, ElementFlags}; -use hyper::header::ContentType; -use hyper::mime::{Mime, SubLevel, TopLevel}; use hyper_serde::Serde; +use mime::{self, Mime}; use msg::constellation_msg::PipelineId; use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError}; use network_listener::PreInvoke; @@ -697,10 +696,11 @@ impl FetchResponseListener for ParserContext { }, Err(_) => None, }; - let content_type = metadata + let content_type: Option = metadata .clone() .and_then(|meta| meta.content_type) - .map(Serde::into_inner); + .map(Serde::into_inner) + .map(Into::into); let parser = match ScriptThread::page_headers_available(&self.id, metadata) { Some(parser) => parser, None => return, @@ -712,7 +712,7 @@ impl FetchResponseListener for ParserContext { self.parser = Some(Trusted::new(&*parser)); match content_type { - Some(ContentType(Mime(TopLevel::Image, _, _))) => { + Some(ref mime) if mime.type_() == mime::IMAGE => { self.is_synthesized_document = true; let page = "".into(); parser.push_string_input_chunk(page); @@ -725,14 +725,14 @@ impl FetchResponseListener for ParserContext { doc_body.AppendChild(&DomRoot::upcast::(img)).expect("Appending failed"); }, - Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) => { + Some(ref mime) if mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN => { // https://html.spec.whatwg.org/multipage/#read-text let page = "
\n".into();
                 parser.push_string_input_chunk(page);
                 parser.parse_sync();
                 parser.tokenizer.borrow_mut().set_plaintext_state();
             },
-            Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, _))) => {
+            Some(ref mime) if mime.type_() == mime::TEXT && mime.subtype() == mime::HTML => {
                 // Handle text/html
                 if let Some(reason) = ssl_error {
                     self.is_synthesized_document = true;
@@ -749,15 +749,18 @@ impl FetchResponseListener for ParserContext {
                     parser.parse_sync();
                 }
             },
-            Some(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _))) | // Handle text/xml, application/xml
-            Some(ContentType(Mime(TopLevel::Application, SubLevel::Xml, _))) => {},
-            Some(ContentType(Mime(TopLevel::Application, SubLevel::Ext(ref sub), _)))
-                if sub.as_str() == "xhtml+xml".to_owned() => {}, // Handle xhtml (application/xhtml+xml)
-            Some(ContentType(Mime(toplevel, sublevel, _))) => {
+            // Handle text/xml, application/xml
+            Some(ref mime) if (mime.type_() == mime::TEXT && mime.subtype() == mime::XML) ||
+                (mime.type_() == mime::APPLICATION && mime.subtype() == mime::XML) => {},
+            Some(ref mime) if mime.type_() == mime::APPLICATION &&
+                mime.subtype().as_str() == "xhtml" &&
+                mime.suffix() == Some(mime::XML)
+                => {}, // Handle xhtml (application/xhtml+xml)
+            Some(ref mime) => {
                 // Show warning page for unknown mime types.
                 let page = format!("

Unknown content type ({}/{}).

", - toplevel.as_str(), - sublevel.as_str()); + mime.type_().as_str(), + mime.subtype().as_str()); self.is_synthesized_document = true; parser.push_string_input_chunk(page); parser.parse_sync(); diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 38d206b3a1bf..6ed6a7ffab41 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -39,12 +39,12 @@ use dom_struct::dom_struct; use encoding_rs::{Encoding, UTF_8}; use euclid::Length; use fetch::FetchCanceller; +use headers_core::HeaderMapExt; +use headers_ext::{ContentLength, ContentType}; use html5ever::serialize; use html5ever::serialize::SerializeOpts; -use hyper::header::{ContentLength, ContentType, ContentEncoding}; -use hyper::header::Headers; -use hyper::method::Method; -use hyper::mime::{self, Attr as MimeAttr, Mime, Value as MimeValue}; +use http::header::{self, HeaderMap, HeaderName, HeaderValue}; +use hyper::Method; use hyper_serde::Serde; use ipc_channel::ipc; use ipc_channel::router::ROUTER; @@ -53,6 +53,7 @@ use js::jsapi::JS_ClearPendingException; use js::jsval::{JSVal, NullValue, UndefinedValue}; use js::rust::wrappers::JS_ParseJSON; use js::typedarray::{ArrayBuffer, CreateWith}; +use mime::{self, Mime, Name}; use net_traits::{FetchChannels, FetchMetadata, FilteredMetadata}; use net_traits::{FetchResponseListener, NetworkError, ReferrerPolicy}; use net_traits::CoreResourceMsg::Fetch; @@ -68,7 +69,7 @@ use std::default::Default; use std::ptr; use std::ptr::NonNull; use std::slice; -use std::str; +use std::str::{self, FromStr}; use std::sync::{Arc, Mutex}; use task_source::TaskSourceName; use task_source::networking::NetworkingTaskSource; @@ -100,7 +101,7 @@ struct XHRContext { #[derive(Clone)] pub enum XHRProgress { /// Notify that headers have been received - HeadersReceived(GenerationId, Option, Option<(u16, Vec)>), + HeadersReceived(GenerationId, Option, Option<(u16, Vec)>), /// Partial progress (after receiving headers), containing portion of the response Loading(GenerationId, ByteString), /// Loading is done @@ -138,7 +139,7 @@ pub struct XMLHttpRequest { #[ignore_malloc_size_of = "Defined in rust-mozjs"] response_json: Heap, #[ignore_malloc_size_of = "Defined in hyper"] - response_headers: DomRefCell, + response_headers: DomRefCell, #[ignore_malloc_size_of = "Defined in hyper"] override_mime_type: DomRefCell>, override_charset: DomRefCell>, @@ -148,7 +149,7 @@ pub struct XMLHttpRequest { request_method: DomRefCell, request_url: DomRefCell>, #[ignore_malloc_size_of = "Defined in hyper"] - request_headers: DomRefCell, + request_headers: DomRefCell, request_body_len: Cell, sync: Cell, upload_complete: Cell, @@ -188,13 +189,13 @@ impl XMLHttpRequest { response_blob: Default::default(), response_arraybuffer: Heap::default(), response_json: Heap::default(), - response_headers: DomRefCell::new(Headers::new()), + response_headers: DomRefCell::new(HeaderMap::new()), override_mime_type: DomRefCell::new(None), override_charset: DomRefCell::new(None), - request_method: DomRefCell::new(Method::Get), + request_method: DomRefCell::new(Method::GET), request_url: DomRefCell::new(None), - request_headers: DomRefCell::new(Headers::new()), + request_headers: DomRefCell::new(HeaderMap::new()), request_body_len: Cell::new(0), sync: Cell::new(false), upload_complete: Cell::new(false), @@ -347,8 +348,8 @@ impl XMLHttpRequestMethods for XMLHttpRequest { match maybe_method { // Step 4 - Some(Method::Connect) | Some(Method::Trace) => Err(Error::Security), - Some(Method::Extension(ref t)) if &**t == "TRACK" => Err(Error::Security), + Some(Method::CONNECT) | Some(Method::TRACE) => Err(Error::Security), + Some(ref t) if t.as_str() == "TRACK" => Err(Error::Security), Some(parsed_method) => { // Step 3 if !is_token(&method) { @@ -395,7 +396,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest { *self.request_method.borrow_mut() = parsed_method; *self.request_url.borrow_mut() = Some(parsed_url); self.sync.set(!async); - *self.request_headers.borrow_mut() = Headers::new(); + *self.request_headers.borrow_mut() = HeaderMap::new(); self.send_flag.set(false); *self.status_text.borrow_mut() = ByteString::new(vec![]); self.status.set(0); @@ -450,19 +451,17 @@ impl XMLHttpRequestMethods for XMLHttpRequest { let mut headers = self.request_headers.borrow_mut(); // Step 6 - let value = match headers.get_raw(name_str) { + let value = match headers.get(name_str).map(HeaderValue::as_bytes) { Some(raw) => { - debug!("SetRequestHeader: old value = {:?}", raw[0]); - let mut buf = raw[0].clone(); + let mut buf = raw.to_vec(); buf.extend_from_slice(b", "); buf.extend_from_slice(value); - debug!("SetRequestHeader: new value = {:?}", buf); buf }, None => value.into(), }; - headers.set_raw(name_str.to_owned(), vec![value]); + headers.insert(HeaderName::from_str(name_str).unwrap(), HeaderValue::from_bytes(&value).unwrap()); Ok(()) } @@ -532,8 +531,8 @@ impl XMLHttpRequestMethods for XMLHttpRequest { // Step 3 let data = match *self.request_method.borrow() { - Method::Get | Method::Head => None, - _ => data, + Method::GET | Method::HEAD => None, + _ => data }; // Step 4 (first half) let extracted_or_serialized = match data { @@ -638,30 +637,46 @@ impl XMLHttpRequestMethods for XMLHttpRequest { // XHR spec differs from http, and says UTF-8 should be in capitals, // instead of "utf-8", which is what Hyper defaults to. So not // using content types provided by Hyper. - { - Some(MimeValue::Ext("UTF-8".to_string())) - }, + Some("UTF-8"), _ => None, }; let mut content_type_set = false; if let Some(ref ct) = *content_type { - if !request.headers.has::() { - request - .headers - .set_raw("content-type", vec![ct.bytes().collect()]); + if !request.headers.contains_key(header::CONTENT_TYPE) { + request.headers.insert(header::CONTENT_TYPE, HeaderValue::from_str(ct).unwrap()); content_type_set = true; } } if !content_type_set { - let ct = request.headers.get_mut::(); + let ct = request.headers.typed_get::(); if let Some(ct) = ct { if let Some(encoding) = encoding { - for param in &mut (ct.0).2 { - if param.0 == MimeAttr::Charset { - if !param.0.as_str().eq_ignore_ascii_case(encoding.as_str()) { - *param = (MimeAttr::Charset, encoding.clone()); + let mime: Mime = ct.into(); + for param in mime.params() { + if param.0 == mime::CHARSET { + if !param.1.as_ref().eq_ignore_ascii_case(encoding) { + let new_params: Vec<(Name, Name)> = + mime.params() + .filter(|p| p.0 != mime::CHARSET) + .map(|p| (p.0, p.1)) + .collect(); + + let new_mime = + format!("{}/{}; charset={}{}{}", + mime.type_().as_ref(), + mime.subtype().as_ref(), + encoding, + if new_params.is_empty() { "" } else { "; " }, + new_params + .iter() + .map(|p| format!("{}={}", p.0, p.1)) + .collect::>() + .join("; ") + ); + let new_mime: Mime = new_mime.parse().unwrap(); + request.headers.typed_insert(ContentType::from(new_mime)) } } } @@ -672,8 +687,6 @@ impl XMLHttpRequestMethods for XMLHttpRequest { _ => (), } - debug!("request.headers = {:?}", request.headers); - self.fetch_time.set(time::now().to_timespec().sec); let rv = self.fetch(request, &self.global()); @@ -728,15 +741,48 @@ impl XMLHttpRequestMethods for XMLHttpRequest { // https://xhr.spec.whatwg.org/#the-getresponseheader()-method fn GetResponseHeader(&self, name: ByteString) -> Option { - self.filter_response_headers() - .iter() - .find(|h| name.eq_ignore_case(&h.name().parse().unwrap())) - .map(|h| ByteString::new(h.value_string().into_bytes())) + let headers = self.filter_response_headers(); + let headers = headers.get_all(HeaderName::from_str(&name.as_str()?.to_lowercase()).ok()?); + let mut first = true; + let s = headers.iter() + .fold(Vec::new(), |mut vec, value| { + if !first { + vec.extend(", ".as_bytes()); + } + first = false; + vec.extend(value.as_bytes()); + vec + }); + + // There was no header with that name so we never got to change that value + if first { + None + } else { + Some(ByteString::new(s)) + } } // https://xhr.spec.whatwg.org/#the-getallresponseheaders()-method fn GetAllResponseHeaders(&self) -> ByteString { - ByteString::new(self.filter_response_headers().to_string().into_bytes()) + let headers = self.filter_response_headers(); + let keys = headers.keys(); + let v = keys.fold(Vec::new(), |mut vec, k| { + let values = headers.get_all(k); + vec.extend(k.as_str().as_bytes()); + vec.extend(": ".as_bytes()); + let mut first = true; + for value in values { + if !first { + vec.extend(", ".as_bytes()); + first = false; + } + vec.extend(value.as_bytes()); + } + vec.extend("\r\n".as_bytes()); + vec + }); + + ByteString::new(v) } // https://xhr.spec.whatwg.org/#the-overridemimetype()-method @@ -751,12 +797,20 @@ impl XMLHttpRequestMethods for XMLHttpRequest { // Step 2 let override_mime = mime.parse::().map_err(|_| Error::Syntax)?; // Step 3 - let mime_no_params = Mime(override_mime.clone().0, override_mime.clone().1, vec![]); + let mime_str = override_mime.as_ref(); + let mime_parts: Vec<&str> = mime_str.split(";").collect(); + let mime_no_params = if mime_parts.len() > 1 { + mime_parts[0].parse().unwrap() + } else { + override_mime.clone() + }; + *self.override_mime_type.borrow_mut() = Some(mime_no_params); // Step 4 - let value = override_mime.get_param(mime::Attr::Charset); - *self.override_charset.borrow_mut() = - value.and_then(|value| Encoding::for_label(value.as_bytes())); + let value = override_mime.get_param(mime::CHARSET); + *self.override_charset.borrow_mut() = value.and_then(|value| { + Encoding::for_label(value.as_ref().as_bytes()) + }); Ok(()) } @@ -1077,20 +1131,17 @@ impl XMLHttpRequest { fn dispatch_progress_event(&self, upload: bool, type_: Atom, loaded: u64, total: Option) { let (total_length, length_computable) = - if self.response_headers.borrow().has::() { + if self.response_headers.borrow().contains_key(header::CONTENT_ENCODING) { (0, false) } else { (total.unwrap_or(0), total.is_some()) }; - let progressevent = ProgressEvent::new( - &self.global(), - type_, - EventBubbles::DoesNotBubble, - EventCancelable::NotCancelable, - length_computable, - loaded, - total_length, - ); + let progressevent = ProgressEvent::new(&self.global(), + type_, + EventBubbles::DoesNotBubble, + EventCancelable::NotCancelable, + length_computable, loaded, + total_length); let target = if upload { self.upload.upcast() } else { @@ -1108,13 +1159,10 @@ impl XMLHttpRequest { fn dispatch_response_progress_event(&self, type_: Atom) { let len = self.response.borrow().len() as u64; - let total = self - .response_headers - .borrow() - .get::() - .map(|x| **x as u64); + let total = self.response_headers.borrow().typed_get::().map(|v| v.0); self.dispatch_progress_event(false, type_, len, total); } + fn set_timeout(&self, duration_ms: u32) { // Sets up the object to timeout in a given number of milliseconds // This will cancel all previous timeouts @@ -1154,11 +1202,7 @@ impl XMLHttpRequest { return response; } // Step 2 - let mime = self - .final_mime_type() - .as_ref() - .map(Mime::to_string) - .unwrap_or("".to_owned()); + let mime = self.final_mime_type().as_ref().map(|m| m.to_string()).unwrap_or("".to_owned()); // Step 3, 4 let bytes = self.response.borrow().to_vec(); @@ -1200,7 +1244,7 @@ impl XMLHttpRequest { let charset = self.final_charset().unwrap_or(UTF_8); let temp_doc: DomRoot; match mime_type { - Some(Mime(mime::TopLevel::Text, mime::SubLevel::Html, _)) => { + Some(ref mime) if mime.type_() == mime::TEXT && mime.subtype() == mime::HTML => { // Step 5 if self.response_type.get() == XMLHttpRequestResponseType::_empty { return None; @@ -1210,17 +1254,15 @@ impl XMLHttpRequest { } }, // Step 7 - Some(Mime(mime::TopLevel::Text, mime::SubLevel::Xml, _)) | - Some(Mime(mime::TopLevel::Application, mime::SubLevel::Xml, _)) | + Some(ref mime) if (mime.type_() == mime::TEXT && mime.subtype() == mime::XML) || + (mime.type_() == mime::APPLICATION && mime.subtype() == mime::XML) => { + temp_doc = self.handle_xml(); + }, None => { temp_doc = self.handle_xml(); }, - Some(Mime(_, mime::SubLevel::Ext(sub), _)) => { - if sub.ends_with("+xml") { - temp_doc = self.handle_xml(); - } else { - return None; - } + Some(ref mime) if mime.suffix() == Some(mime::XML) => { + temp_doc = self.handle_xml(); }, // Step 4 _ => { @@ -1336,34 +1378,13 @@ impl XMLHttpRequest { ) } - fn filter_response_headers(&self) -> Headers { + fn filter_response_headers(&self) -> HeaderMap { // https://fetch.spec.whatwg.org/#concept-response-header-list - use hyper::error::Result; - use hyper::header::{Header, HeaderFormat}; - use hyper::header::SetCookie; - use std::fmt; - - // a dummy header so we can use headers.remove::() - #[derive(Clone, Debug, MallocSizeOf)] - struct SetCookie2; - impl Header for SetCookie2 { - fn header_name() -> &'static str { - "set-cookie2" - } - - fn parse_header(_: &[Vec]) -> Result { - unimplemented!() - } - } - impl HeaderFormat for SetCookie2 { - fn fmt_header(&self, _f: &mut fmt::Formatter) -> fmt::Result { - unimplemented!() - } - } + use http::header::{self, HeaderName}; let mut headers = self.response_headers.borrow().clone(); - headers.remove::(); - headers.remove::(); + headers.remove(header::SET_COOKIE); + headers.remove(HeaderName::from_static("set-cookie2")); // XXXManishearth additional CORS filtering goes here headers } @@ -1416,12 +1437,15 @@ impl XMLHttpRequest { if self.override_charset.borrow().is_some() { self.override_charset.borrow().clone() } else { - match self.response_headers.borrow().get() { - Some(&ContentType(ref mime)) => { - let value = mime.get_param(mime::Attr::Charset); - value.and_then(|value| Encoding::for_label(value.as_bytes())) - }, - None => None, + match self.response_headers.borrow().typed_get::() { + Some(ct) => { + let mime: Mime = ct.into(); + let value = mime.get_param(mime::CHARSET); + value.and_then(|value|{ + Encoding::for_label(value.as_ref().as_bytes()) + }) + } + None => { None } } } } @@ -1430,9 +1454,9 @@ impl XMLHttpRequest { if self.override_mime_type.borrow().is_some() { self.override_mime_type.borrow().clone() } else { - match self.response_headers.borrow().get() { - Some(&ContentType(ref mime)) => Some(mime.clone()), - None => None, + match self.response_headers.borrow().typed_get::() { + Some(ct) => { Some(ct.into()) }, + None => { None } } } } diff --git a/components/script/lib.rs b/components/script/lib.rs index a402bec7cf3c..ef0205b68b6b 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -45,9 +45,11 @@ extern crate euclid; extern crate fnv; extern crate gleam; extern crate half; +extern crate headers_core; +extern crate headers_ext; #[macro_use] extern crate html5ever; -#[macro_use] +extern crate http; extern crate hyper; extern crate hyper_serde; extern crate image; @@ -65,7 +67,6 @@ extern crate malloc_size_of; #[macro_use] extern crate malloc_size_of_derive; extern crate metrics; -#[macro_use] extern crate mime; extern crate mime_guess; extern crate mitochondria; diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 8795a65cd138..e1d9fd4c0e4c 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -65,9 +65,9 @@ use dom::workletglobalscope::WorkletGlobalScopeInit; use embedder_traits::EmbedderMsg; use euclid::{Point2D, Vector2D, Rect}; use fetch::FetchCanceller; -use hyper::header::{ContentType, HttpDate, Headers, LastModified}; -use hyper::header::ReferrerPolicy as ReferrerPolicyHeader; -use hyper::mime::{Mime, SubLevel, TopLevel}; +use headers_core::HeaderMapExt; +use headers_ext::LastModified; +use headers_ext::ReferrerPolicy as ReferrerPolicyHeader; use hyper_serde::Serde; use ipc_channel::ipc::{self, IpcSender}; use js::glue::GetWindowProxyClass; @@ -76,6 +76,7 @@ use js::jsapi::{JSTracer, SetWindowProxyClass}; use js::jsval::UndefinedValue; use metrics::{MAX_TASK_NS, PaintTimeMetrics}; use microtask::{MicrotaskQueue, Microtask}; +use mime::{self, Mime}; use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId}; use msg::constellation_msg::{PipelineNamespace, TopLevelBrowsingContextId}; use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg}; @@ -115,6 +116,7 @@ use std::rc::Rc; use std::result::Result; use std::sync::Arc; use std::thread; +use std::time::SystemTime; use style::thread_state::{self, ThreadState}; use task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue}; use task_source::TaskSourceName; @@ -127,7 +129,7 @@ use task_source::performance_timeline::PerformanceTimelineTaskSource; use task_source::remote_event::RemoteEventTaskSource; use task_source::user_interaction::UserInteractionTaskSource; use task_source::websocket::WebsocketTaskSource; -use time::{get_time, precise_time_ns, Tm}; +use time::{at_utc, get_time, precise_time_ns, Timespec}; use url::Position; use url::percent_encoding::percent_decode; use webdriver_handlers; @@ -2611,37 +2613,27 @@ impl ScriptThread { window.init_window_proxy(&window_proxy); let last_modified = metadata.headers.as_ref().and_then(|headers| { - headers - .get() - .map(|&LastModified(HttpDate(ref tm))| dom_last_modified(tm)) + headers.typed_get::() + .map(|tm| dom_last_modified(&tm.into())) }); - let content_type = metadata - .content_type - .as_ref() - .map(|&Serde(ContentType(ref mimetype))| mimetype.clone()); - let loader = DocumentLoader::new_with_threads( self.resource_threads.clone(), Some(final_url.clone()), ); - let is_html_document = match metadata.content_type { - Some(Serde(ContentType(Mime( - TopLevel::Application, - SubLevel::Ext(ref sub_level), - _, - )))) - if sub_level.ends_with("+xml") => - { - IsHTMLDocument::NonHTMLDocument - }, + let content_type: Option = metadata.content_type + .map(Serde::into_inner) + .map(Into::into); - Some(Serde(ContentType(Mime(TopLevel::Application, SubLevel::Xml, _)))) | - Some(Serde(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _)))) => { - IsHTMLDocument::NonHTMLDocument - }, + let is_html_document = match content_type { + Some(ref mime) if mime.type_() == mime::APPLICATION && + mime.suffix() == Some(mime::XML) => IsHTMLDocument::NonHTMLDocument, + Some(ref mime) if + (mime.type_() == mime::TEXT && mime.subtype() == mime::XML) || + (mime.type_() == mime::APPLICATION && mime.subtype() == mime::XML) + => IsHTMLDocument::NonHTMLDocument, _ => IsHTMLDocument::HTMLDocument, }; @@ -2650,28 +2642,25 @@ impl ScriptThread { None => None, }; - let referrer_policy = metadata - .headers - .as_ref() - .map(Serde::deref) - .and_then(Headers::get::) - .map(ReferrerPolicy::from); - - let document = Document::new( - &window, - HasBrowsingContext::Yes, - Some(final_url.clone()), - incomplete.origin, - is_html_document, - content_type, - last_modified, - incomplete.activity, - DocumentSource::FromParser, - loader, - referrer, - referrer_policy, - incomplete.canceller, - ); + let referrer_policy = metadata.headers + .as_ref() + .map(Serde::deref) + .and_then(|h| h.typed_get::()) + .map(ReferrerPolicy::from); + + let document = Document::new(&window, + HasBrowsingContext::Yes, + Some(final_url.clone()), + incomplete.origin, + is_html_document, + content_type, + last_modified, + incomplete.activity, + DocumentSource::FromParser, + loader, + referrer, + referrer_policy, + incomplete.canceller); document.set_ready_state(DocumentReadyState::Loading); self.documents @@ -3112,7 +3101,7 @@ impl ScriptThread { let mut context = ParserContext::new(id, url.clone()); let mut meta = Metadata::default(url); - meta.set_content_type(Some(&mime!(Text / Html))); + meta.set_content_type(Some(&mime::TEXT_HTML)); // If this page load is the result of a javascript scheme url, map // the evaluation result into a response. @@ -3221,7 +3210,10 @@ impl Drop for ScriptThread { } } -fn dom_last_modified(tm: &Tm) -> String { +fn dom_last_modified(tm: &SystemTime) -> String { + let tm = tm.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let tm = Timespec::new(tm.as_secs() as i64, 0); + let tm = at_utc(tm); tm.to_local() .strftime("%m/%d/%Y %H:%M:%S") .unwrap() diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs index 8ae75a6e35b3..6562dcf7c2a4 100644 --- a/components/script/stylesheet_loader.rs +++ b/components/script/stylesheet_loader.rs @@ -14,11 +14,9 @@ use dom::htmlelement::HTMLElement; use dom::htmllinkelement::{RequestGenerationId, HTMLLinkElement}; use dom::node::{document_from_node, window_from_node}; use encoding_rs::UTF_8; -use hyper::header::ContentType; -use hyper::mime::{Mime, TopLevel, SubLevel}; -use hyper_serde::Serde; use ipc_channel::ipc; use ipc_channel::router::ROUTER; +use mime::{self, Mime}; use net_traits::{FetchResponseListener, FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy}; use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode}; use network_listener::{NetworkListener, PreInvoke}; @@ -117,18 +115,12 @@ impl FetchResponseListener for StylesheetContext { Some(meta) => meta, None => return, }; - let is_css = - metadata - .content_type - .map_or(false, |Serde(ContentType(Mime(top, sub, _)))| { - top == TopLevel::Text && sub == SubLevel::Css - }); - - let data = if is_css { - mem::replace(&mut self.data, vec![]) - } else { - vec![] - }; + let is_css = metadata.content_type.map_or(false, |ct| { + let mime: Mime = ct.into_inner().into(); + mime.type_() == mime::TEXT && mime.subtype() == mime::CSS + }); + + let data = if is_css { mem::replace(&mut self.data, vec![]) } else { vec![] }; // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding let environment_encoding = UTF_8; diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 6c3e7deb9102..3ac4362f8bda 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -299,7 +299,11 @@ pub fn handle_add_cookie( }, }; let url = document.url(); - let method = if cookie.http_only() { HTTP } else { NonHTTP }; + let method = if cookie.http_only().unwrap_or(false) { + HTTP + } else { + NonHTTP + }; let domain = cookie.domain().map(ToOwned::to_owned); reply diff --git a/components/script_traits/Cargo.toml b/components/script_traits/Cargo.toml index 580897fcc587..3656990aafe8 100644 --- a/components/script_traits/Cargo.toml +++ b/components/script_traits/Cargo.toml @@ -12,13 +12,14 @@ path = "lib.rs" [dependencies] bluetooth_traits = {path = "../bluetooth_traits"} canvas_traits = {path = "../canvas_traits"} -cookie = "0.10" +cookie = "0.11" devtools_traits = {path = "../devtools_traits"} embedder_traits = {path = "../embedder_traits"} euclid = "0.19" gfx_traits = {path = "../gfx_traits"} -hyper = "0.10" -hyper_serde = "0.8" +http = "0.1" +hyper = "0.12" +hyper_serde = "0.9" ipc-channel = "0.11" keyboard-types = {version = "0.4.2-servo", features = ["serde"]} libc = "0.2" diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index cc9787d47215..6ac224d0b51d 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -16,6 +16,7 @@ extern crate devtools_traits; extern crate embedder_traits; extern crate euclid; extern crate gfx_traits; +extern crate http; extern crate hyper; extern crate hyper_serde; extern crate ipc_channel; @@ -47,8 +48,8 @@ use canvas_traits::webgl::WebGLPipeline; use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId}; use euclid::{Length, Point2D, Vector2D, Rect, TypedSize2D, TypedScale}; use gfx_traits::Epoch; -use hyper::header::Headers; -use hyper::method::Method; +use http::HeaderMap; +use hyper::Method; use ipc_channel::{Error as IpcError}; use ipc_channel::ipc::{IpcReceiver, IpcSender}; use keyboard_types::KeyboardEvent; @@ -148,7 +149,7 @@ pub struct LoadData { deserialize_with = "::hyper_serde::deserialize", serialize_with = "::hyper_serde::serialize" )] - pub headers: Headers, + pub headers: HeaderMap, /// The data. pub data: Option>, /// The result of evaluating a javascript scheme url. @@ -180,8 +181,8 @@ impl LoadData { LoadData { url: url, creator_pipeline_id: creator_pipeline_id, - method: Method::Get, - headers: Headers::new(), + method: Method::GET, + headers: HeaderMap::new(), data: None, js_eval_result: None, referrer_policy: referrer_policy, diff --git a/components/webdriver_server/Cargo.toml b/components/webdriver_server/Cargo.toml index d5f4c6fd76cc..18d13d309df8 100644 --- a/components/webdriver_server/Cargo.toml +++ b/components/webdriver_server/Cargo.toml @@ -10,10 +10,10 @@ name = "webdriver_server" path = "lib.rs" [dependencies] -base64 = "0.6" -cookie = "0.10" +base64 = "0.9" +cookie = "0.11" euclid = "0.19" -hyper = "0.10" +hyper = "0.12" image = "0.19" ipc-channel = "0.11" keyboard-types = {version = "0.4.2-servo", features = ["serde"]} @@ -21,11 +21,12 @@ log = "0.4" msg = {path = "../msg"} net_traits = {path = "../net_traits"} regex = "1.0" -rustc-serialize = "0.3.4" +serde = "1" +serde_json = "1" script_traits = {path = "../script_traits"} servo_channel = {path = "../channel"} servo_config = {path = "../config"} servo_url = {path = "../url"} url = "1.2" uuid = {version = "0.6", features = ["v4"]} -webdriver = "0.35" +webdriver = "0.37" diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 300096061d0e..6c1bbbf80949 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -18,8 +18,10 @@ extern crate log; extern crate msg; extern crate net_traits; extern crate regex; -extern crate rustc_serialize; extern crate script_traits; +#[macro_use] +extern crate serde; +extern crate serde_json; extern crate servo_channel; extern crate servo_config; extern crate servo_url; @@ -29,77 +31,55 @@ extern crate webdriver; mod keys; use euclid::TypedSize2D; -use hyper::method::Method::{self, Post}; +use hyper::Method; use image::{DynamicImage, ImageFormat, RgbImage}; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use keys::keycodes_to_keys; use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, TraversalDirection}; use net_traits::image::base::PixelFormat; use regex::Captures; -use rustc_serialize::json::{Json, ToJson}; use script_traits::{ConstellationMsg, LoadData, WebDriverCommandMsg}; use script_traits::webdriver_msg::{LoadStatus, WebDriverCookieError, WebDriverFrameId}; -use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult, WebDriverScriptCommand}; +use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult, WebDriverScriptCommand, WebDriverJSValue}; +use serde::de::{Deserialize, Deserializer, MapAccess, Visitor}; +use serde::ser::{Serialize, Serializer}; +use serde_json::Value; use servo_channel::Sender; use servo_config::prefs::{PREFS, PrefValue}; use servo_url::ServoUrl; use std::borrow::ToOwned; use std::collections::BTreeMap; +use std::fmt; use std::net::{SocketAddr, SocketAddrV4}; use std::thread; use std::time::Duration; use uuid::Uuid; -use webdriver::command::{AddCookieParameters, GetParameters, JavascriptCommandParameters}; -use webdriver::command::{LocatorParameters, Parameters}; +use webdriver::command::{AddCookieParameters, GetParameters, JavascriptCommandParameters, LocatorParameters}; use webdriver::command::{SendKeysParameters, SwitchToFrameParameters, TimeoutsParameters}; -use webdriver::command::{WebDriverCommand, WebDriverExtensionCommand, WebDriverMessage}; -use webdriver::command::WindowRectParameters; -use webdriver::common::{Date, LocatorStrategy, Nullable, WebElement}; +use webdriver::command::{WebDriverCommand, WebDriverExtensionCommand, WebDriverMessage, WindowRectParameters}; +use webdriver::common::{Cookie, Date, LocatorStrategy, WebElement}; use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult}; use webdriver::httpapi::WebDriverExtensionRoute; -use webdriver::response::{Cookie, CookieResponse, CookiesResponse}; +use webdriver::response::{CookieResponse, CookiesResponse}; use webdriver::response::{ElementRectResponse, NewSessionResponse, ValueResponse}; use webdriver::response::{WebDriverResponse, WindowRectResponse}; use webdriver::server::{self, Session, WebDriverHandler}; fn extension_routes() -> Vec<(Method, &'static str, ServoExtensionRoute)> { - return vec![ - ( - Post, - "/session/{sessionId}/servo/prefs/get", - ServoExtensionRoute::GetPrefs, - ), - ( - Post, - "/session/{sessionId}/servo/prefs/set", - ServoExtensionRoute::SetPrefs, - ), - ( - Post, - "/session/{sessionId}/servo/prefs/reset", - ServoExtensionRoute::ResetPrefs, - ), - ]; + return vec![(Method::POST, "/session/{sessionId}/servo/prefs/get", ServoExtensionRoute::GetPrefs), + (Method::POST, "/session/{sessionId}/servo/prefs/set", ServoExtensionRoute::SetPrefs), + (Method::POST, "/session/{sessionId}/servo/prefs/reset", ServoExtensionRoute::ResetPrefs)] } fn cookie_msg_to_cookie(cookie: cookie_rs::Cookie) -> Cookie { Cookie { name: cookie.name().to_owned(), value: cookie.value().to_owned(), - path: match cookie.path() { - Some(path) => Nullable::Value(path.to_string()), - None => Nullable::Null, - }, - domain: match cookie.domain() { - Some(domain) => Nullable::Value(domain.to_string()), - None => Nullable::Null, - }, - expiry: match cookie.expires() { - Some(time) => Nullable::Value(Date::new(time.to_timespec().sec as u64)), - None => Nullable::Null, - }, - secure: cookie.secure(), - httpOnly: cookie.http_only(), + path: cookie.path().map(|s| s.to_owned()), + domain: cookie.domain().map(|s| s.to_owned()), + expiry: cookie.expires().map(|time| Date(time.to_timespec().sec as u64)), + secure: cookie.secure().unwrap_or(false), + httpOnly: cookie.http_only().unwrap_or(false), } } @@ -167,22 +147,20 @@ enum ServoExtensionRoute { impl WebDriverExtensionRoute for ServoExtensionRoute { type Command = ServoExtensionCommand; - fn command( - &self, - _captures: &Captures, - body_data: &Json, - ) -> WebDriverResult> { + fn command(&self, + _captures: &Captures, + body_data: &Value) -> WebDriverResult> { let command = match *self { ServoExtensionRoute::GetPrefs => { - let parameters: GetPrefsParameters = Parameters::from_json(&body_data)?; + let parameters: GetPrefsParameters = serde_json::from_value(body_data.clone())?; ServoExtensionCommand::GetPrefs(parameters) }, ServoExtensionRoute::SetPrefs => { - let parameters: SetPrefsParameters = Parameters::from_json(&body_data)?; + let parameters: SetPrefsParameters = serde_json::from_value(body_data.clone())?; ServoExtensionCommand::SetPrefs(parameters) }, ServoExtensionRoute::ResetPrefs => { - let parameters: GetPrefsParameters = Parameters::from_json(&body_data)?; + let parameters: GetPrefsParameters = serde_json::from_value(body_data.clone())?; ServoExtensionCommand::ResetPrefs(parameters) }, }; @@ -198,95 +176,148 @@ enum ServoExtensionCommand { } impl WebDriverExtensionCommand for ServoExtensionCommand { - fn parameters_json(&self) -> Option { + fn parameters_json(&self) -> Option { match *self { - ServoExtensionCommand::GetPrefs(ref x) => Some(x.to_json()), - ServoExtensionCommand::SetPrefs(ref x) => Some(x.to_json()), - ServoExtensionCommand::ResetPrefs(ref x) => Some(x.to_json()), + ServoExtensionCommand::GetPrefs(ref x) => serde_json::to_value(x).ok(), + ServoExtensionCommand::SetPrefs(ref x) => serde_json::to_value(x).ok(), + ServoExtensionCommand::ResetPrefs(ref x) => serde_json::to_value(x).ok(), } } } -#[derive(Clone, Debug, PartialEq)] -struct GetPrefsParameters { - prefs: Vec, +struct SendableWebDriverJSValue(pub WebDriverJSValue); + +impl Serialize for SendableWebDriverJSValue { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self.0 { + WebDriverJSValue::Undefined => serializer.serialize_unit(), + WebDriverJSValue::Null => serializer.serialize_unit(), + WebDriverJSValue::Boolean(x) => serializer.serialize_bool(x), + WebDriverJSValue::Number(x) => serializer.serialize_f64(x), + WebDriverJSValue::String(ref x) => serializer.serialize_str(&x), + } + } } -impl Parameters for GetPrefsParameters { - fn from_json(body: &Json) -> WebDriverResult { - let data = body.as_object().ok_or(WebDriverError::new( - ErrorStatus::InvalidArgument, - "Message body was not an object", - ))?; - let prefs_value = data.get("prefs").ok_or(WebDriverError::new( - ErrorStatus::InvalidArgument, - "Missing prefs key", - ))?; - let items = prefs_value.as_array().ok_or(WebDriverError::new( - ErrorStatus::InvalidArgument, - "prefs was not an array", - ))?; - let params = items - .iter() - .map(|x| { - x.as_string() - .map(|y| y.to_owned()) - .ok_or(WebDriverError::new( - ErrorStatus::InvalidArgument, - "Pref is not a string", - )) - }).collect::, _>>()?; - Ok(GetPrefsParameters { prefs: params }) +#[derive(Clone, Debug, PartialEq)] +struct WebDriverPrefValue(pub PrefValue); + +impl Serialize for WebDriverPrefValue { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self.0 { + PrefValue::Boolean(b) => serializer.serialize_bool(b), + PrefValue::String(ref s) => serializer.serialize_str(&s), + PrefValue::Number(f) => serializer.serialize_f64(f), + PrefValue::Missing => serializer.serialize_unit(), + } } } -impl ToJson for GetPrefsParameters { - fn to_json(&self) -> Json { - let mut data = BTreeMap::new(); - data.insert("prefs".to_owned(), self.prefs.to_json()); - Json::Object(data) +impl<'de> Deserialize<'de> for WebDriverPrefValue { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct Visitor; + + + impl<'de> ::serde::de::Visitor<'de> for Visitor { + type Value = WebDriverPrefValue; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("preference value") + } + + fn visit_f64(self, value: f64) -> Result + where + E: ::serde::de::Error, + { + Ok(WebDriverPrefValue(PrefValue::Number(value))) + } + + fn visit_i64(self, value: i64) -> Result + where + E: ::serde::de::Error, + { + Ok(WebDriverPrefValue(PrefValue::Number(value as f64))) + } + + fn visit_u64(self, value: u64) -> Result + where + E: ::serde::de::Error, + { + Ok(WebDriverPrefValue(PrefValue::Number(value as f64))) + } + + fn visit_str(self, value: &str) -> Result + where + E: ::serde::de::Error, + { + Ok(WebDriverPrefValue(PrefValue::String(value.to_owned()))) + } + + fn visit_bool(self, value: bool) -> Result + where + E: ::serde::de::Error, + { + Ok(WebDriverPrefValue(PrefValue::Boolean(value))) + } + } + + deserializer.deserialize_any(Visitor) } } -#[derive(Clone, Debug, PartialEq)] + +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +struct GetPrefsParameters { + prefs: Vec, +} + +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] struct SetPrefsParameters { - prefs: Vec<(String, PrefValue)>, + #[serde(deserialize_with = "map_to_vec")] + prefs: Vec<(String, WebDriverPrefValue)>, } -impl Parameters for SetPrefsParameters { - fn from_json(body: &Json) -> WebDriverResult { - let data = body.as_object().ok_or(WebDriverError::new( - ErrorStatus::InvalidArgument, - "Message body was not an object", - ))?; - let items = data - .get("prefs") - .ok_or(WebDriverError::new( - ErrorStatus::InvalidArgument, - "Missing prefs key", - ))?.as_object() - .ok_or(WebDriverError::new( - ErrorStatus::InvalidArgument, - "prefs was not an array", - ))?; - let mut params = Vec::with_capacity(items.len()); - for (name, val) in items.iter() { - let value = PrefValue::from_json(val.clone()).or(Err(WebDriverError::new( - ErrorStatus::InvalidArgument, - "Pref is not a boolean or string", - )))?; - let key = name.to_owned(); - params.push((key, value)); - } - Ok(SetPrefsParameters { prefs: params }) - } +fn map_to_vec<'de, D>(de: D) -> Result, D::Error> + where D: Deserializer<'de> { + de.deserialize_map(TupleVecMapVisitor) } -impl ToJson for SetPrefsParameters { - fn to_json(&self) -> Json { - let mut data = BTreeMap::new(); - data.insert("prefs".to_owned(), self.prefs.to_json()); - Json::Object(data) +struct TupleVecMapVisitor; + +impl<'de> Visitor<'de> for TupleVecMapVisitor +{ + type Value = Vec<(String, WebDriverPrefValue)>; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a map") + } + + #[inline] + fn visit_unit(self) -> Result { + Ok(Vec::new()) + } + + #[inline] + fn visit_map(self, mut access: T) -> Result + where + T: MapAccess<'de>, + { + let mut values = Vec::new(); + + while let Some((key, value)) = access.next_entry()? { + values.push((key, value)); + } + + Ok(values) } } @@ -349,12 +380,11 @@ impl Handler { let top_level_browsing_context_id = self.focus_top_level_browsing_context_id()?; let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); let session = WebDriverSession::new(browsing_context_id, top_level_browsing_context_id); - let mut capabilities = BTreeMap::new(); - capabilities.insert("browserName".to_owned(), "servo".to_json()); - capabilities.insert("browserVersion".to_owned(), "0.0.1".to_json()); - capabilities.insert("acceptInsecureCerts".to_owned(), false.to_json()); - let response = - NewSessionResponse::new(session.id.to_string(), Json::Object(capabilities)); + let mut capabilities = serde_json::Map::new(); + capabilities.insert("browserName".to_owned(), serde_json::to_value("servo")?); + capabilities.insert("browserVersion".to_owned(), serde_json::to_value("0.0.1")?); + capabilities.insert("acceptInsecureCerts".to_owned(), serde_json::to_value(false)?); + let response = NewSessionResponse::new(session.id.to_string(), Value::Object(capabilities)); debug!("new session created {}.", session.id); self.session = Some(session); Ok(WebDriverResponse::NewSession(response)) @@ -447,9 +477,7 @@ impl Handler { let url = receiver.recv().unwrap(); - Ok(WebDriverResponse::Generic(ValueResponse::new( - url.as_str().to_json(), - ))) + Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(url.as_str())?))) } fn handle_window_size(&self) -> WebDriverResult { @@ -478,12 +506,12 @@ impl Handler { ) -> WebDriverResult { let (sender, receiver) = ipc::channel().unwrap(); let width = match params.width { - Nullable::Value(v) => v, - Nullable::Null => 0, + Some(v) => v, + None => 0, }; let height = match params.height { - Nullable::Value(v) => v, - Nullable::Null => 0, + Some(v) => v, + None => 0, }; let size = TypedSize2D::new(width as u32, height as u32); let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id; @@ -526,13 +554,8 @@ impl Handler { ))?; match receiver.recv().unwrap() { - Ok(is_enabled) => Ok(WebDriverResponse::Generic(ValueResponse::new( - is_enabled.to_json(), - ))), - Err(_) => Err(WebDriverError::new( - ErrorStatus::StaleElementReference, - "Element not found", - )), + Ok(is_enabled) => Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(is_enabled)?))), + Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, "Element not found")) } } @@ -545,13 +568,8 @@ impl Handler { ))?; match receiver.recv().unwrap() { - Ok(is_selected) => Ok(WebDriverResponse::Generic(ValueResponse::new( - is_selected.to_json(), - ))), - Err(_) => Err(WebDriverError::new( - ErrorStatus::StaleElementReference, - "Element not found", - )), + Ok(is_selected) => Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(is_selected)?))), + Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, "Element not found")) } } @@ -590,27 +608,21 @@ impl Handler { self.top_level_script_command(WebDriverScriptCommand::GetTitle(sender))?; let value = receiver.recv().unwrap(); - Ok(WebDriverResponse::Generic(ValueResponse::new( - value.to_json(), - ))) + Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(value)?))) } fn handle_window_handle(&self) -> WebDriverResult { // For now we assume there's only one window so just use the session // id as the window id let handle = self.session.as_ref().unwrap().id.to_string(); - Ok(WebDriverResponse::Generic(ValueResponse::new( - handle.to_json(), - ))) + Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(handle)?))) } fn handle_window_handles(&self) -> WebDriverResult { // For now we assume there's only one window so just use the session // id as the window id - let handles = vec![self.session.as_ref().unwrap().id.to_string().to_json()]; - Ok(WebDriverResponse::Generic(ValueResponse::new( - handles.to_json(), - ))) + let handles = vec![serde_json::to_value(self.session.as_ref().unwrap().id.to_string())?]; + Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(handles)?))) } fn handle_find_element( @@ -631,13 +643,13 @@ impl Handler { match receiver.recv().unwrap() { Ok(value) => { - let value_resp = value.map(|x| WebElement::new(x).to_json()).to_json(); - Ok(WebDriverResponse::Generic(ValueResponse::new(value_resp))) - }, - Err(_) => Err(WebDriverError::new( - ErrorStatus::InvalidSelector, - "Invalid selector", - )), + let value_resp = serde_json::to_value( + value.map(|x| serde_json::to_value(WebElement::new(x)).unwrap()) + )?; + Ok(WebDriverResponse::Generic(ValueResponse(value_resp))) + } + Err(_) => Err(WebDriverError::new(ErrorStatus::InvalidSelector, + "Invalid selector")) } } @@ -647,14 +659,14 @@ impl Handler { ) -> WebDriverResult { use webdriver::common::FrameId; let frame_id = match parameters.id { - FrameId::Null => { + None => { let session = self.session_mut()?; session.browsing_context_id = BrowsingContextId::from(session.top_level_browsing_context_id); return Ok(WebDriverResponse::Void); }, - FrameId::Short(ref x) => WebDriverFrameId::Short(*x), - FrameId::Element(ref x) => WebDriverFrameId::Element(x.id.clone()), + Some(FrameId::Short(ref x)) => WebDriverFrameId::Short(*x), + Some(FrameId::Element(ref x)) => WebDriverFrameId::Element(x.id.clone()) }; self.switch_to_frame(frame_id) @@ -704,18 +716,12 @@ impl Handler { self.browsing_context_script_command(cmd)?; match receiver.recv().unwrap() { Ok(value) => { - let resp_value: Vec = value - .into_iter() - .map(|x| WebElement::new(x).to_json()) - .collect(); - Ok(WebDriverResponse::Generic(ValueResponse::new( - resp_value.to_json(), - ))) - }, - Err(_) => Err(WebDriverError::new( - ErrorStatus::InvalidSelector, - "Invalid selector", - )), + let resp_value: Vec = value.into_iter().map( + |x| serde_json::to_value(WebElement::new(x)).unwrap()).collect(); + Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(resp_value)?))) + } + Err(_) => Err(WebDriverError::new(ErrorStatus::InvalidSelector, + "Invalid selector")) } } @@ -746,13 +752,9 @@ impl Handler { let cmd = WebDriverScriptCommand::GetElementText(element.id.clone(), sender); self.browsing_context_script_command(cmd)?; match receiver.recv().unwrap() { - Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new( - value.to_json(), - ))), - Err(_) => Err(WebDriverError::new( - ErrorStatus::StaleElementReference, - "Unable to find element in document", - )), + Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(value)?))), + Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, + "Unable to find element in document")) } } @@ -760,13 +762,8 @@ impl Handler { let (sender, receiver) = ipc::channel().unwrap(); let cmd = WebDriverScriptCommand::GetActiveElement(sender); self.browsing_context_script_command(cmd)?; - let value = receiver - .recv() - .unwrap() - .map(|x| WebElement::new(x).to_json()); - Ok(WebDriverResponse::Generic(ValueResponse::new( - value.to_json(), - ))) + let value = receiver.recv().unwrap().map(|x| serde_json::to_value(WebElement::new(x)).unwrap()); + Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(value)?))) } fn handle_element_tag_name(&self, element: &WebElement) -> WebDriverResult { @@ -774,13 +771,9 @@ impl Handler { let cmd = WebDriverScriptCommand::GetElementTagName(element.id.clone(), sender); self.browsing_context_script_command(cmd)?; match receiver.recv().unwrap() { - Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new( - value.to_json(), - ))), - Err(_) => Err(WebDriverError::new( - ErrorStatus::StaleElementReference, - "Unable to find element in document", - )), + Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(value)?))), + Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, + "Unable to find element in document")) } } @@ -797,13 +790,9 @@ impl Handler { ); self.browsing_context_script_command(cmd)?; match receiver.recv().unwrap() { - Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new( - value.to_json(), - ))), - Err(_) => Err(WebDriverError::new( - ErrorStatus::StaleElementReference, - "Unable to find element in document", - )), + Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(value)?))), + Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, + "Unable to find element in document")) } } @@ -817,13 +806,9 @@ impl Handler { WebDriverScriptCommand::GetElementCSS(element.id.clone(), name.to_owned(), sender); self.browsing_context_script_command(cmd)?; match receiver.recv().unwrap() { - Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new( - value.to_json(), - ))), - Err(_) => Err(WebDriverError::new( - ErrorStatus::StaleElementReference, - "Unable to find element in document", - )), + Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(value)?))), + Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, + "Unable to find element in document")) } } @@ -832,13 +817,10 @@ impl Handler { let cmd = WebDriverScriptCommand::GetCookies(sender); self.browsing_context_script_command(cmd)?; let cookies = receiver.recv().unwrap(); - let response = cookies - .into_iter() - .map(|cookie| cookie_msg_to_cookie(cookie.into_inner())) - .collect::>(); - Ok(WebDriverResponse::Cookies(CookiesResponse { - value: response, - })) + let response = cookies.into_iter().map(|cookie| { + cookie_msg_to_cookie(cookie.into_inner()) + }).collect::>(); + Ok(WebDriverResponse::Cookies(CookiesResponse(response))) } fn handle_get_cookie(&self, name: &str) -> WebDriverResult { @@ -846,14 +828,10 @@ impl Handler { let cmd = WebDriverScriptCommand::GetCookie(name.to_owned(), sender); self.browsing_context_script_command(cmd)?; let cookies = receiver.recv().unwrap(); - let response = cookies - .into_iter() - .map(|cookie| cookie_msg_to_cookie(cookie.into_inner())) - .next() - .unwrap(); - Ok(WebDriverResponse::Cookie(CookieResponse { - value: response, - })) + let response = cookies.into_iter().map(|cookie| { + cookie_msg_to_cookie(cookie.into_inner()) + }).next().unwrap(); + Ok(WebDriverResponse::Cookie(CookieResponse(response))) } fn handle_add_cookie( @@ -866,11 +844,11 @@ impl Handler { .secure(params.secure) .http_only(params.httpOnly); let cookie = match params.domain { - Nullable::Value(ref domain) => cookie.domain(domain.to_owned()), + Some(ref domain) => cookie.domain(domain.to_owned()), _ => cookie, }; let cookie = match params.path { - Nullable::Value(ref path) => cookie.path(path.to_owned()).finish(), + Some(ref path) => cookie.path(path.to_owned()).finish(), _ => cookie.finish(), }; @@ -958,9 +936,8 @@ impl Handler { result: WebDriverJSResult, ) -> WebDriverResult { match result { - Ok(value) => Ok(WebDriverResponse::Generic(ValueResponse::new( - value.to_json(), - ))), + Ok(value) => + Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(SendableWebDriverJSValue(value))?))), Err(WebDriverJSError::Timeout) => Err(WebDriverError::new(ErrorStatus::Timeout, "")), Err(WebDriverJSError::UnknownType) => Err(WebDriverError::new( ErrorStatus::UnsupportedOperation, @@ -1055,9 +1032,7 @@ impl Handler { .unwrap(); let encoded = base64::encode(&png_data); - Ok(WebDriverResponse::Generic(ValueResponse::new( - encoded.to_json(), - ))) + Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(encoded)?))) } fn handle_get_prefs( @@ -1067,12 +1042,10 @@ impl Handler { let prefs = parameters .prefs .iter() - .map(|item| (item.clone(), PREFS.get(item).to_json())) + .map(|item| (item.clone(), serde_json::to_value(PREFS.get(item)).unwrap())) .collect::>(); - Ok(WebDriverResponse::Generic(ValueResponse::new( - prefs.to_json(), - ))) + Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(prefs)?))) } fn handle_set_prefs( @@ -1080,7 +1053,7 @@ impl Handler { parameters: &SetPrefsParameters, ) -> WebDriverResult { for &(ref key, ref value) in parameters.prefs.iter() { - PREFS.set(key, value.clone()); + PREFS.set(key, value.0.clone()); } Ok(WebDriverResponse::Void) } @@ -1096,12 +1069,10 @@ impl Handler { parameters .prefs .iter() - .map(|item| (item.clone(), PREFS.reset(item).to_json())) + .map(|item| (item.clone(), serde_json::to_value(PREFS.reset(item)).unwrap())) .collect::>() }; - Ok(WebDriverResponse::Generic(ValueResponse::new( - prefs.to_json(), - ))) + Ok(WebDriverResponse::Generic(ValueResponse(serde_json::to_value(prefs)?))) } } diff --git a/servo-tidy.toml b/servo-tidy.toml index 06aac1020799..addfab8963fd 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -25,6 +25,7 @@ rand = [ "rayon-core", "servo_rand", "tempfile", + "tokio-threadpool", "uuid", "ws", ] @@ -32,8 +33,8 @@ rand = [ [ignore] # Ignored packages with duplicated versions packages = [ - "bitflags", "core-graphics", + "crossbeam-deque", "crossbeam-epoch", "crossbeam-utils", "log", @@ -42,9 +43,8 @@ packages = [ "proc-macro2", "quote", "rand", - # TODO: remove slab when #21426 lands - "slab", "syn", + "unicase", "winapi", ] # Files that are ignored for all tidy and lint checks. diff --git a/tests/unit/metrics/paint_time.rs b/tests/unit/metrics/paint_time.rs index 20c43b28c841..0207324a9c2d 100644 --- a/tests/unit/metrics/paint_time.rs +++ b/tests/unit/metrics/paint_time.rs @@ -10,7 +10,7 @@ use msg::constellation_msg::TEST_PIPELINE_ID; use profile_traits::time::{ProfilerChan, TimerMetadata}; use servo_url::ServoUrl; use time; -use webrender_api::{AlphaType, ImageDisplayItem, ImageKey, ImageRendering, LayoutSize, ColorF}; +use webrender_api::{AlphaType, ColorF, ImageDisplayItem, ImageKey, ImageRendering, LayoutSize}; struct DummyProfilerMetadataFactory {} impl ProfilerMetadataFactory for DummyProfilerMetadataFactory { diff --git a/tests/wpt/metadata/cors/access-control-expose-headers-parsing.window.js.ini b/tests/wpt/metadata/cors/access-control-expose-headers-parsing.window.js.ini index d5d99a122835..efbfad792a90 100644 --- a/tests/wpt/metadata/cors/access-control-expose-headers-parsing.window.js.ini +++ b/tests/wpt/metadata/cors/access-control-expose-headers-parsing.window.js.ini @@ -1,5 +1,4 @@ [access-control-expose-headers-parsing.window.html] - type: testharness [Access-Control-Expose-Headers parsing: #1] expected: FAIL diff --git a/tests/wpt/metadata/cors/allow-headers.htm.ini b/tests/wpt/metadata/cors/allow-headers.htm.ini index c41fcae641b7..6b73e9141ba6 100644 --- a/tests/wpt/metadata/cors/allow-headers.htm.ini +++ b/tests/wpt/metadata/cors/allow-headers.htm.ini @@ -12,3 +12,18 @@ [Allow origin: [tab\]undefined//undefined] expected: FAIL + [Allow origin: _*__] + expected: FAIL + + [Allow origin: _http://web-platform.test:8000___[tab\]_] + expected: FAIL + + [Disallow origin: HTTP://web-platform.test:8000] + expected: FAIL + + [Disallow origin: http://web-platform.test:8000#] + expected: FAIL + + [Disallow origin: http://web-platform.test:8000/] + expected: FAIL + diff --git a/tests/wpt/metadata/cors/origin.htm.ini b/tests/wpt/metadata/cors/origin.htm.ini new file mode 100644 index 000000000000..224c803a5e6c --- /dev/null +++ b/tests/wpt/metadata/cors/origin.htm.ini @@ -0,0 +1,16 @@ +[origin.htm] + [Allow origin: _*__] + expected: FAIL + + [Allow origin: _http://web-platform.test:8000___[tab\]_] + expected: FAIL + + [Disallow origin: HTTP://web-platform.test:8000] + expected: FAIL + + [Disallow origin: http://web-platform.test:8000#] + expected: FAIL + + [Disallow origin: http://web-platform.test:8000/] + expected: FAIL + diff --git a/tests/wpt/metadata/cors/redirect-origin.htm.ini b/tests/wpt/metadata/cors/redirect-origin.htm.ini index 02481d435c14..f3be237aea1e 100644 --- a/tests/wpt/metadata/cors/redirect-origin.htm.ini +++ b/tests/wpt/metadata/cors/redirect-origin.htm.ini @@ -20,12 +20,6 @@ [local (none) to remote (*), expect origin=undefined//undefined] expected: FAIL - [remote (*) to local (*), expect origin=null] - expected: FAIL - - [remote (*) to local (null), expect origin=null] - expected: FAIL - [remote (undefined//undefined) to local (*), expect origin=null] expected: FAIL @@ -44,27 +38,9 @@ [remote (undefined//undefined) to remote (undefined//undefined), expect origin=undefined//undefined] expected: FAIL - [remote (*) to remote2 (*), expect origin=null] - expected: FAIL - - [remote (*) to remote2 (null), expect origin=null] - expected: FAIL - [remote (undefined//undefined) to remote2 (*), expect origin=null] expected: FAIL [remote (undefined//undefined) to remote2 (null), expect origin=null] expected: FAIL - [remote (http://web-platform.test:8000) to local (*), expect origin=null] - expected: FAIL - - [remote (http://web-platform.test:8000) to local (null), expect origin=null] - expected: FAIL - - [remote (http://web-platform.test:8000) to remote2 (*), expect origin=null] - expected: FAIL - - [remote (http://web-platform.test:8000) to remote2 (null), expect origin=null] - expected: FAIL - diff --git a/tests/wpt/metadata/cors/redirect-userinfo.htm.ini b/tests/wpt/metadata/cors/redirect-userinfo.htm.ini deleted file mode 100644 index 78a8ba345864..000000000000 --- a/tests/wpt/metadata/cors/redirect-userinfo.htm.ini +++ /dev/null @@ -1,5 +0,0 @@ -[redirect-userinfo.htm] - type: testharness - [Allow redirect without userinfo (:@ is trimmed during URL parsing)] - expected: FAIL - diff --git a/tests/wpt/metadata/cors/request-headers.htm.ini b/tests/wpt/metadata/cors/request-headers.htm.ini new file mode 100644 index 000000000000..d5a0e025561c --- /dev/null +++ b/tests/wpt/metadata/cors/request-headers.htm.ini @@ -0,0 +1,4 @@ +[request-headers.htm] + [Strange allowheaders (case insensitive)] + expected: FAIL + diff --git a/tests/wpt/metadata/cors/status-async.htm.ini b/tests/wpt/metadata/cors/status-async.htm.ini new file mode 100644 index 000000000000..74385e9e7be0 --- /dev/null +++ b/tests/wpt/metadata/cors/status-async.htm.ini @@ -0,0 +1,37 @@ +[status-async.htm] + [Status on POST 500] + expected: FAIL + + [Status on HEAD 401] + expected: FAIL + + [Status on POST 404] + expected: FAIL + + [Status on GET 299] + expected: FAIL + + [Status on GET 400] + expected: FAIL + + [Status on GET 206] + expected: FAIL + + [Status on GET 204] + expected: FAIL + + [Status on GET 205] + expected: FAIL + + [Status on GET 202] + expected: FAIL + + [Status on GET 203] + expected: FAIL + + [Status on GET 201] + expected: FAIL + + [Status on GET 209] + expected: FAIL + diff --git a/tests/wpt/metadata/cors/status-preflight.htm.ini b/tests/wpt/metadata/cors/status-preflight.htm.ini new file mode 100644 index 000000000000..cf220f7f4aeb --- /dev/null +++ b/tests/wpt/metadata/cors/status-preflight.htm.ini @@ -0,0 +1,7 @@ +[status-preflight.htm] + [CORS - status after preflight on HEAD 699] + expected: FAIL + + [CORS - status after preflight on PUT 699] + expected: FAIL + diff --git a/tests/wpt/metadata/css/CSS2/backgrounds/background-043.xht.ini b/tests/wpt/metadata/css/CSS2/backgrounds/background-043.xht.ini index e9b801cb297e..5d83aba3f7b1 100644 --- a/tests/wpt/metadata/css/CSS2/backgrounds/background-043.xht.ini +++ b/tests/wpt/metadata/css/CSS2/backgrounds/background-043.xht.ini @@ -1,3 +1,2 @@ [background-043.xht] - type: reftest expected: FAIL diff --git a/tests/wpt/metadata/css/CSS2/backgrounds/background-048.xht.ini b/tests/wpt/metadata/css/CSS2/backgrounds/background-048.xht.ini index acf3a0819f65..4f08e157d7ac 100644 --- a/tests/wpt/metadata/css/CSS2/backgrounds/background-048.xht.ini +++ b/tests/wpt/metadata/css/CSS2/backgrounds/background-048.xht.ini @@ -1,3 +1,5 @@ +[background-043.xht] + expected: FAIL + [background-048.xht] - type: reftest expected: FAIL diff --git a/tests/wpt/metadata/css/cssom-view/elementFromPoint-001.html.ini b/tests/wpt/metadata/css/cssom-view/elementFromPoint-001.html.ini index 72b093710382..e38782d8c85a 100644 --- a/tests/wpt/metadata/css/cssom-view/elementFromPoint-001.html.ini +++ b/tests/wpt/metadata/css/cssom-view/elementFromPoint-001.html.ini @@ -1,3 +1,4 @@ [elementFromPoint-001.html] [CSSOM View - 5 - extensions to the Document interface] expected: FAIL + diff --git a/tests/wpt/metadata/css/cssom-view/elementFromPoint-dynamic-anon-box.html.ini b/tests/wpt/metadata/css/cssom-view/elementFromPoint-dynamic-anon-box.html.ini index cf67b5d03dd4..4596f046e93a 100644 --- a/tests/wpt/metadata/css/cssom-view/elementFromPoint-dynamic-anon-box.html.ini +++ b/tests/wpt/metadata/css/cssom-view/elementFromPoint-dynamic-anon-box.html.ini @@ -1,3 +1,4 @@ [elementFromPoint-dynamic-anon-box.html] [Link should be clickable after hiding a scrollbox with an anonymous table inside] expected: FAIL + diff --git a/tests/wpt/metadata/eventsource/format-mime-trailing-semicolon.htm.ini b/tests/wpt/metadata/eventsource/format-mime-trailing-semicolon.htm.ini new file mode 100644 index 000000000000..7d8960be4963 --- /dev/null +++ b/tests/wpt/metadata/eventsource/format-mime-trailing-semicolon.htm.ini @@ -0,0 +1,4 @@ +[format-mime-trailing-semicolon.htm] + [EventSource: MIME type with trailing ;] + expected: FAIL + diff --git a/tests/wpt/metadata/fetch/api/abort/general.any.js.ini b/tests/wpt/metadata/fetch/api/abort/general.any.js.ini index f7ffeaa41d2c..10e4a5a2ec61 100644 --- a/tests/wpt/metadata/fetch/api/abort/general.any.js.ini +++ b/tests/wpt/metadata/fetch/api/abort/general.any.js.ini @@ -100,6 +100,8 @@ [Clone aborts with original controller] expected: FAIL + [TypeError from request constructor takes priority - RequestInit's method is invalid] + expected: FAIL [general.any.html] type: testharness @@ -142,6 +144,8 @@ expected: FAIL [TypeError from request constructor takes priority - Bad redirect init parameter value] expected: FAIL + [TypeError from request constructor takes priority - RequestInit's method is invalid] + expected: FAIL [Request objects have a signal property] expected: FAIL [Signal on request object] diff --git a/tests/wpt/metadata/fetch/api/cors/cors-cookies-redirect.any.js.ini b/tests/wpt/metadata/fetch/api/cors/cors-cookies-redirect.any.js.ini index a87a4de03328..016ba7b482d5 100644 --- a/tests/wpt/metadata/fetch/api/cors/cors-cookies-redirect.any.js.ini +++ b/tests/wpt/metadata/fetch/api/cors/cors-cookies-redirect.any.js.ini @@ -24,8 +24,4 @@ [cors-cookies-redirect] expected: FAIL - [Testing credentials after cross-origin redirection with CORS and no preflight] - expected: FAIL - [Testing credentials after cross-origin redirection with CORS and preflight] - expected: FAIL diff --git a/tests/wpt/metadata/fetch/api/cors/cors-redirect.any.js.ini b/tests/wpt/metadata/fetch/api/cors/cors-redirect.any.js.ini index 40a3372ee885..60b5048cc85a 100644 --- a/tests/wpt/metadata/fetch/api/cors/cors-redirect.any.js.ini +++ b/tests/wpt/metadata/fetch/api/cors/cors-redirect.any.js.ini @@ -3,93 +3,33 @@ [Redirect 301: cors to same cors] expected: FAIL - [Redirect 301: cors to another cors] - expected: FAIL - [Redirect 301: same origin to cors] expected: FAIL - [Redirect 301: cors to same origin] - expected: FAIL - [Redirect 302: cors to same cors] expected: FAIL - [Redirect 302: cors to another cors] - expected: FAIL - [Redirect 302: same origin to cors] expected: FAIL - [Redirect 302: cors to same origin] - expected: FAIL - [Redirect 303: cors to same cors] expected: FAIL - [Redirect 303: cors to another cors] - expected: FAIL - [Redirect 303: same origin to cors] expected: FAIL - [Redirect 303: cors to same origin] - expected: FAIL - [Redirect 307: cors to same cors] expected: FAIL - [Redirect 307: cors to another cors] - expected: FAIL - [Redirect 307: same origin to cors] expected: FAIL - [Redirect 307: cors to same origin] - expected: FAIL - [Redirect 308: cors to same cors] expected: FAIL - [Redirect 308: cors to another cors] - expected: FAIL - [Redirect 308: same origin to cors] expected: FAIL - [Redirect 308: cors to same origin] - expected: FAIL - [cors-redirect.any.html] type: testharness - [Redirect 301: cors to another cors] - expected: FAIL - - [Redirect 301: cors to same origin] - expected: FAIL - - [Redirect 302: cors to another cors] - expected: FAIL - - [Redirect 302: cors to same origin] - expected: FAIL - - [Redirect 303: cors to another cors] - expected: FAIL - - [Redirect 303: cors to same origin] - expected: FAIL - - [Redirect 307: cors to another cors] - expected: FAIL - - [Redirect 307: cors to same origin] - expected: FAIL - - [Redirect 308: cors to another cors] - expected: FAIL - - [Redirect 308: cors to same origin] - expected: FAIL - diff --git a/tests/wpt/metadata/fetch/api/redirect/redirect-empty-location.any.js.ini b/tests/wpt/metadata/fetch/api/redirect/redirect-empty-location.any.js.ini index 32d2e40bec4f..f7d8e67b4b3f 100644 --- a/tests/wpt/metadata/fetch/api/redirect/redirect-empty-location.any.js.ini +++ b/tests/wpt/metadata/fetch/api/redirect/redirect-empty-location.any.js.ini @@ -1,15 +1,9 @@ [redirect-empty-location.any.worker.html] - [redirect response with empty Location, follow mode] - expected: FAIL - [redirect response with empty Location, manual mode] expected: FAIL [redirect-empty-location.any.html] - [redirect response with empty Location, follow mode] - expected: FAIL - [redirect response with empty Location, manual mode] expected: FAIL diff --git a/tests/wpt/metadata/fetch/api/redirect/redirect-origin.any.js.ini b/tests/wpt/metadata/fetch/api/redirect/redirect-origin.any.js.ini deleted file mode 100644 index 473d1e45206b..000000000000 --- a/tests/wpt/metadata/fetch/api/redirect/redirect-origin.any.js.ini +++ /dev/null @@ -1,33 +0,0 @@ -[redirect-origin.any.html] - [Other origin to same origin redirection 301] - expected: FAIL - - [Other origin to same origin redirection 302] - expected: FAIL - - [Other origin to same origin redirection 303] - expected: FAIL - - [Other origin to same origin redirection 307] - expected: FAIL - - [Other origin to same origin redirection 308] - expected: FAIL - - -[redirect-origin.any.worker.html] - [Other origin to same origin redirection 301] - expected: FAIL - - [Other origin to same origin redirection 302] - expected: FAIL - - [Other origin to same origin redirection 303] - expected: FAIL - - [Other origin to same origin redirection 307] - expected: FAIL - - [Other origin to same origin redirection 308] - expected: FAIL - diff --git a/tests/wpt/metadata/fetch/api/request/request-error.html.ini b/tests/wpt/metadata/fetch/api/request/request-error.html.ini index 9deb35c1e9c5..1745c4a0aa9e 100644 --- a/tests/wpt/metadata/fetch/api/request/request-error.html.ini +++ b/tests/wpt/metadata/fetch/api/request/request-error.html.ini @@ -2,5 +2,3 @@ type: testharness [Request error] expected: FAIL - [RequestInit's method is invalid] - expected: FAIL diff --git a/tests/wpt/metadata/fetch/api/response/response-consume.html.ini b/tests/wpt/metadata/fetch/api/response/response-consume.html.ini index 00047323b01f..94ca58262d7a 100644 --- a/tests/wpt/metadata/fetch/api/response/response-consume.html.ini +++ b/tests/wpt/metadata/fetch/api/response/response-consume.html.ini @@ -73,6 +73,3 @@ [Consume response's body: from multipart form data blob to formData] expected: FAIL - [Consume response's body: from URLSearchParams to blob] - expected: FAIL - diff --git a/tests/wpt/metadata/fetch/data-urls/processing.any.js.ini b/tests/wpt/metadata/fetch/data-urls/processing.any.js.ini index 43b62775d0aa..fca83c027a59 100644 --- a/tests/wpt/metadata/fetch/data-urls/processing.any.js.ini +++ b/tests/wpt/metadata/fetch/data-urls/processing.any.js.ini @@ -17,33 +17,15 @@ ["data:text/plain ,X"] expected: FAIL - ["data:text/plain%20,X"] - expected: FAIL - - ["data:text/plain\\f,X"] - expected: FAIL - - ["data:text/plain%0C,X"] - expected: FAIL - ["data:;x=x;charset=x,X"] expected: FAIL ["data:;x=x,X"] expected: FAIL - ["data:text/plain;charset=windows-1252,%C2%B1"] - expected: FAIL - ["data:text/plain;Charset=UTF-8,%C2%B1"] expected: FAIL - ["data:IMAGE/gif;hi=x,%C2%B1"] - expected: FAIL - - ["data:IMAGE/gif;CHARSET=x,%C2%B1"] - expected: FAIL - ["data: ,%FF"] expected: FAIL @@ -71,18 +53,12 @@ ["data:†,X"] expected: FAIL - ["data:†/†,X"] - expected: FAIL - ["data:X,X"] expected: FAIL ["data:text/plain;a=\\",\\",X"] expected: FAIL - ["data:text/plain;a=%2C,X"] - expected: FAIL - ["data:;base64;base64,WA"] expected: FAIL @@ -137,9 +113,6 @@ ["data:%3Bbase64,WA"] expected: FAIL - ["data:;charset=x,X"] - expected: FAIL - ["data:; charset=x,X"] expected: FAIL @@ -161,51 +134,48 @@ ["data:;CHARSET=\\"X\\",X"] expected: FAIL - -[processing.any.html] - ["data://test/,X"] + ["data:†,X"] expected: FAIL - ["data:,X"] + ["data:†,X"] expected: FAIL - ["data:,"] + ["data:text/plain;,X"] expected: FAIL - ["data:,X#X"] + ["data:x/x;base64;base64x,WA"] expected: FAIL - ["data:,%FF"] + ["data:x/x;base64;base64,WA"] expected: FAIL - ["data:text/plain ,X"] - expected: FAIL - ["data:text/plain%20,X"] +[processing.any.html] + ["data://test/,X"] expected: FAIL - ["data:text/plain\\f,X"] + ["data:,X"] expected: FAIL - ["data:text/plain%0C,X"] + ["data:,"] expected: FAIL - ["data:;x=x;charset=x,X"] + ["data:,X#X"] expected: FAIL - ["data:;x=x,X"] + ["data:,%FF"] expected: FAIL - ["data:text/plain;charset=windows-1252,%C2%B1"] + ["data:text/plain ,X"] expected: FAIL - ["data:text/plain;Charset=UTF-8,%C2%B1"] + ["data:;x=x;charset=x,X"] expected: FAIL - ["data:IMAGE/gif;hi=x,%C2%B1"] + ["data:;x=x,X"] expected: FAIL - ["data:IMAGE/gif;CHARSET=x,%C2%B1"] + ["data:text/plain;Charset=UTF-8,%C2%B1"] expected: FAIL ["data: ,%FF"] @@ -235,18 +205,12 @@ ["data:†,X"] expected: FAIL - ["data:†/†,X"] - expected: FAIL - ["data:X,X"] expected: FAIL ["data:text/plain;a=\\",\\",X"] expected: FAIL - ["data:text/plain;a=%2C,X"] - expected: FAIL - ["data:;base64;base64,WA"] expected: FAIL @@ -301,9 +265,6 @@ ["data:%3Bbase64,WA"] expected: FAIL - ["data:;charset=x,X"] - expected: FAIL - ["data:; charset=x,X"] expected: FAIL @@ -325,3 +286,18 @@ ["data:;CHARSET=\\"X\\",X"] expected: FAIL + ["data:†,X"] + expected: FAIL + + ["data:†,X"] + expected: FAIL + + ["data:text/plain;,X"] + expected: FAIL + + ["data:x/x;base64;base64x,WA"] + expected: FAIL + + ["data:x/x;base64;base64,WA"] + expected: FAIL + diff --git a/tests/wpt/metadata/fetch/nosniff/importscripts.html.ini b/tests/wpt/metadata/fetch/nosniff/importscripts.html.ini new file mode 100644 index 000000000000..7b5fc2a3eb01 --- /dev/null +++ b/tests/wpt/metadata/fetch/nosniff/importscripts.html.ini @@ -0,0 +1,5 @@ +[importscripts.html] + expected: ERROR + [Test importScripts()] + expected: TIMEOUT + diff --git a/tests/wpt/metadata/fetch/nosniff/script.html.ini b/tests/wpt/metadata/fetch/nosniff/script.html.ini new file mode 100644 index 000000000000..1582de16a3ed --- /dev/null +++ b/tests/wpt/metadata/fetch/nosniff/script.html.ini @@ -0,0 +1,4 @@ +[script.html] + [URL query: text/ecmascript;blah] + expected: FAIL + diff --git a/tests/wpt/metadata/fetch/nosniff/stylesheet.html.ini b/tests/wpt/metadata/fetch/nosniff/stylesheet.html.ini index c87f89ee811e..70bfecb9fd1a 100644 --- a/tests/wpt/metadata/fetch/nosniff/stylesheet.html.ini +++ b/tests/wpt/metadata/fetch/nosniff/stylesheet.html.ini @@ -11,3 +11,9 @@ [Revalidated URL query: text/json] expected: FAIL + [Revalidated URL query: text/css;blah] + expected: FAIL + + [URL query: text/css;blah] + expected: FAIL + diff --git a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini index bcad0d568237..c0bcb73d5649 100644 --- a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini +++ b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini @@ -36,21 +36,6 @@ [video/webm; codecs="vp9.0" (optional)] expected: FAIL - [audio/mp4 with and without codecs] - expected: FAIL - - [audio/ogg with and without codecs] - expected: FAIL - - [audio/wav with and without codecs] - expected: FAIL - - [video/mp4 with and without codecs] - expected: FAIL - - [video/ogg with and without codecs] - expected: FAIL - [video/x-new-fictional-format] expected: FAIL @@ -78,15 +63,9 @@ [audio/webm with bogus codec] expected: FAIL - [audio/webm with and without codecs] - expected: FAIL - [video/3gpp with bogus codec] expected: FAIL - [video/3gpp with and without codecs] - expected: FAIL - [video/mp4; codecs="mp4a.40.2" (optional)] expected: FAIL @@ -120,9 +99,30 @@ [video/webm with bogus codec] expected: FAIL - [video/webm with and without codecs] + [fictional formats and codecs not supported] + expected: FAIL + + [audio/webm (optional)] expected: FAIL - [fictional formats and codecs not supported] + [video/mp4 (optional)] + expected: FAIL + + [video/webm (optional)] + expected: FAIL + + [audio/wav (optional)] + expected: FAIL + + [video/ogg (optional)] + expected: FAIL + + [audio/mp4 (optional)] + expected: FAIL + + [video/3gpp (optional)] + expected: FAIL + + [audio/ogg (optional)] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-img-element/update-the-source-set.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-img-element/update-the-source-set.html.ini index 92a61676381d..cf6b9408e6ba 100644 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-img-element/update-the-source-set.html.ini +++ b/tests/wpt/metadata/html/semantics/embedded-content/the-img-element/update-the-source-set.html.ini @@ -24,3 +24,6 @@ [] expected: FAIL + [] + expected: FAIL + diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-credentials.sub.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-credentials.sub.html.ini new file mode 100644 index 000000000000..d6db2e55af7f --- /dev/null +++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-credentials.sub.html.ini @@ -0,0 +1,4 @@ +[dynamic-imports-credentials.sub.html] + [Dynamic imports should be loaded with or without the credentials based on the same-origin-ness and the parent script's crossOrigin attribute] + expected: FAIL + diff --git a/tests/wpt/metadata/url/a-element-origin-xhtml.xhtml.ini b/tests/wpt/metadata/url/a-element-origin-xhtml.xhtml.ini index 21b2a4a5d2c3..cc2702303bcc 100644 --- a/tests/wpt/metadata/url/a-element-origin-xhtml.xhtml.ini +++ b/tests/wpt/metadata/url/a-element-origin-xhtml.xhtml.ini @@ -1,8 +1,5 @@ [a-element-origin-xhtml.xhtml] type: testharness - [Parsing origin: ^_`{|}~/> against ] - expected: FAIL - [Parsing origin: against ] expected: FAIL diff --git a/tests/wpt/metadata/url/a-element-origin.html.ini b/tests/wpt/metadata/url/a-element-origin.html.ini index c4f8964312b3..467203dcd451 100644 --- a/tests/wpt/metadata/url/a-element-origin.html.ini +++ b/tests/wpt/metadata/url/a-element-origin.html.ini @@ -1,8 +1,4 @@ [a-element-origin.html] type: testharness - [Parsing origin: ^_`{|}~/> against ] - expected: FAIL - [Parsing origin: against ] expected: FAIL - diff --git a/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini b/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini index 8abf0e965525..c4ca103fea68 100644 --- a/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini +++ b/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini @@ -1,56 +1,8 @@ [a-element-xhtml.xhtml] type: testharness - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: ^_`{|}~/> against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -63,9 +15,6 @@ [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -96,21 +45,6 @@ [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -153,18 +87,6 @@ [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -213,3 +135,27 @@ [Parsing: against ] expected: FAIL + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: <#x> against ] + expected: FAIL + diff --git a/tests/wpt/metadata/url/a-element.html.ini b/tests/wpt/metadata/url/a-element.html.ini index 43d58c6105b4..c970ed63dfd8 100644 --- a/tests/wpt/metadata/url/a-element.html.ini +++ b/tests/wpt/metadata/url/a-element.html.ini @@ -1,56 +1,8 @@ [a-element.html] type: testharness - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: ^_`{|}~/> against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -63,9 +15,6 @@ [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -96,21 +45,6 @@ [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -153,18 +87,6 @@ [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -213,3 +135,27 @@ [Parsing: against ] expected: FAIL + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: <#x> against ] + expected: FAIL + diff --git a/tests/wpt/metadata/url/failure.html.ini b/tests/wpt/metadata/url/failure.html.ini index 45a5d6b2372c..631e3e992a0c 100644 --- a/tests/wpt/metadata/url/failure.html.ini +++ b/tests/wpt/metadata/url/failure.html.ini @@ -5,169 +5,244 @@ [window.open(): file://example:1/ should throw] expected: FAIL + [window.open(): file://example:test/ should throw] expected: FAIL + [window.open(): file://example%/ should throw] expected: FAIL - [window.open(): file://\[example\]/ should throw] + + [window.open(): file://[example\]/ should throw] expected: FAIL + [window.open(): http://user:pass@/ should throw] expected: FAIL + [window.open(): http://foo:-80/ should throw] expected: FAIL + [XHR: http:/:@/www.example.com should throw] expected: FAIL + [window.open(): http:/:@/www.example.com should throw] expected: FAIL + [window.open(): http://user@/www.example.com should throw] expected: FAIL + [XHR: http:@/www.example.com should throw] expected: FAIL + [window.open(): http:@/www.example.com should throw] expected: FAIL + [XHR: http:/@/www.example.com should throw] expected: FAIL + [window.open(): http:/@/www.example.com should throw] expected: FAIL + [window.open(): http://@/www.example.com should throw] expected: FAIL + [window.open(): https:@/www.example.com should throw] expected: FAIL + [XHR: http:a:b@/www.example.com should throw] expected: FAIL + [window.open(): http:a:b@/www.example.com should throw] expected: FAIL + [XHR: http:/a:b@/www.example.com should throw] expected: FAIL + [window.open(): http:/a:b@/www.example.com should throw] expected: FAIL + [window.open(): http://a:b@/www.example.com should throw] expected: FAIL + [XHR: http::@/www.example.com should throw] expected: FAIL + [window.open(): http::@/www.example.com should throw] expected: FAIL + [XHR: http:@:www.example.com should throw] expected: FAIL + [window.open(): http:@:www.example.com should throw] expected: FAIL + [XHR: http:/@:www.example.com should throw] expected: FAIL + [window.open(): http:/@:www.example.com should throw] expected: FAIL + [window.open(): http://@:www.example.com should throw] expected: FAIL + [window.open(): https://� should throw] expected: FAIL + [window.open(): https://%EF%BF%BD should throw] expected: FAIL + [window.open(): https://x x:12 should throw] expected: FAIL - [window.open(): http://\[www.google.com\]/ should throw] + + [window.open(): http://[www.google.com\]/ should throw] expected: FAIL + [window.open(): sc:/// should throw] expected: FAIL + [window.open(): sc:// / should throw] expected: FAIL + [URL's constructor's base argument: sc://@/ should throw] expected: FAIL + [URL's href: sc://@/ should throw] expected: FAIL + [XHR: sc://@/ should throw] expected: FAIL + [Location's href: sc://@/ should throw] expected: FAIL + [window.open(): sc://@/ should throw] expected: FAIL + [URL's constructor's base argument: sc://te@s:t@/ should throw] expected: FAIL + [URL's href: sc://te@s:t@/ should throw] expected: FAIL + [XHR: sc://te@s:t@/ should throw] expected: FAIL + [Location's href: sc://te@s:t@/ should throw] expected: FAIL + [window.open(): sc://te@s:t@/ should throw] expected: FAIL + [URL's constructor's base argument: sc://:/ should throw] expected: FAIL + [URL's href: sc://:/ should throw] expected: FAIL + [XHR: sc://:/ should throw] expected: FAIL + [Location's href: sc://:/ should throw] expected: FAIL + [window.open(): sc://:/ should throw] expected: FAIL + [URL's constructor's base argument: sc://:12/ should throw] expected: FAIL + [URL's href: sc://:12/ should throw] expected: FAIL + [XHR: sc://:12/ should throw] expected: FAIL + [Location's href: sc://:12/ should throw] expected: FAIL + [window.open(): sc://:12/ should throw] expected: FAIL - [window.open(): sc://\[/ should throw] + + [window.open(): sc://[/ should throw] expected: FAIL + [window.open(): sc://\\/ should throw] expected: FAIL + [window.open(): sc://\]/ should throw] expected: FAIL + [window.open(): sc://\x00/ should throw] expected: FAIL + [window.open(): ftp://example.com%80/ should throw] expected: FAIL + [window.open(): ftp://example.com%A0/ should throw] expected: FAIL + [window.open(): https://example.com%80/ should throw] expected: FAIL + [window.open(): https://example.com%A0/ should throw] expected: FAIL - [URL's constructor's base argument: https://0x100000000/test should throw] - expected: FAIL - [URL's href: https://0x100000000/test should throw] - expected: FAIL - [XHR: https://0x100000000/test should throw] - expected: FAIL - [Location's href: https://0x100000000/test should throw] - expected: FAIL + [window.open(): https://0x100000000/test should throw] expected: FAIL + [window.open(): https://256.0.0.1/test should throw] expected: FAIL - [window.open(): https://\[0::0::0\] should throw] + + [window.open(): https://[0::0::0\] should throw] expected: FAIL - [window.open(): https://\[0:.0\] should throw] + + [window.open(): https://[0:.0\] should throw] expected: FAIL - [window.open(): https://\[0:0:\] should throw] + + [window.open(): https://[0:0:\] should throw] expected: FAIL - [window.open(): https://\[0:1:2:3:4:5:6:7.0.0.0.1\] should throw] + + [window.open(): https://[0:1:2:3:4:5:6:7.0.0.0.1\] should throw] expected: FAIL - [window.open(): https://\[0:1.00.0.0.0\] should throw] + + [window.open(): https://[0:1.00.0.0.0\] should throw] expected: FAIL - [window.open(): https://\[0:1.290.0.0.0\] should throw] + + [window.open(): https://[0:1.290.0.0.0\] should throw] expected: FAIL - [window.open(): https://\[0:1.23.23\] should throw] + + [window.open(): https://[0:1.23.23\] should throw] expected: FAIL + [window.open(): http://? should throw] expected: FAIL + [window.open(): http://# should throw] expected: FAIL - [window.open(): non-special://\[:80/ should throw] + + [window.open(): non-special://[:80/ should throw] expected: FAIL - [window.open(): http://\[::127.0.0.0.1\] should throw] + + [window.open(): http://[::127.0.0.0.1\] should throw] expected: FAIL + [XHR: a should throw] expected: FAIL + [window.open(): a should throw] expected: FAIL + [XHR: a/ should throw] expected: FAIL + [window.open(): a/ should throw] expected: FAIL + [XHR: a// should throw] expected: FAIL + [window.open(): a// should throw] expected: FAIL + + [window.open(): https://� should throw] + expected: FAIL + diff --git a/tests/wpt/metadata/url/url-constructor.html.ini b/tests/wpt/metadata/url/url-constructor.html.ini index e8a51ab3de00..e3ffc72c5caa 100644 --- a/tests/wpt/metadata/url/url-constructor.html.ini +++ b/tests/wpt/metadata/url/url-constructor.html.ini @@ -1,56 +1,8 @@ [url-constructor.html] type: testharness - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: ^_`{|}~/> against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -63,9 +15,6 @@ [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -96,21 +45,6 @@ [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -153,18 +87,6 @@ [Parsing: against ] expected: FAIL - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - - [Parsing: against ] - expected: FAIL - [Parsing: against ] expected: FAIL @@ -204,3 +126,27 @@ [Parsing: against ] expected: FAIL + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: <#x> against ] + expected: FAIL + diff --git a/tests/wpt/metadata/url/url-origin.html.ini b/tests/wpt/metadata/url/url-origin.html.ini index 76abb3c7a438..5d0f79285e8c 100644 --- a/tests/wpt/metadata/url/url-origin.html.ini +++ b/tests/wpt/metadata/url/url-origin.html.ini @@ -1,6 +1,6 @@ [url-origin.html] type: testharness - [Origin parsing: ^_`{|}~/> against ] + [Origin parsing: against ] expected: FAIL [Origin parsing: against ] diff --git a/tests/wpt/metadata/url/url-setters.html.ini b/tests/wpt/metadata/url/url-setters.html.ini index a78f6df7be7d..b33b1118516d 100644 --- a/tests/wpt/metadata/url/url-setters.html.ini +++ b/tests/wpt/metadata/url/url-setters.html.ini @@ -636,18 +636,6 @@ [: Setting .hostname = '[::1.\]'] expected: FAIL - [URL: Setting .pathname = '\\a\\%2E\\b\\%2e.\\c' \\ is *not* a segment delimiter for non-'special' URLs] - expected: FAIL - - [: Setting .pathname = '\\a\\%2E\\b\\%2e.\\c' \\ is *not* a segment delimiter for non-'special' URLs] - expected: FAIL - - [URL: Setting .pathname = '%2e%2E%c3%89té' Bytes already percent-encoded are left as-is, including %2E outside dotted segments.] - expected: FAIL - - [: Setting .pathname = '%2e%2E%c3%89té' Bytes already percent-encoded are left as-is, including %2E outside dotted segments.] - expected: FAIL - [: Setting .pathname = '%2e%2E%c3%89té' Bytes already percent-encoded are left as-is, including %2E outside dotted segments.] expected: FAIL @@ -660,48 +648,18 @@ [: Setting .pathname = '#' # needs to be encoded, non-special scheme] expected: FAIL - [URL: Setting .username = 'x'] - expected: FAIL - - [: Setting .username = 'x'] - expected: FAIL - [: Setting .username = 'x'] expected: FAIL - [URL: Setting .username = 'test'] - expected: FAIL - - [: Setting .username = 'test'] - expected: FAIL - [: Setting .username = 'test'] expected: FAIL - [URL: Setting .password = 'x'] - expected: FAIL - - [: Setting .password = 'x'] - expected: FAIL - [: Setting .password = 'x'] expected: FAIL - [URL: Setting .password = 'test'] - expected: FAIL - - [: Setting .password = 'test'] - expected: FAIL - [: Setting .password = 'test'] expected: FAIL - [URL: Setting .host = 'ß'] - expected: FAIL - - [: Setting .host = 'ß'] - expected: FAIL - [: Setting .host = 'ß'] expected: FAIL @@ -807,12 +765,6 @@ [: Setting .port = '12'] expected: FAIL - [URL: Setting .port = '12'] - expected: FAIL - - [: Setting .port = '12'] - expected: FAIL - [: Setting .port = '12'] expected: FAIL @@ -981,3 +933,117 @@ [: Setting .host = 'example.com:80' Port number is removed if new port is scheme default and existing URL has a non-default port] expected: FAIL + [URL: Setting .hash = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' Simple percent-encoding; nuls, tabs, and newlines are removed] + expected: FAIL + + [: Setting .pathname = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the default encode set. Tabs and newlines are removed.] + expected: FAIL + + [: Setting .search = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the query encode set. Tabs and newlines are removed.] + expected: FAIL + + [: Setting .host = 'ß' IDNA Nontransitional_Processing] + expected: FAIL + + [URL: Setting .search = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the query encode set. Tabs and newlines are removed.] + expected: FAIL + + [: Setting .protocol = 'b' Can’t switch from special scheme to non-special] + expected: FAIL + + [: Setting .protocol = 'http' Can’t switch from file URL with no host] + expected: FAIL + + [: Setting .protocol = 'bé' Non-ASCII is rejected] + expected: FAIL + + [: Setting .username = '%c3%89té' Bytes already percent-encoded are left as-is.] + expected: FAIL + + [: Setting .pathname = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the default encode set. Tabs and newlines are removed.] + expected: FAIL + + [: Setting .pathname = '/foo' Cannot-be-a-base don’t have a path] + expected: FAIL + + [: Setting .protocol = 'é' Non-ASCII is rejected] + expected: FAIL + + [: Setting .password = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.] + expected: FAIL + + [: Setting .host = 'ß' IDNA Nontransitional_Processing] + expected: FAIL + + [: Setting .hash = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' Simple percent-encoding; nuls, tabs, and newlines are removed] + expected: FAIL + + [: Setting .protocol = 'b' Can’t switch from special scheme to non-special] + expected: FAIL + + [: Setting .protocol = 'file' Can’t switch from URL containing username/password/port to file] + expected: FAIL + + [URL: Setting .protocol = 'http' Can’t switch from non-special scheme to special] + expected: FAIL + + [: Setting .protocol = 'file' Can’t switch from URL containing username/password/port to file] + expected: FAIL + + [: Setting .password = '%c3%89té' Bytes already percent-encoded are left as-is.] + expected: FAIL + + [: Setting .protocol = 'http' Cannot-be-a-base URL doesn’t have a host, but URL in a special scheme must.] + expected: FAIL + + [URL: Setting .protocol = 'file' Can’t switch from URL containing username/password/port to file] + expected: FAIL + + [: Setting .protocol = 'é' Non-ASCII is rejected] + expected: FAIL + + [: Setting .host = 'ß'] + expected: FAIL + + [URL: Setting .protocol = 'b' Can’t switch from special scheme to non-special] + expected: FAIL + + [: Setting .username = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.] + expected: FAIL + + [URL: Setting .protocol = 'bé' Non-ASCII is rejected] + expected: FAIL + + [: Setting .search = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the query encode set. Tabs and newlines are removed.] + expected: FAIL + + [URL: Setting .pathname = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the default encode set. Tabs and newlines are removed.] + expected: FAIL + + [: Setting .pathname = '%2e%2E%c3%89té' Bytes already percent-encoded are left as-is, including %2E outside dotted segments.] + expected: FAIL + + [: Setting .hash = '%c3%89té' Bytes already percent-encoded are left as-is] + expected: FAIL + + [: Setting .protocol = 'http' Can’t switch from non-special scheme to special] + expected: FAIL + + [: Setting .search = '%c3%89té' Bytes already percent-encoded are left as-is] + expected: FAIL + + [URL: Setting .protocol = 'é' Non-ASCII is rejected] + expected: FAIL + + [: Setting .hash = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' Simple percent-encoding; nuls, tabs, and newlines are removed] + expected: FAIL + + [URL: Setting .host = 'ß' IDNA Nontransitional_Processing] + expected: FAIL + + [: Setting .protocol = 'http' Can’t switch from non-special scheme to special] + expected: FAIL + + [: Setting .protocol = 'bé' Non-ASCII is rejected] + expected: FAIL + diff --git a/tests/wpt/metadata/websockets/basic-auth.any.js.ini b/tests/wpt/metadata/websockets/basic-auth.any.js.ini index 82ab5c1ee6a4..d6f36dd4c7dd 100644 --- a/tests/wpt/metadata/websockets/basic-auth.any.js.ini +++ b/tests/wpt/metadata/websockets/basic-auth.any.js.ini @@ -13,20 +13,10 @@ [basic-auth] expected: FAIL + [basic-auth.any.sharedworker.html] [Untitled] expected: FAIL [basic-auth] expected: FAIL - - -[basic-auth.any.html] - [HTTP basic authentication should work with WebSockets] - expected: FAIL - - -[basic-auth.any.worker.html] - [HTTP basic authentication should work with WebSockets] - expected: FAIL - diff --git a/tests/wpt/metadata/xhr/access-control-and-redirects.htm.ini b/tests/wpt/metadata/xhr/access-control-and-redirects.htm.ini deleted file mode 100644 index 0e557f621cb2..000000000000 --- a/tests/wpt/metadata/xhr/access-control-and-redirects.htm.ini +++ /dev/null @@ -1,5 +0,0 @@ -[access-control-and-redirects.htm] - type: testharness - [Remote sync redirect to local origin] - expected: FAIL - diff --git a/tests/wpt/metadata/xhr/access-control-basic-allow-access-control-origin-header-data-url.htm.ini b/tests/wpt/metadata/xhr/access-control-basic-allow-access-control-origin-header-data-url.htm.ini deleted file mode 100644 index 314fe9ed7671..000000000000 --- a/tests/wpt/metadata/xhr/access-control-basic-allow-access-control-origin-header-data-url.htm.ini +++ /dev/null @@ -1,5 +0,0 @@ -[access-control-basic-allow-access-control-origin-header-data-url.htm] - type: testharness - [Access granted to null-origin iframe] - expected: FAIL - diff --git a/tests/wpt/metadata/xhr/allow-lists-starting-with-comma.htm.ini b/tests/wpt/metadata/xhr/allow-lists-starting-with-comma.htm.ini new file mode 100644 index 000000000000..0c3fc9aa2c26 --- /dev/null +++ b/tests/wpt/metadata/xhr/allow-lists-starting-with-comma.htm.ini @@ -0,0 +1,4 @@ +[allow-lists-starting-with-comma.htm] + [Allow lists starting with a comma should be parsed correctly] + expected: FAIL + diff --git a/tests/wpt/metadata/xhr/getresponseheader-chunked-trailer.htm.ini b/tests/wpt/metadata/xhr/getresponseheader-chunked-trailer.htm.ini index 0ee1ddfee54a..586a42bd4640 100644 --- a/tests/wpt/metadata/xhr/getresponseheader-chunked-trailer.htm.ini +++ b/tests/wpt/metadata/xhr/getresponseheader-chunked-trailer.htm.ini @@ -1,5 +1,6 @@ [getresponseheader-chunked-trailer.htm] type: testharness + expected: TIMEOUT [XMLHttpRequest: getResponseHeader() and HTTP trailer] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/metadata/xhr/headers-normalize-response.htm.ini b/tests/wpt/metadata/xhr/headers-normalize-response.htm.ini index c5dc615ee071..01ee7293a40a 100644 --- a/tests/wpt/metadata/xhr/headers-normalize-response.htm.ini +++ b/tests/wpt/metadata/xhr/headers-normalize-response.htm.ini @@ -12,3 +12,9 @@ [Header value: [tab\]hello_world[tab\]] expected: FAIL + [Header value: hello_world__] + expected: FAIL + + [Header value: __hello_world__] + expected: FAIL + diff --git a/tests/wpt/metadata/xhr/overridemimetype-blob.html.ini b/tests/wpt/metadata/xhr/overridemimetype-blob.html.ini index a72e097385e1..92513ff0e20c 100644 --- a/tests/wpt/metadata/xhr/overridemimetype-blob.html.ini +++ b/tests/wpt/metadata/xhr/overridemimetype-blob.html.ini @@ -168,3 +168,45 @@ [57) MIME types need to be parsed and serialized: Ā/Ā] expected: FAIL + [7) MIME types need to be parsed and serialized: text/html;charset =gbk] + expected: FAIL + + [38) MIME types need to be parsed and serialized: x/x;x="\t !\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"] + expected: FAIL + + [44) MIME types need to be parsed and serialized: x/x;test=�;x=x] + expected: FAIL + + [43) MIME types need to be parsed and serialized: text/html;test=ÿ;charset=gbk] + expected: FAIL + + [42) MIME types need to be parsed and serialized: x/x;x=\t] + expected: FAIL + + [54) MIME types need to be parsed and serialized: ÿ/ÿ] + expected: FAIL + + [57) MIME types need to be parsed and serialized: Ā/Ā] + expected: FAIL + + [38) MIME types need to be parsed and serialized: x/x;x="\t !\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"] + expected: FAIL + + [44) MIME types need to be parsed and serialized: x/x;test=�;x=x] + expected: FAIL + + [43) MIME types need to be parsed and serialized: text/html;test=ÿ;charset=gbk] + expected: FAIL + + [54) MIME types need to be parsed and serialized: ÿ/ÿ] + expected: FAIL + + [57) MIME types need to be parsed and serialized: Ā/Ā] + expected: FAIL + + [41) MIME types need to be parsed and serialized: x/x;x= ] + expected: FAIL + + [39) MIME types need to be parsed and serialized: x/x;test] + expected: FAIL + diff --git a/tests/wpt/metadata/xhr/preserve-ua-header-on-redirect.htm.ini b/tests/wpt/metadata/xhr/preserve-ua-header-on-redirect.htm.ini deleted file mode 100644 index 468b61c35129..000000000000 --- a/tests/wpt/metadata/xhr/preserve-ua-header-on-redirect.htm.ini +++ /dev/null @@ -1,5 +0,0 @@ -[preserve-ua-header-on-redirect.htm] - type: testharness - [XMLHttpRequest: User-Agent header is preserved on redirect 1] - expected: FAIL - diff --git a/tests/wpt/metadata/xhr/responsexml-media-type.htm.ini b/tests/wpt/metadata/xhr/responsexml-media-type.htm.ini new file mode 100644 index 000000000000..956871eb01f9 --- /dev/null +++ b/tests/wpt/metadata/xhr/responsexml-media-type.htm.ini @@ -0,0 +1,4 @@ +[responsexml-media-type.htm] + [XMLHttpRequest: responseXML MIME type tests ('text/plain;+xml', should not parse)] + expected: FAIL + diff --git a/tests/wpt/metadata/xhr/send-accept-language.htm.ini b/tests/wpt/metadata/xhr/send-accept-language.htm.ini deleted file mode 100644 index 32239786ffde..000000000000 --- a/tests/wpt/metadata/xhr/send-accept-language.htm.ini +++ /dev/null @@ -1,5 +0,0 @@ -[send-accept-language.htm] - type: testharness - [XMLHttpRequest: send() - Accept-Language] - expected: FAIL - diff --git a/tests/wpt/metadata/xhr/send-content-type-charset.htm.ini b/tests/wpt/metadata/xhr/send-content-type-charset.htm.ini index c2a07ab0aa74..cbd029230173 100644 --- a/tests/wpt/metadata/xhr/send-content-type-charset.htm.ini +++ b/tests/wpt/metadata/xhr/send-content-type-charset.htm.ini @@ -24,9 +24,6 @@ [charset given but wrong, fix it (known MIME, actual charset)] expected: FAIL - [If no charset= param is given, implementation should not add one - known MIME, unknown param, two spaces] - expected: FAIL - [Multiple charset parameters deduplicate, bogus parameter dropped] expected: FAIL @@ -45,9 +42,6 @@ [unknown parameters need to be preserved] expected: FAIL - [charset with space that is UTF-8 does not change] - expected: FAIL - [charset in double quotes with backslashes that is UTF-8 does not change] expected: FAIL @@ -57,9 +51,3 @@ [Multiple non-UTF-8 charset parameters deduplicate, bogus parameter dropped] expected: FAIL - [If charset= param is UTF-8 (case-insensitive), it should not be changed] - expected: FAIL - - [charset in double quotes that is UTF-8 does not change] - expected: FAIL - diff --git a/tests/wpt/metadata/xhr/send-data-unexpected-tostring.htm.ini b/tests/wpt/metadata/xhr/send-data-unexpected-tostring.htm.ini index 83018dbd05be..8fa623e7c068 100644 --- a/tests/wpt/metadata/xhr/send-data-unexpected-tostring.htm.ini +++ b/tests/wpt/metadata/xhr/send-data-unexpected-tostring.htm.ini @@ -3,3 +3,6 @@ [abort() called from data stringification] expected: FAIL + [open() called from data stringification] + expected: FAIL + diff --git a/tests/wpt/metadata/xhr/send-redirect-no-location.htm.ini b/tests/wpt/metadata/xhr/send-redirect-no-location.htm.ini new file mode 100644 index 000000000000..ae569b6da873 --- /dev/null +++ b/tests/wpt/metadata/xhr/send-redirect-no-location.htm.ini @@ -0,0 +1,13 @@ +[send-redirect-no-location.htm] + [XMLHttpRequest: send() - Redirects (no Location header) (303)] + expected: FAIL + + [XMLHttpRequest: send() - Redirects (no Location header) (301)] + expected: FAIL + + [XMLHttpRequest: send() - Redirects (no Location header) (307)] + expected: FAIL + + [XMLHttpRequest: send() - Redirects (no Location header) (302)] + expected: FAIL + diff --git a/tests/wpt/metadata/xhr/setrequestheader-allow-empty-value.htm.ini b/tests/wpt/metadata/xhr/setrequestheader-allow-empty-value.htm.ini deleted file mode 100644 index 6085cd772160..000000000000 --- a/tests/wpt/metadata/xhr/setrequestheader-allow-empty-value.htm.ini +++ /dev/null @@ -1,11 +0,0 @@ -[setrequestheader-allow-empty-value.htm] - type: testharness - [XMLHttpRequest: setRequestHeader() - empty header ()] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - empty header (null)] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - empty header (undefined)] - expected: FAIL - diff --git a/tests/wpt/metadata/xhr/setrequestheader-allow-whitespace-in-value.htm.ini b/tests/wpt/metadata/xhr/setrequestheader-allow-whitespace-in-value.htm.ini deleted file mode 100644 index 7607e617629e..000000000000 --- a/tests/wpt/metadata/xhr/setrequestheader-allow-whitespace-in-value.htm.ini +++ /dev/null @@ -1,14 +0,0 @@ -[setrequestheader-allow-whitespace-in-value.htm] - type: testharness - [XMLHttpRequest: setRequestHeader() - header value with whitespace ( )] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - header value with whitespace ( t)] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - header value with whitespace (t )] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - header value with whitespace ( t )] - expected: FAIL - diff --git a/tests/wpt/metadata/xhr/setrequestheader-case-insensitive.htm.ini b/tests/wpt/metadata/xhr/setrequestheader-case-insensitive.htm.ini index d8b4df09bc5c..fe3deba59022 100644 --- a/tests/wpt/metadata/xhr/setrequestheader-case-insensitive.htm.ini +++ b/tests/wpt/metadata/xhr/setrequestheader-case-insensitive.htm.ini @@ -2,3 +2,6 @@ [XMLHttpRequest: setRequestHeader() - headers that differ in case 1] expected: FAIL + [XMLHttpRequest: setRequestHeader() - headers that differ in case] + expected: FAIL + diff --git a/tests/wpt/metadata/xhr/setrequestheader-content-type.htm.ini b/tests/wpt/metadata/xhr/setrequestheader-content-type.htm.ini index 6a6aba997c13..c66121aa9f69 100644 --- a/tests/wpt/metadata/xhr/setrequestheader-content-type.htm.ini +++ b/tests/wpt/metadata/xhr/setrequestheader-content-type.htm.ini @@ -1,11 +1,5 @@ [setrequestheader-content-type.htm] type: testharness - [ArrayBuffer request keeps setRequestHeader() Content-Type and charset] - expected: FAIL - - [ArrayBufferView request keeps setRequestHeader() Content-Type and charset] - expected: FAIL - [URLSearchParams request keeps setRequestHeader() Content-Type, with charset adjusted to UTF-8] expected: FAIL @@ -18,75 +12,15 @@ [ReadableStream request keeps setRequestHeader() Content-Type and charset] expected: FAIL - [setRequestHeader("") sends a blank string] - expected: FAIL - - [setRequestHeader(" ") sends the string " "] - expected: FAIL - - [setRequestHeader(null) sends the string "null"] - expected: FAIL - - [setRequestHeader(undefined) sends the string "undefined"] - expected: FAIL - - [String request has correct default Content-Type of "text/plain;charset=UTF-8"] - expected: FAIL - [String request keeps setRequestHeader() Content-Type, with charset adjusted to UTF-8] expected: FAIL - [XML Document request respects setRequestHeader("")] - expected: FAIL - - [XML Document request has correct default Content-Type of "application/xml;charset=UTF-8"] - expected: FAIL - [XML Document request keeps setRequestHeader() Content-Type, with charset adjusted to UTF-8] expected: FAIL - [HTML Document request respects setRequestHeader("")] - expected: FAIL - - [HTML Document request has correct default Content-Type of "text/html;charset=UTF-8"] - expected: FAIL - [HTML Document request keeps setRequestHeader() Content-Type, with charset adjusted to UTF-8] expected: FAIL - [Blob request respects setRequestHeader("") to be specified] - expected: FAIL - - [Blob request with unset type keeps setRequestHeader() Content-Type and charset] - expected: FAIL - - [Blob request with set type uses that it for Content-Type unless setRequestHeader()] - expected: FAIL - - [Blob request with set type keeps setRequestHeader() Content-Type and charset] - expected: FAIL - - [ArrayBuffer request respects setRequestHeader("")] - expected: FAIL - - [ArrayBufferView request respects setRequestHeader("")] - expected: FAIL - - [FormData request respects setRequestHeader("")] - expected: FAIL - [FormData request has correct default Content-Type of "multipart/form-data; boundary=_"] expected: FAIL - [FormData request keeps setRequestHeader() Content-Type and charset] - expected: FAIL - - [URLSearchParams respects setRequestHeader("")] - expected: FAIL - - [URLSearchParams request has correct default Content-Type of "application/x-www-form-urlencoded;charset=UTF-8"] - expected: FAIL - - [Blob request with set type respects setRequestHeader("") to be specified] - expected: FAIL - diff --git a/tests/wpt/metadata/xhr/setrequestheader-header-allowed.htm.ini b/tests/wpt/metadata/xhr/setrequestheader-header-allowed.htm.ini index 9a8d9b02b440..3a000edc060b 100644 --- a/tests/wpt/metadata/xhr/setrequestheader-header-allowed.htm.ini +++ b/tests/wpt/metadata/xhr/setrequestheader-header-allowed.htm.ini @@ -1,29 +1,7 @@ [setrequestheader-header-allowed.htm] type: testharness - [XMLHttpRequest: setRequestHeader() - headers that are allowed (Authorization)] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - headers that are allowed (Pragma)] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - headers that are allowed (User-Agent)] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - headers that are allowed (Content-Transfer-Encoding)] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - headers that are allowed (Content-Type)] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - headers that are allowed (Overwrite)] - expected: FAIL - - [XMLHttpRequest: setRequestHeader() - headers that are allowed (If)] - expected: FAIL - + expected: CRASH + bug: https://github.com/hyperium/http/pull/271 [XMLHttpRequest: setRequestHeader() - headers that are allowed (Status-URI)] expected: FAIL - [XMLHttpRequest: setRequestHeader() - headers that are allowed (X-Pink-Unicorn)] - expected: FAIL - diff --git a/tests/wpt/metadata/xhr/status-async.htm.ini b/tests/wpt/metadata/xhr/status-async.htm.ini new file mode 100644 index 000000000000..3a50b76d527b --- /dev/null +++ b/tests/wpt/metadata/xhr/status-async.htm.ini @@ -0,0 +1,82 @@ +[status-async.htm] + [XMLHttpRequest: status/statusText - various responses 24 (CHICKEN 503)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 8 (HEAD 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 5 (HEAD 401)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 14 (HEAD 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 19 (GET 502)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 2 (HEAD 204)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 4 (GET 401)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 9 (CHICKEN 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 6 (CHICKEN 401)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 22 (GET 503)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 20 (HEAD 502)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 10 (GET 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 21 (CHICKEN 502)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 11 (HEAD 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 1 (GET 204)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 25 (GET 699)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 16 (GET 502)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 12 (CHICKEN 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 7 (GET 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 27 (CHICKEN 699)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 26 (HEAD 699)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 13 (GET 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 17 (HEAD 502)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 3 (CHICKEN 204)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 23 (HEAD 503)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 15 (CHICKEN 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 18 (CHICKEN 502)] + expected: FAIL + diff --git a/tests/wpt/metadata/xhr/status-basic.htm.ini b/tests/wpt/metadata/xhr/status-basic.htm.ini new file mode 100644 index 000000000000..6f08c0d29bd0 --- /dev/null +++ b/tests/wpt/metadata/xhr/status-basic.htm.ini @@ -0,0 +1,82 @@ +[status-basic.htm] + [XMLHttpRequest: status/statusText - various responses 24 (CHICKEN 503)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 8 (HEAD 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 5 (HEAD 401)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 14 (HEAD 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 19 (GET 502)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 2 (HEAD 204)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 4 (GET 401)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 9 (CHICKEN 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 6 (CHICKEN 401)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 22 (GET 503)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 20 (HEAD 502)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 10 (GET 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 21 (CHICKEN 502)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 11 (HEAD 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 1 (GET 204)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 25 (GET 699)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 16 (GET 502)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 12 (CHICKEN 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 7 (GET 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 27 (CHICKEN 699)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 26 (HEAD 699)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 13 (GET 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 17 (HEAD 502)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 3 (CHICKEN 204)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 23 (HEAD 503)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 15 (CHICKEN 402)] + expected: FAIL + + [XMLHttpRequest: status/statusText - various responses 18 (CHICKEN 502)] + expected: FAIL + diff --git a/tests/wpt/metadata/xhr/status-error.htm.ini b/tests/wpt/metadata/xhr/status-error.htm.ini new file mode 100644 index 000000000000..922f4647fe4e --- /dev/null +++ b/tests/wpt/metadata/xhr/status-error.htm.ini @@ -0,0 +1,13 @@ +[status-error.htm] + [XMLHttpRequest: status error handling GET 699] + expected: FAIL + + [XMLHttpRequest: status error handling POST 699] + expected: FAIL + + [XMLHttpRequest: status error handling PUT 699] + expected: FAIL + + [XMLHttpRequest: status error handling HEAD 699] + expected: FAIL +