browser_window/core/cookie/
c.rs1use std::{
2 borrow::Cow,
3 ffi::c_void,
4 mem::MaybeUninit,
5 ops::Add,
6 os::raw::c_uint,
7 ptr,
8 time::{Duration, SystemTime},
9};
10
11use browser_window_c::*;
12
13use super::*;
14
15pub struct CookieImpl(pub(crate) *mut cbw_Cookie);
16
17pub struct CookieMutImpl(CookieImpl);
18
19pub struct CookieJarImpl(pub(crate) *mut cbw_CookieJar);
20
21pub struct CookieIteratorImpl(pub(crate) *mut cbw_CookieIterator);
22
23struct CookieStorageCallbackData {
24 callback: CookieStorageCallbackFn,
25 data: *mut (),
26}
27
28struct CookieDeleteCallbackData {
29 callback: CookieDeleteCallbackFn,
30 data: *mut (),
31}
32
33struct CookieIteratorNextCallbackData {
34 callback: CookieIteratorNextCallbackFn,
35 data: *mut (),
36}
37
38impl CookieExt for CookieImpl {
39 fn creation_time(&self) -> SystemTime {
40 let timestamp = unsafe { cbw_Cookie_getCreationTime(self.0) };
41
42 SystemTime::UNIX_EPOCH.add(Duration::from_millis(timestamp))
43 }
44
45 fn expires(&self) -> Option<SystemTime> {
46 let timestamp = unsafe { cbw_Cookie_getExpires(self.0) };
47
48 if timestamp != 0 {
49 Some(SystemTime::UNIX_EPOCH.add(Duration::from_millis(timestamp)))
50 } else {
51 None
52 }
53 }
54
55 fn domain<'a>(&'a self) -> Cow<'a, str> {
56 let slice;
57 let owned;
58 unsafe {
59 let mut slice_uninit: MaybeUninit<cbw_StrSlice> = MaybeUninit::uninit();
60 owned = cbw_Cookie_getDomain(self.0, slice_uninit.as_mut_ptr());
61 slice = slice_uninit.assume_init();
62 }
63
64 if owned > 0 {
65 let string: String = slice.into();
66 unsafe { cbw_string_free(slice) };
67 string.into()
68 } else {
69 let string: &str = slice.into();
70 string.into()
71 }
72 }
73
74 fn free(&mut self) { unsafe { cbw_Cookie_free(self.0) }; }
75
76 fn is_http_only(&self) -> bool { (unsafe { cbw_Cookie_isHttpOnly(self.0) }) > 0 }
77
78 fn is_secure(&self) -> bool { (unsafe { cbw_Cookie_isSecure(self.0) }) > 0 }
79
80 fn name<'a>(&'a self) -> Cow<'a, str> {
81 let slice;
82 let owned;
83 unsafe {
84 let mut slice_uninit: MaybeUninit<cbw_StrSlice> = MaybeUninit::uninit();
85 owned = cbw_Cookie_getName(self.0, slice_uninit.as_mut_ptr());
86 slice = slice_uninit.assume_init();
87 }
88
89 if owned > 0 {
90 let string: String = slice.into();
91 unsafe { cbw_string_free(slice) };
92 string.into()
93 } else {
94 let string: &str = slice.into();
95 string.into()
96 }
97 }
98
99 fn new(name: &str, value: &str) -> Self {
100 let inner = unsafe { cbw_Cookie_new(name.into(), value.into()) };
101
102 Self(inner)
103 }
104
105 fn path<'a>(&'a self) -> Cow<'a, str> {
106 let slice;
107 let owned;
108 unsafe {
109 let mut slice_uninit: MaybeUninit<cbw_StrSlice> = MaybeUninit::uninit();
110 owned = cbw_Cookie_getPath(self.0, slice_uninit.as_mut_ptr());
111 slice = slice_uninit.assume_init();
112 }
113
114 if owned > 0 {
115 let string: String = slice.into();
116 unsafe { cbw_string_free(slice) };
117 string.into()
118 } else {
119 let string: &str = slice.into();
120 string.into()
121 }
122 }
123
124 fn value<'a>(&'a self) -> Cow<'a, str> {
125 let slice;
126 let owned;
127 unsafe {
128 let mut slice_uninit: MaybeUninit<cbw_StrSlice> = MaybeUninit::uninit();
129 owned = cbw_Cookie_getValue(self.0, slice_uninit.as_mut_ptr());
130 slice = slice_uninit.assume_init();
131 }
132
133 if owned > 0 {
134 let string: String = slice.into();
135 unsafe { cbw_string_free(slice) };
136 string.into()
137 } else {
138 let string: &str = slice.into();
139 string.into()
140 }
141 }
142
143 fn make_http_only(&mut self) { unsafe { cbw_Cookie_makeHttpOnly(self.0) }; }
144
145 fn make_secure(&mut self) { unsafe { cbw_Cookie_makeSecure(self.0) }; }
146
147 fn set_creation_time(&mut self, time: &SystemTime) {
148 unsafe {
149 cbw_Cookie_setCreationTime(
150 self.0,
151 time.duration_since(SystemTime::UNIX_EPOCH)
152 .unwrap()
153 .as_millis() as _,
154 )
155 };
156 }
157
158 fn set_expires(&mut self, time: &SystemTime) {
159 unsafe {
160 cbw_Cookie_setExpires(
161 self.0,
162 time.duration_since(SystemTime::UNIX_EPOCH)
163 .unwrap()
164 .as_millis() as _,
165 )
166 };
167 }
168
169 fn set_domain(&mut self, domain: &str) {
170 unsafe { cbw_Cookie_setDomain(self.0, domain.into()) };
171 }
172
173 fn set_name(&mut self, name: &str) { unsafe { cbw_Cookie_setName(self.0, name.into()) }; }
174
175 fn set_path(&mut self, path: &str) { unsafe { cbw_Cookie_setPath(self.0, path.into()) }; }
176
177 fn set_value(&mut self, value: &str) { unsafe { cbw_Cookie_setValue(self.0, value.into()) }; }
178}
179
180impl CookieJarExt for CookieJarImpl {
181 fn delete(
182 &mut self, url: &str, name: &str, complete_cb: CookieDeleteCallbackFn, cb_data: *mut (),
183 ) {
184 let data = Box::into_raw(Box::new(CookieDeleteCallbackData {
185 callback: complete_cb,
186 data: cb_data,
187 }));
188
189 unsafe {
190 cbw_CookieJar_delete(
191 self.0,
192 url.into(),
193 name.into(),
194 Some(ffi_cookie_delete_callback_handler),
195 data as _,
196 )
197 };
198 }
199
200 fn free(&mut self) { unsafe { cbw_CookieJar_free(self.0) }; }
201
202 fn global() -> Option<CookieJarImpl> {
203 let inner = unsafe { cbw_CookieJar_newGlobal() };
204
205 if inner != ptr::null_mut() {
206 Some(CookieJarImpl(inner))
207 } else {
208 None
209 }
210 }
211
212 fn iterator<'a>(&'a self, url: &str, include_http_only: bool) -> CookieIteratorImpl {
213 unsafe {
214 let mut iterator: *mut cbw_CookieIterator = ptr::null_mut();
215 cbw_CookieJar_iterator(
216 self.0,
217 &mut iterator as _,
218 if include_http_only { 1 } else { 0 },
219 url.into(),
220 );
221
222 return CookieIteratorImpl(iterator);
223 }
224 }
225
226 fn iterator_all<'a>(&'a self) -> CookieIteratorImpl {
227 let mut iterator = CookieIteratorImpl(ptr::null_mut());
228 unsafe {
229 cbw_CookieJar_iteratorAll(self.0, &mut iterator.0);
230 }
231 iterator
232 }
233
234 fn store(
235 &mut self, url: &str, cookie: &CookieImpl, complete_cb: Option<CookieStorageCallbackFn>,
236 cb_data: *mut (),
237 ) {
238 let data = if !complete_cb.is_none() {
239 Box::into_raw(Box::new(CookieStorageCallbackData {
240 callback: complete_cb.unwrap(),
241 data: cb_data,
242 }))
243 } else {
244 ptr::null_mut()
245 };
246
247 unsafe {
248 let mut error = cbw_CookieJar_store(
249 self.0,
250 url.into(),
251 cookie.0,
252 complete_cb.map(|_| ffi_cookie_storage_callback_handler as _),
253 data as _,
254 );
255
256 if error.code != 0 && !complete_cb.is_none() {
257 (complete_cb.unwrap())(
258 CookieJarImpl(self.0),
259 cb_data,
260 Err(CookieStorageError::Unknown),
261 );
262 }
263
264 cbw_Err_free(&mut error);
265 }
266 }
267}
268
269impl CookieIteratorExt for CookieIteratorImpl {
270 fn free(&mut self) { unsafe { cbw_CookieIterator_free(self.0) } }
271
272 fn next(&mut self, on_next: CookieIteratorNextCallbackFn, cb_data: *mut ()) -> bool {
273 let data = Box::into_raw(Box::new(CookieIteratorNextCallbackData {
274 callback: on_next,
275 data: cb_data,
276 }));
277
278 let success = unsafe {
279 cbw_CookieIterator_next(self.0, Some(ffi_cookie_iterator_next_handler), data as _)
280 };
281
282 return success > 0;
283 }
284}
285
286unsafe extern "C" fn ffi_cookie_storage_callback_handler(
287 cookie_jar: *mut cbw_CookieJar, _data: *mut c_void, error: cbw_Err,
288) {
289 let data_ptr = _data as *mut CookieStorageCallbackData;
290 let data: Box<CookieStorageCallbackData> = Box::from_raw(data_ptr);
291
292 let handle = CookieJarImpl(cookie_jar);
293 let result = if error.code == 0 {
294 Ok(())
295 } else {
296 Err(CookieStorageError::Unknown)
297 };
298
299 (data.callback)(handle, data.data, result);
300}
301
302unsafe extern "C" fn ffi_cookie_delete_callback_handler(
303 cookie_jar: *mut cbw_CookieJar, _data: *mut c_void, deleted: c_uint,
304) {
305 let data_ptr = _data as *mut CookieDeleteCallbackData;
306 let data: Box<CookieDeleteCallbackData> = Box::from_raw(data_ptr);
307
308 let handle = CookieJarImpl(cookie_jar);
309
310 (data.callback)(handle, data.data, deleted as _);
311}
312
313unsafe extern "C" fn ffi_cookie_iterator_next_handler(
314 cookie_iterator: *mut cbw_CookieIterator, _data: *mut c_void, inner: *mut cbw_Cookie,
315) {
316 let data_ptr = _data as *mut CookieIteratorNextCallbackData;
317 let data: Box<CookieIteratorNextCallbackData> = Box::from_raw(data_ptr);
318
319 let handle = CookieIteratorImpl(cookie_iterator);
320 let cookie = if inner == ptr::null_mut() {
321 None
322 } else {
323 Some(CookieImpl(inner))
324 };
325
326 (data.callback)(handle, data.data, cookie);
327}