Skip to content

chore: unified cookie storage - WPB-23404#4596

Open
samwyndham wants to merge 75 commits intodevelopfrom
chore/review-cookie-handling-WPB-23404
Open

chore: unified cookie storage - WPB-23404#4596
samwyndham wants to merge 75 commits intodevelopfrom
chore/review-cookie-handling-WPB-23404

Conversation

@samwyndham
Copy link
Copy Markdown
Contributor

@samwyndham samwyndham commented Apr 21, 2026

TaskWPB-23404 [iOS] Review cookie handling

Issue

My apologies. This PR has turned into something much bigger than I intended 🙏.

Currently the app has two versions of CookieStorage - the legacy obj-c ZMPersistentCookieStorage & the new CookieStorage. There are some issues with this such as the legacy version using a cache and the new one not... E.g. if the cookie is updated via the new cookie storage, this may not be reflected in the legacy cookie due to it's cache.

This PR attempts to unify the cookie storage mechanisms and make some other safety improvements to try to make everything work well in a concurrent and multiprocess environment. Specifically it:

  • Refactors CookieStorage making it a non actor and removing async methods so that it can be used from non async contexts. It's access it protected by a lock to ensure that storing, fetching & deleting are generally atomic operations.
  • Made CookieStorage act on all users not a single user. Eg. a call to fetchCookies() is now fetchCookies(userID: UUID). The reasoning for this is that 1. in some cases cookie storage is not cleanly tied to a user session, 2. There are currently some static methods on LegacyCookieStorage (e.g. testing that any cookie exists). These methods should move to CookieStorage eventually and it would be better to make them non static to allow for injection etc.
  • Moves in memory cache to CookieStorage and changes how it works. We now store an epoch as metadata to Keychain items when they are . When adding to the cache we also store the epoch. When fetching from the cache we compare an items epoch to that in the Keychain to determine if the cached item is still valid. This works across processes meaning that we can now uses caching in app extensions and an cookie update coming from an app extension would now not break the cache in the main app (I'm not sure this happens in practice but believe it could happen).
  • Refactored ZMPersistentCookieStorage into LegacyCookieStorage which now wraps CookieStorage and is a much simpler object. Interestingly I started this refactor by using Claude to convert ZMPersistentCookieStorage and its tests from obj-c to swift. This worked well.
  • Moved CookieStorageTests to the app test target so that I could write tests against the real keychain - I think this is worthwhile vs mocking because we can see that the behavior is really what we expect.
  • Removed the concept of cookie policies from the legacy store as in practice this was always NSHTTPCookieAcceptPolicyAlways.

This PR also fixes: https://wearezeta.atlassian.net/browse/WPB-24720

@johnxnguyen @netbe I accidently merged as dependent PR - 84eafe5 - into this before this was reviewed. This contains UI tests and has been independently reviewed. Feel free to skip over reviewing the UI test code.

Testing

General regression test logging in & out of multiple accounts, and making use of app extensions.


Checklist

  • Title contains a reference JIRA issue number like [WPB-XXX].
  • Description is filled and free of optional paragraphs.
  • Adds/updates automated tests.

This is dead code apart from in tests
Account name should be unique per server. That is the assumption we are making when storing in the keychain so no point doing something different for the cache. As far as I understand it was only there for legacy migrations
This is a Swift version of ZMPersistentCookieStorage
This file isn't used

# Conflicts:
#	WireNetwork/Sources/WireNetwork/Assembly.swift
@samwyndham samwyndham requested review from johnxnguyen and netbe April 21, 2026 08:53
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Test Results – WireTransport

  1 files   30 suites   9s ⏱️
462 tests 461 ✅ 0 💤 1 ❌
462 runs  462 ✅ 0 💤 0 ❌

For more details on these failures, see this check.

Results for commit 98643d8.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Test Results – WireFoundationAll

47 tests   47 ✅  9s ⏱️
11 suites   0 💤
 1 files     0 ❌

Results for commit 98643d8.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Test Results – WireNetworkAll

375 tests   375 ✅  7s ⏱️
 37 suites    0 💤
  1 files      0 ❌

Results for commit 98643d8.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Test Results – WireDomain

  1 files  139 suites   20s ⏱️
547 tests 546 ✅ 0 💤 1 ❌
548 runs  548 ✅ 0 💤 0 ❌

For more details on these failures, see this check.

Results for commit 98643d8.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Test Results – WireMockTransport

237 tests   237 ✅  24s ⏱️
 25 suites    0 💤
  1 files      0 ❌

Results for commit 98643d8.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Test Results – WireSyncEngine

1 106 tests   1 106 ✅  1m 28s ⏱️
  133 suites      0 💤
    1 files        0 ❌

Results for commit 98643d8.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Test Results – WireDataModel

2 377 tests   2 377 ✅  4m 2s ⏱️
  245 suites      0 💤
    1 files        0 ❌

Results for commit 98643d8.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Test Results – Wire-iOS

1 879 tests   1 851 ✅  2m 14s ⏱️
  302 suites     27 💤
    1 files        1 ❌

For more details on these failures, see this check.

Results for commit 98643d8.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Test Results – WireShareEngine

15 tests   15 ✅  0s ⏱️
 4 suites   0 💤
 1 files     0 ❌

Results for commit 98643d8.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Test Results – WireMessagingAll

302 tests   289 ✅  3m 17s ⏱️
 59 suites    0 💤
  1 files     13 ❌

For more details on these failures, see this check.

Results for commit 98643d8.

♻️ This comment has been updated with latest results.

@datadog-wireapp
Copy link
Copy Markdown

datadog-wireapp Bot commented Apr 21, 2026

Tests

Fix all issues with Cursor

⚠️ Warnings

🧪 14 Tests failed

testThatItRendersLinkPreviewMessagePreview() from Wire-iOS-Tests.MessageReplyPreviewViewTests   View in Datadog   (Fix with Cursor)
Test crashed with signal segv.
hasMore() from WireMessagingTests.FilesViewModelTests   View in Datadog   (Fix with Cursor)
Test crashed with signal trap.
isLoading() from WireMessagingTests.FilesViewModelTests   View in Datadog   (Fix with Cursor)
Test crashed with signal trap.
View all

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 98643d8 | Docs | Give us feedback!

Copy link
Copy Markdown
Collaborator

@johnxnguyen johnxnguyen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Left a couple comments.

Comment thread wire-ios/Wire-iOS Tests/Authentication/CookieStorageTests.swift
samwyndham added 2 commits May 5, 2026 14:10
# Conflicts:
#	wire-ios-sync-engine/Source/SessionManager/SessionManager.swift
#	wire-ios-sync-engine/Source/UserSession/ZMUserSession/ZMUserSession.swift
#	wire-ios-sync-engine/WireSyncEngine.xcodeproj/project.pbxproj
#	wire-ios/WireUITests/FederationTests.swift
#	wire-ios/WireUITests/Helper/WireUITestCase.swift
#	wire-ios/WireUITests/MultiBackendSupportTests.swift
do {
try cookieStorage.storeCookies(userInfo.cookies)
} catch {
WireLogger.authentication.critical("Failed to store cookies: \(error)")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: if it's critical we could add a assertionFailure here for debug

Copy link
Copy Markdown
Contributor Author

@samwyndham samwyndham May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't bothered adding the assertionFailure because I don't want to add too much code. I feel that it should be done via requireInternal(::file:line:) but I think that method needs to work to ensure it works in safe public which is outside the scope of this PR.

Copy link
Copy Markdown
Collaborator

@netbe netbe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, left some suggestions, also check sonarQube comments some are relevant can be fixed by any AI tool

do {
try cookieStorage.storeCookies(userInfo.cookies)
} catch {
WireLogger.authentication.critical("Failed to store cookies: \(error)")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: if it's critical we could add a assertionFailure here for debug

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider if the error should be safePublic

Copy link
Copy Markdown
Contributor Author

@samwyndham samwyndham May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented as safe public in 799f528.

I haven't bothered adding the assertionFailure because I don't want to add too much code. I feel that it should be done via requireInternal(_:_:file:line:) but I think that method needs to work to ensure it works in safe public which is outside the scope of this PR.

Comment thread wire-ios-sync-engine/Source/UserSession/ZMUserSession/ZMUserSession.swift Outdated
Comment thread wire-ios-sync-engine/Source/UserSession/ZMClientRegistrationStatus.swift Outdated
Comment thread wire-ios-transport/Source/Authentication/LegacyCookieStorage.swift Outdated
Comment thread wire-ios/WireUITests/MultiBackendSupportTests.swift
Comment thread WireDomain/Sources/WireDomain/Account/AccountManager.swift
@samwyndham
Copy link
Copy Markdown
Contributor Author

"DO NOT MERGE" label is applied as there is a crash when sending gifs (due to a nil response)

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 8, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants