Auto merge of #10328 - DDEFISHER:master, r=jdm

401 authorization UI then restart request/save successful auth creds

Step 7 of the NCSU student project Implement HTTP authorization UI

> make an authorization UI appear when a 401 HTTP response is received (StatusCode::Unauthorized) - in load in http_loader.rs, right before trying to process an HTTP redirection, use the new tinyfiledialogs library to make two prompts appear (username and password), then restart the request with the new authorization value present applied. If an authorization value was present and the response is successful, add the credentials to the authorization cache.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10328)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-04-15 08:01:23 +05:30
commit 7bd2381518
7 changed files with 282 additions and 61 deletions

View file

@ -32,6 +32,9 @@ git = "https://github.com/servo/ipc-channel"
[dependencies.webrender_traits]
git = "https://github.com/servo/webrender_traits"
[dependencies.tinyfiledialogs]
git = "https://github.com/jdm/tinyfiledialogs"
[dependencies]
cookie = "0.2"
flate2 = "0.2.0"

View file

@ -41,6 +41,7 @@ use std::sync::mpsc::Sender;
use std::sync::{Arc, RwLock};
use time;
use time::Tm;
use tinyfiledialogs;
use url::Url;
use util::resource_files::resources_dir_path;
use util::thread::spawn_named;
@ -150,8 +151,10 @@ fn load_for_consumer(load_data: LoadData,
let factory = NetworkHttpRequestFactory {
connector: connector,
};
let ui_provider = TFDProvider;
let context = load_data.context.clone();
match load::<WrappedHttpRequest>(load_data, &http_state,
match load::<WrappedHttpRequest, TFDProvider>(load_data, &ui_provider, &http_state,
devtools_chan, &factory,
user_agent, &cancel_listener) {
Err(LoadError::UnsupportedScheme(url)) => {
@ -694,13 +697,27 @@ pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>,
Ok(response)
}
pub fn load<A>(load_data: LoadData,
pub trait UIProvider {
fn input_username_and_password(&self) -> (Option<String>, Option<String>);
}
impl UIProvider for TFDProvider {
fn input_username_and_password(&self) -> (Option<String>, Option<String>) {
(tinyfiledialogs::input_box("Enter username", "Username:", ""),
tinyfiledialogs::input_box("Enter password", "Password:", ""))
}
}
struct TFDProvider;
pub fn load<A, B>(load_data: LoadData,
ui_provider: &B,
http_state: &HttpState,
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
request_factory: &HttpRequestFactory<R=A>,
user_agent: String,
cancel_listener: &CancellationListener)
-> Result<StreamedResponse<A::R>, LoadError> where A: HttpRequest + 'static {
-> Result<StreamedResponse<A::R>, LoadError> where A: HttpRequest + 'static, B: UIProvider {
// FIXME: At the time of writing this FIXME, servo didn't have any central
// location for configuration. If you're reading this and such a
// repository DOES exist, please update this constant to use it.
@ -711,6 +728,8 @@ pub fn load<A>(load_data: LoadData,
let mut redirected_to = HashSet::new();
let mut method = load_data.method.clone();
let mut new_auth_header: Option<Authorization<Basic>> = None;
if cancel_listener.is_cancelled() {
return Err(LoadError::Cancelled(doc_url, "load cancelled".to_owned()));
}
@ -765,12 +784,43 @@ pub fn load<A>(load_data: LoadData,
&user_agent, &http_state.cookie_jar,
&http_state.auth_cache, &load_data);
//if there is a new auth header then set the request headers with it
if let Some(ref auth_header) = new_auth_header {
request_headers.set(auth_header.clone());
}
let response = try!(obtain_response(request_factory, &doc_url, &method, &request_headers,
&cancel_listener, &load_data.data, &load_data.method,
&load_data.pipeline_id, iters, &devtools_chan, &request_id));
process_response_headers(&response, &doc_url, &http_state.cookie_jar, &http_state.hsts_list, &load_data);
//if response status is unauthorized then prompt user for username and password
if response.status() == StatusCode::Unauthorized {
let (username_option, password_option) = ui_provider.input_username_and_password();
match username_option {
Some(name) => {
new_auth_header = Some(Authorization(Basic { username: name, password: password_option }));
continue;
},
None => {},
}
}
new_auth_header = None;
if let Some(auth_header) = request_headers.get::<Authorization<Basic>>() {
if response.status().class() == StatusClass::Success {
let auth_entry = AuthCacheEntry {
user_name: auth_header.username.to_owned(),
password: auth_header.password.to_owned().unwrap(),
};
http_state.auth_cache.write().unwrap().insert(doc_url.clone(), auth_entry);
}
}
// --- Loop if there's a redirect
if response.status().class() == StatusClass::Redirection {
if let Some(&Location(ref new_url)) = response.headers().get::<Location>() {

View file

@ -29,6 +29,7 @@ extern crate openssl;
extern crate rustc_serialize;
extern crate threadpool;
extern crate time;
extern crate tinyfiledialogs;
extern crate unicase;
extern crate url;
extern crate util;

View file

@ -1286,6 +1286,7 @@ dependencies = [
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
"tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)",
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
@ -2090,6 +2091,14 @@ dependencies = [
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tinyfiledialogs"
version = "0.1.0"
source = "git+https://github.com/jdm/tinyfiledialogs#2d2285985db1168da4d516000f24842aba46fd94"
dependencies = [
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "traitobject"
version = "0.0.1"

9
ports/cef/Cargo.lock generated
View file

@ -1199,6 +1199,7 @@ dependencies = [
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
"tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)",
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
@ -1976,6 +1977,14 @@ dependencies = [
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tinyfiledialogs"
version = "0.1.0"
source = "git+https://github.com/jdm/tinyfiledialogs#2d2285985db1168da4d516000f24842aba46fd94"
dependencies = [
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "traitobject"
version = "0.0.1"

9
ports/gonk/Cargo.lock generated
View file

@ -1181,6 +1181,7 @@ dependencies = [
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
"tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)",
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
@ -1956,6 +1957,14 @@ dependencies = [
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tinyfiledialogs"
version = "0.1.0"
source = "git+https://github.com/jdm/tinyfiledialogs#2d2285985db1168da4d516000f24842aba46fd94"
dependencies = [
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "traitobject"
version = "0.0.1"

View file

@ -20,7 +20,7 @@ use msg::constellation_msg::PipelineId;
use net::cookie::Cookie;
use net::cookie_storage::CookieStorage;
use net::hsts::HSTSEntry;
use net::http_loader::{load, LoadError, HttpRequestFactory, HttpRequest, HttpResponse, HttpState};
use net::http_loader::{load, LoadError, HttpRequestFactory, HttpRequest, HttpResponse, UIProvider, HttpState};
use net::resource_thread::{AuthCacheEntry, CancellationListener};
use net_traits::{LoadData, CookieSource, LoadContext, IncludeSubdomains};
use std::borrow::Cow;
@ -96,6 +96,33 @@ fn redirect_to(host: String) -> MockResponse {
)
}
struct TestProvider {
username: String,
password: String,
}
impl TestProvider {
fn new() -> TestProvider {
TestProvider { username: "default".to_owned(), password: "default".to_owned() }
}
}
impl UIProvider for TestProvider {
fn input_username_and_password(&self) -> (Option<String>, Option<String>) {
(Some(self.username.to_owned()),
Some(self.password.to_owned()))
}
}
fn basic_auth(headers: Headers) -> MockResponse {
MockResponse::new(
headers,
StatusCode::Unauthorized,
RawStatus(401, Cow::Borrowed("Unauthorized")),
b"".to_vec()
)
}
fn redirect_with_headers(host: String, mut headers: Headers) -> MockResponse {
headers.set(Location(host.to_string()));
@ -132,7 +159,7 @@ fn response_for_request_type(t: ResponseType) -> Result<MockResponse, LoadError>
},
ResponseType::RedirectWithHeaders(location, headers) => {
Ok(redirect_with_headers(location, headers))
}
},
ResponseType::Text(b) => {
Ok(respond_with(b))
},
@ -171,7 +198,41 @@ impl HttpRequest for AssertRequestMustHaveHeaders {
fn send(self, _: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> {
assert_eq!(self.request_headers, self.expected_headers);
response_for_request_type(self.t)
response_for_request_type(self.t)
}
}
struct AssertAuthHeaderRequest {
expected_headers: Headers,
request_headers: Headers,
t: ResponseType
}
impl AssertAuthHeaderRequest {
fn new(t: ResponseType, expected_headers: Headers) -> Self {
AssertAuthHeaderRequest { expected_headers: expected_headers, request_headers: Headers::new(), t: t }
}
}
impl HttpRequest for AssertAuthHeaderRequest {
type R = MockResponse;
fn headers_mut(&mut self) -> &mut Headers { &mut self.request_headers }
fn send(self, _: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> {
if self.request_headers.has::<Authorization<Basic>>() {
for header in self.expected_headers.iter() {
assert!(self.request_headers.get_raw(header.name()).is_some());
assert_eq!(
self.request_headers.get_raw(header.name()).unwrap(),
self.expected_headers.get_raw(header.name()).unwrap()
)
}
response_for_request_type(self.t)
} else {
Ok(basic_auth(self.request_headers))
}
}
}
@ -236,6 +297,23 @@ impl HttpRequestFactory for AssertMustHaveHeadersRequestFactory {
}
}
struct AssertAuthHeaderRequestFactory {
expected_headers: Headers,
body: Vec<u8>
}
impl HttpRequestFactory for AssertAuthHeaderRequestFactory {
type R = AssertAuthHeaderRequest;
fn create(&self, _: Url, _: Method) -> Result<AssertAuthHeaderRequest, LoadError> {
Ok(
AssertAuthHeaderRequest::new(
ResponseType::Text(self.body.clone()),
self.expected_headers.clone()
)
)
}
}
struct AssertMustIncludeHeadersRequestFactory {
expected_headers: Headers,
@ -375,6 +453,7 @@ fn test_check_default_headers_loaded_in_every_request() {
let url = Url::parse("http://mozilla.com").unwrap();
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
load_data.data = None;
@ -395,7 +474,7 @@ fn test_check_default_headers_loaded_in_every_request() {
headers.set(UserAgent(DEFAULT_USER_AGENT.to_owned()));
// Testing for method.GET
let _ = load::<AssertRequestMustHaveHeaders>(load_data.clone(), &http_state, None,
let _ = load::<AssertRequestMustHaveHeaders, TestProvider>(load_data.clone(), &ui_provider, &http_state, None,
&AssertMustHaveHeadersRequestFactory {
expected_headers: headers.clone(),
body: <[_]>::to_vec(&[])
@ -406,7 +485,7 @@ fn test_check_default_headers_loaded_in_every_request() {
headers.set(ContentLength(0 as u64));
let _ = load::<AssertRequestMustHaveHeaders>(load_data.clone(), &http_state, None,
let _ = load::<AssertRequestMustHaveHeaders, TestProvider>(load_data.clone(), &ui_provider, &http_state, None,
&AssertMustHaveHeadersRequestFactory {
expected_headers: headers,
body: <[_]>::to_vec(&[])
@ -418,6 +497,7 @@ fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length
let url = Url::parse("http://mozilla.com").unwrap();
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
load_data.data = None;
@ -426,8 +506,8 @@ fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length
let mut content_length = Headers::new();
content_length.set(ContentLength(0));
let _ = load::<AssertRequestMustIncludeHeaders>(
load_data.clone(), &http_state,
let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(
load_data.clone(), &ui_provider, &http_state,
None, &AssertMustIncludeHeadersRequestFactory {
expected_headers: content_length,
body: <[_]>::to_vec(&[])
@ -451,6 +531,7 @@ fn test_request_and_response_data_with_network_messages() {
}
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let url = Url::parse("https://mozilla.com").unwrap();
let (devtools_chan, devtools_port) = mpsc::channel::<DevtoolsControlMsg>();
@ -460,7 +541,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 });
load_data.headers = request_headers.clone();
let _ = load::<MockRequest>(load_data, &http_state, Some(devtools_chan), &Factory,
let _ = load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, Some(devtools_chan), &Factory,
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
// notification received from devtools
@ -525,11 +606,12 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() {
}
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let url = Url::parse("https://mozilla.com").unwrap();
let (devtools_chan, devtools_port) = mpsc::channel::<DevtoolsControlMsg>();
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let _ = load::<MockRequest>(load_data, &http_state, Some(devtools_chan), &Factory,
let _ = load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, Some(devtools_chan), &Factory,
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
// notification received from devtools
@ -561,8 +643,9 @@ fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() {
load_data.method = Method::Post;
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let _ = load::<MockRequest>(load_data, &http_state, None, &Factory,
let _ = load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, None, &Factory,
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
}
@ -588,9 +671,10 @@ fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_co
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let mut response = load::<MockRequest>(
load_data, &http_state, None,
let mut response = load::<MockRequest, TestProvider>(
load_data, &ui_provider, &http_state, None,
&Factory,
DEFAULT_USER_AGENT.to_owned(),
&CancellationListener::new(None))
@ -620,10 +704,11 @@ fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_conte
let url = Url::parse("http://mozilla.com").unwrap();
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let mut response = load::<MockRequest>(
let mut response = load::<MockRequest, TestProvider>(
load_data,
&http_state,
&ui_provider, &http_state,
None, &Factory,
DEFAULT_USER_AGENT.to_owned(),
&CancellationListener::new(None))
@ -663,9 +748,10 @@ fn test_load_doesnt_send_request_body_on_any_redirect() {
load_data.data = Some(<[_]>::to_vec("Body on POST!".as_bytes()));
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let _ = load::<AssertMustHaveBodyRequest>(
load_data, &http_state,
let _ = load::<AssertMustHaveBodyRequest, TestProvider>(
load_data, &ui_provider, &http_state,
None,
&Factory,
DEFAULT_USER_AGENT.to_owned(),
@ -692,9 +778,10 @@ fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_ar
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let _ = load::<MockRequest>(load_data,
&http_state,
let _ = load::<MockRequest, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&Factory,
DEFAULT_USER_AGENT.to_owned(),
@ -723,9 +810,10 @@ fn test_load_adds_host_to_sts_list_when_url_is_https_and_sts_headers_are_present
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let _ = load::<MockRequest>(load_data,
&http_state,
let _ = load::<MockRequest, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&Factory,
DEFAULT_USER_AGENT.to_owned(),
@ -752,13 +840,14 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_
let url = Url::parse("http://mozilla.com").unwrap();
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
assert_cookie_for_domain(http_state.cookie_jar.clone(), "http://mozilla.com", "");
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let _ = load::<MockRequest>(load_data,
&http_state,
let _ = load::<MockRequest, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&Factory,
DEFAULT_USER_AGENT.to_owned(),
@ -775,6 +864,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re
load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
{
let mut cookie_jar = http_state.cookie_jar.write().unwrap();
@ -790,7 +880,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re
let mut cookie = Headers::new();
cookie.set(CookieHeader(vec![CookiePair::new("mozillaIs".to_owned(), "theBest".to_owned())]));
let _ = load::<AssertRequestMustIncludeHeaders>(load_data.clone(), &http_state, None,
let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data.clone(), &ui_provider, &http_state, None,
&AssertMustIncludeHeadersRequestFactory {
expected_headers: cookie,
body: <[_]>::to_vec(&*load_data.data.unwrap())
@ -802,7 +892,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re
fn test_load_sends_secure_cookie_if_http_changed_to_https_due_to_entry_in_hsts_store() {
let url = Url::parse("http://mozilla.com").unwrap();
let secured_url = Url::parse("https://mozilla.com").unwrap();
let ui_provider = TestProvider::new();
let http_state = HttpState::new();
{
let mut hsts_list = http_state.hsts_list.write().unwrap();
@ -832,8 +922,8 @@ fn test_load_sends_secure_cookie_if_http_changed_to_https_due_to_entry_in_hsts_s
let mut headers = Headers::new();
headers.set_raw("Cookie".to_owned(), vec![<[_]>::to_vec("mozillaIs=theBest".as_bytes())]);
let _ = load::<AssertRequestMustIncludeHeaders>(
load_data.clone(), &http_state, None,
let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(
load_data.clone(), &ui_provider, &http_state, None,
&AssertMustIncludeHeadersRequestFactory {
expected_headers: headers,
body: <[_]>::to_vec(&*load_data.data.unwrap())
@ -845,6 +935,7 @@ fn test_load_sends_cookie_if_nonhttp() {
let url = Url::parse("http://mozilla.com").unwrap();
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
{
let mut cookie_jar = http_state.cookie_jar.write().unwrap();
@ -863,8 +954,8 @@ fn test_load_sends_cookie_if_nonhttp() {
let mut headers = Headers::new();
headers.set_raw("Cookie".to_owned(), vec![<[_]>::to_vec("mozillaIs=theBest".as_bytes())]);
let _ = load::<AssertRequestMustIncludeHeaders>(
load_data.clone(), &http_state, None,
let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(
load_data.clone(), &ui_provider, &http_state, None,
&AssertMustIncludeHeadersRequestFactory {
expected_headers: headers,
body: <[_]>::to_vec(&*load_data.data.unwrap())
@ -889,10 +980,11 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl(
let url = Url::parse("http://mozilla.com").unwrap();
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let _ = load::<MockRequest>(load_data,
&http_state,
let _ = load::<MockRequest, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&Factory,
DEFAULT_USER_AGENT.to_owned(),
@ -918,10 +1010,11 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() {
}
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let load_data = LoadData::new(LoadContext::Browsing, Url::parse("http://mozilla.com").unwrap(), None);
let _ = load::<MockRequest>(load_data,
&http_state,
let _ = load::<MockRequest, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&Factory,
DEFAULT_USER_AGENT.to_owned(),
@ -937,6 +1030,7 @@ fn test_when_cookie_set_marked_httpsonly_secure_isnt_sent_on_http_request() {
let url = Url::parse("http://mozilla.com").unwrap();
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
{
let mut cookie_jar = http_state.cookie_jar.write().unwrap();
@ -954,8 +1048,8 @@ fn test_when_cookie_set_marked_httpsonly_secure_isnt_sent_on_http_request() {
assert_cookie_for_domain(http_state.cookie_jar.clone(), "https://mozilla.com", "mozillaIs=theBest");
let _ = load::<AssertRequestMustNotIncludeHeaders>(
load_data.clone(), &http_state, None,
let _ = load::<AssertRequestMustNotIncludeHeaders, TestProvider>(
load_data.clone(), &ui_provider, &http_state, None,
&AssertMustNotIncludeHeadersRequestFactory {
headers_not_expected: vec!["Cookie".to_owned()],
body: <[_]>::to_vec(&*load_data.data.unwrap())
@ -974,8 +1068,9 @@ fn test_load_sets_content_length_to_length_of_request_body() {
content_len_headers.set(ContentLength(content.as_bytes().len() as u64));
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let _ = load::<AssertRequestMustIncludeHeaders>(load_data.clone(), &http_state,
let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data.clone(), &ui_provider, &http_state,
None, &AssertMustIncludeHeadersRequestFactory {
expected_headers: content_len_headers,
body: <[_]>::to_vec(&*load_data.data.unwrap())
@ -996,9 +1091,10 @@ fn test_load_uses_explicit_accept_from_headers_in_load_data() {
load_data.headers.set(Accept(vec![text_html.clone()]));
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let _ = load::<AssertRequestMustIncludeHeaders>(load_data,
&http_state,
let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&AssertMustIncludeHeadersRequestFactory {
expected_headers: accept_headers,
@ -1022,9 +1118,10 @@ fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() {
load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let _ = load::<AssertRequestMustIncludeHeaders>(load_data,
&http_state,
let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&AssertMustIncludeHeadersRequestFactory {
expected_headers: accept_headers,
@ -1044,9 +1141,10 @@ fn test_load_uses_explicit_accept_encoding_from_load_data_headers() {
load_data.headers.set(AcceptEncoding(vec![qitem(Encoding::Chunked)]));
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let _ = load::<AssertRequestMustIncludeHeaders>(load_data,
&http_state,
let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&AssertMustIncludeHeadersRequestFactory {
expected_headers: accept_encoding_headers,
@ -1067,9 +1165,10 @@ fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() {
load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let _ = load::<AssertRequestMustIncludeHeaders>(load_data,
&http_state,
let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&AssertMustIncludeHeadersRequestFactory {
expected_headers: accept_encoding_headers,
@ -1100,8 +1199,9 @@ fn test_load_errors_when_there_a_redirect_loop() {
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
match load::<MockRequest>(load_data, &http_state, None, &Factory,
match load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, None, &Factory,
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) {
Err(LoadError::InvalidRedirect(_, msg)) => {
assert_eq!(msg, "redirect loop");
@ -1130,8 +1230,9 @@ fn test_load_errors_when_there_is_too_many_redirects() {
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
match load::<MockRequest>(load_data, &http_state, None, &Factory,
match load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, None, &Factory,
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) {
Err(LoadError::MaxRedirects(url)) => {
assert_eq!(url.domain().unwrap(), "mozilla.com")
@ -1168,8 +1269,9 @@ fn test_load_follows_a_redirect() {
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
match load::<MockRequest>(load_data, &http_state, None, &Factory,
match load::<MockRequest, TestProvider>(load_data, &ui_provider, &http_state, None, &Factory,
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) {
Err(e) => panic!("expected to follow a redirect {:?}", e),
Ok(mut lr) => {
@ -1195,9 +1297,10 @@ fn test_load_errors_when_scheme_is_not_http_or_https() {
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
match load::<MockRequest>(load_data,
&http_state,
match load::<MockRequest, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&DontConnectFactory,
DEFAULT_USER_AGENT.to_owned(),
@ -1213,9 +1316,10 @@ fn test_load_errors_when_viewing_source_and_inner_url_scheme_is_not_http_or_http
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
match load::<MockRequest>(load_data,
&http_state,
match load::<MockRequest, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&DontConnectFactory,
DEFAULT_USER_AGENT.to_owned(),
@ -1254,9 +1358,10 @@ fn test_load_errors_when_cancelled() {
let url = Url::parse("https://mozilla.com").unwrap();
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
match load::<MockRequest>(load_data,
&http_state,
match load::<MockRequest, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&Factory,
DEFAULT_USER_AGENT.to_owned(),
@ -1301,6 +1406,7 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() {
let load_data = LoadData::new(LoadContext::Browsing, url_x.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
{
let mut cookie_jar = http_state.cookie_jar.write().unwrap();
@ -1322,8 +1428,8 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() {
cookie_jar.push(cookie_y, CookieSource::HTTP);
}
match load::<AssertRequestMustIncludeHeaders>(load_data,
&http_state,
match load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&Factory,
DEFAULT_USER_AGENT.to_owned(),
@ -1368,9 +1474,10 @@ fn test_redirect_from_x_to_x_provides_x_with_cookie_from_first_response() {
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
match load::<AssertRequestMustIncludeHeaders>(load_data,
&http_state,
match load::<AssertRequestMustIncludeHeaders, TestProvider>(load_data,
&ui_provider, &http_state,
None,
&Factory,
DEFAULT_USER_AGENT.to_owned(),
@ -1388,6 +1495,7 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() {
let url = Url::parse("http://mozilla.com").unwrap();
let http_state = HttpState::new();
let ui_provider = TestProvider::new();
let auth_entry = AuthCacheEntry {
user_name: "username".to_owned(),
@ -1410,10 +1518,42 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() {
)
);
let _ = load::<AssertRequestMustIncludeHeaders>(
load_data.clone(), &http_state,
let _ = load::<AssertRequestMustIncludeHeaders, TestProvider>(
load_data.clone(), &ui_provider, &http_state,
None, &AssertMustIncludeHeadersRequestFactory {
expected_headers: auth_header,
body: <[_]>::to_vec(&[])
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
}
#[test]
fn test_auth_ui_sets_header_on_401() {
let url = Url::parse("http://mozilla.com").unwrap();
let http_state = HttpState::new();
let ui_provider = TestProvider { username: "test".to_owned(), password: "test".to_owned() };
let mut auth_header = Headers::new();
auth_header.set(
Authorization(
Basic {
username: "test".to_owned(),
password: Some("test".to_owned())
}
)
);
let load_data = LoadData::new(LoadContext::Browsing, url, None);
match load::<AssertAuthHeaderRequest, TestProvider>(
load_data.clone(), &ui_provider, &http_state,
None, &AssertAuthHeaderRequestFactory {
expected_headers: auth_header,
body: <[_]>::to_vec(&[])
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) {
Err(e) => panic!("response contained error {:?}", e),
Ok(response) => {
assert_eq!(response.metadata.status, Some(RawStatus(200, Cow::Borrowed("Ok"))));
}
}
}