Hi, thanks for maintaining ComposeNativeWebView.
While integrating the library's CookieManager across Android, Desktop/Wry, and iOS, I noticed a few iOS-specific cookie handling issues that may cause inconsistent behavior across platforms.
The public/common Cookie.expiresDate appears to be treated as a millisecond timestamp on Android/JVM/Desktop/Wry, but the iOS implementation currently passes it directly to NSDate.dateWithTimeIntervalSince1970, whose input is seconds.
This can make iOS cookie expiration dates incorrect by a factor of 1000.
Affected area
webview-compose/src/iosMain/kotlin/.../cookie/IOSCookieManager.kt
Relevant behavior:
expiresDate = cookie.expiresDate?.timeIntervalSince1970?.toLong()
and:
NSDate.dateWithTimeIntervalSince1970(expires.toDouble())
Issues found
1. expiresDate unit mismatch on iOS
Other platforms appear to use milliseconds:
- Android/JVM use
Date(expiresDate)
- Wry-side field is named/handled as
expires_date_ms
- Ktor-style timestamps are usually milliseconds
But iOS APIs use seconds:
NSDate.dateWithTimeIntervalSince1970(...)
NSHTTPCookie.expiresDate?.timeIntervalSince1970
So iOS should likely convert:
// writing to iOS
NSDate.dateWithTimeIntervalSince1970(expiresMs / 1000.0)
// reading from iOS
(cookie.expiresDate?.timeIntervalSince1970?.times(1000))?.toLong()
2. domain = null becomes an empty iOS cookie domain
Current behavior appears to use:
NSHTTPCookieDomain to (cookie.domain ?: "")
For host-only cookies, it may be better to derive the host from the request URL when cookie.domain is null or blank.
Suggested behavior:
NSHTTPCookieDomain to (cookie.domain?.takeIf { it.isNotBlank() } ?: urlHost)
3. URL/domain matching uses string containment
The iOS implementation appears to match cookies with logic similar to:
url.contains(cookie.domain.removePrefix("."))
This may produce false positives or false negatives. A safer check would parse the URL host and compare:
host == cookieDomain || host.endsWith(".$cookieDomain")
Path matching could also follow normal cookie path rules.
Expected behavior
Cookie behavior should be consistent across Android, Desktop/Wry, and iOS:
Cookie.expiresDate has one documented unit across all platforms, preferably milliseconds.
- Host-only cookies can be set from a request URL without requiring an explicit domain.
getCookies(url) and removeCookies(url) match cookies by parsed host/path rather than substring matching.
Suggested fix
- Document
Cookie.expiresDate as milliseconds.
- Convert milliseconds ↔ seconds inside the iOS adapter.
- Derive domain from request URL when
cookie.domain is null/blank.
- Replace
url.contains(...) matching with parsed URL host/path matching.
Notes
This issue was found during cross-platform cookie synchronization testing. No app-specific behavior is required to reproduce the underlying problem; it appears to be in the iOS platform adapter itself.
Thanks again for the library.
Hi, thanks for maintaining ComposeNativeWebView.
While integrating the library's
CookieManageracross Android, Desktop/Wry, and iOS, I noticed a few iOS-specific cookie handling issues that may cause inconsistent behavior across platforms.The public/common
Cookie.expiresDateappears to be treated as a millisecond timestamp on Android/JVM/Desktop/Wry, but the iOS implementation currently passes it directly toNSDate.dateWithTimeIntervalSince1970, whose input is seconds.This can make iOS cookie expiration dates incorrect by a factor of 1000.
Affected area
webview-compose/src/iosMain/kotlin/.../cookie/IOSCookieManager.ktRelevant behavior:
expiresDate = cookie.expiresDate?.timeIntervalSince1970?.toLong()and:
NSDate.dateWithTimeIntervalSince1970(expires.toDouble())Issues found
1.
expiresDateunit mismatch on iOSOther platforms appear to use milliseconds:
Date(expiresDate)expires_date_msBut iOS APIs use seconds:
So iOS should likely convert:
2.
domain = nullbecomes an empty iOS cookie domainCurrent behavior appears to use:
For host-only cookies, it may be better to derive the host from the request URL when
cookie.domainis null or blank.Suggested behavior:
3. URL/domain matching uses string containment
The iOS implementation appears to match cookies with logic similar to:
url.contains(cookie.domain.removePrefix("."))This may produce false positives or false negatives. A safer check would parse the URL host and compare:
Path matching could also follow normal cookie path rules.
Expected behavior
Cookie behavior should be consistent across Android, Desktop/Wry, and iOS:
Cookie.expiresDatehas one documented unit across all platforms, preferably milliseconds.getCookies(url)andremoveCookies(url)match cookies by parsed host/path rather than substring matching.Suggested fix
Cookie.expiresDateas milliseconds.cookie.domainis null/blank.url.contains(...)matching with parsed URL host/path matching.Notes
This issue was found during cross-platform cookie synchronization testing. No app-specific behavior is required to reproduce the underlying problem; it appears to be in the iOS platform adapter itself.
Thanks again for the library.