mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Prompt user for credentials when http request needs it (#34620)
* prompt user to get their credentials Signed-off-by: Lloyd Massiah artmis9@protonmail.com move credential prompt to a function Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * add prompt for step 15.4 Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * add new prompt definition for user credentials Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * remove default implementation for HttpState which allowed making the embedder_proxy non-optional - default implementation was only used in tests so created an alternative create_http_state function Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> add credentials to authentication cache Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * add tests that are successful for the happy path Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * add test for user cancels prompt and user inputs incorrect credentials, and refactor shared code between tests Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * handle error when setting username and password in Url and ran formatting Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> renaming test functions Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * change authentication flag to false for proxy authentication. The spec doesn't specify that the flag should be true, and the flag is by default false Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * clean up test code a bit Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * add skeleton implementation to support open harmony and android Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * update warning message to include Android Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * fix build error for OH os and Android Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> * remove unused import to fix warning Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> --------- Signed-off-by: Lloyd Massiah <artmis9@protonmail.com> Co-authored-by: lazypassion <25536767+lazypassion@users.noreply.github.com>
This commit is contained in:
parent
a9539d8b03
commit
aa40b8f820
8 changed files with 379 additions and 51 deletions
|
@ -16,6 +16,9 @@ use devtools_traits::{
|
|||
ChromeToDevtoolsControlMsg, DevtoolsControlMsg, HttpRequest as DevtoolsHttpRequest,
|
||||
HttpResponse as DevtoolsHttpResponse, NetworkEvent,
|
||||
};
|
||||
use embedder_traits::{
|
||||
EmbedderMsg, EmbedderProxy, PromptCredentialsInput, PromptDefinition, PromptOrigin,
|
||||
};
|
||||
use futures::{future, StreamExt, TryFutureExt, TryStreamExt};
|
||||
use headers::authorization::Basic;
|
||||
use headers::{
|
||||
|
@ -60,10 +63,7 @@ use tokio::sync::mpsc::{
|
|||
use tokio_stream::wrappers::ReceiverStream;
|
||||
|
||||
use crate::async_runtime::HANDLE;
|
||||
use crate::connector::{
|
||||
create_http_client, create_tls_config, CACertificates, CertificateErrorOverrideManager,
|
||||
Connector,
|
||||
};
|
||||
use crate::connector::{CertificateErrorOverrideManager, Connector};
|
||||
use crate::cookie::ServoCookie;
|
||||
use crate::cookie_storage::CookieStorage;
|
||||
use crate::decoder::Decoder;
|
||||
|
@ -72,7 +72,7 @@ use crate::fetch::headers::{SecFetchDest, SecFetchMode, SecFetchSite, SecFetchUs
|
|||
use crate::fetch::methods::{main_fetch, Data, DoneChannel, FetchContext, Target};
|
||||
use crate::hsts::HstsList;
|
||||
use crate::http_cache::{CacheKey, HttpCache};
|
||||
use crate::resource_thread::AuthCache;
|
||||
use crate::resource_thread::{AuthCache, AuthCacheEntry};
|
||||
|
||||
/// <https://fetch.spec.whatwg.org/#document-accept-header-value>
|
||||
pub const DOCUMENT_ACCEPT_HEADER_VALUE: HeaderValue =
|
||||
|
@ -103,26 +103,7 @@ pub struct HttpState {
|
|||
pub history_states: RwLock<HashMap<HistoryStateId, Vec<u8>>>,
|
||||
pub client: Client<Connector, Body>,
|
||||
pub override_manager: CertificateErrorOverrideManager,
|
||||
}
|
||||
|
||||
impl Default for HttpState {
|
||||
fn default() -> Self {
|
||||
let override_manager = CertificateErrorOverrideManager::new();
|
||||
Self {
|
||||
hsts_list: RwLock::new(HstsList::default()),
|
||||
cookie_jar: RwLock::new(CookieStorage::new(150)),
|
||||
auth_cache: RwLock::new(AuthCache::default()),
|
||||
history_states: RwLock::new(HashMap::new()),
|
||||
http_cache: RwLock::new(HttpCache::default()),
|
||||
http_cache_state: Mutex::new(HashMap::new()),
|
||||
client: create_http_client(create_tls_config(
|
||||
CACertificates::Default,
|
||||
false, /* ignore_certificate_errors */
|
||||
override_manager.clone(),
|
||||
)),
|
||||
override_manager,
|
||||
}
|
||||
}
|
||||
pub embedder_proxy: Mutex<EmbedderProxy>,
|
||||
}
|
||||
|
||||
/// Step 13 of <https://fetch.spec.whatwg.org/#concept-fetch>.
|
||||
|
@ -1590,12 +1571,26 @@ async fn http_network_or_cache_fetch(
|
|||
|
||||
// Step 14.3 If request’s use-URL-credentials flag is unset or isAuthenticationFetch is true, then:
|
||||
if !http_request.use_url_credentials || authentication_fetch_flag {
|
||||
// TODO(#33616, #27439): Prompt the user for username and password from the window
|
||||
let Some(credentials) = prompt_user_for_credentials(&context.state.embedder_proxy)
|
||||
else {
|
||||
return response;
|
||||
};
|
||||
let Some(username) = credentials.username else {
|
||||
return response;
|
||||
};
|
||||
let Some(password) = credentials.password else {
|
||||
return response;
|
||||
};
|
||||
|
||||
// Wrong, but will have to do until we are able to prompt the user
|
||||
// otherwise this creates an infinite loop
|
||||
// We basically pretend that the user declined to enter credentials (#33616)
|
||||
return response;
|
||||
if let Err(err) = http_request.current_url_mut().set_username(&username) {
|
||||
error!("error setting username for url: {:?}", err);
|
||||
return response;
|
||||
};
|
||||
|
||||
if let Err(err) = http_request.current_url_mut().set_password(Some(&password)) {
|
||||
error!("error setting password for url: {:?}", err);
|
||||
return response;
|
||||
};
|
||||
}
|
||||
|
||||
// Make sure this is set to None,
|
||||
|
@ -1627,15 +1622,43 @@ async fn http_network_or_cache_fetch(
|
|||
|
||||
// TODO(#33616): Step 15.3 If fetchParams is canceled, then return
|
||||
// the appropriate network error for fetchParams.
|
||||
// TODO(#33616): Step 15.4 Prompt the end user as appropriate in request’s window and store the
|
||||
// result as a proxy-authentication entry.
|
||||
|
||||
// Step 15.4 Prompt the end user as appropriate in request’s window
|
||||
// window and store the result as a proxy-authentication entry.
|
||||
let Some(credentials) = prompt_user_for_credentials(&context.state.embedder_proxy) else {
|
||||
return response;
|
||||
};
|
||||
let Some(user_name) = credentials.username else {
|
||||
return response;
|
||||
};
|
||||
let Some(password) = credentials.password else {
|
||||
return response;
|
||||
};
|
||||
|
||||
// store the credentials as a proxy-authentication entry.
|
||||
let entry = AuthCacheEntry {
|
||||
user_name,
|
||||
password,
|
||||
};
|
||||
{
|
||||
let mut auth_cache = context.state.auth_cache.write().unwrap();
|
||||
let key = http_request.current_url().origin().ascii_serialization();
|
||||
auth_cache.entries.insert(key, entry);
|
||||
}
|
||||
|
||||
// Make sure this is set to None,
|
||||
// since we're about to start a new `http_network_or_cache_fetch`.
|
||||
*done_chan = None;
|
||||
|
||||
// Step 15.5 Set response to the result of running HTTP-network-or-cache fetch given fetchParams.
|
||||
|
||||
// Wrong, but will have to do until we are able to prompt the user
|
||||
// otherwise this creates an infinite loop
|
||||
// We basically pretend that the user declined to enter credentials (#33616)
|
||||
return response;
|
||||
response = http_network_or_cache_fetch(
|
||||
http_request,
|
||||
false, /* authentication flag */
|
||||
cors_flag,
|
||||
done_chan,
|
||||
context,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
// TODO(#33616): Step 16. If all of the following are true:
|
||||
|
@ -1737,6 +1760,29 @@ impl Drop for ResponseEndTimer {
|
|||
}
|
||||
}
|
||||
|
||||
fn prompt_user_for_credentials(
|
||||
embedder_proxy: &Mutex<EmbedderProxy>,
|
||||
) -> Option<PromptCredentialsInput> {
|
||||
let proxy = embedder_proxy.lock().unwrap();
|
||||
|
||||
let (ipc_sender, ipc_receiver) = ipc::channel().unwrap();
|
||||
|
||||
proxy.send((
|
||||
None,
|
||||
EmbedderMsg::Prompt(
|
||||
PromptDefinition::Credentials(ipc_sender),
|
||||
PromptOrigin::Trusted,
|
||||
),
|
||||
));
|
||||
|
||||
let Ok(credentials) = ipc_receiver.recv() else {
|
||||
warn!("error getting user credentials");
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(credentials)
|
||||
}
|
||||
|
||||
/// [HTTP network fetch](https://fetch.spec.whatwg.org/#http-network-fetch)
|
||||
async fn http_network_fetch(
|
||||
request: &mut Request,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue