diff --git a/components/net/fetch/cors_cache.rs b/components/net/fetch/cors_cache.rs index 4a16f9d9b00..6c30782453d 100644 --- a/components/net/fetch/cors_cache.rs +++ b/components/net/fetch/cors_cache.rs @@ -66,7 +66,7 @@ impl CorsCacheEntry { } fn match_headers(cors_cache: &CorsCacheEntry, cors_req: &Request) -> bool { - cors_cache.origin == *cors_req.origin.borrow() && + cors_cache.origin == cors_req.origin && cors_cache.url == cors_req.current_url() && (cors_cache.credentials || cors_req.credentials_mode != CredentialsMode::Include) } @@ -97,7 +97,7 @@ impl CorsCache { pub fn clear(&mut self, request: &Request) { let CorsCache(buf) = self.clone(); let new_buf: Vec = - buf.into_iter().filter(|e| e.origin == *request.origin.borrow() && + buf.into_iter().filter(|e| e.origin == request.origin && request.current_url() == e.url).collect(); *self = CorsCache(new_buf); } @@ -127,7 +127,7 @@ impl CorsCache { 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.borrow().clone(), request.current_url(), new_max_age, + self.insert(CorsCacheEntry::new(request.origin.clone(), request.current_url(), new_max_age, request.credentials_mode == CredentialsMode::Include, HeaderOrMethod::HeaderData(header_name.to_owned()))); false @@ -149,7 +149,7 @@ impl CorsCache { match self.find_entry_by_method(&request, method.clone()).map(|e| e.max_age = new_max_age) { Some(_) => true, None => { - self.insert(CorsCacheEntry::new(request.origin.borrow().clone(), request.current_url(), new_max_age, + self.insert(CorsCacheEntry::new(request.origin.clone(), request.current_url(), new_max_age, request.credentials_mode == CredentialsMode::Include, HeaderOrMethod::MethodData(method))); false diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index 4f5e91471b0..e824d09d0bf 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -3,13 +3,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use blob_loader::load_blob_sync; +use connector::Connector; 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 hyper::Error; -use hyper::error::Result as HyperResult; +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}; @@ -27,8 +28,8 @@ use std::fmt; use std::fs::File; use std::io::Read; use std::mem; -use std::rc::Rc; use std::str; +use std::sync::Arc; use std::sync::mpsc::{Sender, Receiver}; use subresource_integrity::is_response_integrity_valid; @@ -40,40 +41,41 @@ pub enum Data { } pub struct FetchContext { - pub state: HttpState, + pub state: Arc, pub user_agent: Cow<'static, str>, pub devtools_chan: Option>, pub filemanager: FileManager, + pub connector: Arc>, } pub type DoneChannel = Option<(Sender, Receiver)>; /// [Fetch](https://fetch.spec.whatwg.org#concept-fetch) -pub fn fetch(request: Rc, +pub fn fetch(request: &mut Request, target: Target, context: &FetchContext) { fetch_with_cors_cache(request, &mut CorsCache::new(), target, context); } -pub fn fetch_with_cors_cache(request: Rc, +pub fn fetch_with_cors_cache(request: &mut Request, cache: &mut CorsCache, target: Target, context: &FetchContext) { // Step 1 - if request.window.get() == Window::Client { + if request.window == Window::Client { // TODO: Set window to request's client object if client is a Window object } else { - request.window.set(Window::NoWindow); + request.window = Window::NoWindow; } // Step 2 - if *request.origin.borrow() == Origin::Client { + if request.origin == Origin::Client { // TODO: set request's origin to request's client's origin unimplemented!() } // Step 3 - if !request.headers.borrow().has::() { + if !request.headers.has::() { let value = match request.type_ { // Substep 2 _ if request.is_navigation_request() => @@ -102,11 +104,11 @@ pub fn fetch_with_cors_cache(request: Rc, }; // Substep 4 - request.headers.borrow_mut().set(Accept(value)); + request.headers.set(Accept(value)); } // Step 4 - set_default_accept_language(&mut request.headers.borrow_mut()); + set_default_accept_language(&mut request.headers); // Step 5 // TODO: Figure out what a Priority object is @@ -121,7 +123,7 @@ pub fn fetch_with_cors_cache(request: Rc, } /// [Main fetch](https://fetch.spec.whatwg.org/#concept-main-fetch) -pub fn main_fetch(request: Rc, +pub fn main_fetch(request: &mut Request, cache: &mut CorsCache, cors_flag: bool, recursive_flag: bool, @@ -129,12 +131,10 @@ pub fn main_fetch(request: Rc, done_chan: &mut DoneChannel, context: &FetchContext) -> Response { - // TODO: Implement main fetch spec - - // Step 1 + // Step 1. let mut response = None; - // Step 2 + // Step 2. if request.local_urls_only { match request.current_url().scheme() { "about" | "blob" | "data" | "filesystem" => (), // Ok, the URL is local. @@ -142,120 +142,121 @@ pub fn main_fetch(request: Rc, } } - // Step 3 - // TODO be able to execute report CSP + // Step 3. + // TODO: handle content security policy violations. - // Step 4 - // TODO this step, based off of http_loader.rs (upgrade) + // Step 4. + // TODO: handle upgrade to a potentially secure URL. - // Step 5 - // TODO this step (CSP port/content blocking) + // Step 5. if should_be_blocked_due_to_bad_port(&request.url()) { response = Some(Response::network_error(NetworkError::Internal("Request attempted on bad port".into()))); } + // TODO: handle blocking as mixed content. + // TODO: handle blocking by content security policy. // Step 6 - // TODO this step (referrer policy) - // currently the clients themselves set referrer policy in RequestInit + // TODO: handle request's client's referrer policy. - // Step 7 - let referrer_policy = request.referrer_policy.get().unwrap_or(ReferrerPolicy::NoReferrerWhenDowngrade); - request.referrer_policy.set(Some(referrer_policy)); + // Step 7. + let referrer_policy = request.referrer_policy.unwrap_or(ReferrerPolicy::NoReferrerWhenDowngrade); + request.referrer_policy = Some(referrer_policy); - // Step 8 + // Step 8. { - let mut referrer = request.referrer.borrow_mut(); - let referrer_url = match mem::replace(&mut *referrer, Referrer::NoReferrer) { + let referrer_url = match mem::replace(&mut request.referrer, Referrer::NoReferrer) { Referrer::NoReferrer => None, Referrer::Client => { // FIXME(#14507): We should never get this value here; it should // already have been handled in the script thread. - request.headers.borrow_mut().remove::(); + request.headers.remove::(); None }, Referrer::ReferrerUrl(url) => { - request.headers.borrow_mut().remove::(); - determine_request_referrer(&mut *request.headers.borrow_mut(), + request.headers.remove::(); + let current_url = request.current_url().clone(); + determine_request_referrer(&mut request.headers, referrer_policy, url, - request.current_url().clone()) + current_url) } }; if let Some(referrer_url) = referrer_url { - *referrer = Referrer::ReferrerUrl(referrer_url); + request.referrer = Referrer::ReferrerUrl(referrer_url); } } - // Step 9 + // Step 9. + // TODO: handle FTP URLs. + + // Step 10. if !request.current_url().is_secure_scheme() && request.current_url().domain().is_some() { if context.state .hsts_list .read() .unwrap() .is_host_secure(request.current_url().domain().unwrap()) { - request.url_list.borrow_mut().last_mut().unwrap().as_mut_url().set_scheme("https").unwrap(); + request.url_list.last_mut().unwrap().as_mut_url().set_scheme("https").unwrap(); } } - // Step 10 - // this step is obsoleted by fetch_async + // Step 11. + // Not applicable: see fetch_async. - // Step 11 - let response = match response { - Some(response) => response, - None => { - let current_url = request.current_url(); - let same_origin = if let Origin::Origin(ref origin) = *request.origin.borrow() { - *origin == current_url.origin() - } else { - false - }; + // Step 12. + let response = response.unwrap_or_else(|| { + let current_url = request.current_url(); + let same_origin = if let Origin::Origin(ref origin) = request.origin { + *origin == current_url.origin() + } else { + false + }; - if (same_origin && !cors_flag ) || - current_url.scheme() == "data" || - current_url.scheme() == "file" || - current_url.scheme() == "about" || - request.mode == RequestMode::Navigate { - basic_fetch(request.clone(), cache, target, done_chan, context) + if (same_origin && !cors_flag ) || + current_url.scheme() == "data" || + current_url.scheme() == "file" || + current_url.scheme() == "about" || + request.mode == RequestMode::Navigate { + basic_fetch(request, cache, target, done_chan, context) - } else if request.mode == RequestMode::SameOrigin { - Response::network_error(NetworkError::Internal("Cross-origin response".into())) + } else if request.mode == RequestMode::SameOrigin { + Response::network_error(NetworkError::Internal("Cross-origin response".into())) - } else if request.mode == RequestMode::NoCors { - request.response_tainting.set(ResponseTainting::Opaque); - basic_fetch(request.clone(), cache, target, done_chan, context) + } else if request.mode == RequestMode::NoCors { + request.response_tainting = ResponseTainting::Opaque; + basic_fetch(request, cache, target, done_chan, context) - } else if !matches!(current_url.scheme(), "http" | "https") { - Response::network_error(NetworkError::Internal("Non-http scheme".into())) + } else if !matches!(current_url.scheme(), "http" | "https") { + Response::network_error(NetworkError::Internal("Non-http scheme".into())) - } else if request.use_cors_preflight || - (request.unsafe_request && - (!is_simple_method(&request.method.borrow()) || - request.headers.borrow().iter().any(|h| !is_simple_header(&h)))) { - request.response_tainting.set(ResponseTainting::CorsTainting); - let response = http_fetch(request.clone(), cache, true, true, false, - target, done_chan, context); - if response.is_network_error() { - // TODO clear cache entries using request - } - response - - } else { - request.response_tainting.set(ResponseTainting::CorsTainting); - http_fetch(request.clone(), cache, true, false, false, target, done_chan, context) + } else if request.use_cors_preflight || + (request.unsafe_request && + (!is_simple_method(&request.method) || + request.headers.iter().any(|h| !is_simple_header(&h)))) { + request.response_tainting = ResponseTainting::CorsTainting; + let response = http_fetch(request, cache, true, true, false, + target, done_chan, context); + if response.is_network_error() { + // TODO clear cache entries using request } - } - }; + response - // Step 12 + } else { + request.response_tainting = ResponseTainting::CorsTainting; + http_fetch(request, cache, true, false, false, target, done_chan, context) + } + }); + + // Step 13. if recursive_flag { return response; } - // Step 13 - // no need to check if response is a network error, since the type would not be `Default` - let response = if response.response_type == ResponseType::Default { - let response_type = match request.response_tainting.get() { + // Step 14. + // We don't need to check whether response is a network error, + // given its type would not be `Default` in this case. + let mut response = if response.response_type == ResponseType::Default { + let response_type = match request.response_tainting { ResponseTainting::Basic => ResponseType::Basic, ResponseTainting::CorsTainting => ResponseType::Cors, ResponseTainting::Opaque => ResponseType::Opaque, @@ -265,26 +266,32 @@ pub fn main_fetch(request: Rc, response }; - let internal_error = { // Inner scope to reborrow response - // Step 14 - let network_error_response; - let internal_response = if let Some(error) = response.get_network_error() { - network_error_response = Response::network_error(error.clone()); - &network_error_response + let internal_error = { + // Tests for steps 17 and 18, before step 15 for borrowing concerns. + let response_is_network_error = response.is_network_error(); + let should_replace_with_nosniff_error = + !response_is_network_error && should_be_blocked_due_to_nosniff(request.type_, &response.headers); + + // Step 15. + let mut network_error_response = response.get_network_error().cloned().map(Response::network_error); + let internal_response = if let Some(error_response) = network_error_response.as_mut() { + error_response } else { - response.actual_response() + response.actual_response_mut() }; - // Step 15 - if internal_response.url_list.borrow().is_empty() { - *internal_response.url_list.borrow_mut() = request.url_list.borrow().clone(); + // Step 16. + if internal_response.url_list.is_empty() { + internal_response.url_list = request.url_list.clone(); } - // Step 16 - // TODO Blocking for CSP, mixed content, MIME type + // Step 17. + // TODO: handle blocking as mixed content. + // TODO: handle blocking by content security policy. + // TODO: handle blocking due to MIME type. let blocked_error_response; let internal_response = - if !response.is_network_error() && should_be_blocked_due_to_nosniff(request.type_, &response.headers) { + if should_replace_with_nosniff_error { // Defer rebinding result blocked_error_response = Response::network_error(NetworkError::Internal("Blocked by nosniff".into())); &blocked_error_response @@ -292,11 +299,12 @@ pub fn main_fetch(request: Rc, internal_response }; - // Step 17 - // We check `internal_response` since we did not mutate `response` in the previous step. - let not_network_error = !response.is_network_error() && !internal_response.is_network_error(); + // Step 18. + // We check `internal_response` since we did not mutate `response` + // in the previous step. + 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.borrow() { + match request.method { Method::Head | Method::Connect => true, _ => false }) { // when Fetch is used only asynchronously, we will need to make sure @@ -308,22 +316,22 @@ pub fn main_fetch(request: Rc, internal_response.get_network_error().map(|e| e.clone()) }; - // Execute deferred rebinding of response + // Execute deferred rebinding of response. let response = if let Some(error) = internal_error { Response::network_error(error) } else { response }; - // Step 18 + // Step 19. let mut response_loaded = false; - let response = if !response.is_network_error() && *request.integrity_metadata.borrow() != "" { - // Substep 1 + let response = if !response.is_network_error() && !request.integrity_metadata.is_empty() { + // Step 19.1. wait_for_response(&response, target, done_chan); response_loaded = true; - // Substep 2 - let ref integrity_metadata = *request.integrity_metadata.borrow(); + // Step 19.2. + let ref integrity_metadata = &request.integrity_metadata; if response.termination_reason.is_none() && !is_response_integrity_valid(integrity_metadata, &response) { Response::network_error(NetworkError::Internal("Subresource integrity validation failed".into())) @@ -334,7 +342,7 @@ pub fn main_fetch(request: Rc, response }; - // Step 19 + // Step 20. if request.synchronous { // process_response is not supposed to be used // by sync fetch, but we overload it here for simplicity @@ -347,8 +355,8 @@ pub fn main_fetch(request: Rc, return response; } - // Step 20 - if request.body.borrow().is_some() && matches!(request.current_url().scheme(), "http" | "https") { + // Step 21. + if request.body.is_some() && matches!(request.current_url().scheme(), "http" | "https") { // XXXManishearth: We actually should be calling process_request // in http_network_fetch. However, we can't yet follow the request // upload progress, so I'm keeping it here for now and pretending @@ -357,19 +365,20 @@ pub fn main_fetch(request: Rc, target.process_request_eof(&request); } - // Step 21 + // Step 22. target.process_response(&response); - // Step 22 + // Step 23. if !response_loaded { wait_for_response(&response, target, done_chan); } - // Step 24 + // Step 24. target.process_response_eof(&response); - // TODO remove this line when only asynchronous fetches are used - return response; + // Steps 25-27. + // TODO: remove this line when only asynchronous fetches are used + response } fn wait_for_response(response: &Response, target: Target, done_chan: &mut DoneChannel) { @@ -397,7 +406,7 @@ fn wait_for_response(response: &Response, target: Target, done_chan: &mut DoneCh } /// [Basic fetch](https://fetch.spec.whatwg.org#basic-fetch) -fn basic_fetch(request: Rc, +fn basic_fetch(request: &mut Request, cache: &mut CorsCache, target: Target, done_chan: &mut DoneChannel, @@ -414,11 +423,11 @@ fn basic_fetch(request: Rc, }, "http" | "https" => { - http_fetch(request.clone(), cache, false, false, false, target, done_chan, context) + http_fetch(request, cache, false, false, false, target, done_chan, context) }, "data" => { - if *request.method.borrow() == Method::Get { + if request.method == Method::Get { match decode(&url) { Ok((mime, bytes)) => { let mut response = Response::new(url); @@ -434,7 +443,7 @@ fn basic_fetch(request: Rc, }, "file" => { - if *request.method.borrow() == Method::Get { + if request.method == Method::Get { match url.to_file_path() { Ok(file_path) => { match File::open(file_path.clone()) { @@ -461,7 +470,7 @@ fn basic_fetch(request: Rc, "blob" => { println!("Loading blob {}", url.as_str()); // Step 2. - if *request.method.borrow() != Method::Get { + if request.method != Method::Get { return Response::network_error(NetworkError::Internal("Unexpected method for blob".into())); } diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index f99e4306137..f55b94b533c 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use brotli::Decompressor; -use connector::{Connector, create_http_connector, create_ssl_client}; +use connector::Connector; use cookie; use cookie_storage::CookieStorage; use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, HttpRequest as DevtoolsHttpRequest}; @@ -44,7 +44,6 @@ use std::io::{self, Read, Write}; use std::iter::FromIterator; use std::mem; use std::ops::Deref; -use std::rc::Rc; use std::sync::{Arc, RwLock}; use std::sync::mpsc::{channel, Sender}; use std::thread; @@ -67,20 +66,17 @@ fn read_block(reader: &mut R) -> Result { } pub struct HttpState { - pub hsts_list: Arc>, - pub cookie_jar: Arc>, - pub auth_cache: Arc>, - pub connector_pool: Arc>, + pub hsts_list: RwLock, + pub cookie_jar: RwLock, + pub auth_cache: RwLock, } impl HttpState { - pub fn new(certificate_path: &str) -> HttpState { - let ssl_client = create_ssl_client(certificate_path); + pub fn new() -> HttpState { HttpState { - hsts_list: Arc::new(RwLock::new(HstsList::new())), - cookie_jar: Arc::new(RwLock::new(CookieStorage::new(150))), - auth_cache: Arc::new(RwLock::new(AuthCache::new())), - connector_pool: create_http_connector(ssl_client), + hsts_list: RwLock::new(HstsList::new()), + cookie_jar: RwLock::new(CookieStorage::new(150)), + auth_cache: RwLock::new(AuthCache::new()), } } } @@ -241,7 +237,7 @@ pub fn determine_request_referrer(headers: &mut Headers, } } -pub fn set_request_cookies(url: &ServoUrl, headers: &mut Headers, cookie_jar: &Arc>) { +pub fn set_request_cookies(url: &ServoUrl, headers: &mut Headers, 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(); @@ -250,7 +246,7 @@ pub fn set_request_cookies(url: &ServoUrl, headers: &mut Headers, cookie_jar: &A } } -fn set_cookie_for_url(cookie_jar: &Arc>, +fn set_cookie_for_url(cookie_jar: &RwLock, request: &ServoUrl, cookie_val: String) { let mut cookie_jar = cookie_jar.write().unwrap(); @@ -266,7 +262,7 @@ fn set_cookie_for_url(cookie_jar: &Arc>, } } -fn set_cookies_from_headers(url: &ServoUrl, headers: &Headers, cookie_jar: &Arc>) { +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()) { @@ -366,7 +362,7 @@ fn send_response_to_devtools(devtools_chan: &Sender, let _ = devtools_chan.send(DevtoolsControlMsg::FromChrome(msg)); } -fn auth_from_cache(auth_cache: &Arc>, 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()); @@ -477,7 +473,7 @@ fn obtain_response(request_factory: &NetworkHttpRequestFactory, } /// [HTTP fetch](https://fetch.spec.whatwg.org#http-fetch) -pub fn http_fetch(request: Rc, +pub fn http_fetch(request: &mut Request, cache: &mut CorsCache, cors_flag: bool, cors_preflight_flag: bool, @@ -495,7 +491,7 @@ pub fn http_fetch(request: Rc, // nothing to do, since actual_response is a function on response // Step 3 - if !request.skip_service_worker.get() && !request.is_service_worker_global_scope { + if !request.skip_service_worker && !request.is_service_worker_global_scope { // Substep 1 // TODO (handle fetch unimplemented) @@ -507,9 +503,8 @@ pub fn http_fetch(request: Rc, if (res.response_type == ResponseType::Opaque && request.mode != RequestMode::NoCors) || (res.response_type == ResponseType::OpaqueRedirect && - request.redirect_mode.get() != RedirectMode::Manual) || - (res.url_list.borrow().len() > 1 && - request.redirect_mode.get() != RedirectMode::Follow) || + request.redirect_mode != RedirectMode::Manual) || + (res.url_list.len() > 1 && request.redirect_mode != RedirectMode::Follow) || res.is_network_error() { return Response::network_error(NetworkError::Internal("Request failed".into())); } @@ -522,7 +517,7 @@ pub fn http_fetch(request: Rc, // Step 4 let credentials = match request.credentials_mode { CredentialsMode::Include => true, - CredentialsMode::CredentialsSameOrigin if request.response_tainting.get() == ResponseTainting::Basic + CredentialsMode::CredentialsSameOrigin if request.response_tainting == ResponseTainting::Basic => true, _ => false }; @@ -532,17 +527,17 @@ pub fn http_fetch(request: Rc, // Substep 1 if cors_preflight_flag { let method_cache_match = cache.match_method(&*request, - request.method.borrow().clone()); + request.method.clone()); - let method_mismatch = !method_cache_match && (!is_simple_method(&request.method.borrow()) || + let method_mismatch = !method_cache_match && (!is_simple_method(&request.method) || request.use_cors_preflight); - let header_mismatch = request.headers.borrow().iter().any(|view| + let header_mismatch = request.headers.iter().any(|view| !cache.match_header(&*request, view.name()) && !is_simple_header(&view) ); // Sub-substep 1 if method_mismatch || header_mismatch { - let preflight_result = cors_preflight_fetch(request.clone(), cache, context); + let preflight_result = cors_preflight_fetch(&request, cache, context); // Sub-substep 2 if let Some(e) = preflight_result.get_network_error() { return Response::network_error(e.clone()); @@ -551,18 +546,18 @@ pub fn http_fetch(request: Rc, } // Substep 2 - request.skip_service_worker.set(true); + request.skip_service_worker = true; // Substep 3 - let fetch_result = http_network_or_cache_fetch(request.clone(), authentication_fetch_flag, - cors_flag, done_chan, context); + let mut fetch_result = http_network_or_cache_fetch( + request, authentication_fetch_flag, cors_flag, done_chan, context); // Substep 4 - if cors_flag && cors_check(request.clone(), &fetch_result).is_err() { + if cors_flag && cors_check(&request, &fetch_result).is_err() { return Response::network_error(NetworkError::Internal("CORS check failed".into())); } - fetch_result.return_internal.set(false); + fetch_result.return_internal = false; response = Some(fetch_result); } @@ -573,14 +568,14 @@ pub fn http_fetch(request: Rc, match response.actual_response().status { // Code 301, 302, 303, 307, 308 status if status.map_or(false, is_redirect_status) => { - response = match request.redirect_mode.get() { + response = match request.redirect_mode { RedirectMode::Error => Response::network_error(NetworkError::Internal("Redirect mode error".into())), RedirectMode::Manual => { response.to_filtered(ResponseType::OpaqueRedirect) }, RedirectMode::Follow => { // set back to default - response.return_internal.set(true); + response.return_internal = true; http_redirect_fetch(request, cache, response, cors_flag, target, done_chan, context) } @@ -643,13 +638,13 @@ pub fn http_fetch(request: Rc, } // set back to default - response.return_internal.set(true); + response.return_internal = true; // Step 7 response } /// [HTTP redirect fetch](https://fetch.spec.whatwg.org#http-redirect-fetch) -fn http_redirect_fetch(request: Rc, +fn http_redirect_fetch(request: &mut Request, cache: &mut CorsCache, response: Response, cors_flag: bool, @@ -658,7 +653,7 @@ fn http_redirect_fetch(request: Rc, context: &FetchContext) -> Response { // Step 1 - assert_eq!(response.return_internal.get(), true); + assert!(response.return_internal); // Step 2 if !response.actual_response().headers.has::() { @@ -684,12 +679,12 @@ fn http_redirect_fetch(request: Rc, } // Step 5 - if request.redirect_count.get() >= 20 { + if request.redirect_count >= 20 { return Response::network_error(NetworkError::Internal("Too many redirects".into())); } // Step 6 - request.redirect_count.set(request.redirect_count.get() + 1); + request.redirect_count += 1; // Step 7 let same_origin = location_url.origin()== request.current_url().origin(); @@ -706,20 +701,20 @@ fn http_redirect_fetch(request: Rc, // Step 9 if cors_flag && !same_origin { - *request.origin.borrow_mut() = Origin::Origin(ImmutableOrigin::new_opaque()); + request.origin = Origin::Origin(ImmutableOrigin::new_opaque()); } // Step 10 let status_code = response.actual_response().status.unwrap(); if ((status_code == StatusCode::MovedPermanently || status_code == StatusCode::Found) && - *request.method.borrow() == Method::Post) || + request.method == Method::Post) || status_code == StatusCode::SeeOther { - *request.method.borrow_mut() = Method::Get; - *request.body.borrow_mut() = None; + request.method = Method::Get; + request.body = None; } // Step 11 - request.url_list.borrow_mut().push(location_url); + request.url_list.push(location_url); // Step 12 // TODO implement referrer policy @@ -738,7 +733,7 @@ fn try_immutable_origin_to_hyper_origin(url_origin: &ImmutableOrigin) -> Option< } /// [HTTP network or cache fetch](https://fetch.spec.whatwg.org#http-network-or-cache-fetch) -fn http_network_or_cache_fetch(request: Rc, +fn http_network_or_cache_fetch(request: &mut Request, authentication_fetch_flag: bool, cors_flag: bool, done_chan: &mut DoneChannel, @@ -748,26 +743,28 @@ fn http_network_or_cache_fetch(request: Rc, let request_has_no_window = true; // Step 2 + let mut http_request; let http_request = if request_has_no_window && - request.redirect_mode.get() == RedirectMode::Error { + request.redirect_mode == RedirectMode::Error { request } else { // Step 3 // TODO Implement body source - Rc::new((*request).clone()) + http_request = request.clone(); + &mut http_request }; // Step 4 let credentials_flag = match http_request.credentials_mode { CredentialsMode::Include => true, - CredentialsMode::CredentialsSameOrigin if http_request.response_tainting.get() == ResponseTainting::Basic + CredentialsMode::CredentialsSameOrigin if http_request.response_tainting == ResponseTainting::Basic => true, _ => false }; - let content_length_value = match *http_request.body.borrow() { + let content_length_value = match http_request.body { None => - match *http_request.method.borrow() { + match http_request.method { // Step 6 Method::Post | Method::Put => Some(0), @@ -780,16 +777,16 @@ fn http_network_or_cache_fetch(request: Rc, // Step 8 if let Some(content_length_value) = content_length_value { - http_request.headers.borrow_mut().set(ContentLength(content_length_value)); + http_request.headers.set(ContentLength(content_length_value)); } // Step 9 TODO: needs request's client object // Step 10 - match *http_request.referrer.borrow() { + match http_request.referrer { Referrer::NoReferrer => (), Referrer::ReferrerUrl(ref http_request_referrer) => - http_request.headers.borrow_mut().set(Referer(http_request_referrer.to_string())), + http_request.headers.set(Referer(http_request_referrer.to_string())), Referrer::Client => // it should be impossible for referrer to be anything else during fetching // https://fetch.spec.whatwg.org/#concept-request-referrer @@ -797,45 +794,45 @@ fn http_network_or_cache_fetch(request: Rc, }; // Step 11 - if !http_request.omit_origin_header.get() { - let method = http_request.method.borrow(); + if !http_request.omit_origin_header { + let method = &http_request.method; if cors_flag || (*method != Method::Get && *method != Method::Head) { - debug_assert!(*http_request.origin.borrow() != Origin::Client); - if let Origin::Origin(ref url_origin) = *http_request.origin.borrow() { + debug_assert!(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.borrow_mut().set(hyper_origin) + http_request.headers.set(hyper_origin) } } } } // Step 12 - if !http_request.headers.borrow().has::() { + if !http_request.headers.has::() { let user_agent = context.user_agent.clone().into_owned(); - http_request.headers.borrow_mut().set(UserAgent(user_agent)); + http_request.headers.set(UserAgent(user_agent)); } - match http_request.cache_mode.get() { + match http_request.cache_mode { // Step 13 - CacheMode::Default if is_no_store_cache(&http_request.headers.borrow()) => { - http_request.cache_mode.set(CacheMode::NoStore); + CacheMode::Default if is_no_store_cache(&http_request.headers) => { + http_request.cache_mode = CacheMode::NoStore; }, // Step 14 - CacheMode::NoCache if !http_request.headers.borrow().has::() => { - http_request.headers.borrow_mut().set(CacheControl(vec![CacheDirective::MaxAge(0)])); + CacheMode::NoCache if !http_request.headers.has::() => { + http_request.headers.set(CacheControl(vec![CacheDirective::MaxAge(0)])); }, // Step 15 CacheMode::Reload | CacheMode::NoStore => { // Substep 1 - if !http_request.headers.borrow().has::() { - http_request.headers.borrow_mut().set(Pragma::NoCache); + if !http_request.headers.has::() { + http_request.headers.set(Pragma::NoCache); } // Substep 2 - if !http_request.headers.borrow().has::() { - http_request.headers.borrow_mut().set(CacheControl(vec![CacheDirective::NoCache])); + if !http_request.headers.has::() { + http_request.headers.set(CacheControl(vec![CacheDirective::NoCache])); } }, @@ -844,17 +841,14 @@ fn http_network_or_cache_fetch(request: Rc, // Step 16 let current_url = http_request.current_url(); - { - let headers = &mut *http_request.headers.borrow_mut(); - let host = Host { - hostname: current_url.host_str().unwrap().to_owned(), - port: current_url.port() - }; - headers.set(host); - // unlike http_loader, we should not set the accept header - // here, according to the fetch spec - set_default_accept_encoding(headers); - } + let host = Host { + hostname: current_url.host_str().unwrap().to_owned(), + port: current_url.port() + }; + http_request.headers.set(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); // Step 17 // TODO some of this step can't be implemented yet @@ -863,10 +857,10 @@ fn http_network_or_cache_fetch(request: Rc, // TODO http://mxr.mozilla.org/servo/source/components/net/http_loader.rs#504 // XXXManishearth http_loader has block_cookies: support content blocking here too set_request_cookies(¤t_url, - &mut *http_request.headers.borrow_mut(), + &mut http_request.headers, &context.state.cookie_jar); // Substep 2 - if !http_request.headers.borrow().has::>() { + if !http_request.headers.has::>() { // Substep 3 let mut authorization_value = None; @@ -889,7 +883,7 @@ fn http_network_or_cache_fetch(request: Rc, // Substep 6 if let Some(basic) = authorization_value { - http_request.headers.borrow_mut().set(Authorization(basic)); + http_request.headers.set(Authorization(basic)); } } } @@ -906,8 +900,8 @@ fn http_network_or_cache_fetch(request: Rc, // Step 21 // TODO have a HTTP cache to check for a completed response let complete_http_response_from_cache: Option = None; - if http_request.cache_mode.get() != CacheMode::NoStore && - http_request.cache_mode.get() != CacheMode::Reload && + if http_request.cache_mode != CacheMode::NoStore && + http_request.cache_mode != CacheMode::Reload && complete_http_response_from_cache.is_some() { // TODO Substep 1 and 2. Select a response from HTTP cache. @@ -917,8 +911,8 @@ fn http_network_or_cache_fetch(request: Rc, }; // Substep 4 - if http_request.cache_mode.get() == CacheMode::ForceCache || - http_request.cache_mode.get() == CacheMode::OnlyIfCached { + if http_request.cache_mode == CacheMode::ForceCache || + http_request.cache_mode == CacheMode::OnlyIfCached { // TODO pull response from HTTP cache // response = http_request } @@ -938,18 +932,18 @@ fn http_network_or_cache_fetch(request: Rc, // Step 22 if response.is_none() { // Substep 1 - if http_request.cache_mode.get() == CacheMode::OnlyIfCached { + if http_request.cache_mode == CacheMode::OnlyIfCached { return Response::network_error( NetworkError::Internal("Couldn't find response in cache".into())) } // Substep 2 - let forward_response = http_network_fetch(http_request.clone(), credentials_flag, + let forward_response = http_network_fetch(http_request, credentials_flag, done_chan, context); match forward_response.raw_status { // Substep 3 Some((200...303, _)) | Some((305...399, _)) => { - if !http_request.method.borrow().safe() { + if !http_request.method.safe() { // TODO Invalidate HTTP cache response } }, @@ -983,7 +977,7 @@ fn http_network_or_cache_fetch(request: Rc, // TODO: Spec says requires testing on multiple WWW-Authenticate headers // Substep 2 - if http_request.body.borrow().is_some() { + if http_request.body.is_some() { // TODO Implement body source } @@ -1033,7 +1027,7 @@ fn http_network_or_cache_fetch(request: Rc, } /// [HTTP network fetch](https://fetch.spec.whatwg.org/#http-network-fetch) -fn http_network_fetch(request: Rc, +fn http_network_fetch(request: &Request, credentials_flag: bool, done_chan: &mut DoneChannel, context: &FetchContext) @@ -1051,7 +1045,7 @@ fn http_network_fetch(request: Rc, // Step 4 let factory = NetworkHttpRequestFactory { - connector: context.state.connector_pool.clone(), + connector: context.connector.clone(), }; let url = request.current_url(); @@ -1064,13 +1058,13 @@ fn http_network_fetch(request: Rc, // 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(&factory, &url, &request.method.borrow(), - &request.headers.borrow(), - &request.body.borrow(), &request.method.borrow(), - &request.pipeline_id.get(), request.redirect_count.get() + 1, + let wrapped_response = obtain_response(&factory, &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.get(); + let pipeline_id = request.pipeline_id; let (res, msg) = match wrapped_response { Ok(wrapped_response) => wrapped_response, Err(error) => return Response::network_error(error), @@ -1081,7 +1075,7 @@ fn http_network_fetch(request: Rc, response.raw_status = Some((res.response.status_raw().0, res.response.status_raw().1.as_bytes().to_vec())); response.headers = res.response.headers.clone(); - response.referrer = request.referrer.borrow().to_url().cloned(); + response.referrer = request.referrer.to_url().cloned(); let res_body = response.body.clone(); @@ -1177,7 +1171,7 @@ fn http_network_fetch(request: Rc, // TODO this step isn't possible yet (CSP) // Step 12 - if response.is_network_error() && request.cache_mode.get() == CacheMode::NoStore { + if response.is_network_error() && request.cache_mode == CacheMode::NoStore { // TODO update response in the HTTP cache for request } @@ -1204,41 +1198,41 @@ fn http_network_fetch(request: Rc, } /// [CORS preflight fetch](https://fetch.spec.whatwg.org#cors-preflight-fetch) -fn cors_preflight_fetch(request: Rc, +fn cors_preflight_fetch(request: &Request, cache: &mut CorsCache, context: &FetchContext) -> Response { // Step 1 - let mut preflight = Request::new(request.current_url(), Some(request.origin.borrow().clone()), - request.is_service_worker_global_scope, request.pipeline_id.get()); - *preflight.method.borrow_mut() = Method::Options; + let mut preflight = Request::new(request.current_url(), Some(request.origin.clone()), + request.is_service_worker_global_scope, request.pipeline_id); + preflight.method = Method::Options; preflight.initiator = request.initiator.clone(); preflight.type_ = request.type_.clone(); preflight.destination = request.destination.clone(); - *preflight.referrer.borrow_mut() = request.referrer.borrow().clone(); - preflight.referrer_policy.set(request.referrer_policy.get()); + preflight.referrer = request.referrer.clone(); + preflight.referrer_policy = request.referrer_policy; // Step 2 - preflight.headers.borrow_mut().set::( - AccessControlRequestMethod(request.method.borrow().clone())); + preflight.headers.set::( + AccessControlRequestMethod(request.method.clone())); // Step 3, 4 - let mut value = request.headers.borrow().iter() - .filter(|view| !is_simple_header(view)) - .map(|view| UniCase(view.name().to_owned())) - .collect::>>(); + let mut value = request.headers + .iter() + .filter(|view| !is_simple_header(view)) + .map(|view| UniCase(view.name().to_owned())) + .collect::>>(); value.sort(); // Step 5 - preflight.headers.borrow_mut().set::( + preflight.headers.set::( AccessControlRequestHeaders(value)); // Step 6 - let preflight = Rc::new(preflight); - let response = http_network_or_cache_fetch(preflight.clone(), false, false, &mut None, context); + let response = http_network_or_cache_fetch(&mut preflight, false, false, &mut None, context); // Step 7 - if cors_check(request.clone(), &response).is_ok() && + if cors_check(&request, &response).is_ok() && response.status.map_or(false, |status| status.is_success()) { // Substep 1 let mut methods = if response.headers.has::() { @@ -1264,23 +1258,21 @@ fn cors_preflight_fetch(request: Rc, // Substep 4 if methods.is_empty() && request.use_cors_preflight { - methods = vec![request.method.borrow().clone()]; + methods = vec![request.method.clone()]; } // Substep 5 debug!("CORS check: Allowed methods: {:?}, current method: {:?}", - methods, request.method.borrow()); - if methods.iter().all(|method| *method != *request.method.borrow()) && - !is_simple_method(&*request.method.borrow()) { + methods, request.method); + if methods.iter().all(|method| *method != request.method) && + !is_simple_method(&request.method) { return Response::network_error(NetworkError::Internal("CORS method check failed".into())); } // Substep 6 - debug!("CORS check: Allowed headers: {:?}, current headers: {:?}", - header_names, request.headers.borrow()); + debug!("CORS check: Allowed headers: {:?}, current headers: {:?}", header_names, request.headers); let set: HashSet<&UniCase> = HashSet::from_iter(header_names.iter()); - if request.headers.borrow().iter().any(|ref hv| !set.contains(&UniCase(hv.name().to_owned())) && - !is_simple_header(hv)) { + if request.headers.iter().any(|ref hv| !set.contains(&UniCase(hv.name().to_owned())) && !is_simple_header(hv)) { return Response::network_error(NetworkError::Internal("CORS headers check failed".into())); } @@ -1308,7 +1300,7 @@ fn cors_preflight_fetch(request: Rc, } /// [CORS check](https://fetch.spec.whatwg.org#concept-cors-check) -fn cors_check(request: Rc, response: &Response) -> Result<(), ()> { +fn cors_check(request: &Request, response: &Response) -> Result<(), ()> { // Step 1 let origin = response.headers.get::().cloned(); @@ -1328,7 +1320,7 @@ fn cors_check(request: Rc, response: &Response) -> Result<(), ()> { _ => return Err(()) }; - match *request.origin.borrow() { + match request.origin { Origin::Origin(ref o) if o.ascii_serialization() == origin => {}, _ => return Err(()) } diff --git a/components/net/lib.rs b/components/net/lib.rs index 648118d10c0..34018dc6a65 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -42,7 +42,7 @@ extern crate websocket; mod blob_loader; mod chrome_loader; -mod connector; +pub mod connector; pub mod cookie; pub mod cookie_storage; mod data_loader; diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index acf1d1e80da..987f085855b 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -33,7 +33,6 @@ use std::fs::File; use std::io::prelude::*; use std::ops::Deref; use std::path::{Path, PathBuf}; -use std::rc::Rc; use std::sync::{Arc, RwLock}; use std::sync::mpsc::Sender; use std::thread; @@ -44,9 +43,7 @@ const TFD_PROVIDER: &'static TFDProvider = &TFDProvider; #[derive(Clone)] pub struct ResourceGroup { - cookie_jar: Arc>, - auth_cache: Arc>, - hsts_list: Arc>, + http_state: Arc, ssl_client: OpensslClient, connector: Arc>, } @@ -106,18 +103,19 @@ fn create_resource_groups(config_dir: Option<&Path>) read_json_from_file(&mut hsts_list, config_dir, "hsts_list.json"); read_json_from_file(&mut cookie_jar, config_dir, "cookie_jar.json"); } + let http_state = HttpState { + cookie_jar: RwLock::new(cookie_jar), + auth_cache: RwLock::new(auth_cache), + hsts_list: RwLock::new(hsts_list), + }; let ssl_client = create_ssl_client("certs"); let resource_group = ResourceGroup { - cookie_jar: Arc::new(RwLock::new(cookie_jar)), - auth_cache: Arc::new(RwLock::new(auth_cache)), - hsts_list: Arc::new(RwLock::new(hsts_list.clone())), + http_state: Arc::new(http_state), ssl_client: ssl_client.clone(), connector: create_http_connector(ssl_client.clone()), }; let private_resource_group = ResourceGroup { - cookie_jar: Arc::new(RwLock::new(CookieStorage::new(150))), - auth_cache: Arc::new(RwLock::new(AuthCache::new())), - hsts_list: Arc::new(RwLock::new(HstsList::new())), + http_state: Arc::new(HttpState::new()), ssl_client: ssl_client.clone(), connector: create_http_connector(ssl_client), }; @@ -171,14 +169,14 @@ impl ResourceChannelManager { } } CoreResourceMsg::GetCookiesForUrl(url, consumer, source) => { - let mut cookie_jar = group.cookie_jar.write().unwrap(); + let mut cookie_jar = group.http_state.cookie_jar.write().unwrap(); consumer.send(cookie_jar.cookies_for_url(&url, source)).unwrap(); } CoreResourceMsg::NetworkMediator(mediator_chan) => { self.resource_manager.swmanager_chan = Some(mediator_chan) } CoreResourceMsg::GetCookiesDataForUrl(url, consumer, source) => { - let mut cookie_jar = group.cookie_jar.write().unwrap(); + let mut cookie_jar = group.http_state.cookie_jar.write().unwrap(); let cookies = cookie_jar.cookies_data_for_url(&url, source).map(Serde).collect(); consumer.send(cookies).unwrap(); } @@ -194,15 +192,15 @@ impl ResourceChannelManager { CoreResourceMsg::ToFileManager(msg) => self.resource_manager.filemanager.handle(msg, TFD_PROVIDER), CoreResourceMsg::Exit(sender) => { if let Some(ref config_dir) = self.config_dir { - match group.auth_cache.read() { + match group.http_state.auth_cache.read() { Ok(auth_cache) => write_json_to_file(&*auth_cache, config_dir, "auth_cache.json"), Err(_) => warn!("Error writing auth cache to disk"), } - match group.cookie_jar.read() { + match group.http_state.cookie_jar.read() { Ok(jar) => write_json_to_file(&*jar, config_dir, "cookie_jar.json"), Err(_) => warn!("Error writing cookie jar to disk"), } - match group.hsts_list.read() { + match group.http_state.hsts_list.read() { Ok(hsts) => write_json_to_file(&*hsts, config_dir, "hsts_list.json"), Err(_) => warn!("Error writing hsts list to disk"), } @@ -318,7 +316,7 @@ impl CoreResourceManager { source: CookieSource, resource_group: &ResourceGroup) { if let Some(cookie) = cookie::Cookie::new_wrapped(cookie, request, source) { - let mut cookie_jar = resource_group.cookie_jar.write().unwrap(); + let mut cookie_jar = resource_group.http_state.cookie_jar.write().unwrap(); cookie_jar.push(cookie, request, source) } } @@ -327,19 +325,15 @@ impl CoreResourceManager { init: RequestInit, mut sender: IpcSender, group: &ResourceGroup) { - let http_state = HttpState { - hsts_list: group.hsts_list.clone(), - cookie_jar: group.cookie_jar.clone(), - auth_cache: group.auth_cache.clone(), - // FIXME(#15694): use group.connector.clone() instead. - connector_pool: create_http_connector(group.ssl_client.clone()), - }; + let http_state = group.http_state.clone(); let ua = self.user_agent.clone(); let dc = self.devtools_chan.clone(); let filemanager = self.filemanager.clone(); + // FIXME(#15694): use group.connector.clone() instead. + let connector = create_http_connector(group.ssl_client.clone()); thread::Builder::new().name(format!("fetch thread for {}", init.url)).spawn(move || { - let request = Request::from_init(init); + let mut request = Request::from_init(init); // XXXManishearth: Check origin against pipeline id (also ensure that the mode is allowed) // todo load context / mimesniff in fetch // todo referrer policy? @@ -349,8 +343,9 @@ impl CoreResourceManager { user_agent: ua, devtools_chan: dc, filemanager: filemanager, + connector: connector, }; - fetch(Rc::new(request), &mut sender, &context); + fetch(&mut request, &mut sender, &context); }).expect("Thread spawning failed"); } @@ -360,6 +355,6 @@ impl CoreResourceManager { resource_grp: &ResourceGroup) { websocket_loader::init(connect, connect_data, - resource_grp.cookie_jar.clone()); + resource_grp.http_state.clone()); } } diff --git a/components/net/websocket_loader.rs b/components/net/websocket_loader.rs index c4670d6b727..948a2261c60 100644 --- a/components/net/websocket_loader.rs +++ b/components/net/websocket_loader.rs @@ -6,7 +6,7 @@ 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::{is_redirect_status, set_request_cookies}; +use http_loader::{HttpState, is_redirect_status, 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}; @@ -35,12 +35,12 @@ use websocket::sender::Sender; pub fn init(connect: WebSocketCommunicate, connect_data: WebSocketConnectData, - cookie_jar: Arc>) { + http_state: Arc) { thread::Builder::new().name(format!("WebSocket connection to {}", connect_data.resource_url)).spawn(move || { let channel = establish_a_websocket_connection(&connect_data.resource_url, connect_data.origin, connect_data.protocols, - cookie_jar); + &http_state.cookie_jar); 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 +150,7 @@ fn obtain_a_websocket_connection(url: &ServoUrl) -> Result fn establish_a_websocket_connection(resource_url: &ServoUrl, origin: String, protocols: Vec, - cookie_jar: Arc>) + cookie_jar: &RwLock) -> Result<(Option, Sender, Receiver), @@ -272,7 +272,7 @@ struct Response { fn fetch(url: &ServoUrl, origin: String, mut headers: Headers, - cookie_jar: Arc>) + cookie_jar: &RwLock) -> Result { // Step 1. // TODO: handle request's window. @@ -323,7 +323,7 @@ fn fetch(url: &ServoUrl, fn main_fetch(url: &ServoUrl, origin: String, mut headers: Headers, - cookie_jar: Arc>) + cookie_jar: &RwLock) -> Result { // Step 1. let mut response = None; @@ -404,7 +404,7 @@ fn main_fetch(url: &ServoUrl, fn basic_fetch(url: &ServoUrl, origin: String, headers: &mut Headers, - cookie_jar: Arc>) + cookie_jar: &RwLock) -> Result { // In the case of a WebSocket request, HTTP fetch is always used. http_fetch(url, origin, headers, cookie_jar) @@ -414,7 +414,7 @@ fn basic_fetch(url: &ServoUrl, fn http_fetch(url: &ServoUrl, origin: String, headers: &mut Headers, - cookie_jar: Arc>) + cookie_jar: &RwLock) -> Result { // Step 1. // Not applicable: with step 3 being useless here, this one is too. @@ -464,7 +464,7 @@ fn http_fetch(url: &ServoUrl, fn http_network_or_cache_fetch(url: &ServoUrl, origin: String, headers: &mut Headers, - cookie_jar: Arc>) + cookie_jar: &RwLock) -> Result { // Steps 1-3. // Not applicable: we don't even have a request yet, and there is no body @@ -569,7 +569,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: Arc>) + cookie_jar: &RwLock) -> Result { // Step 1. // Not applicable: credentials flag is set. diff --git a/components/net_traits/request.rs b/components/net_traits/request.rs index 7178ec8ca99..c2c58ff1694 100644 --- a/components/net_traits/request.rs +++ b/components/net_traits/request.rs @@ -7,7 +7,6 @@ use hyper::header::Headers; use hyper::method::Method; use msg::constellation_msg::PipelineId; use servo_url::{ImmutableOrigin, ServoUrl}; -use std::cell::{Cell, RefCell}; use std::default::Default; /// An [initiator](https://fetch.spec.whatwg.org/#concept-request-initiator) @@ -191,42 +190,42 @@ impl Default for RequestInit { #[derive(Clone, HeapSizeOf)] pub struct Request { #[ignore_heap_size_of = "Defined in hyper"] - pub method: RefCell, + pub method: Method, pub local_urls_only: bool, pub sandboxed_storage_area_urls: bool, #[ignore_heap_size_of = "Defined in hyper"] - pub headers: RefCell, + pub headers: Headers, pub unsafe_request: bool, - pub body: RefCell>>, + pub body: Option>, // TODO: client object pub is_service_worker_global_scope: bool, - pub window: Cell, + pub window: Window, // TODO: target browsing context - pub keep_alive: Cell, - pub skip_service_worker: Cell, + pub keep_alive: bool, + pub skip_service_worker: bool, pub initiator: Initiator, pub type_: Type, pub destination: Destination, // TODO: priority object - pub origin: RefCell, - pub omit_origin_header: Cell, + pub origin: Origin, + pub omit_origin_header: bool, /// https://fetch.spec.whatwg.org/#concept-request-referrer - pub referrer: RefCell, - pub referrer_policy: Cell>, - pub pipeline_id: Cell>, + pub referrer: Referrer, + pub referrer_policy: Option, + pub pipeline_id: Option, pub synchronous: bool, pub mode: RequestMode, pub use_cors_preflight: bool, pub credentials_mode: CredentialsMode, pub use_url_credentials: bool, - pub cache_mode: Cell, - pub redirect_mode: Cell, - pub integrity_metadata: RefCell, + pub cache_mode: CacheMode, + pub redirect_mode: RedirectMode, + pub integrity_metadata: String, // Use the last method on url_list to act as spec current url field, and // first method to act as spec url field - pub url_list: RefCell>, - pub redirect_count: Cell, - pub response_tainting: Cell, + pub url_list: Vec, + pub redirect_count: u32, + pub response_tainting: ResponseTainting, } impl Request { @@ -236,35 +235,35 @@ impl Request { pipeline_id: Option) -> Request { Request { - method: RefCell::new(Method::Get), + method: Method::Get, local_urls_only: false, sandboxed_storage_area_urls: false, - headers: RefCell::new(Headers::new()), + headers: Headers::new(), unsafe_request: false, - body: RefCell::new(None), + body: None, is_service_worker_global_scope: is_service_worker_global_scope, - window: Cell::new(Window::Client), - keep_alive: Cell::new(false), - skip_service_worker: Cell::new(false), + window: Window::Client, + keep_alive: false, + skip_service_worker: false, initiator: Initiator::None, type_: Type::None, destination: Destination::None, - origin: RefCell::new(origin.unwrap_or(Origin::Client)), - omit_origin_header: Cell::new(false), - referrer: RefCell::new(Referrer::Client), - referrer_policy: Cell::new(None), - pipeline_id: Cell::new(pipeline_id), + origin: origin.unwrap_or(Origin::Client), + omit_origin_header: false, + referrer: Referrer::Client, + referrer_policy: None, + pipeline_id: pipeline_id, synchronous: false, mode: RequestMode::NoCors, use_cors_preflight: false, credentials_mode: CredentialsMode::Omit, use_url_credentials: false, - cache_mode: Cell::new(CacheMode::Default), - redirect_mode: Cell::new(RedirectMode::Follow), - integrity_metadata: RefCell::new(String::new()), - url_list: RefCell::new(vec![url]), - redirect_count: Cell::new(0), - response_tainting: Cell::new(ResponseTainting::Basic), + cache_mode: CacheMode::Default, + redirect_mode: RedirectMode::Follow, + integrity_metadata: String::new(), + url_list: vec![url], + redirect_count: 0, + response_tainting: ResponseTainting::Basic, } } @@ -273,10 +272,10 @@ impl Request { Some(Origin::Origin(init.origin.origin())), false, init.pipeline_id); - *req.method.borrow_mut() = init.method; - *req.headers.borrow_mut() = init.headers; + req.method = init.method; + req.headers = init.headers; req.unsafe_request = init.unsafe_request; - *req.body.borrow_mut() = init.body; + req.body = init.body; req.type_ = init.type_; req.destination = init.destination; req.synchronous = init.synchronous; @@ -284,25 +283,25 @@ impl Request { req.use_cors_preflight = init.use_cors_preflight; req.credentials_mode = init.credentials_mode; req.use_url_credentials = init.use_url_credentials; - req.cache_mode.set(init.cache_mode); - *req.referrer.borrow_mut() = if let Some(url) = init.referrer_url { + req.cache_mode = init.cache_mode; + req.referrer = if let Some(url) = init.referrer_url { Referrer::ReferrerUrl(url) } else { Referrer::NoReferrer }; - req.referrer_policy.set(init.referrer_policy); - req.pipeline_id.set(init.pipeline_id); - req.redirect_mode.set(init.redirect_mode); - *req.integrity_metadata.borrow_mut() = init.integrity_metadata; + req.referrer_policy = init.referrer_policy; + req.pipeline_id = init.pipeline_id; + req.redirect_mode = init.redirect_mode; + req.integrity_metadata = init.integrity_metadata; req } pub fn url(&self) -> ServoUrl { - self.url_list.borrow().first().unwrap().clone() + self.url_list.first().unwrap().clone() } pub fn current_url(&self) -> ServoUrl { - self.url_list.borrow().last().unwrap().clone() + self.url_list.last().unwrap().clone() } pub fn is_navigation_request(&self) -> bool { diff --git a/components/net_traits/response.rs b/components/net_traits/response.rs index 57abad46a01..7d0bfe57000 100644 --- a/components/net_traits/response.rs +++ b/components/net_traits/response.rs @@ -10,7 +10,6 @@ use hyper::status::StatusCode; use hyper_serde::Serde; use servo_url::ServoUrl; use std::ascii::AsciiExt; -use std::cell::{Cell, RefCell}; use std::sync::{Arc, Mutex}; /// [Response type](https://fetch.spec.whatwg.org/#concept-response-type) @@ -81,7 +80,7 @@ pub struct Response { pub response_type: ResponseType, pub termination_reason: Option, url: Option, - pub url_list: RefCell>, + pub url_list: Vec, /// `None` can be considered a StatusCode of `0`. #[ignore_heap_size_of = "Defined in hyper"] pub status: Option, @@ -97,7 +96,7 @@ pub struct Response { /// is a filtered response pub internal_response: Option>, /// whether or not to try to return the internal_response when asked for actual_response - pub return_internal: Cell, + pub return_internal: bool, } impl Response { @@ -106,7 +105,7 @@ impl Response { response_type: ResponseType::Default, termination_reason: None, url: Some(url), - url_list: RefCell::new(Vec::new()), + url_list: vec![], status: Some(StatusCode::Ok), raw_status: Some((200, b"OK".to_vec())), headers: Headers::new(), @@ -115,7 +114,7 @@ impl Response { https_state: HttpsState::None, referrer: None, internal_response: None, - return_internal: Cell::new(true), + return_internal: true, } } @@ -124,7 +123,7 @@ impl Response { response_type: ResponseType::Error(e), termination_reason: None, url: None, - url_list: RefCell::new(vec![]), + url_list: vec![], status: None, raw_status: None, headers: Headers::new(), @@ -133,7 +132,7 @@ impl Response { https_state: HttpsState::None, referrer: None, internal_response: None, - return_internal: Cell::new(true), + return_internal: true, } } @@ -156,15 +155,23 @@ impl Response { } pub fn actual_response(&self) -> &Response { - if self.return_internal.get() && self.internal_response.is_some() { + if self.return_internal && self.internal_response.is_some() { &**self.internal_response.as_ref().unwrap() } else { self } } + pub fn actual_response_mut(&mut self) -> &mut Response { + if self.return_internal && self.internal_response.is_some() { + &mut **self.internal_response.as_mut().unwrap() + } else { + self + } + } + pub fn to_actual(self) -> Response { - if self.return_internal.get() && self.internal_response.is_some() { + if self.return_internal && self.internal_response.is_some() { *self.internal_response.unwrap() } else { self @@ -226,7 +233,7 @@ impl Response { }, ResponseType::Opaque => { - response.url_list = RefCell::new(vec![]); + response.url_list = vec![]; response.url = None; response.headers = Headers::new(); response.status = None; diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs index a6ba6700533..acbd5758bed 100644 --- a/components/script/dom/request.rs +++ b/components/script/dom/request.rs @@ -158,9 +158,9 @@ impl Request { request.method = temporary_request.method; request.headers = temporary_request.headers.clone(); request.unsafe_request = true; - request.window.set(window); + request.window = window; // TODO: `entry settings object` is not implemented in Servo yet. - *request.origin.borrow_mut() = Origin::Client; + request.origin = Origin::Client; request.omit_origin_header = temporary_request.omit_origin_header; request.referrer = temporary_request.referrer; request.referrer_policy = temporary_request.referrer_policy; @@ -187,11 +187,11 @@ impl Request { request.mode = NetTraitsRequestMode::SameOrigin; } // Step 13.2 - request.omit_origin_header.set(false); + request.omit_origin_header = false; // Step 13.3 - *request.referrer.borrow_mut() = NetTraitsRequestReferrer::Client; + request.referrer = NetTraitsRequestReferrer::Client; // Step 13.4 - request.referrer_policy.set(None); + request.referrer_policy = None; } // Step 14 @@ -200,7 +200,7 @@ impl Request { let ref referrer = init_referrer.0; // Step 14.2 if referrer.is_empty() { - *request.referrer.borrow_mut() = NetTraitsRequestReferrer::NoReferrer; + request.referrer = NetTraitsRequestReferrer::NoReferrer; } else { // Step 14.3 let parsed_referrer = base_url.join(referrer); @@ -215,10 +215,10 @@ impl Request { parsed_referrer.scheme() == "about" && parsed_referrer.path() == "client") || parsed_referrer.origin() != origin { - *request.referrer.borrow_mut() = NetTraitsRequestReferrer::Client; + request.referrer = NetTraitsRequestReferrer::Client; } else { // Step 14.6 - *request.referrer.borrow_mut() = NetTraitsRequestReferrer::ReferrerUrl(parsed_referrer); + request.referrer = NetTraitsRequestReferrer::ReferrerUrl(parsed_referrer); } } } @@ -227,7 +227,7 @@ impl Request { // Step 15 if let Some(init_referrerpolicy) = init.referrerPolicy.as_ref() { let init_referrer_policy = init_referrerpolicy.clone().into(); - request.referrer_policy.set(Some(init_referrer_policy)); + request.referrer_policy = Some(init_referrer_policy); } // Step 16 @@ -254,11 +254,11 @@ impl Request { // Step 21 if let Some(init_cache) = init.cache.as_ref() { let cache = init_cache.clone().into(); - request.cache_mode.set(cache); + request.cache_mode = cache; } // Step 22 - if request.cache_mode.get() == NetTraitsRequestCache::OnlyIfCached { + if request.cache_mode == NetTraitsRequestCache::OnlyIfCached { if request.mode != NetTraitsRequestMode::SameOrigin { return Err(Error::Type( "Cache is 'only-if-cached' and mode is not 'same-origin'".to_string())); @@ -268,13 +268,13 @@ impl Request { // Step 23 if let Some(init_redirect) = init.redirect.as_ref() { let redirect = init_redirect.clone().into(); - request.redirect_mode.set(redirect); + request.redirect_mode = redirect; } // Step 24 if let Some(init_integrity) = init.integrity.as_ref() { let integrity = init_integrity.clone().to_string(); - *request.integrity_metadata.borrow_mut() = integrity; + request.integrity_metadata = integrity; } // Step 25 @@ -292,7 +292,7 @@ impl Request { None => return Err(Error::Type("Method is not a valid UTF8".to_string())), }; // Step 25.3 - *request.method.borrow_mut() = method; + request.method = method; } // Step 26 @@ -334,12 +334,12 @@ impl Request { if r.request.borrow().mode == NetTraitsRequestMode::NoCors { let borrowed_request = r.request.borrow(); // Step 30.1 - if !is_cors_safelisted_method(&borrowed_request.method.borrow()) { + if !is_cors_safelisted_method(&borrowed_request.method) { return Err(Error::Type( "The mode is 'no-cors' but the method is not a cors-safelisted method".to_string())); } // Step 30.2 - if !borrowed_request.integrity_metadata.borrow().is_empty() { + if !borrowed_request.integrity_metadata.is_empty() { return Err(Error::Type("Integrity metadata is not an empty string".to_string())); } // Step 30.3 @@ -364,8 +364,7 @@ impl Request { // Step 32 let mut input_body = if let RequestInfo::Request(ref input_request) = input { let input_request_request = input_request.request.borrow(); - let body = input_request_request.body.borrow(); - body.clone() + input_request_request.body.clone() } else { None }; @@ -374,11 +373,11 @@ impl Request { if let Some(init_body_option) = init.body.as_ref() { if init_body_option.is_some() || input_body.is_some() { let req = r.request.borrow(); - let req_method = req.method.borrow(); - match &*req_method { - &HttpMethod::Get => return Err(Error::Type( + 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( + HttpMethod::Head => return Err(Error::Type( "Init's body is non-null, and request method is HEAD".to_string())), _ => {}, } @@ -402,10 +401,7 @@ impl Request { } // Step 35 - { - let borrowed_request = r.request.borrow(); - *borrowed_request.body.borrow_mut() = input_body; - } + r.request.borrow_mut().body = input_body; // Step 36 let extracted_mime_type = r.Headers().extract_mime_type(); @@ -445,10 +441,10 @@ impl Request { let mime_type = r.mime_type.borrow().clone(); let headers_guard = r.Headers().get_guard(); let r_clone = Request::new(&r.global(), url, is_service_worker_global_scope); - r_clone.request.borrow_mut().pipeline_id.set(req.pipeline_id.get()); + r_clone.request.borrow_mut().pipeline_id = req.pipeline_id; { let mut borrowed_r_request = r_clone.request.borrow_mut(); - *borrowed_r_request.origin.borrow_mut() = req.origin.borrow().clone(); + borrowed_r_request.origin = req.origin.clone(); } *r_clone.request.borrow_mut() = req.clone(); r_clone.body_used.set(body_used); @@ -540,15 +536,13 @@ impl RequestMethods for Request { // https://fetch.spec.whatwg.org/#dom-request-method fn Method(&self) -> ByteString { let r = self.request.borrow(); - let m = r.method.borrow(); - ByteString::new(m.as_ref().as_bytes().into()) + ByteString::new(r.method.as_ref().as_bytes().into()) } // https://fetch.spec.whatwg.org/#dom-request-url fn Url(&self) -> USVString { let r = self.request.borrow(); - let url = r.url_list.borrow(); - USVString(url.get(0).map_or("", |u| u.as_str()).into()) + USVString(r.url_list.get(0).map_or("", |u| u.as_str()).into()) } // https://fetch.spec.whatwg.org/#dom-request-headers @@ -569,11 +563,10 @@ impl RequestMethods for Request { // https://fetch.spec.whatwg.org/#dom-request-referrer fn Referrer(&self) -> USVString { let r = self.request.borrow(); - let referrer = r.referrer.borrow(); - USVString(match &*referrer { - &NetTraitsRequestReferrer::NoReferrer => String::from("no-referrer"), - &NetTraitsRequestReferrer::Client => String::from("about:client"), - &NetTraitsRequestReferrer::ReferrerUrl(ref u) => { + USVString(match r.referrer { + NetTraitsRequestReferrer::NoReferrer => String::from("no-referrer"), + NetTraitsRequestReferrer::Client => String::from("about:client"), + NetTraitsRequestReferrer::ReferrerUrl(ref u) => { let u_c = u.clone(); u_c.into_string() } @@ -582,7 +575,7 @@ impl RequestMethods for Request { // https://fetch.spec.whatwg.org/#dom-request-referrerpolicy fn ReferrerPolicy(&self) -> ReferrerPolicy { - self.request.borrow().referrer_policy.get().map(|m| m.into()).unwrap_or(ReferrerPolicy::_empty) + self.request.borrow().referrer_policy.map(|m| m.into()).unwrap_or(ReferrerPolicy::_empty) } // https://fetch.spec.whatwg.org/#dom-request-mode @@ -599,20 +592,19 @@ impl RequestMethods for Request { // https://fetch.spec.whatwg.org/#dom-request-cache fn Cache(&self) -> RequestCache { let r = self.request.borrow().clone(); - r.cache_mode.get().into() + r.cache_mode.into() } // https://fetch.spec.whatwg.org/#dom-request-redirect fn Redirect(&self) -> RequestRedirect { let r = self.request.borrow().clone(); - r.redirect_mode.get().into() + r.redirect_mode.into() } // https://fetch.spec.whatwg.org/#dom-request-integrity fn Integrity(&self) -> DOMString { let r = self.request.borrow(); - let integrity = r.integrity_metadata.borrow(); - DOMString::from_string(integrity.clone()) + DOMString::from_string(r.integrity_metadata.clone()) } // https://fetch.spec.whatwg.org/#dom-body-bodyused @@ -675,8 +667,8 @@ impl BodyOperations for Request { } fn take_body(&self) -> Option> { - let request = self.request.borrow_mut(); - let body = request.body.borrow_mut().take(); + let mut request = self.request.borrow_mut(); + let body = request.body.take(); Some(body.unwrap_or(vec![])) } diff --git a/components/script/fetch.rs b/components/script/fetch.rs index 0e7cacdfc1a..39c5cbc8f97 100644 --- a/components/script/fetch.rs +++ b/components/script/fetch.rs @@ -37,17 +37,16 @@ struct FetchContext { } fn from_referrer_to_referrer_url(request: &NetTraitsRequest) -> Option { - let referrer = request.referrer.borrow(); - referrer.to_url().map(|url| url.clone()) + request.referrer.to_url().map(|url| url.clone()) } fn request_init_from_request(request: NetTraitsRequest) -> NetTraitsRequestInit { NetTraitsRequestInit { - method: request.method.borrow().clone(), + method: request.method.clone(), url: request.url(), - headers: request.headers.borrow().clone(), + headers: request.headers.clone(), unsafe_request: request.unsafe_request, - body: request.body.borrow().clone(), + body: request.body.clone(), type_: request.type_, destination: request.destination, synchronous: request.synchronous, @@ -60,9 +59,9 @@ fn request_init_from_request(request: NetTraitsRequest) -> NetTraitsRequestInit // ... NetTraitsRequest.origin: RefCell origin: request.url(), referrer_url: from_referrer_to_referrer_url(&request), - referrer_policy: request.referrer_policy.get(), - pipeline_id: request.pipeline_id.get(), - redirect_mode: request.redirect_mode.get(), + referrer_policy: request.referrer_policy, + pipeline_id: request.pipeline_id, + redirect_mode: request.redirect_mode, ..NetTraitsRequestInit::default() } } diff --git a/tests/unit/net/data_loader.rs b/tests/unit/net/data_loader.rs index 0cf0726c296..409757ee61f 100644 --- a/tests/unit/net/data_loader.rs +++ b/tests/unit/net/data_loader.rs @@ -19,9 +19,9 @@ fn assert_parse(url: &'static str, data: Option<&[u8]>) { let url = ServoUrl::parse(url).unwrap(); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); + let mut request = Request::new(url, Some(origin), false, None); - let response = fetch(request, None); + let response = fetch(&mut request, None); match data { Some(data) => { diff --git a/tests/unit/net/fetch.rs b/tests/unit/net/fetch.rs index f7342a576eb..73be2a5fbbd 100644 --- a/tests/unit/net/fetch.rs +++ b/tests/unit/net/fetch.rs @@ -23,6 +23,7 @@ use hyper::status::StatusCode; use hyper::uri::RequestUri; use hyper_openssl; use msg::constellation_msg::TEST_PIPELINE_ID; +use net::connector::{create_http_connector, create_ssl_client}; use net::fetch::cors_cache::CorsCache; use net::fetch::methods::FetchContext; use net::filemanager_thread::FileManager; @@ -37,7 +38,6 @@ use servo_config::resource_files::resources_dir_path; use servo_url::{ImmutableOrigin, ServoUrl}; use std::fs::File; use std::io::Read; -use std::rc::Rc; use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::{Sender, channel}; @@ -55,9 +55,9 @@ fn test_fetch_response_is_not_network_error() { let (mut server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + let fetch_response = fetch(&mut request, None); let _ = server.close(); if fetch_response.is_network_error() { @@ -69,9 +69,9 @@ fn test_fetch_response_is_not_network_error() { fn test_fetch_on_bad_port_is_network_error() { let url = ServoUrl::parse("http://www.example.org:6667").unwrap(); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + let fetch_response = fetch(&mut request, None); assert!(fetch_response.is_network_error()); let fetch_error = fetch_response.get_network_error().unwrap(); assert!(fetch_error == &NetworkError::Internal("Request attempted on bad port".into())) @@ -86,9 +86,9 @@ fn test_fetch_response_body_matches_const_message() { let (mut server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + let fetch_response = fetch(&mut request, None); let _ = server.close(); assert!(!fetch_response.is_network_error()); @@ -106,9 +106,9 @@ fn test_fetch_response_body_matches_const_message() { fn test_fetch_aboutblank() { let url = ServoUrl::parse("about:blank").unwrap(); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + let fetch_response = fetch(&mut request, None); assert!(!fetch_response.is_network_error()); assert!(*fetch_response.body.lock().unwrap() == ResponseBody::Done(vec![])); } @@ -136,8 +136,8 @@ fn test_fetch_blob() { let url = ServoUrl::parse(&format!("blob:{}{}", origin.as_str(), id.simple())).unwrap(); - let request = Request::new(url, Some(Origin::Origin(origin.origin())), false, None); - let fetch_response = fetch_with_context(request, &context); + let mut request = Request::new(url, Some(Origin::Origin(origin.origin())), false, None); + let fetch_response = fetch_with_context(&mut request, &context); assert!(!fetch_response.is_network_error()); @@ -160,9 +160,9 @@ fn test_fetch_file() { let url = ServoUrl::from_file_path(path.clone()).unwrap(); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); + let mut request = Request::new(url, Some(origin), false, None); - let fetch_response = fetch(request, None); + 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(); @@ -185,9 +185,9 @@ fn test_fetch_file() { fn test_fetch_ftp() { let url = ServoUrl::parse("ftp://not-supported").unwrap(); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + let fetch_response = fetch(&mut request, None); assert!(fetch_response.is_network_error()); } @@ -195,9 +195,9 @@ fn test_fetch_ftp() { fn test_fetch_bogus_scheme() { let url = ServoUrl::parse("bogus://whatever").unwrap(); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + let fetch_response = fetch(&mut request, None); assert!(fetch_response.is_network_error()); } @@ -224,11 +224,11 @@ fn test_cors_preflight_fetch() { let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let mut request = Request::new(url.clone(), Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::ReferrerUrl(target_url); - *request.referrer_policy.get_mut() = Some(ReferrerPolicy::Origin); + request.referrer = Referrer::ReferrerUrl(target_url); + request.referrer_policy = Some(ReferrerPolicy::Origin); request.use_cors_preflight = true; request.mode = RequestMode::CorsMode; - let fetch_response = fetch(request, None); + let fetch_response = fetch(&mut request, None); let _ = server.close(); assert!(!fetch_response.is_network_error()); @@ -261,14 +261,14 @@ fn test_cors_preflight_cache_fetch() { let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let mut request = Request::new(url.clone(), Some(origin.clone()), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; + request.referrer = Referrer::NoReferrer; request.use_cors_preflight = true; request.mode = RequestMode::CorsMode; - let wrapped_request0 = Rc::new(request.clone()); - let wrapped_request1 = Rc::new(request); + let mut wrapped_request0 = request.clone(); + let mut wrapped_request1 = request; - let fetch_response0 = fetch_with_cors_cache(wrapped_request0.clone(), &mut cache); - let fetch_response1 = fetch_with_cors_cache(wrapped_request1.clone(), &mut cache); + let fetch_response0 = fetch_with_cors_cache(&mut wrapped_request0, &mut cache); + let fetch_response1 = fetch_with_cors_cache(&mut wrapped_request1, &mut cache); let _ = server.close(); assert!(!fetch_response0.is_network_error() && !fetch_response1.is_network_error()); @@ -277,8 +277,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), @@ -310,11 +310,11 @@ fn test_cors_preflight_fetch_network_error() { let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let mut request = Request::new(url, Some(origin), false, None); - *request.method.borrow_mut() = Method::Extension("CHICKEN".to_owned()); - *request.referrer.borrow_mut() = Referrer::NoReferrer; + request.method = Method::Extension("CHICKEN".to_owned()); + request.referrer = Referrer::NoReferrer; request.use_cors_preflight = true; request.mode = RequestMode::CorsMode; - let fetch_response = fetch(request, None); + let fetch_response = fetch(&mut request, None); let _ = server.close(); assert!(fetch_response.is_network_error()); @@ -333,9 +333,9 @@ fn test_fetch_response_is_basic_filtered() { let (mut server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + let fetch_response = fetch(&mut request, None); let _ = server.close(); assert!(!fetch_response.is_network_error()); @@ -379,9 +379,9 @@ fn test_fetch_response_is_cors_filtered() { // an origin mis-match will stop it from defaulting to a basic filtered response let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let mut request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; + request.referrer = Referrer::NoReferrer; request.mode = RequestMode::CorsMode; - let fetch_response = fetch(request, None); + let fetch_response = fetch(&mut request, None); let _ = server.close(); assert!(!fetch_response.is_network_error()); @@ -410,16 +410,16 @@ fn test_fetch_response_is_opaque_filtered() { // an origin mis-match will fall through to an Opaque filtered response let origin = Origin::Origin(ImmutableOrigin::new_opaque()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + let fetch_response = fetch(&mut request, None); let _ = server.close(); assert!(!fetch_response.is_network_error()); assert_eq!(fetch_response.response_type, ResponseType::Opaque); assert!(fetch_response.url().is_none()); - assert!(fetch_response.url_list.into_inner().len() == 0); + 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()); @@ -457,10 +457,10 @@ fn test_fetch_response_is_opaque_redirect_filtered() { let (mut server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - request.redirect_mode.set(RedirectMode::Manual); - let fetch_response = fetch(request, None); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + request.redirect_mode = RedirectMode::Manual; + let fetch_response = fetch(&mut request, None); let _ = server.close(); assert!(!fetch_response.is_network_error()); @@ -492,12 +492,12 @@ fn test_fetch_with_local_urls_only() { let do_fetch = |url: ServoUrl| { let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; + request.referrer = Referrer::NoReferrer; // Set the flag. request.local_urls_only = true; - fetch(request, None) + fetch(&mut request, None) }; let local_url = ServoUrl::parse("about:blank").unwrap(); @@ -530,11 +530,15 @@ fn test_fetch_with_hsts() { //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 ssl_client = create_ssl_client("self_signed_certificate_for_testing.crt"); + let connector = create_http_connector(ssl_client); + let context = FetchContext { - state: HttpState::new("self_signed_certificate_for_testing.crt"), + state: Arc::new(HttpState::new()), user_agent: DEFAULT_USER_AGENT.into(), devtools_chan: None, filemanager: FileManager::new(), + connector: connector, }; { @@ -546,10 +550,10 @@ fn test_fetch_with_hsts() { let url = ServoUrl::parse(&url_string).unwrap(); let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; + request.referrer = Referrer::NoReferrer; // Set the flag. request.local_urls_only = false; - let response = fetch_with_context(request, &context); + let response = fetch_with_context(&mut request, &context); let _ = server.close(); assert_eq!(response.internal_response.unwrap().url().unwrap().scheme(), "https"); @@ -565,15 +569,15 @@ fn test_fetch_with_sri_network_error() { let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; + request.referrer = Referrer::NoReferrer; // To calulate hash use : // echo -n "alert('Hello, Network Error');" | openssl dgst -sha384 -binary | openssl base64 -A - *request.integrity_metadata.borrow_mut() = + request.integrity_metadata = "sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO".to_owned(); // Set the flag. request.local_urls_only = false; - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); assert!(response.is_network_error()); @@ -589,15 +593,15 @@ fn test_fetch_with_sri_sucess() { let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; + request.referrer = Referrer::NoReferrer; // To calulate hash use : // echo -n "alert('Hello, Network Error');" | openssl dgst -sha384 -binary | openssl base64 -A - *request.integrity_metadata.borrow_mut() = + request.integrity_metadata = "sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO".to_owned(); // Set the flag. request.local_urls_only = false; - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); assert_eq!(response_is_done(&response), true); @@ -629,7 +633,7 @@ fn test_fetch_blocked_nosniff() { let origin = Origin::Origin(url.origin()); let mut request = Request::new(url, Some(origin), false, None); request.type_ = request_type; - let fetch_response = fetch(request, None); + let fetch_response = fetch(&mut request, None); let _ = server.close(); assert_eq!(fetch_response.is_network_error(), should_error); @@ -669,9 +673,9 @@ fn setup_server_and_fetch(message: &'static [u8], redirect_cap: u32) -> Response let (mut server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + let fetch_response = fetch(&mut request, None); let _ = server.close(); fetch_response } @@ -752,11 +756,11 @@ fn test_fetch_redirect_updates_method_runner(tx: Sender, status_code: Stat let (mut server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - *request.method.borrow_mut() = method; + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + request.method = method; - let _ = fetch(request, None); + let _ = fetch(&mut request, None); let _ = server.close(); } @@ -827,10 +831,10 @@ fn test_fetch_async_returns_complete_response() { let (mut server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let fetch_response = fetch(&mut request, None); let _ = server.close(); assert_eq!(response_is_done(&fetch_response), true); @@ -846,10 +850,10 @@ fn test_opaque_filtered_fetch_async_returns_complete_response() { // an origin mis-match will fall through to an Opaque filtered response let origin = Origin::Origin(ImmutableOrigin::new_opaque()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; - let fetch_response = fetch(request, None); + let fetch_response = fetch(&mut request, None); let _ = server.close(); @@ -881,11 +885,11 @@ fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() { let (mut server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); - let request = Request::new(url, Some(origin), false, None); - *request.referrer.borrow_mut() = Referrer::NoReferrer; - request.redirect_mode.set(RedirectMode::Manual); + let mut request = Request::new(url, Some(origin), false, None); + request.referrer = Referrer::NoReferrer; + request.redirect_mode = RedirectMode::Manual; - let fetch_response = fetch(request, None); + let fetch_response = fetch(&mut request, None); let _ = server.close(); @@ -903,12 +907,12 @@ fn test_fetch_with_devtools() { let (mut server, url) = make_server(handler); let origin = Origin::Origin(url.origin()); - let request = Request::new(url.clone(), Some(origin), false, Some(TEST_PIPELINE_ID)); - *request.referrer.borrow_mut() = Referrer::NoReferrer; + let mut request = Request::new(url.clone(), Some(origin), false, Some(TEST_PIPELINE_ID)); + request.referrer = Referrer::NoReferrer; let (devtools_chan, devtools_port) = channel::(); - let _ = fetch(request, Some(devtools_chan)); + let _ = fetch(&mut request, Some(devtools_chan)); let _ = server.close(); // notification received from devtools diff --git a/tests/unit/net/http_loader.rs b/tests/unit/net/http_loader.rs index 4a41b3c112f..30da574875e 100644 --- a/tests/unit/net/http_loader.rs +++ b/tests/unit/net/http_loader.rs @@ -50,7 +50,7 @@ fn read_response(reader: &mut Read) -> String { } } -fn assert_cookie_for_domain(cookie_jar: Arc>, domain: &str, cookie: Option<&str>) { +fn assert_cookie_for_domain(cookie_jar: &RwLock, domain: &str, cookie: Option<&str>) { let mut cookie_jar = cookie_jar.write().unwrap(); let url = ServoUrl::parse(&*domain).unwrap(); let cookies = cookie_jar.cookies_for_url(&url, CookieSource::HTTP); @@ -134,7 +134,7 @@ fn test_check_default_headers_loaded_in_every_request() { *expected_headers.lock().unwrap() = Some(headers.clone()); // Testing for method.GET - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, destination: Destination::Document, @@ -142,7 +142,7 @@ fn test_check_default_headers_loaded_in_every_request() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); assert!(response.status.unwrap().is_success()); // Testing for method.POST @@ -153,7 +153,7 @@ fn test_check_default_headers_loaded_in_every_request() { // "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()); *expected_headers.lock().unwrap() = Some(post_headers); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Post, destination: Destination::Document, @@ -161,7 +161,7 @@ fn test_check_default_headers_loaded_in_every_request() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); assert!(response.status.unwrap().is_success()); let _ = server.close(); @@ -174,7 +174,7 @@ fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length }; let (mut server, url) = make_server(handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Post, body: None, @@ -183,7 +183,7 @@ fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); assert!(response.status.unwrap().is_success()); let _ = server.close(); @@ -199,7 +199,7 @@ fn test_request_and_response_data_with_network_messages() { let mut request_headers = Headers::new(); request_headers.set(Host { hostname: "bar.foo".to_owned(), port: None }); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, headers: request_headers, @@ -210,7 +210,7 @@ fn test_request_and_response_data_with_network_messages() { .. RequestInit::default() }); let (devtools_chan, devtools_port) = mpsc::channel(); - let response = fetch(request, Some(devtools_chan)); + let response = fetch(&mut request, Some(devtools_chan)); assert!(response.status.unwrap().is_success()); let _ = server.close(); @@ -288,7 +288,7 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() { }; let (mut server, url) = make_server(handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, destination: Destination::Document, @@ -297,7 +297,7 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() { .. RequestInit::default() }); let (devtools_chan, devtools_port) = mpsc::channel(); - let response = fetch(request, Some(devtools_chan)); + let response = fetch(&mut request, Some(devtools_chan)); assert!(response.status.unwrap().is_success()); let _ = server.close(); @@ -323,7 +323,7 @@ fn test_redirected_request_to_devtools() { }; let (mut pre_server, pre_url) = make_server(pre_handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: pre_url.clone(), method: Method::Post, destination: Destination::Document, @@ -332,7 +332,7 @@ fn test_redirected_request_to_devtools() { .. RequestInit::default() }); let (devtools_chan, devtools_port) = mpsc::channel(); - fetch(request, Some(devtools_chan)); + fetch(&mut request, Some(devtools_chan)); let _ = pre_server.close(); let _ = post_server.close(); @@ -371,7 +371,7 @@ fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() { }; let (mut pre_server, pre_url) = make_server(pre_handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: pre_url.clone(), method: Method::Post, destination: Destination::Document, @@ -379,7 +379,7 @@ fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = pre_server.close(); let _ = post_server.close(); @@ -398,7 +398,7 @@ fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_co }; let (mut server, url) = make_server(handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, body: None, @@ -407,7 +407,7 @@ fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_co pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); @@ -427,7 +427,7 @@ fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_conte }; let (mut server, url) = make_server(handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, body: None, @@ -436,7 +436,7 @@ fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_conte pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); @@ -465,7 +465,7 @@ fn test_load_doesnt_send_request_body_on_any_redirect() { }; let (mut pre_server, pre_url) = make_server(pre_handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: pre_url.clone(), body: Some(b"Body on POST!".to_vec()), method: Method::Post, @@ -474,7 +474,7 @@ fn test_load_doesnt_send_request_body_on_any_redirect() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = pre_server.close(); let _ = post_server.close(); @@ -490,7 +490,7 @@ fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_ar }; let (mut server, url) = make_server(handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, body: None, @@ -500,7 +500,7 @@ fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_ar .. RequestInit::default() }); let context = new_fetch_context(None); - let response = fetch_with_context(request, &context); + let response = fetch_with_context(&mut request, &context); let _ = server.close(); @@ -518,9 +518,9 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_ let context = new_fetch_context(None); - assert_cookie_for_domain(context.state.cookie_jar.clone(), url.as_str(), None); + assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, body: None, @@ -530,13 +530,13 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_ credentials_mode: CredentialsMode::Include, .. RequestInit::default() }); - let response = fetch_with_context(request, &context); + let response = fetch_with_context(&mut request, &context); let _ = server.close(); assert!(response.status.unwrap().is_success()); - assert_cookie_for_domain(context.state.cookie_jar.clone(), url.as_str(), Some("mozillaIs=theBest")); + assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), Some("mozillaIs=theBest")); } #[test] @@ -560,7 +560,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re cookie_jar.push(cookie, &url, CookieSource::HTTP); } - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, body: None, @@ -570,7 +570,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re credentials_mode: CredentialsMode::Include, .. RequestInit::default() }); - let response = fetch_with_context(request, &context); + let response = fetch_with_context(&mut request, &context); let _ = server.close(); @@ -598,7 +598,7 @@ fn test_load_sends_cookie_if_nonhttp() { cookie_jar.push(cookie, &url, CookieSource::HTTP); } - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, body: None, @@ -608,7 +608,7 @@ fn test_load_sends_cookie_if_nonhttp() { credentials_mode: CredentialsMode::Include, .. RequestInit::default() }); - let response = fetch_with_context(request, &context); + let response = fetch_with_context(&mut request, &context); let _ = server.close(); @@ -626,9 +626,9 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl( let context = new_fetch_context(None); - assert_cookie_for_domain(context.state.cookie_jar.clone(), url.as_str(), None); + assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, body: None, @@ -638,13 +638,13 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl( credentials_mode: CredentialsMode::Include, .. RequestInit::default() }); - let response = fetch_with_context(request, &context); + let response = fetch_with_context(&mut request, &context); let _ = server.close(); assert!(response.status.unwrap().is_success()); - assert_cookie_for_domain(context.state.cookie_jar.clone(), url.as_str(), Some("mozillaIs=theBest")); + assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), Some("mozillaIs=theBest")); let mut cookie_jar = context.state.cookie_jar.write().unwrap(); assert!(cookie_jar.cookies_for_url(&url, CookieSource::NonHTTP).is_none()); } @@ -660,9 +660,9 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() { let context = new_fetch_context(None); - assert_cookie_for_domain(context.state.cookie_jar.clone(), url.as_str(), None); + assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, body: None, @@ -672,13 +672,13 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() { credentials_mode: CredentialsMode::Include, .. RequestInit::default() }); - let response = fetch_with_context(request, &context); + let response = fetch_with_context(&mut request, &context); let _ = server.close(); assert!(response.status.unwrap().is_success()); - assert_cookie_for_domain(context.state.cookie_jar.clone(), url.as_str(), None); + assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None); } #[test] @@ -691,7 +691,7 @@ fn test_load_sets_content_length_to_length_of_request_body() { }; let (mut server, url) = make_server(handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Post, body: Some(content.to_vec()), @@ -700,7 +700,7 @@ fn test_load_sets_content_length_to_length_of_request_body() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); @@ -719,7 +719,7 @@ fn test_load_uses_explicit_accept_from_headers_in_load_data() { let mut accept_headers = Headers::new(); accept_headers.set(accept); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, headers: accept_headers, @@ -728,7 +728,7 @@ fn test_load_uses_explicit_accept_from_headers_in_load_data() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); @@ -748,7 +748,7 @@ fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() { }; let (mut server, url) = make_server(handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, destination: Destination::Document, @@ -756,7 +756,7 @@ fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); @@ -775,7 +775,7 @@ fn test_load_uses_explicit_accept_encoding_from_load_data_headers() { let mut accept_encoding_headers = Headers::new(); accept_encoding_headers.set(accept_encoding); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, headers: accept_encoding_headers, @@ -784,7 +784,7 @@ fn test_load_uses_explicit_accept_encoding_from_load_data_headers() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); @@ -803,7 +803,7 @@ fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() { }; let (mut server, url) = make_server(handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, destination: Destination::Document, @@ -811,7 +811,7 @@ fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); @@ -839,7 +839,7 @@ fn test_load_errors_when_there_a_redirect_loop() { *url_b_for_a.lock().unwrap() = Some(url_b.clone()); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url_a.clone(), method: Method::Get, destination: Destination::Document, @@ -847,7 +847,7 @@ fn test_load_errors_when_there_a_redirect_loop() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server_a.close(); let _ = server_b.close(); @@ -882,7 +882,7 @@ fn test_load_succeeds_with_a_redirect_loop() { *url_b_for_a.lock().unwrap() = Some(url_b.clone()); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url_a.clone(), method: Method::Get, destination: Destination::Document, @@ -890,14 +890,13 @@ fn test_load_succeeds_with_a_redirect_loop() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server_a.close(); let _ = server_b.close(); let response = response.to_actual(); - assert_eq!(*response.url_list.borrow(), - [url_a.clone(), url_b, url_a]); + assert_eq!(response.url_list, [url_a.clone(), url_b, url_a]); assert_eq!(*response.body.lock().unwrap(), ResponseBody::Done(b"Success".to_vec())); } @@ -919,7 +918,7 @@ fn test_load_follows_a_redirect() { }; let (mut pre_server, pre_url) = make_server(pre_handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: pre_url.clone(), method: Method::Get, destination: Destination::Document, @@ -927,7 +926,7 @@ fn test_load_follows_a_redirect() { pipeline_id: Some(TEST_PIPELINE_ID), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = pre_server.close(); let _ = post_server.close(); @@ -996,7 +995,7 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() { cookie_jar.push(cookie_y, &url_y, CookieSource::HTTP); } - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url_x.clone(), method: Method::Get, destination: Destination::Document, @@ -1005,7 +1004,7 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() { credentials_mode: CredentialsMode::Include, .. RequestInit::default() }); - let response = fetch_with_context(request, &context); + let response = fetch_with_context(&mut request, &context); let _ = server.close(); @@ -1040,7 +1039,7 @@ fn test_redirect_from_x_to_x_provides_x_with_cookie_from_first_response() { let url = url.join("/initial/").unwrap(); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, destination: Destination::Document, @@ -1049,7 +1048,7 @@ fn test_redirect_from_x_to_x_provides_x_with_cookie_from_first_response() { credentials_mode: CredentialsMode::Include, .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); @@ -1071,7 +1070,7 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() { }; let (mut server, url) = make_server(handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, body: None, @@ -1090,7 +1089,7 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() { context.state.auth_cache.write().unwrap().entries.insert(url.origin().clone().ascii_serialization(), auth_entry); - let response = fetch_with_context(request, &context); + let response = fetch_with_context(&mut request, &context); let _ = server.close(); @@ -1105,7 +1104,7 @@ fn test_auth_ui_needs_www_auth() { }; let (mut server, url) = make_server(handler); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, body: None, @@ -1116,7 +1115,7 @@ fn test_auth_ui_needs_www_auth() { .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); let _ = server.close(); @@ -1139,20 +1138,20 @@ fn test_origin_set() { let mut origin = Origin::new(url.scheme(), url.host_str().unwrap(), url.port()); *origin_header_clone.lock().unwrap() = Some(origin.clone()); - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Post, body: None, origin: url.clone(), .. RequestInit::default() }); - let response = fetch(request, None); + let response = fetch(&mut request, None); assert!(response.status.unwrap().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()); // Test Origin header is set on Get request with CORS mode - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Get, mode: RequestMode::CorsMode, @@ -1162,11 +1161,11 @@ fn test_origin_set() { }); *origin_header_clone.lock().unwrap() = Some(origin.clone()); - let response = fetch(request, None); + let response = fetch(&mut request, None); assert!(response.status.unwrap().is_success()); // Test Origin header is not set on method Head - let request = Request::from_init(RequestInit { + let mut request = Request::from_init(RequestInit { url: url.clone(), method: Method::Head, body: None, @@ -1175,7 +1174,7 @@ fn test_origin_set() { }); *origin_header_clone.lock().unwrap() = None; - let response = fetch(request, None); + let response = fetch(&mut request, None); assert!(response.status.unwrap().is_success()); let _ = server.close(); diff --git a/tests/unit/net/lib.rs b/tests/unit/net/lib.rs index a6047517dda..6326faade4d 100644 --- a/tests/unit/net/lib.rs +++ b/tests/unit/net/lib.rs @@ -34,6 +34,7 @@ extern crate url; use devtools_traits::DevtoolsControlMsg; use hyper::server::{Handler, Listening, Server}; +use net::connector::{create_http_connector, create_ssl_client}; use net::fetch::cors_cache::CorsCache; use net::fetch::methods::{self, FetchContext}; use net::filemanager_thread::FileManager; @@ -42,7 +43,7 @@ use net_traits::FetchTaskTarget; use net_traits::request::Request; use net_traits::response::Response; use servo_url::ServoUrl; -use std::rc::Rc; +use std::sync::Arc; use std::sync::mpsc::{Sender, channel}; const DEFAULT_USER_AGENT: &'static str = "Such Browser. Very Layout. Wow."; @@ -52,11 +53,14 @@ struct FetchResponseCollector { } fn new_fetch_context(dc: Option>) -> FetchContext { + let ssl_client = create_ssl_client("certs"); + let connector = create_http_connector(ssl_client); FetchContext { - state: HttpState::new("certs"), + state: Arc::new(HttpState::new()), user_agent: DEFAULT_USER_AGENT.into(), devtools_chan: dc, filemanager: FileManager::new(), + connector: connector, } } impl FetchTaskTarget for FetchResponseCollector { @@ -70,22 +74,22 @@ impl FetchTaskTarget for FetchResponseCollector { } } -fn fetch(request: Request, dc: Option>) -> Response { +fn fetch(request: &mut Request, dc: Option>) -> Response { fetch_with_context(request, &new_fetch_context(dc)) } -fn fetch_with_context(request: Request, context: &FetchContext) -> Response { +fn fetch_with_context(request: &mut Request, context: &FetchContext) -> Response { let (sender, receiver) = channel(); let mut target = FetchResponseCollector { sender: sender, }; - methods::fetch(Rc::new(request), &mut target, context); + methods::fetch(request, &mut target, context); receiver.recv().unwrap() } -fn fetch_with_cors_cache(request: Rc, cache: &mut CorsCache) -> Response { +fn fetch_with_cors_cache(request: &mut Request, cache: &mut CorsCache) -> Response { let (sender, receiver) = channel(); let mut target = FetchResponseCollector { sender: sender,