1use std::ops::{Deref, DerefMut};
5use std::path::PathBuf;
6use std::str::FromStr;
7
8use malloc_size_of_derive::MallocSizeOf;
9use serde::{Deserialize, Serialize};
10use servo_base::generic_channel::{
11 self, GenericCallback, GenericReceiver, GenericSender, SendResult,
12};
13use servo_base::id::WebViewId;
14use servo_url::ImmutableOrigin;
15
16#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
17pub struct ClientStorageThreadHandle {
18 sender: GenericSender<ClientStorageThreadMessage>,
19}
20
21impl ClientStorageThreadHandle {
22 pub fn new(sender: GenericSender<ClientStorageThreadMessage>) -> Self {
23 ClientStorageThreadHandle { sender }
24 }
25
26 pub fn obtain_a_storage_bottle_map(
27 &self,
28 storage_type: StorageType,
29 webview: Option<WebViewId>,
30 storage_identifier: StorageIdentifier,
31 origin: ImmutableOrigin,
32 ) -> GenericReceiver<Result<StorageProxyMap, String>> {
33 let (sender, receiver) = generic_channel::channel().unwrap();
34 let message = ClientStorageThreadMessage::ObtainBottleMap {
35 storage_type,
36 webview,
37 storage_identifier,
38 origin,
39 sender,
40 };
41 self.sender.send(message).unwrap();
42 receiver
43 }
44
45 pub fn create_database(
46 &self,
47 bottle_id: i64,
48 name: String,
49 ) -> GenericReceiver<Result<(PathBuf, bool), String>> {
50 let (sender, receiver) = generic_channel::channel().unwrap();
51 let message = ClientStorageThreadMessage::CreateDatabase {
52 bottle_id,
53 name,
54 sender,
55 };
56 self.sender.send(message).unwrap();
57 receiver
58 }
59
60 pub fn delete_database(
61 &self,
62 bottle_id: i64,
63 name: String,
64 ) -> GenericReceiver<Result<(), String>> {
65 let (sender, receiver) = generic_channel::channel().unwrap();
66 let message = ClientStorageThreadMessage::DeleteDatabase {
67 bottle_id,
68 name,
69 sender,
70 };
71 self.sender.send(message).unwrap();
72 receiver
73 }
74
75 pub fn persisted(
76 &self,
77 origin: ImmutableOrigin,
78 sender: GenericCallback<Result<bool, String>>,
79 ) -> SendResult {
80 self.sender
81 .send(ClientStorageThreadMessage::Persisted { origin, sender })
82 }
83
84 pub fn persist(
85 &self,
86 origin: ImmutableOrigin,
87 permission_granted: bool,
88 sender: GenericCallback<Result<bool, String>>,
89 ) -> SendResult {
90 self.sender.send(ClientStorageThreadMessage::Persist {
91 origin,
92 permission_granted,
93 sender,
94 })
95 }
96
97 pub fn estimate(
98 &self,
99 origin: ImmutableOrigin,
100 sender: GenericCallback<Result<(u64, u64), String>>,
101 ) -> SendResult {
102 self.sender
103 .send(ClientStorageThreadMessage::Estimate { origin, sender })
104 }
105}
106
107impl From<ClientStorageThreadHandle> for GenericSender<ClientStorageThreadMessage> {
108 fn from(handle: ClientStorageThreadHandle) -> Self {
109 handle.sender
110 }
111}
112
113impl From<GenericSender<ClientStorageThreadMessage>> for ClientStorageThreadHandle {
114 fn from(sender: GenericSender<ClientStorageThreadMessage>) -> Self {
115 ClientStorageThreadHandle::new(sender)
116 }
117}
118
119impl Deref for ClientStorageThreadHandle {
120 type Target = GenericSender<ClientStorageThreadMessage>;
121
122 fn deref(&self) -> &Self::Target {
123 &self.sender
124 }
125}
126
127impl DerefMut for ClientStorageThreadHandle {
128 fn deref_mut(&mut self) -> &mut Self::Target {
129 &mut self.sender
130 }
131}
132
133#[derive(Debug, Deserialize, Serialize)]
135pub enum StorageType {
136 Local,
137 Session,
138}
139
140impl StorageType {
141 pub fn as_str(&self) -> &str {
142 match self {
143 StorageType::Local => "local",
144 StorageType::Session => "session",
145 }
146 }
147}
148
149#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
151pub enum Mode {
152 #[default]
154 BestEffort,
155 Persistent,
156}
157
158impl Mode {
159 pub fn as_str(&self) -> &str {
160 match self {
161 Mode::BestEffort => "best-effort",
162 Mode::Persistent => "persistent",
163 }
164 }
165}
166
167impl FromStr for Mode {
168 type Err = ();
169
170 fn from_str(value: &str) -> Result<Self, Self::Err> {
172 match value {
173 "best-effort" => Ok(Mode::BestEffort),
174 "persistent" => Ok(Mode::Persistent),
175 _ => Err(()),
176 }
177 }
178}
179
180#[derive(Debug, Deserialize, Serialize)]
182pub enum StorageIdentifier {
183 Caches,
184 IndexedDB,
185 LocalStorage,
186 ServiceWorkerRegistrations,
187 SessionStorage,
188}
189
190impl StorageIdentifier {
191 pub fn as_str(&self) -> &str {
192 match self {
193 StorageIdentifier::Caches => "caches",
194 StorageIdentifier::IndexedDB => "indexeddb",
195 StorageIdentifier::LocalStorage => "localstorage",
196 StorageIdentifier::ServiceWorkerRegistrations => "serviceworkerregistration",
197 StorageIdentifier::SessionStorage => "sessionstorage",
198 }
199 }
200}
201
202#[derive(Debug, Deserialize, Serialize)]
203pub enum CreateBucketError<T> {
204 BucketAlreadyExists,
205 Internal(T),
206}
207
208impl<T> From<T> for CreateBucketError<T> {
209 fn from(err: T) -> Self {
210 CreateBucketError::Internal(err)
211 }
212}
213
214#[derive(Debug, Deserialize, Serialize)]
215pub enum ClientStorageErrorr<T> {
216 BottleAlreadyExists,
217 BucketDoesNotExist,
218 DatabaseAlreadyExists,
219 DatabaseDoesNotExist,
220 DirectoryCreationFailed,
221 DirectoryDeletionFailed,
222 SessionStorageRequiresWindow,
223 Internal(T),
224}
225
226impl<T> From<T> for ClientStorageErrorr<T> {
227 fn from(err: T) -> Self {
228 ClientStorageErrorr::Internal(err)
229 }
230}
231
232#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
234pub struct StorageProxyMap {
235 pub bottle_id: i64,
236 pub handle: ClientStorageThreadHandle,
237}
238
239#[derive(Debug, Deserialize, Serialize)]
240pub enum ClientStorageThreadMessage {
241 ObtainBottleMap {
242 storage_type: StorageType,
243 webview: Option<WebViewId>,
244 storage_identifier: StorageIdentifier,
245 origin: ImmutableOrigin,
246 sender: GenericSender<Result<StorageProxyMap, String>>,
247 },
248 CreateDatabase {
249 bottle_id: i64,
250 name: String,
251 sender: GenericSender<Result<(PathBuf, bool), String>>,
253 },
254 DeleteDatabase {
255 bottle_id: i64,
256 name: String,
257 sender: GenericSender<Result<(), String>>,
258 },
259 Persisted {
260 origin: ImmutableOrigin,
261 sender: GenericCallback<Result<bool, String>>,
262 },
263 Persist {
264 origin: ImmutableOrigin,
265 permission_granted: bool,
266 sender: GenericCallback<Result<bool, String>>,
267 },
268 Estimate {
269 origin: ImmutableOrigin,
270 sender: GenericCallback<Result<(u64, u64), String>>,
271 },
272 Exit(GenericSender<()>),
273}