use super::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SameSite {
None,
Lax,
Strict,
}
impl SameSite {
fn from_raw(value: COREWEBVIEW2_COOKIE_SAME_SITE_KIND) -> Self {
match value {
0 => Self::None,
2 => Self::Strict,
_ => Self::Lax,
}
}
fn to_raw(self) -> COREWEBVIEW2_COOKIE_SAME_SITE_KIND {
match self {
Self::None => 0,
Self::Lax => 1,
Self::Strict => 2,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Cookie {
pub name: String,
pub value: String,
pub domain: String,
pub path: String,
pub is_secure: bool,
pub is_http_only: bool,
pub same_site: SameSite,
pub expires: Option<f64>,
}
impl Cookie {
pub fn new(name: &str, value: &str, domain: &str, path: &str) -> Self {
Self {
name: name.to_string(),
value: value.to_string(),
domain: domain.to_string(),
path: path.to_string(),
is_secure: false,
is_http_only: false,
same_site: SameSite::Lax,
expires: None,
}
}
fn from_com(cookie: &ICoreWebView2Cookie) -> Result<Self> {
unsafe {
let expires = if cookie.IsSession()?.as_bool() {
None
} else {
Some(cookie.Expires()?)
};
Ok(Self {
name: string::take(cookie.Name()?),
value: string::take(cookie.Value()?),
domain: string::take(cookie.Domain()?),
path: string::take(cookie.Path()?),
is_secure: cookie.IsSecure()?.as_bool(),
is_http_only: cookie.IsHttpOnly()?.as_bool(),
same_site: SameSite::from_raw(cookie.SameSite()?),
expires,
})
}
}
}
pub struct CookieManager(pub(crate) ICoreWebView2CookieManager);
impl CookieManager {
pub fn get_cookies<F: FnOnce(Result<Vec<Cookie>>) + 'static>(
&self,
uri: &str,
handler: F,
) -> Result<()> {
let uri = HSTRING::from(uri);
let handler = handler::GetCookiesCompleted::create(handler);
unsafe { self.0.GetCookies(&uri, &handler) }.ok()
}
pub fn add_or_update_cookie(&self, cookie: &Cookie) -> Result<()> {
let name = HSTRING::from(&cookie.name);
let value = HSTRING::from(&cookie.value);
let domain = HSTRING::from(&cookie.domain);
let path = HSTRING::from(&cookie.path);
unsafe {
let raw = self.0.CreateCookie(&name, &value, &domain, &path)?;
raw.SetIsSecure(cookie.is_secure).ok()?;
raw.SetIsHttpOnly(cookie.is_http_only).ok()?;
raw.SetSameSite(cookie.same_site.to_raw()).ok()?;
if let Some(expires) = cookie.expires {
raw.SetExpires(expires).ok()?;
}
self.0.AddOrUpdateCookie(&raw).ok()
}
}
pub fn delete_cookies(&self, name: &str, uri: &str) -> Result<()> {
let name = HSTRING::from(name);
let uri = HSTRING::from(uri);
unsafe { self.0.DeleteCookies(&name, &uri) }.ok()
}
pub fn delete_cookies_with_domain_and_path(
&self,
name: &str,
domain: &str,
path: &str,
) -> Result<()> {
let name = HSTRING::from(name);
let domain = HSTRING::from(domain);
let path = HSTRING::from(path);
unsafe { self.0.DeleteCookiesWithDomainAndPath(&name, &domain, &path) }.ok()
}
pub fn delete_all_cookies(&self) -> Result<()> {
unsafe { self.0.DeleteAllCookies() }.ok()
}
}
pub(crate) fn collect(list: &ICoreWebView2CookieList) -> Result<Vec<Cookie>> {
let count = unsafe { list.Count()? };
let mut cookies = Vec::with_capacity(count as usize);
for index in 0..count {
let cookie = unsafe { list.GetValueAtIndex(index)? };
cookies.push(Cookie::from_com(&cookie)?);
}
Ok(cookies)
}