diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 7625393c582..8bd03e86e54 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -294,6 +294,32 @@ fn set_default_accept(headers: &mut Headers) { } } +#[inline(always)] +fn set_request_cookies(url: Url, headers: &mut Headers, resource_mgr_chan: &IpcSender) { + let (tx, rx) = ipc::channel().unwrap(); + resource_mgr_chan.send(ControlMsg::GetCookiesForUrl(url.clone(), + tx, + CookieSource::HTTP)).unwrap(); + if let Some(cookie_list) = rx.recv().unwrap() { + let mut v = Vec::new(); + v.push(cookie_list.into_bytes()); + headers.set_raw("Cookie".to_owned(), v); + } +} + +#[inline(always)] +fn set_cookies_from_response(url: Url, response: &HttpResponse, resource_mgr_chan: &IpcSender) { + if let Some(cookies) = response.headers().get_raw("set-cookie") { + for cookie in cookies.iter() { + if let Ok(cookies) = String::from_utf8(cookie.clone()) { + resource_mgr_chan.send(ControlMsg::SetCookiesForUrl(url.clone(), + cookies, + CookieSource::HTTP)).unwrap(); + } + } + } +} + pub fn load(mut load_data: LoadData, resource_mgr_chan: IpcSender, devtools_chan: Option>, @@ -363,17 +389,7 @@ pub fn load(mut load_data: LoadData, set_default_accept(&mut request_headers); set_default_accept_encoding(&mut request_headers); - - // --- Fetch cookies - let (tx, rx) = ipc::channel().unwrap(); - resource_mgr_chan.send(ControlMsg::GetCookiesForUrl(doc_url.clone(), - tx, - CookieSource::HTTP)).unwrap(); - if let Some(cookie_list) = rx.recv().unwrap() { - let mut v = Vec::new(); - v.push(cookie_list.into_bytes()); - request_headers.set_raw("Cookie".to_owned(), v); - } + set_request_cookies(doc_url.clone(), &mut request_headers, &resource_mgr_chan); // --- Send the request let mut req = try!(request_factory.create(url.clone(), load_data.method.clone())); @@ -416,16 +432,7 @@ pub fn load(mut load_data: LoadData, } } - // --- Update the resource manager that we've gotten a cookie - if let Some(cookies) = response.headers().get_raw("set-cookie") { - for cookie in cookies.iter() { - if let Ok(cookies) = String::from_utf8(cookie.clone()) { - resource_mgr_chan.send(ControlMsg::SetCookiesForUrl(doc_url.clone(), - cookies, - CookieSource::HTTP)).unwrap(); - } - } - } + set_cookies_from_response(doc_url.clone(), &response, &resource_mgr_chan); if url.scheme == "https" { if let Some(header) = response.headers().get::() { diff --git a/tests/unit/net/http_loader.rs b/tests/unit/net/http_loader.rs index e8f9a2a7b4a..25662619cb8 100644 --- a/tests/unit/net/http_loader.rs +++ b/tests/unit/net/http_loader.rs @@ -4,6 +4,7 @@ use net::http_loader::{load, LoadError, HttpRequestFactory, HttpRequest, HttpResponse}; use net::resource_task::new_resource_task; +use net_traits::{ResourceTask, ControlMsg, CookieSource}; use url::Url; use std::sync::{Arc, Mutex}; use ipc_channel::ipc; @@ -21,8 +22,12 @@ fn respond_with(body: Vec) -> MockResponse { let mut headers = Headers::new(); headers.set(ContentLength(body.len() as u64)); + respond_with_headers(body, headers) +} + +fn respond_with_headers(body: Vec, headers: Headers) -> MockResponse { MockResponse::new( - headers, + headers.clone(), StatusCode::Ok, RawStatus(200, Cow::Borrowed("Ok")), body @@ -86,7 +91,8 @@ fn redirect_to(host: String) -> MockResponse { enum RequestType { Redirect(String), - Text(Vec) + Text(Vec), + WithHeaders(Vec, Headers) } struct MockRequest { @@ -107,6 +113,9 @@ fn response_for_request_type(t: RequestType) -> Result }, RequestType::Text(b) => { Ok(respond_with(b)) + }, + RequestType::WithHeaders(b, h) => { + Ok(respond_with_headers(b, h)) } } } @@ -169,6 +178,67 @@ impl HttpRequestFactory for AssertMustHaveHeadersRequestFactory { } } +fn assert_cookie_for_domain(resource_mgr: &ResourceTask, domain: &str, cookie: &str) { + let (tx, rx) = ipc::channel().unwrap(); + resource_mgr.send(ControlMsg::GetCookiesForUrl(Url::parse(&*domain).unwrap(), + tx, + CookieSource::HTTP)).unwrap(); + if let Some(cookie_list) = rx.recv().unwrap() { + assert_eq!(cookie.to_string(), cookie_list); + } else { + assert_eq!(cookie.len(), 0); + } +} + +#[test] +fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_in_response() { + struct Factory; + + impl HttpRequestFactory for Factory { + type R=MockRequest; + + fn create(&self, _: Url, _: Method) -> Result { + let content = <[_]>::to_vec("Yay!".as_bytes()); + let mut headers = Headers::new(); + headers.set_raw("set-cookie", vec![b"mozillaIs=theBest".to_vec()]); + Ok(MockRequest::new(RequestType::WithHeaders(content, headers))) + } + } + + let url = Url::parse("http://mozilla.com").unwrap(); + let resource_mgr = new_resource_task(None, None); + assert_cookie_for_domain(&resource_mgr, "http://mozilla.com", ""); + + let load_data = LoadData::new(url.clone(), None); + let hsts_list = Arc::new(Mutex::new(HSTSList { entries: Vec::new() })); + + let _ = load::(load_data, resource_mgr.clone(), None, hsts_list, &Factory); + + assert_cookie_for_domain(&resource_mgr, "http://mozilla.com", "mozillaIs=theBest"); +} + +#[test] +fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_resource_manager() { + let url = Url::parse("http://mozilla.com").unwrap(); + let resource_mgr = new_resource_task(None, None); + resource_mgr.send(ControlMsg::SetCookiesForUrl(Url::parse("http://mozilla.com").unwrap(), + "mozillaIs=theBest".to_string(), + CookieSource::HTTP)).unwrap(); + + let mut load_data = LoadData::new(url.clone(), None); + load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes())); + + let mut cookie = Headers::new(); + cookie.set_raw("Cookie".to_owned(), vec![<[_]>::to_vec("mozillaIs=theBest".as_bytes())]); + + let hsts_list = Arc::new(Mutex::new(HSTSList { entries: Vec::new() })); + + let _ = load::(load_data.clone(), resource_mgr, None, hsts_list, &AssertMustHaveHeadersRequestFactory { + expected_headers: cookie, + body: <[_]>::to_vec(&*load_data.data.unwrap()) + }); +} + #[test] fn test_load_sets_content_length_to_length_of_request_body() { let content = "This is a request body";