mirror of
https://github.com/servo/servo.git
synced 2025-09-27 15:20:09 +01:00
script: initial CookieStore implementation (#37968)
This is a first draft at implementing the required infrastructure for CookieStore, which requires setting up IPC between script and the resource thread to allow for async/"in parallel" handling of cookie changes that have a promise API. Cookie Store also will need to receive change events when cookies for a url are changed so the architecture needs to support that. Expect this PR to be reworked once the architecture becomes more settled, cookie change events will be implemented in follow up PRs Testing: WPT tests exist for this API Part of #37674 --------- Signed-off-by: Sebastian C <sebsebmc@gmail.com>
This commit is contained in:
parent
a75f3fd09b
commit
b869b7eb96
35 changed files with 917 additions and 305 deletions
|
@ -205,6 +205,27 @@ impl CookieStorage {
|
|||
}
|
||||
}
|
||||
|
||||
/// <https://cookiestore.spec.whatwg.org/#query-cookies>
|
||||
pub fn query_cookies(&mut self, url: &ServoUrl, name: Option<String>) -> Vec<Cookie<'static>> {
|
||||
// 1. Retrieve cookie-list given request-uri and "non-HTTP" source
|
||||
let cookie_list = self.cookies_data_for_url(url, CookieSource::NonHTTP);
|
||||
|
||||
// 3. For each cookie in cookie-list, run these steps:
|
||||
// 3.2. If name is given, then run these steps:
|
||||
if let Some(name) = name {
|
||||
// Let cookieName be the result of running UTF-8 decode without BOM on cookie’s name.
|
||||
// If cookieName does not equal name, then continue.
|
||||
cookie_list.filter(|cookie| cookie.name() == name).collect()
|
||||
} else {
|
||||
cookie_list.collect()
|
||||
}
|
||||
|
||||
// Note: we do not convert the list into CookieListItem's here, we do that in script to not not have to define
|
||||
// the binding types in net.
|
||||
|
||||
// Return list
|
||||
}
|
||||
|
||||
pub fn cookies_data_for_url<'a>(
|
||||
&'a mut self,
|
||||
url: &'a ServoUrl,
|
||||
|
|
|
@ -14,6 +14,7 @@ use std::sync::{Arc, Mutex, RwLock, Weak};
|
|||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use base::id::CookieStoreId;
|
||||
use cookie::Cookie;
|
||||
use crossbeam_channel::Sender;
|
||||
use devtools_traits::DevtoolsControlMsg;
|
||||
|
@ -29,9 +30,10 @@ use net_traits::request::{Destination, RequestBuilder, RequestId};
|
|||
use net_traits::response::{Response, ResponseInit};
|
||||
use net_traits::storage_thread::StorageThreadMsg;
|
||||
use net_traits::{
|
||||
AsyncRuntime, CookieSource, CoreResourceMsg, CoreResourceThread, CustomResponseMediator,
|
||||
DiscardFetch, FetchChannels, FetchTaskTarget, ResourceFetchTiming, ResourceThreads,
|
||||
ResourceTimingType, WebSocketDomAction, WebSocketNetworkEvent,
|
||||
AsyncRuntime, CookieAsyncResponse, CookieData, CookieSource, CoreResourceMsg,
|
||||
CoreResourceThread, CustomResponseMediator, DiscardFetch, FetchChannels, FetchTaskTarget,
|
||||
ResourceFetchTiming, ResourceThreads, ResourceTimingType, WebSocketDomAction,
|
||||
WebSocketNetworkEvent,
|
||||
};
|
||||
use profile_traits::mem::{
|
||||
ProcessReports, ProfilerChan as MemProfilerChan, Report, ReportKind, ReportsChan,
|
||||
|
@ -152,6 +154,7 @@ pub fn new_core_resource_thread(
|
|||
ca_certificates,
|
||||
ignore_certificate_errors,
|
||||
cancellation_listeners: Default::default(),
|
||||
cookie_listeners: Default::default(),
|
||||
};
|
||||
|
||||
mem_profiler_chan.run_with_memory_reporting(
|
||||
|
@ -179,6 +182,7 @@ struct ResourceChannelManager {
|
|||
ca_certificates: CACertificates,
|
||||
ignore_certificate_errors: bool,
|
||||
cancellation_listeners: HashMap<RequestId, Weak<CancellationListener>>,
|
||||
cookie_listeners: HashMap<CookieStoreId, IpcSender<CookieAsyncResponse>>,
|
||||
}
|
||||
|
||||
fn create_http_states(
|
||||
|
@ -335,6 +339,20 @@ impl ResourceChannelManager {
|
|||
cancellation_listener
|
||||
}
|
||||
|
||||
fn send_cookie_response(&self, store_id: CookieStoreId, data: CookieData) {
|
||||
let Some(sender) = self.cookie_listeners.get(&store_id) else {
|
||||
warn!(
|
||||
"Async cookie request made for store id that is non-existent {:?}",
|
||||
store_id
|
||||
);
|
||||
return;
|
||||
};
|
||||
let res = sender.send(CookieAsyncResponse { data });
|
||||
if res.is_err() {
|
||||
warn!("Unable to send cookie response to script thread");
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns false if the thread should exit.
|
||||
fn process_msg(
|
||||
&mut self,
|
||||
|
@ -398,6 +416,14 @@ impl ResourceChannelManager {
|
|||
.delete_cookie_with_name(&request, name);
|
||||
return true;
|
||||
},
|
||||
CoreResourceMsg::DeleteCookieAsync(cookie_store_id, url, name) => {
|
||||
http_state
|
||||
.cookie_jar
|
||||
.write()
|
||||
.unwrap()
|
||||
.delete_cookie_with_name(&url, name);
|
||||
self.send_cookie_response(cookie_store_id, CookieData::Delete(Ok(())));
|
||||
},
|
||||
CoreResourceMsg::FetchRedirect(request_builder, res_init, sender) => {
|
||||
let cancellation_listener =
|
||||
self.get_or_create_cancellation_listener(request_builder.id);
|
||||
|
@ -423,6 +449,15 @@ impl ResourceChannelManager {
|
|||
);
|
||||
}
|
||||
},
|
||||
CoreResourceMsg::SetCookieForUrlAsync(cookie_store_id, url, cookie, source) => {
|
||||
self.resource_manager.set_cookie_for_url(
|
||||
&url,
|
||||
cookie.into_inner().to_owned(),
|
||||
source,
|
||||
http_state,
|
||||
);
|
||||
self.send_cookie_response(cookie_store_id, CookieData::Set(Ok(())));
|
||||
},
|
||||
CoreResourceMsg::GetCookiesForUrl(url, consumer, source) => {
|
||||
let mut cookie_jar = http_state.cookie_jar.write().unwrap();
|
||||
cookie_jar.remove_expired_cookies_for_url(&url);
|
||||
|
@ -430,6 +465,33 @@ impl ResourceChannelManager {
|
|||
.send(cookie_jar.cookies_for_url(&url, source))
|
||||
.unwrap();
|
||||
},
|
||||
CoreResourceMsg::GetCookieDataForUrlAsync(cookie_store_id, url, name) => {
|
||||
let mut cookie_jar = http_state.cookie_jar.write().unwrap();
|
||||
cookie_jar.remove_expired_cookies_for_url(&url);
|
||||
let cookie = cookie_jar
|
||||
.query_cookies(&url, name)
|
||||
.into_iter()
|
||||
.map(Serde)
|
||||
.next();
|
||||
self.send_cookie_response(cookie_store_id, CookieData::Get(cookie));
|
||||
},
|
||||
CoreResourceMsg::GetAllCookieDataForUrlAsync(cookie_store_id, url, name) => {
|
||||
let mut cookie_jar = http_state.cookie_jar.write().unwrap();
|
||||
cookie_jar.remove_expired_cookies_for_url(&url);
|
||||
let cookies = cookie_jar
|
||||
.query_cookies(&url, name)
|
||||
.into_iter()
|
||||
.map(Serde)
|
||||
.collect();
|
||||
self.send_cookie_response(cookie_store_id, CookieData::GetAll(cookies));
|
||||
},
|
||||
CoreResourceMsg::NewCookieListener(cookie_store_id, sender, _url) => {
|
||||
// TODO: Use the URL for setting up the actual monitoring
|
||||
self.cookie_listeners.insert(cookie_store_id, sender);
|
||||
},
|
||||
CoreResourceMsg::RemoveCookieListener(cookie_store_id) => {
|
||||
self.cookie_listeners.remove(&cookie_store_id);
|
||||
},
|
||||
CoreResourceMsg::NetworkMediator(mediator_chan, origin) => {
|
||||
self.resource_manager
|
||||
.sw_managers
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue