browser_window/core/cookie/
c.rs

1use 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}