servo/
site_data_manager.rs1use bitflags::bitflags;
6use log::warn;
7use net_traits::pub_domains::registered_domain_name;
8use net_traits::{ResourceThreads, SiteDescriptor};
9use rustc_hash::FxHashMap;
10use servo_url::ServoUrl;
11use storage_traits::StorageThreads;
12use storage_traits::webstorage_thread::{OriginDescriptor, WebStorageType};
13
14bitflags! {
15 #[derive(Clone, Copy, Debug, PartialEq)]
23 pub struct StorageType: u8 {
24 const Cookies = 1 << 0;
27
28 const Local = 1 << 1;
31
32 const Session = 1 << 2;
35 }
36}
37
38#[derive(Clone, Debug, PartialEq)]
39pub struct SiteData {
40 name: String,
41 storage_types: StorageType,
42}
43
44impl SiteData {
45 pub fn new(name: impl Into<String>, storage_types: StorageType) -> SiteData {
46 SiteData {
47 name: name.into(),
48 storage_types,
49 }
50 }
51
52 pub fn name(&self) -> String {
53 self.name.clone()
54 }
55
56 pub fn storage_types(&self) -> StorageType {
57 self.storage_types
58 }
59}
60
61pub struct SiteDataManager {
74 public_resource_threads: ResourceThreads,
75 private_resource_threads: ResourceThreads,
76 public_storage_threads: StorageThreads,
77 private_storage_threads: StorageThreads,
78}
79
80impl SiteDataManager {
81 pub(crate) fn new(
82 public_resource_threads: ResourceThreads,
83 private_resource_threads: ResourceThreads,
84 public_storage_threads: StorageThreads,
85 private_storage_threads: StorageThreads,
86 ) -> Self {
87 Self {
88 public_resource_threads,
89 private_resource_threads,
90 public_storage_threads,
91 private_storage_threads,
92 }
93 }
94
95 pub fn site_data(&self, storage_types: StorageType) -> Vec<SiteData> {
106 let mut all_sites: FxHashMap<String, StorageType> = FxHashMap::default();
107
108 let mut add_sites = |sites: Vec<SiteDescriptor>, storage_type: StorageType| {
109 for site in sites {
110 all_sites
111 .entry(site.name)
112 .and_modify(|storage_types| *storage_types |= storage_type)
113 .or_insert(storage_type);
114 }
115 };
116
117 if storage_types.contains(StorageType::Cookies) {
118 let public_cookies = self.public_resource_threads.cookies();
119 add_sites(public_cookies, StorageType::Cookies);
120
121 let private_cookies = self.private_resource_threads.cookies();
122 add_sites(private_cookies, StorageType::Cookies);
123 }
124
125 let mut add_origins = |origins: Vec<OriginDescriptor>, storage_type: StorageType| {
126 for origin in origins {
127 let url =
128 ServoUrl::parse(&origin.name).expect("Should always be able to parse origins.");
129
130 let Some(domain) = registered_domain_name(&url) else {
131 warn!("Failed to get a registered domain name for: {url}.");
132 continue;
133 };
134 let domain = domain.to_string();
135
136 all_sites
137 .entry(domain)
138 .and_modify(|storage_types| *storage_types |= storage_type)
139 .or_insert(storage_type);
140 }
141 };
142
143 if storage_types.contains(StorageType::Local) {
144 let public_origins = self
145 .public_storage_threads
146 .webstorage_origins(WebStorageType::Local);
147 add_origins(public_origins, StorageType::Local);
148
149 let private_origins = self
150 .private_storage_threads
151 .webstorage_origins(WebStorageType::Local);
152 add_origins(private_origins, StorageType::Local);
153 }
154
155 if storage_types.contains(StorageType::Session) {
156 let public_origins = self
157 .public_storage_threads
158 .webstorage_origins(WebStorageType::Session);
159 add_origins(public_origins, StorageType::Session);
160
161 let private_origins = self
162 .private_storage_threads
163 .webstorage_origins(WebStorageType::Session);
164 add_origins(private_origins, StorageType::Session);
165 }
166
167 let mut result: Vec<SiteData> = all_sites
168 .into_iter()
169 .map(|(name, storage_types)| SiteData::new(name, storage_types))
170 .collect();
171
172 result.sort_by_key(SiteData::name);
173
174 result
175 }
176
177 pub fn clear_site_data(&self, sites: &[&str], storage_types: StorageType) {
182 if storage_types.contains(StorageType::Cookies) {
183 self.public_resource_threads.clear_cookies_for_sites(sites);
184 self.private_resource_threads.clear_cookies_for_sites(sites);
185 }
186
187 if storage_types.contains(StorageType::Local) {
188 self.public_storage_threads
189 .clear_webstorage_for_sites(WebStorageType::Local, sites);
190 self.private_storage_threads
191 .clear_webstorage_for_sites(WebStorageType::Local, sites);
192 }
193
194 if storage_types.contains(StorageType::Session) {
195 self.public_storage_threads
196 .clear_webstorage_for_sites(WebStorageType::Session, sites);
197 self.private_storage_threads
198 .clear_webstorage_for_sites(WebStorageType::Session, sites);
199 }
200 }
201
202 pub fn clear_cookies(&self) {
203 self.public_resource_threads.clear_cookies();
204 self.private_resource_threads.clear_cookies();
205 }
206}