From 3485c8371eee0da54875d38bd3aa29488be3ed4c Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 3 Apr 2017 23:54:25 +0200 Subject: [PATCH 1/6] Pass http_state around in websocket_loader --- components/net/websocket_loader.rs | 35 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/components/net/websocket_loader.rs b/components/net/websocket_loader.rs index 948a2261c602..2848c604c4b0 100644 --- a/components/net/websocket_loader.rs +++ b/components/net/websocket_loader.rs @@ -4,7 +4,6 @@ use cookie::Cookie; use cookie_rs; -use cookie_storage::CookieStorage; use fetch::methods::{should_be_blocked_due_to_bad_port, should_be_blocked_due_to_nosniff}; use http_loader::{HttpState, is_redirect_status, set_request_cookies}; use hyper::buffer::BufReader; @@ -23,7 +22,7 @@ use servo_url::ServoUrl; use std::ascii::AsciiExt; use std::io::{self, Write}; use std::net::TcpStream; -use std::sync::{Arc, Mutex, RwLock}; +use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicBool, Ordering}; use std::thread; use url::Position; @@ -40,7 +39,7 @@ pub fn init(connect: WebSocketCommunicate, let channel = establish_a_websocket_connection(&connect_data.resource_url, connect_data.origin, connect_data.protocols, - &http_state.cookie_jar); + &http_state); let (ws_sender, mut receiver) = match channel { Ok((protocol_in_use, sender, receiver)) => { let _ = connect.event_sender.send(WebSocketNetworkEvent::ConnectionEstablished { protocol_in_use }); @@ -150,7 +149,7 @@ fn obtain_a_websocket_connection(url: &ServoUrl) -> Result fn establish_a_websocket_connection(resource_url: &ServoUrl, origin: String, protocols: Vec, - cookie_jar: &RwLock) + http_state: &HttpState) -> Result<(Option, Sender, Receiver), @@ -185,7 +184,7 @@ fn establish_a_websocket_connection(resource_url: &ServoUrl, // TODO: handle permessage-deflate extension. // Step 11 and network error check from step 12. - let response = fetch(resource_url, origin, headers, cookie_jar)?; + let response = fetch(resource_url, origin, headers, http_state)?; // Step 12, the status code check. if response.status != StatusCode::SwitchingProtocols { @@ -272,7 +271,7 @@ struct Response { fn fetch(url: &ServoUrl, origin: String, mut headers: Headers, - cookie_jar: &RwLock) + http_state: &HttpState) -> Result { // Step 1. // TODO: handle request's window. @@ -316,14 +315,14 @@ fn fetch(url: &ServoUrl, } // Step 8. - main_fetch(url, origin, headers, cookie_jar) + main_fetch(url, origin, headers, http_state) } // https://fetch.spec.whatwg.org/#concept-main-fetch fn main_fetch(url: &ServoUrl, origin: String, mut headers: Headers, - cookie_jar: &RwLock) + http_state: &HttpState) -> Result { // Step 1. let mut response = None; @@ -366,7 +365,7 @@ fn main_fetch(url: &ServoUrl, // doesn't need to be filtered at all. // Step 12.2. - basic_fetch(url, origin, &mut headers, cookie_jar) + basic_fetch(url, origin, &mut headers, http_state) }); // Step 13. @@ -404,17 +403,17 @@ fn main_fetch(url: &ServoUrl, fn basic_fetch(url: &ServoUrl, origin: String, headers: &mut Headers, - cookie_jar: &RwLock) + http_state: &HttpState) -> Result { // In the case of a WebSocket request, HTTP fetch is always used. - http_fetch(url, origin, headers, cookie_jar) + http_fetch(url, origin, headers, http_state) } // https://fetch.spec.whatwg.org/#concept-http-fetch fn http_fetch(url: &ServoUrl, origin: String, headers: &mut Headers, - cookie_jar: &RwLock) + http_state: &HttpState) -> Result { // Step 1. // Not applicable: with step 3 being useless here, this one is too. @@ -435,7 +434,7 @@ fn http_fetch(url: &ServoUrl, // Not applicable: request's redirect mode is "error". // Step 4.3. - let response = http_network_or_cache_fetch(url, origin, headers, cookie_jar); + let response = http_network_or_cache_fetch(url, origin, headers, http_state); // Step 4.4. // Not applicable: CORS flag is unset. @@ -464,7 +463,7 @@ fn http_fetch(url: &ServoUrl, fn http_network_or_cache_fetch(url: &ServoUrl, origin: String, headers: &mut Headers, - cookie_jar: &RwLock) + http_state: &HttpState) -> Result { // Steps 1-3. // Not applicable: we don't even have a request yet, and there is no body @@ -515,7 +514,7 @@ fn http_network_or_cache_fetch(url: &ServoUrl, { // Step 17.1. // TODO: handle user agent configured to block cookies. - set_request_cookies(&url, headers, &cookie_jar); + set_request_cookies(&url, headers, &http_state.cookie_jar); // Steps 17.2-6. // Not applicable: request has no Authorization header. @@ -540,7 +539,7 @@ fn http_network_or_cache_fetch(url: &ServoUrl, // Not applicable: cache mode is "no-store". // Step 22.2. - let forward_response = http_network_fetch(url, headers, cookie_jar); + let forward_response = http_network_fetch(url, headers, http_state); // Step 22.3. // Not applicable: request's method is not unsafe. @@ -569,7 +568,7 @@ fn http_network_or_cache_fetch(url: &ServoUrl, // https://fetch.spec.whatwg.org/#concept-http-network-fetch fn http_network_fetch(url: &ServoUrl, headers: &Headers, - cookie_jar: &RwLock) + http_state: &HttpState) -> Result { // Step 1. // Not applicable: credentials flag is set. @@ -595,7 +594,7 @@ fn http_network_fetch(url: &ServoUrl, // Step 15. if let Some(cookies) = response.headers.get::() { - let mut jar = cookie_jar.write().unwrap(); + let mut jar = http_state.cookie_jar.write().unwrap(); for cookie in &**cookies { if let Ok(cookie) = cookie_rs::Cookie::parse(&**cookie) { if let Some(cookie) = Cookie::new_wrapped(cookie.into_owned(), url, CookieSource::HTTP) { From fbd42bb4f8c54110b0d3fdb39483fc85b2bed1ef Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 4 Apr 2017 12:50:25 +0200 Subject: [PATCH 2/6] Use cookie::from_cookie_string in websocket_loader --- components/net/websocket_loader.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/components/net/websocket_loader.rs b/components/net/websocket_loader.rs index 2848c604c4b0..35d59a1db872 100644 --- a/components/net/websocket_loader.rs +++ b/components/net/websocket_loader.rs @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use cookie::Cookie; -use cookie_rs; use fetch::methods::{should_be_blocked_due_to_bad_port, should_be_blocked_due_to_nosniff}; use http_loader::{HttpState, is_redirect_status, set_request_cookies}; use hyper::buffer::BufReader; @@ -596,10 +595,8 @@ fn http_network_fetch(url: &ServoUrl, if let Some(cookies) = response.headers.get::() { let mut jar = http_state.cookie_jar.write().unwrap(); for cookie in &**cookies { - if let Ok(cookie) = cookie_rs::Cookie::parse(&**cookie) { - if let Some(cookie) = Cookie::new_wrapped(cookie.into_owned(), url, CookieSource::HTTP) { - jar.push(cookie, url, CookieSource::HTTP); - } + if let Some(cookie) = Cookie::from_cookie_string(cookie.clone(), url, CookieSource::HTTP) { + jar.push(cookie, url, CookieSource::HTTP); } } } From 053aaedb52b0a073abfdf4b07e85bfdf49562008 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 4 Apr 2017 12:53:08 +0200 Subject: [PATCH 3/6] Properly set Accept-Language in websocket_loader --- components/net/websocket_loader.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/net/websocket_loader.rs b/components/net/websocket_loader.rs index 35d59a1db872..f79048e067f5 100644 --- a/components/net/websocket_loader.rs +++ b/components/net/websocket_loader.rs @@ -4,7 +4,7 @@ use cookie::Cookie; use fetch::methods::{should_be_blocked_due_to_bad_port, should_be_blocked_due_to_nosniff}; -use http_loader::{HttpState, is_redirect_status, set_request_cookies}; +use http_loader::{HttpState, is_redirect_status, set_default_accept_language, set_request_cookies}; use hyper::buffer::BufReader; use hyper::header::{Accept, CacheControl, CacheDirective, Connection, ConnectionOption}; use hyper::header::{Headers, Host, SetCookie, Pragma, Protocol, ProtocolName, Upgrade}; @@ -295,7 +295,7 @@ fn fetch(url: &ServoUrl, } // Step 4. - // TODO: handle `Accept-Language`. + set_default_accept_language(&mut headers); // Step 5. // TODO: handle request's priority. From 42812056621e45924c11b191c161a639d9d8f61b Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 4 Apr 2017 12:55:59 +0200 Subject: [PATCH 4/6] Update the steps in fetch_with_cors_cache --- components/net/fetch/methods.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index e824d09d0bf2..1f003b539cc1 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -61,23 +61,23 @@ pub fn fetch_with_cors_cache(request: &mut Request, cache: &mut CorsCache, target: Target, context: &FetchContext) { - // Step 1 + // Step 1. if request.window == Window::Client { // TODO: Set window to request's client object if client is a Window object } else { request.window = Window::NoWindow; } - // Step 2 + // Step 2. if request.origin == Origin::Client { // TODO: set request's origin to request's client's origin unimplemented!() } - // Step 3 + // Step 3. if !request.headers.has::() { let value = match request.type_ { - // Substep 2 + // Step 3.2. _ if request.is_navigation_request() => vec![qitem(mime!(Text / Html)), // FIXME: This should properly generate a MimeType that has a @@ -86,7 +86,7 @@ pub fn fetch_with_cors_cache(request: &mut Request, QualityItem::new(mime!(Application / Xml), q(0.9)), QualityItem::new(mime!(_ / _), q(0.8))], - // Substep 3 + // Step 3.3. Type::Image => vec![qitem(mime!(Image / Png)), // FIXME: This should properly generate a MimeType that has a @@ -95,30 +95,33 @@ pub fn fetch_with_cors_cache(request: &mut Request, QualityItem::new(mime!(Image / _), q(0.8)), QualityItem::new(mime!(_ / _), q(0.5))], - // Substep 3 + // Step 3.3. Type::Style => vec![qitem(mime!(Text / Css)), QualityItem::new(mime!(_ / _), q(0.1))], - // Substep 1 + // Step 3.1. _ => vec![qitem(mime!(_ / _))] }; - // Substep 4 + // Step 3.4. request.headers.set(Accept(value)); } - // Step 4 + // Step 4. set_default_accept_language(&mut request.headers); - // Step 5 - // TODO: Figure out what a Priority object is + // Step 5. + // TODO: figure out what a Priority object is. - // Step 6 + // Step 6. + // TODO: handle client hints headers. + + // Step 7. if request.is_subresource_request() { - // TODO: create a fetch record and append it to request's client's fetch group list + // TODO: handle client hints headers. } - // Step 7 + // Step 8. main_fetch(request, cache, false, false, target, &mut None, &context); } From 901877da1a1a5e7ad234392d693607226bb448fb Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 4 Apr 2017 13:12:32 +0200 Subject: [PATCH 5/6] Introduce http_loader::set_default_accept --- components/net/fetch/methods.rs | 38 +++----------------- components/net/http_loader.rs | 62 ++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index 1f003b539cc1..41aadda700c7 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -8,12 +8,12 @@ use data_loader::decode; use devtools_traits::DevtoolsControlMsg; use fetch::cors_cache::CorsCache; use filemanager_thread::FileManager; -use http_loader::{HttpState, determine_request_referrer, http_fetch, set_default_accept_language}; +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::client::Pool; use hyper::header::{Accept, AcceptLanguage, ContentLanguage, ContentType}; -use hyper::header::{Header, HeaderFormat, HeaderView, Headers, QualityItem}; -use hyper::header::{Referer as RefererHeader, q, qitem}; +use hyper::header::{Header, HeaderFormat, HeaderView, Headers, Referer as RefererHeader}; use hyper::method::Method; use hyper::mime::{Mime, SubLevel, TopLevel}; use hyper::status::StatusCode; @@ -75,37 +75,7 @@ pub fn fetch_with_cors_cache(request: &mut Request, } // Step 3. - if !request.headers.has::() { - let value = match request.type_ { - // Step 3.2. - _ if request.is_navigation_request() => - vec![qitem(mime!(Text / Html)), - // FIXME: This should properly generate a MimeType that has a - // SubLevel of xhtml+xml (https://github.com/hyperium/mime.rs/issues/22) - qitem(mime!(Application / ("xhtml+xml") )), - QualityItem::new(mime!(Application / Xml), q(0.9)), - QualityItem::new(mime!(_ / _), q(0.8))], - - // Step 3.3. - Type::Image => - vec![qitem(mime!(Image / Png)), - // FIXME: This should properly generate a MimeType that has a - // SubLevel of svg+xml (https://github.com/hyperium/mime.rs/issues/22) - qitem(mime!(Image / ("svg+xml") )), - QualityItem::new(mime!(Image / _), q(0.8)), - QualityItem::new(mime!(_ / _), q(0.5))], - - // Step 3.3. - Type::Style => - vec![qitem(mime!(Text / Css)), - QualityItem::new(mime!(_ / _), q(0.1))], - // Step 3.1. - _ => vec![qitem(mime!(_ / _))] - }; - - // Step 3.4. - request.headers.set(Accept(value)); - } + set_default_accept(request.type_, request.destination, &mut request.headers); // Step 4. set_default_accept_language(&mut request.headers); diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index f55b94b533c2..d4ed98d54cea 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -16,14 +16,16 @@ use hyper::Error as HttpError; use hyper::LanguageTag; use hyper::client::{Pool, Request as HyperRequest, Response as HyperResponse}; use hyper::client::pool::PooledStream; -use hyper::header::{AcceptEncoding, AcceptLanguage, AccessControlAllowCredentials}; -use hyper::header::{AccessControlAllowOrigin, AccessControlAllowHeaders, AccessControlAllowMethods}; -use hyper::header::{AccessControlRequestHeaders, AccessControlMaxAge, AccessControlRequestMethod}; -use hyper::header::{Authorization, Basic, CacheControl, CacheDirective, ContentEncoding}; -use hyper::header::{ContentLength, Encoding, Header, Headers, Host, IfMatch, IfRange}; -use hyper::header::{IfUnmodifiedSince, IfModifiedSince, IfNoneMatch, Location, Pragma, Quality}; -use hyper::header::{QualityItem, Referer, SetCookie, UserAgent, qitem}; -use hyper::header::Origin as HyperOrigin; +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, 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::net::{Fresh, HttpStream, HttpsStream, NetworkConnector}; use hyper::status::StatusCode; @@ -34,7 +36,8 @@ use msg::constellation_msg::PipelineId; use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy}; use net_traits::hosts::replace_host; use net_traits::request::{CacheMode, CredentialsMode, Destination, Origin}; -use net_traits::request::{RedirectMode, Referrer, Request, RequestMode, ResponseTainting}; +use net_traits::request::{RedirectMode, Referrer, Request, RequestMode}; +use net_traits::request::{ResponseTainting, Type}; use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType}; use resource_thread::AuthCache; use servo_url::{ImmutableOrigin, ServoUrl}; @@ -141,6 +144,47 @@ impl NetworkHttpRequestFactory { } } +// Step 3 of https://fetch.spec.whatwg.org/#concept-fetch. +pub fn set_default_accept(type_: Type, destination: Destination, headers: &mut Headers) { + if headers.has::() { + return; + } + let value = match (type_, 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)), + ] + }, + // Step 3.3. + (Type::Image, _) => { + vec![ + qitem(mime!(Image / Png)), + qitem(mime!(Image / ("svg+xml") )), + QualityItem::new(mime!(Image / _), q(0.8)), + QualityItem::new(mime!(_ / _), q(0.5)), + ] + }, + // Step 3.3. + (Type::Style, _) => { + vec![ + qitem(mime!(Text / Css)), + QualityItem::new(mime!(_ / _), q(0.1)) + ] + }, + // Step 3.1. + _ => { + vec![qitem(mime!(_ / _))] + }, + }; + + // Step 3.4. + headers.set(Accept(value)); +} + fn set_default_accept_encoding(headers: &mut Headers) { if headers.has::() { return From a600a60a093bfbcf6e69b274dc3404969a4cb1ec Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 4 Apr 2017 13:14:35 +0200 Subject: [PATCH 6/6] Use set_default_accept in websocket_loader --- components/net/websocket_loader.rs | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/components/net/websocket_loader.rs b/components/net/websocket_loader.rs index f79048e067f5..2f041726e8be 100644 --- a/components/net/websocket_loader.rs +++ b/components/net/websocket_loader.rs @@ -4,9 +4,10 @@ use cookie::Cookie; use fetch::methods::{should_be_blocked_due_to_bad_port, should_be_blocked_due_to_nosniff}; -use http_loader::{HttpState, is_redirect_status, set_default_accept_language, set_request_cookies}; +use http_loader::{HttpState, is_redirect_status, set_default_accept}; +use http_loader::{set_default_accept_language, set_request_cookies}; use hyper::buffer::BufReader; -use hyper::header::{Accept, CacheControl, CacheDirective, Connection, ConnectionOption}; +use hyper::header::{CacheControl, CacheDirective, Connection, ConnectionOption}; use hyper::header::{Headers, Host, SetCookie, Pragma, Protocol, ProtocolName, Upgrade}; use hyper::http::h1::{LINE_ENDING, parse_response}; use hyper::method::Method; @@ -16,7 +17,7 @@ use hyper::version::HttpVersion; use net_traits::{CookieSource, MessageData, NetworkError, WebSocketCommunicate, WebSocketConnectData}; use net_traits::{WebSocketDomAction, WebSocketNetworkEvent}; use net_traits::hosts::replace_host; -use net_traits::request::Type; +use net_traits::request::{Destination, Type}; use servo_url::ServoUrl; use std::ascii::AsciiExt; use std::io::{self, Write}; @@ -279,20 +280,7 @@ fn fetch(url: &ServoUrl, // TODO: handle request's origin. // Step 3. - // We know there is no `Accept` header in `headers`. - { - // Step 3.1. - let value = Accept::star(); - - // Step 3.2. - // Not applicable: not a navigation request. - - // Step 3.3. - // Not applicable: request's type is the empty string. - - // Step 3.4. - headers.set(value); - } + set_default_accept(Type::None, Destination::None, &mut headers); // Step 4. set_default_accept_language(&mut headers);