Aggregate data outside of the RealmCryptoStore.

This commit is contained in:
Benoit Marty 2023-01-05 11:04:20 +01:00 committed by Benoit Marty
parent 30940cb937
commit 27d32188bf
8 changed files with 60 additions and 57 deletions

View File

@ -89,6 +89,7 @@ import org.matrix.android.sdk.internal.crypto.model.SessionInfo
import org.matrix.android.sdk.internal.crypto.model.toRest
import org.matrix.android.sdk.internal.crypto.repository.WarnOnUnknownDeviceRepository
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
import org.matrix.android.sdk.internal.crypto.tasks.DeleteDeviceTask
import org.matrix.android.sdk.internal.crypto.tasks.GetDeviceInfoTask
import org.matrix.android.sdk.internal.crypto.tasks.GetDevicesTask
@ -192,21 +193,21 @@ internal class DefaultCryptoService @Inject constructor(
private val isStarting = AtomicBoolean(false)
private val isStarted = AtomicBoolean(false)
fun onStateEvent(roomId: String, event: Event) {
fun onStateEvent(roomId: String, event: Event, cryptoStoreAggregator: CryptoStoreAggregator?) {
when (event.type) {
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event)
EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event)
EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event, cryptoStoreAggregator)
}
}
fun onLiveEvent(roomId: String, event: Event, isInitialSync: Boolean) {
fun onLiveEvent(roomId: String, event: Event, isInitialSync: Boolean, cryptoStoreAggregator: CryptoStoreAggregator?) {
// handle state events
if (event.isStateEvent()) {
when (event.type) {
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event)
EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event)
EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event, cryptoStoreAggregator)
}
}
@ -384,7 +385,6 @@ internal class DefaultCryptoService @Inject constructor(
}
}
}
cryptoStore.onSyncWillProcess()
}
private fun internalStart() {
@ -432,8 +432,8 @@ internal class DefaultCryptoService @Inject constructor(
*
* @param syncResponse the syncResponse
*/
fun onSyncCompleted(syncResponse: SyncResponse) {
cryptoStore.onSyncCompleted()
fun onSyncCompleted(syncResponse: SyncResponse, cryptoStoreAggregator: CryptoStoreAggregator) {
cryptoStore.storeData(cryptoStoreAggregator)
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
runCatching {
if (syncResponse.deviceLists != null) {
@ -1000,15 +1000,26 @@ internal class DefaultCryptoService @Inject constructor(
}
}
private fun onRoomHistoryVisibilityEvent(roomId: String, event: Event) {
private fun onRoomHistoryVisibilityEvent(roomId: String, event: Event, cryptoStoreAggregator: CryptoStoreAggregator?) {
if (!event.isStateEvent()) return
val eventContent = event.content.toModel<RoomHistoryVisibilityContent>()
val historyVisibility = eventContent?.historyVisibility
if (historyVisibility == null) {
cryptoStore.setShouldShareHistory(roomId, false)
if (cryptoStoreAggregator != null) {
cryptoStoreAggregator.setShouldShareHistoryData[roomId] = false
} else {
// Store immediately
cryptoStore.setShouldShareHistory(roomId, false)
}
} else {
cryptoStore.setShouldEncryptForInvitedMembers(roomId, historyVisibility != RoomHistoryVisibility.JOINED)
cryptoStore.setShouldShareHistory(roomId, historyVisibility.shouldShareHistory())
if (cryptoStoreAggregator != null) {
cryptoStoreAggregator.setShouldEncryptForInvitedMembersData[roomId] = historyVisibility != RoomHistoryVisibility.JOINED
cryptoStoreAggregator.setShouldShareHistoryData[roomId] = historyVisibility.shouldShareHistory()
} else {
// Store immediately
cryptoStore.setShouldEncryptForInvitedMembers(roomId, historyVisibility != RoomHistoryVisibility.JOINED)
cryptoStore.setShouldShareHistory(roomId, historyVisibility.shouldShareHistory())
}
}
}

View File

@ -39,6 +39,7 @@ import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.crypto.model.MXInboundMegolmSessionWrapper
import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper
import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper
import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntity
import org.matrix.olm.OlmAccount
import org.matrix.olm.OlmOutboundGroupSession
@ -48,21 +49,6 @@ import org.matrix.olm.OlmOutboundGroupSession
*/
internal interface IMXCryptoStore {
/**
* Notify the store that a sync response treatment is starting.
* Impacted methods:
* - [setShouldShareHistory]
* - [setShouldEncryptForInvitedMembers]
* @See [onSyncCompleted] to notify that the treatment is over.
*/
fun onSyncWillProcess()
/**
* Notify the store that the sync treatment response is finished.
* The store will save all aggregated data.
*/
fun onSyncCompleted()
/**
* @return the device id
*/
@ -307,7 +293,11 @@ internal interface IMXCryptoStore {
fun shouldEncryptForInvitedMembers(roomId: String): Boolean
/**
* The data is not stored immediately, this MUST be call during a sync response treatment.
* Sets a boolean flag that will determine whether or not this device should encrypt Events for
* invited members.
*
* @param roomId the room id
* @param shouldEncryptForInvitedMembers The boolean flag
*/
fun setShouldEncryptForInvitedMembers(roomId: String, shouldEncryptForInvitedMembers: Boolean)
@ -316,7 +306,6 @@ internal interface IMXCryptoStore {
/**
* Sets a boolean flag that will determine whether or not room history (existing inbound sessions)
* will be shared to new user invites.
* The data is not stored immediately, this MUST be call during a sync response treatment.
*
* @param roomId the room id
* @param shouldShareHistory The boolean flag
@ -601,6 +590,11 @@ internal interface IMXCryptoStore {
fun tidyUpDataBase()
fun getOutgoingRoomKeyRequests(inStates: Set<OutgoingRoomKeyRequestState>): List<OutgoingKeyRequest>
/**
* Store a bunch of data collected during a sync response treatment. @See [CryptoStoreAggregator].
*/
fun storeData(cryptoStoreAggregator: CryptoStoreAggregator)
/**
* Store a bunch of data related to the users. @See [UserDataToStore].
*/

View File

@ -719,13 +719,17 @@ internal class RealmCryptoStore @Inject constructor(
}
override fun setShouldEncryptForInvitedMembers(roomId: String, shouldEncryptForInvitedMembers: Boolean) {
cryptoStoreAggregator?.setShouldEncryptForInvitedMembersData?.put(roomId, shouldEncryptForInvitedMembers)
doRealmTransaction("setShouldEncryptForInvitedMembers", realmConfiguration) {
CryptoRoomEntity.getOrCreate(it, roomId).shouldEncryptForInvitedMembers = shouldEncryptForInvitedMembers
}
}
override fun setShouldShareHistory(roomId: String, shouldShareHistory: Boolean) {
Timber.tag(loggerTag.value)
.v("setShouldShareHistory for room $roomId is $shouldShareHistory")
cryptoStoreAggregator?.setShouldShareHistoryData?.put(roomId, shouldShareHistory)
doRealmTransaction("setShouldShareHistory", realmConfiguration) {
CryptoRoomEntity.getOrCreate(it, roomId).shouldShareHistory = shouldShareHistory
}
}
override fun storeSession(olmSessionWrapper: OlmSessionWrapper, deviceKey: String) {
@ -1823,37 +1827,24 @@ internal class RealmCryptoStore @Inject constructor(
}
}
private var cryptoStoreAggregator: CryptoStoreAggregator? = null
override fun onSyncWillProcess() {
if (cryptoStoreAggregator != null) {
Timber.e("cryptoStoreAggregator is not null...")
}
cryptoStoreAggregator = CryptoStoreAggregator()
}
override fun onSyncCompleted() {
val aggregator = cryptoStoreAggregator ?: return Unit.also {
Timber.e("cryptoStoreAggregator is null...")
}
cryptoStoreAggregator = null
if (aggregator.isEmpty()) {
override fun storeData(cryptoStoreAggregator: CryptoStoreAggregator) {
if (cryptoStoreAggregator.isEmpty()) {
return
}
doRealmTransaction("onSyncCompleted", realmConfiguration) { realm ->
doRealmTransaction("storeData - CryptoStoreAggregator", realmConfiguration) { realm ->
// setShouldShareHistory
aggregator.setShouldShareHistoryData.forEach {
cryptoStoreAggregator.setShouldShareHistoryData.forEach {
CryptoRoomEntity.getOrCreate(realm, it.key).shouldShareHistory = it.value
}
// setShouldEncryptForInvitedMembers
aggregator.setShouldEncryptForInvitedMembersData.forEach {
cryptoStoreAggregator.setShouldEncryptForInvitedMembersData.forEach {
CryptoRoomEntity.getOrCreate(realm, it.key).shouldEncryptForInvitedMembers = it.value
}
}
}
override fun storeData(userDataToStore: UserDataToStore) {
doRealmTransaction("storeUserDataToStore", realmConfiguration) { realm ->
doRealmTransaction("storeData - UserDataToStore", realmConfiguration) { realm ->
userDataToStore.userDevices.forEach {
storeUserDevices(realm, it.key, it.value)
}

View File

@ -176,7 +176,7 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
}
// Give info to crypto module
cryptoService.onStateEvent(roomId, event)
cryptoService.onStateEvent(roomId, event, null)
}
roomMemberContentsByUser.getOrPut(event.senderId) {

View File

@ -29,6 +29,7 @@ import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse
import org.matrix.android.sdk.api.session.sync.model.SyncResponse
import org.matrix.android.sdk.internal.SessionManager
import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.di.SessionId
import org.matrix.android.sdk.internal.session.SessionListeners
@ -92,7 +93,7 @@ internal class SyncResponseHandler @Inject constructor(
postTreatmentSyncResponse(syncResponse, isInitialSync)
markCryptoSyncCompleted(syncResponse)
markCryptoSyncCompleted(syncResponse, aggregator.cryptoStoreAggregator)
handlePostSync()
@ -218,10 +219,10 @@ internal class SyncResponseHandler @Inject constructor(
}
}
private fun markCryptoSyncCompleted(syncResponse: SyncResponse) {
private fun markCryptoSyncCompleted(syncResponse: SyncResponse, cryptoStoreAggregator: CryptoStoreAggregator) {
relevantPlugins.measureSpan("task", "crypto_sync_handler_onSyncCompleted") {
measureTimeMillis {
cryptoSyncHandler.onSyncCompleted(syncResponse)
cryptoSyncHandler.onSyncCompleted(syncResponse, cryptoStoreAggregator)
}.also {
Timber.v("cryptoSyncHandler.onSyncCompleted took $it ms")
}

View File

@ -16,6 +16,8 @@
package org.matrix.android.sdk.internal.session.sync
import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
internal class SyncResponsePostTreatmentAggregator {
// List of RoomId
val ephemeralFilesToDelete = mutableListOf<String>()
@ -28,4 +30,7 @@ internal class SyncResponsePostTreatmentAggregator {
// Set of users to call `crossSigningService.checkTrustAndAffectedRoomShields` once per sync
val userIdsForCheckingTrustAndAffectedRoomShields = mutableSetOf<String>()
// For the crypto store
val cryptoStoreAggregator = CryptoStoreAggregator()
}

View File

@ -29,6 +29,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.sync.model.SyncResponse
import org.matrix.android.sdk.api.session.sync.model.ToDeviceSyncResponse
import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
import org.matrix.android.sdk.internal.crypto.tasks.toDeviceTracingId
import org.matrix.android.sdk.internal.crypto.verification.DefaultVerificationService
import org.matrix.android.sdk.internal.session.sync.ProgressReporter
@ -85,8 +86,8 @@ internal class CryptoSyncHandler @Inject constructor(
}
}
fun onSyncCompleted(syncResponse: SyncResponse) {
cryptoService.onSyncCompleted(syncResponse)
fun onSyncCompleted(syncResponse: SyncResponse, cryptoStoreAggregator: CryptoStoreAggregator) {
cryptoService.onSyncCompleted(syncResponse, cryptoStoreAggregator)
}
/**

View File

@ -258,7 +258,7 @@ internal class RoomSyncHandler @Inject constructor(
root = eventEntity
}
// Give info to crypto module
cryptoService.onStateEvent(roomId, event)
cryptoService.onStateEvent(roomId, event, aggregator.cryptoStoreAggregator)
roomMemberEventHandler.handle(realm, roomId, event, isInitialSync, aggregator)
}
}
@ -495,7 +495,7 @@ internal class RoomSyncHandler @Inject constructor(
}
}
// Give info to crypto module
cryptoService.onLiveEvent(roomEntity.roomId, event, isInitialSync)
cryptoService.onLiveEvent(roomEntity.roomId, event, isInitialSync, aggregator.cryptoStoreAggregator)
// Try to remove local echo
event.unsignedData?.transactionId?.also { txId ->