Skip to content

Commit 61e53ab

Browse files
committed
feat: implement for wkwebview
1 parent ff4fed5 commit 61e53ab

File tree

3 files changed

+123
-3
lines changed

3 files changed

+123
-3
lines changed

src/android/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,16 @@ impl InnerWebView {
416416
rx.recv_timeout(MAIN_PIPE_TIMEOUT).map_err(Into::into)
417417
}
418418

419+
pub fn set_cookie(&self, cookie: &cookie::Cookie<'_>) -> Result<()> {
420+
// Unsupported
421+
Ok(())
422+
}
423+
424+
pub fn delete_cookie(&self, cookie: &cookie::Cookie<'_>) -> Result<()> {
425+
// Unsupported
426+
Ok(())
427+
}
428+
419429
pub fn cookies(&self) -> Result<Vec<cookie::Cookie<'static>>> {
420430
Ok(Vec::new())
421431
}

src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,11 +1836,19 @@ impl WebView {
18361836
}
18371837

18381838
/// Set a cookie for the webview.
1839+
///
1840+
/// ## Platform-specific
1841+
///
1842+
/// - **Android**: Not supported.
18391843
pub fn set_cookie(&self, cookie: &cookie::Cookie<'_>) -> Result<()> {
18401844
self.webview.set_cookie(cookie)
18411845
}
18421846

18431847
/// Delete a cookie for the webview.
1848+
///
1849+
/// ## Platform-specific
1850+
///
1851+
/// - **Android**: Not supported.
18441852
pub fn delete_cookie(&self, cookie: &cookie::Cookie<'_>) -> Result<()> {
18451853
self.webview.delete_cookie(cookie)
18461854
}

src/wkwebview/mod.rs

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@ use objc2_core_foundation::CGSize;
4444
use objc2_core_foundation::{CGPoint, CGRect};
4545
use objc2_foundation::{
4646
ns_string, MainThreadMarker, NSArray, NSBundle, NSDate, NSError, NSHTTPCookie,
47-
NSHTTPCookieSameSiteLax, NSHTTPCookieSameSiteStrict, NSJSONSerialization, NSMutableURLRequest,
48-
NSNumber, NSObjectNSKeyValueCoding, NSObjectProtocol, NSString, NSUTF8StringEncoding, NSURL,
49-
NSUUID,
47+
NSHTTPCookieDomain, NSHTTPCookieExpires, NSHTTPCookieMaximumAge, NSHTTPCookieName,
48+
NSHTTPCookiePath, NSHTTPCookiePropertyKey, NSHTTPCookieSameSiteLax, NSHTTPCookieSameSiteStrict,
49+
NSHTTPCookieSecure, NSHTTPCookieValue, NSHTTPCookieVersion, NSJSONSerialization,
50+
NSMutableDictionary, NSMutableURLRequest, NSNumber, NSObjectNSKeyValueCoding, NSObjectProtocol,
51+
NSString, NSUTF8StringEncoding, NSURL, NSUUID,
5052
};
5153
#[cfg(target_os = "ios")]
5254
use objc2_ui_kit::{UIScrollView, UIViewAutoresizing};
@@ -979,6 +981,70 @@ r#"Object.defineProperty(window, 'ipc', {
979981
cookie_builder.build()
980982
}
981983

984+
unsafe fn cookie_into_wkwebview(cookie: &cookie::Cookie<'_>) -> Retained<NSHTTPCookie> {
985+
let nstring_true: &'static NSString = ns_string!("TRUE");
986+
let nstring_false: &'static NSString = ns_string!("FALSE");
987+
let nstring_0: &'static NSString = ns_string!("0");
988+
let nstring_1: &'static NSString = ns_string!("1");
989+
990+
let name = NSString::from_str(cookie.name());
991+
let value = NSString::from_str(cookie.value());
992+
let path = cookie.path().map_or_else(NSString::new, NSString::from_str);
993+
let domain = cookie
994+
.domain()
995+
.map_or_else(NSString::new, NSString::from_str);
996+
997+
let properties: Retained<NSMutableDictionary<NSHTTPCookiePropertyKey, AnyObject>> =
998+
NSMutableDictionary::from_slices(
999+
&[
1000+
NSHTTPCookieName,
1001+
NSHTTPCookieValue,
1002+
NSHTTPCookiePath,
1003+
NSHTTPCookieDomain,
1004+
],
1005+
&[&*name, &*value, &*path, &*domain],
1006+
);
1007+
1008+
if let Some(max_age_) = cookie.max_age() {
1009+
let max_age = NSString::from_str(&max_age_.whole_seconds().to_string());
1010+
properties.insert(NSHTTPCookieMaximumAge, &*max_age);
1011+
properties.insert(NSHTTPCookieVersion, nstring_1);
1012+
} else if let Some(dt) = cookie.expires_datetime() {
1013+
let expires = NSDate::dateWithTimeIntervalSince1970(dt.unix_timestamp() as f64);
1014+
properties.insert(NSHTTPCookieExpires, &*expires);
1015+
properties.insert(NSHTTPCookieVersion, nstring_0);
1016+
}
1017+
1018+
if let Some(secure) = cookie.secure() {
1019+
let secure = if secure { nstring_true } else { nstring_false };
1020+
properties.insert(NSHTTPCookieSecure, secure);
1021+
}
1022+
1023+
if let Some(http_only) = cookie.http_only() {
1024+
let http_only = if http_only {
1025+
nstring_true
1026+
} else {
1027+
nstring_false
1028+
};
1029+
// ref:
1030+
// - <https://stackoverflow.com/a/41697557>
1031+
// - <https://developer.apple.com/forums/thread/701770?answerId=706717022#706717022>
1032+
properties.insert(ns_string!("HttpOnly"), http_only);
1033+
}
1034+
1035+
let wkwebview_cookie = NSHTTPCookie::cookieWithProperties(&properties)
1036+
.expect("failed to create wkwebview cookie, report this as bug to `wry`");
1037+
1038+
// check if `HttpOnly` works as expected
1039+
debug_assert_eq!(
1040+
wkwebview_cookie.isHTTPOnly(),
1041+
cookie.http_only().unwrap_or(false),
1042+
"HTTPOnly mismatch, report this as bug to `wry`"
1043+
);
1044+
1045+
wkwebview_cookie
1046+
}
1047+
9821048
pub fn cookies_for_url(&self, url: &str) -> Result<Vec<cookie::Cookie<'static>>> {
9831049
let url = url::Url::parse(url)?;
9841050

@@ -1026,6 +1092,42 @@ r#"Object.defineProperty(window, 'ipc', {
10261092
}
10271093
}
10281094

1095+
pub fn set_cookie(&self, cookie: &cookie::Cookie<'_>) -> Result<()> {
1096+
let (tx, rx) = std::sync::mpsc::channel();
1097+
1098+
unsafe {
1099+
let wkwebview_cookie = Self::cookie_into_wkwebview(cookie);
1100+
self
1101+
.data_store
1102+
.httpCookieStore()
1103+
.setCookie_completionHandler(
1104+
&wkwebview_cookie,
1105+
Some(&block2::RcBlock::new(move || {
1106+
let _ = tx.send(());
1107+
})),
1108+
);
1109+
wait_for_blocking_operation(rx)
1110+
}
1111+
}
1112+
1113+
pub fn delete_cookie(&self, cookie: &cookie::Cookie<'_>) -> Result<()> {
1114+
let (tx, rx) = std::sync::mpsc::channel();
1115+
1116+
unsafe {
1117+
let wkwebview_cookie = Self::cookie_into_wkwebview(cookie);
1118+
self
1119+
.data_store
1120+
.httpCookieStore()
1121+
.deleteCookie_completionHandler(
1122+
&wkwebview_cookie,
1123+
Some(&block2::RcBlock::new(move || {
1124+
let _ = tx.send(());
1125+
})),
1126+
);
1127+
wait_for_blocking_operation(rx)
1128+
}
1129+
}
1130+
10291131
#[cfg(target_os = "macos")]
10301132
pub(crate) fn reparent(&self, window: *mut NSWindow) -> crate::Result<()> {
10311133
unsafe {

0 commit comments

Comments
 (0)