-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Include duck AI chat deletions in sync engine #7354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
06dea1c to
1dfedc6
Compare
45fe17a to
dbca43a
Compare
1dfedc6 to
90905ef
Compare
0d8a790 to
1a80afa
Compare
app/src/main/java/com/duckduckgo/app/browser/weblocalstorage/WebLocalStorageManager.kt
Outdated
Show resolved
Hide resolved
1a80afa to
6833195
Compare
...chat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/sync/DuckChatSyncRepository.kt
Show resolved
Hide resolved
malmstein
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven’t tested the functionality yet, just reviewed the code. I don’t understand why you need to store timestamp out of MainProcessLifecycleObserver, maybe we can chat tomorrow.
app/src/main/java/com/duckduckgo/app/browser/weblocalstorage/WebLocalStorageManager.kt
Outdated
Show resolved
Hide resolved
duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/feature/DuckChatFeature.kt
Outdated
Show resolved
Hide resolved
...hat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/sync/DuckChatSyncDataManager.kt
Outdated
Show resolved
Hide resolved
...chat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/sync/DuckChatSyncRepository.kt
Show resolved
Hide resolved
duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/RealDuckChat.kt
Outdated
Show resolved
Hide resolved
sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/AppDeviceSyncState.kt
Outdated
Show resolved
Hide resolved
sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/engine/SyncApiClient.kt
Show resolved
Hide resolved
sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/engine/RealSyncEngine.kt
Outdated
Show resolved
Hide resolved
sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/engine/RealSyncEngine.kt
Outdated
Show resolved
Hide resolved
sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/engine/RealSyncEngine.kt
Outdated
Show resolved
Hide resolved
6833195 to
38e016a
Compare
90905ef to
ab4b982
Compare
7f14801 to
c7269ca
Compare
...hat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/sync/DuckChatSyncDataManager.kt
Show resolved
Hide resolved
c7269ca to
3b1274f
Compare
sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/engine/RealSyncEngine.kt
Show resolved
Hide resolved
b537d28 to
9f55739
Compare
duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/feature/DuckChatFeature.kt
Show resolved
Hide resolved
9f55739 to
7076d7e
Compare
e779640 to
79a5707
Compare
79a5707 to
c3d194b
Compare
ab4b982 to
b1fd8d9
Compare
c3d194b to
4becbdb
Compare
We want the timestamp when app is going to the background because if the automatic data clearing is used then that is the timestamp that is used for the |
4becbdb to
29fc78f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Second clearWebLocalStorage overload doesn't notify deletion listeners
The clearWebLocalStorage(shouldClearBrowserData, shouldClearDuckAiData) overload deletes duck AI data when shouldClearDuckAiData is true (lines 152-156) but does not notify the duckAiChatDeletionListeners. Only the first overload clearWebLocalStorage() (lines 76-120) was updated to track deletions with duckAiDataDeleted and notify listeners. This means duck AI chat deletions via this second code path won't be synced to other devices, breaking the sync feature for scenarios that use this overload.
Please tell me if this was useful or not with a 👍 or 👎.
app/src/main/java/com/duckduckgo/app/browser/weblocalstorage/WebLocalStorageManager.kt#L121-L161
Android/app/src/main/java/com/duckduckgo/app/browser/weblocalstorage/WebLocalStorageManager.kt
Lines 121 to 161 in 29fc78f
| override suspend fun clearWebLocalStorage( | |
| shouldClearBrowserData: Boolean, | |
| shouldClearDuckAiData: Boolean, | |
| ) { | |
| withContext(dispatcherProvider.io()) { | |
| val settings = androidBrowserConfigFeature.webLocalStorage().getSettings() | |
| val webLocalStorageSettings = webLocalStorageSettingsJsonParser.parseJson(settings) | |
| val fireproofedDomains = fireproofWebsiteRepository.fireproofWebsitesSync().map { it.domain } | |
| domains = webLocalStorageSettings.domains.list + fireproofedDomains | |
| keysToDelete = webLocalStorageSettings.keysToDelete.list | |
| matchingRegex = webLocalStorageSettings.matchingRegex.list | |
| logcat { "WebLocalStorageManager: Allowed domains: $domains" } | |
| logcat { "WebLocalStorageManager: Keys to delete: $keysToDelete" } | |
| logcat { "WebLocalStorageManager: Matching regex: $matchingRegex" } | |
| val db = databaseProvider.get() | |
| db.iterator().use { iterator -> | |
| iterator.seekToFirst() | |
| while (iterator.hasNext()) { | |
| val entry = iterator.next() | |
| val key = String(entry.key, StandardCharsets.UTF_8) | |
| val domainForMatchingAllowedKey = getDomainForMatchingAllowedKey(key) | |
| if (domainForMatchingAllowedKey == null && shouldClearBrowserData) { | |
| db.delete(entry.key) | |
| logcat { "WebLocalStorageManager: Deleted key: $key" } | |
| } else if (shouldClearDuckAiData && DUCKDUCKGO_DOMAINS.contains(domainForMatchingAllowedKey)) { | |
| if (keysToDelete.any { key.endsWith(it) }) { | |
| db.delete(entry.key) | |
| logcat { "WebLocalStorageManager: Deleted key: $key" } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } |
f3e5f30 to
e0b3b07
Compare
malmstein
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, thanks for taking the feedback @CDRussell !
c651d8e to
7636a72
Compare
7636a72 to
3dfdcb3
Compare
| override fun onStart(owner: LifecycleOwner) { | ||
| appBackgroundedTimestamp = null | ||
| logcat { "DuckChat-Sync: App came to foreground, cleared background timestamp" } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Background timestamp lost if user foregrounds during clearing
When automatic data clearing runs while the app is backgrounded, onStart (main thread) could clear appBackgroundedTimestamp before onDuckAiChatsDeleted (IO thread) reads it. In this scenario, the deletion timestamp falls back to System.currentTimeMillis() instead of the intended background timestamp. The PR description explicitly states the background timestamp should be used for automatic clearing, so this timing issue deviates from the stated behavior.
Please tell me if this was useful or not with a 👍 or 👎.

Task/Issue URL: https://app.asana.com/1/137249556945/project/72649045549333/task/1212290226255075?focus=true
Description
Ensures sync backend is aware of fire button usage (and automatic data clearing) so duck chat deletions can be synced.
Steps to test this PR
Logcat filter:
Sync disabled / fire button
internalflavor from this branchSettings->Data Clearingand enableClear Duck.ai Chatstoggleduck ai chatbutton. Type a message and send it so there is a chat history.duck AI chats cleared: truerecorded deletion timestampwith a timestamp that was very recently (e.g., some milliseconds ago)Duck AI chats deletion sync successful(because sync isn't enabled)Sync disabled / automatic data clearing
Settings->Data Clearingand tap onAutomatically Clear Data...and chooseTabs, data and Duck.ai chatsClear on...and choose the bottom option with5 secondsduck ai chatbutton. Type a message and send it so there is a chat history.recorded deletion timestampwith a timestamp that was a few seconds ago (e.g., 4.5s - 5s ago); we use the timestamp when the app goes to background in the case of automatic data clearingSync enabled / fire button
Settings->Sync & Backup->Sync and Back Up This Device)duck ai chatbutton. Type a message and send it so there is a chat history.Duck AI chats deletion sync successfulcleared local deletion timestampSmoke test sync generally
Note
Adds end-to-end support to record, expose, and sync Duck AI chat deletions (local clear → timestamp → sync DELETE /sync/ai_chats), with engine and API extensions plus feature gating.
DeletableType(DUCK_AI_CHATS),DeletableDataManager, and engine flow to process deletions before changes.SyncFeatureTypeand updateSyncDeletionRequest/Responseto useDeletableType.DELETE /sync/ai_chats(SyncService,SyncServiceRemote,SyncApiClient.delete), including error recording/pixels generalized toSyncFeatureType.DeletableDataManagerand tests across engine/client.DuckAiChatDeletionListenerAPI and plugin point (BrowserModule).WebLocalStorageManagernow detects and deletes Duck AI chat keys and notifies listeners on deletion.DuckAiChatDeletionListenerImplto capture app background timestamp and record deletions viaDuckChatSyncRepository/DuckChatSyncMetadataStore.DuckChatSyncDataManagersurfaces pending deletions to sync and clears timestamp on success; gated byDuckChatFeature.supportsSyncChatsDeletion().RealDuckChatexposesisChatSyncFeatureEnabledusingDeviceSyncState.isDuckChatSyncFeatureEnabled.SyncFeature.aiChatSync()andSyncFeatureToggle.allowAiChatSync()used byAppDeviceSyncState.isDuckChatSyncFeatureEnabled(); add method toDeviceSyncState(and fake impl).Written by Cursor Bugbot for commit 3dfdcb3. This will update automatically on new commits. Configure here.