Skip to content

Commit

Permalink
Aggregate data outside of the RealmCryptoStore.
Browse files Browse the repository at this point in the history
  • Loading branch information
bmarty committed Jan 5, 2023
1 parent 30940cb commit 27d3218
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -384,7 +385,6 @@ internal class DefaultCryptoService @Inject constructor(
}
}
}
cryptoStore.onSyncWillProcess()
}

private fun internalStart() {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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())
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
*/
Expand Down Expand Up @@ -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)

Expand All @@ -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
Expand Down Expand Up @@ -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].
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -92,7 +93,7 @@ internal class SyncResponseHandler @Inject constructor(

postTreatmentSyncResponse(syncResponse, isInitialSync)

markCryptoSyncCompleted(syncResponse)
markCryptoSyncCompleted(syncResponse, aggregator.cryptoStoreAggregator)

handlePostSync()

Expand Down Expand Up @@ -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")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>()
Expand All @@ -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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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 ->
Expand Down

0 comments on commit 27d3218

Please sign in to comment.