diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 7f6eee9d62a..6e96f1a8864 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -768,18 +768,18 @@ pub fn obtain_response(request_factory: &HttpRequestFactory, } pub trait UIProvider { - fn input_username_and_password(&self) -> (Option, Option); + fn input_username_and_password(&self, prompt: &str) -> (Option, Option); } impl UIProvider for TFDProvider { #[cfg(any(target_os = "macos", target_os = "linux"))] - fn input_username_and_password(&self) -> (Option, Option) { - (tinyfiledialogs::input_box("Enter username", "Username:", ""), - tinyfiledialogs::input_box("Enter password", "Password:", "")) + fn input_username_and_password(&self, prompt: &str) -> (Option, Option) { + (tinyfiledialogs::input_box(prompt, "Username:", ""), + tinyfiledialogs::input_box(prompt, "Password:", "")) } #[cfg(not(any(target_os = "macos", target_os = "linux")))] - fn input_username_and_password(&self) -> (Option, Option) { + fn input_username_and_password(&self, _prompt: &str) -> (Option, Option) { (None, None) } } @@ -870,8 +870,10 @@ pub fn load(load_data: &LoadData, 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(); + if response.status() == StatusCode::Unauthorized && + response.headers().get_raw("WWW-Authenticate").is_some() { + let (username_option, password_option) = + ui_provider.input_username_and_password(doc_url.as_str()); match username_option { Some(name) => { diff --git a/tests/unit/net/http_loader.rs b/tests/unit/net/http_loader.rs index a32df4781bf..422a97fdf07 100644 --- a/tests/unit/net/http_loader.rs +++ b/tests/unit/net/http_loader.rs @@ -109,15 +109,15 @@ impl TestProvider { } } impl UIProvider for TestProvider { - fn input_username_and_password(&self) -> (Option, Option) { + fn input_username_and_password(&self, _prompt: &str) -> (Option, Option) { (Some(self.username.to_owned()), Some(self.password.to_owned())) } } -fn basic_auth() -> MockResponse { +fn basic_auth(headers: Headers) -> MockResponse { MockResponse::new( - Headers::new(), + headers, StatusCode::Unauthorized, RawStatus(401, Cow::Borrowed("Unauthorized")), b"".to_vec() @@ -140,7 +140,7 @@ enum ResponseType { RedirectWithHeaders(String, Headers), Text(Vec), WithHeaders(Vec, Headers), - NeedsAuth, + NeedsAuth(Headers), } struct MockRequest { @@ -167,8 +167,8 @@ fn response_for_request_type(t: ResponseType) -> Result ResponseType::WithHeaders(b, h) => { Ok(respond_with_headers(b, h)) }, - ResponseType::NeedsAuth => { - Ok(basic_auth()) + ResponseType::NeedsAuth(h) => { + Ok(basic_auth(h)) } } } @@ -208,7 +208,9 @@ impl HttpRequestFactory for AssertAuthHeaderRequestFactory { assert_headers_included(&self.expected_headers, &headers); MockRequest::new(ResponseType::Text(self.body.clone())) } else { - MockRequest::new(ResponseType::NeedsAuth) + let mut headers = Headers::new(); + headers.set_raw("WWW-Authenticate", vec![b"Basic realm=\"Test realm\"".to_vec()]); + MockRequest::new(ResponseType::NeedsAuth(headers)) }; Ok(request) @@ -1442,6 +1444,40 @@ fn test_auth_ui_sets_header_on_401() { } } +#[test] +fn test_auth_ui_needs_www_auth() { + let url = Url::parse("http://mozilla.com").unwrap(); + let http_state = HttpState::new(); + struct AuthProvider; + impl UIProvider for AuthProvider { + fn input_username_and_password(&self, _prompt: &str) -> (Option, Option) { + panic!("shouldn't be invoked") + } + } + + struct Factory; + + impl HttpRequestFactory for Factory { + type R = MockRequest; + + fn create(&self, _: Url, _: Method, _: Headers) -> Result { + Ok(MockRequest::new(ResponseType::NeedsAuth(Headers::new()))) + } + } + + let load_data = LoadData::new(LoadContext::Browsing, url, None, None, None); + + let response = load(&load_data, &AuthProvider, &http_state, + None, &Factory, DEFAULT_USER_AGENT.to_owned(), + &CancellationListener::new(None)); + match response { + Err(e) => panic!("response contained error {:?}", e), + Ok(response) => { + assert_eq!(response.metadata.status, Some(RawStatus(401, Cow::Borrowed("Unauthorized")))); + } + } +} + fn assert_referer_header_matches(request_url: &str, referrer_url: &str, referrer_policy: Option,