From 320dc4accd8f09d88e1b26e9103b8c6a4190eb59 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 4 Feb 2020 18:35:46 +0100 Subject: [PATCH 01/11] Refactor Room Shield / Profile shield --- .../main/java/im/vector/matrix/rx/RxRoom.kt | 95 +------------ .../java/im/vector/matrix/rx/RxSession.kt | 28 +--- .../crosssigning/CrossSigningService.kt | 2 +- .../session/room/model/RoomMemberSummary.kt | 4 +- .../android/internal/crypto/CryptoModule.kt | 18 +-- .../crypto/crosssigning/ComputeTrustTask.kt | 76 ++++++++++ .../DefaultCrossSigningService.kt | 46 ++---- .../SessionToCryptoRoomMembersUpdate.kt | 25 ++++ .../crypto/crosssigning/ShieldTrustUpdater.kt | 133 ++++++++++++++++++ .../crypto/store/db/RealmCryptoStore.kt | 11 +- .../mapper/RoomMemberSummaryMapper.kt | 3 +- .../database/mapper/RoomSummaryMapper.kt | 3 +- .../database/model/RoomSummaryEntity.kt | 18 ++- .../internal/session/DefaultSession.kt | 6 +- .../session/room/RoomSummaryUpdater.kt | 16 +++ .../core/epoxy/profiles/ProfileActionItem.kt | 21 ++- .../epoxy/profiles/ProfileItemExtensions.kt | 6 +- .../home/room/detail/RoomDetailViewModel.kt | 10 +- .../action/MessageActionsViewModel.kt | 4 +- .../reactions/ViewReactionsViewModel.kt | 2 +- .../actions/RoomListQuickActionsViewModel.kt | 4 +- .../RoomMemberProfileController.kt | 1 + .../RoomMemberProfileViewModel.kt | 6 +- .../roomprofile/RoomProfileController.kt | 3 + .../roomprofile/RoomProfileViewModel.kt | 2 +- .../members/RoomMemberListController.kt | 2 +- .../members/RoomMemberListViewModel.kt | 38 ++++- .../members/RoomMemberListViewState.kt | 4 +- .../settings/RoomSettingsViewModel.kt | 2 +- .../main/res/layout/item_profile_action.xml | 16 ++- 30 files changed, 404 insertions(+), 201 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ComputeTrustTask.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/SessionToCryptoRoomMembersUpdate.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index d6c05fb0f7..02a72777fe 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -16,8 +16,6 @@ package im.vector.matrix.rx -import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel -import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams @@ -30,103 +28,22 @@ import im.vector.matrix.android.api.session.room.send.UserDraft import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.util.Optional import im.vector.matrix.android.api.util.toOptional -import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo import io.reactivex.Observable import io.reactivex.Single -import io.reactivex.functions.BiFunction -import timber.log.Timber -class RxRoom(private val room: Room, private val session: Session) { +class RxRoom(private val room: Room) { fun liveRoomSummary(): Observable> { - val summaryObservable = room.getRoomSummaryLive() + return room.getRoomSummaryLive() .asObservable() - .startWithCallable { - room.roomSummary().toOptional() - } - .doOnNext { Timber.v("RX: summary emitted for: ${it.getOrNull()?.roomId}") } - - val memberIdsChangeObservable = summaryObservable - .map { - it.getOrNull()?.let { roomSummary -> - if (roomSummary.isEncrypted) { - // Return the list of other users - roomSummary.otherMemberIds + listOf(session.myUserId) - } else { - // Return an empty list, the room is not encrypted - emptyList() - } - }.orEmpty() - }.distinctUntilChanged() - .doOnNext { Timber.v("RX: memberIds emitted. Size: ${it.size}") } - - // Observe the device info of the users in the room - val cryptoDeviceInfoObservable = memberIdsChangeObservable - .switchMap { membersIds -> - session.getLiveCryptoDeviceInfo(membersIds) - .asObservable() - .map { - // If any key change, emit the userIds list - membersIds - } - .startWith(membersIds) - .doOnNext { Timber.v("RX: CryptoDeviceInfo emitted. Size: ${it.size}") } - } - .doOnNext { Timber.v("RX: cryptoDeviceInfo emitted 2. Size: ${it.size}") } - - val roomEncryptionTrustLevelObservable = cryptoDeviceInfoObservable - .map { userIds -> - if (userIds.isEmpty()) { - Optional(null) - } else { - session.getCrossSigningService().getTrustLevelForUsers(userIds).toOptional() - } - } - .doOnNext { Timber.v("RX: roomEncryptionTrustLevel emitted: ${it.getOrNull()?.name}") } - - return Observable - .combineLatest, Optional, Optional>( - summaryObservable, - roomEncryptionTrustLevelObservable, - BiFunction { summary, level -> - summary.getOrNull()?.copy( - roomEncryptionTrustLevel = level.getOrNull() - ).toOptional() - } - ) - .doOnNext { Timber.v("RX: final room summary emitted for ${it.getOrNull()?.roomId}") } + .startWith(room.roomSummary().toOptional()) } fun liveRoomMembers(queryParams: RoomMemberQueryParams): Observable> { - val roomMembersObservable = room.getRoomMembersLive(queryParams).asObservable() + return room.getRoomMembersLive(queryParams).asObservable() .startWithCallable { room.getRoomMembers(queryParams) } - .doOnNext { Timber.v("RX: room members emitted. Size: ${it.size}") } - - // TODO Do it only for room members of the room (switchMap) - val cryptoDeviceInfoObservable = session.getLiveCryptoDeviceInfo().asObservable() - .startWith(emptyList()) - .doOnNext { Timber.v("RX: cryptoDeviceInfo emitted. Size: ${it.size}") } - - return Observable - .combineLatest, List, List>( - roomMembersObservable, - cryptoDeviceInfoObservable, - BiFunction { summaries, _ -> - summaries.map { - if (room.isEncrypted()) { - it.copy( - // Get the trust level of a virtual room with only this user - userEncryptionTrustLevel = session.getCrossSigningService().getTrustLevelForUsers(listOf(it.userId)) - ) - } else { - it - } - } - } - ) - .doOnNext { Timber.v("RX: final room members emitted. Size: ${it.size}") } } fun liveAnnotationSummary(eventId: String): Observable> { @@ -180,6 +97,6 @@ class RxRoom(private val room: Room, private val session: Session) { } } -fun Room.rx(session: Session): RxRoom { - return RxRoom(this, session) +fun Room.rx(): RxRoom { + return RxRoom(this) } diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index 31e1834d2b..c43616f574 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -33,40 +33,14 @@ import im.vector.matrix.android.api.util.toOptional import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo import io.reactivex.Observable import io.reactivex.Single -import io.reactivex.functions.BiFunction -import timber.log.Timber class RxSession(private val session: Session) { fun liveRoomSummaries(queryParams: RoomSummaryQueryParams): Observable> { - val summariesObservable = session.getRoomSummariesLive(queryParams).asObservable() + return session.getRoomSummariesLive(queryParams).asObservable() .startWithCallable { session.getRoomSummaries(queryParams) } - .doOnNext { Timber.v("RX: summaries emitted: size: ${it.size}") } - - val cryptoDeviceInfoObservable = session.getLiveCryptoDeviceInfo().asObservable() - .startWith(emptyList()) - .doOnNext { Timber.v("RX: crypto device info emitted: size: ${it.size}") } - - return Observable - .combineLatest, List, List>( - summariesObservable, - cryptoDeviceInfoObservable, - BiFunction { summaries, _ -> - summaries.map { - if (it.isEncrypted) { - it.copy( - roomEncryptionTrustLevel = session.getCrossSigningService() - .getTrustLevelForUsers(it.otherMemberIds + session.myUserId) - ) - } else { - it - } - } - } - ) - .doOnNext { Timber.d("RX: final summaries emitted: size: ${it.size}") } } fun liveGroupSummaries(queryParams: GroupSummaryQueryParams): Observable> { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt index a9d7a9e241..2b1c48174e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt @@ -64,5 +64,5 @@ interface CrossSigningService { otherDeviceId: String, locallyTrusted: Boolean?): DeviceTrustResult - fun getTrustLevelForUsers(userIds: List): RoomEncryptionTrustLevel + suspend fun getTrustLevelForUsers(userIds: List): RoomEncryptionTrustLevel } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMemberSummary.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMemberSummary.kt index d3b7f3f026..62f632b557 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMemberSummary.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMemberSummary.kt @@ -25,7 +25,5 @@ data class RoomMemberSummary constructor( val membership: Membership, val userId: String, val displayName: String? = null, - val avatarUrl: String? = null, - // TODO Warning: Will not be populated if not using RxRoom - val userEncryptionTrustLevel: RoomEncryptionTrustLevel? = null + val avatarUrl: String? = null ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt index 35ad49f42f..c30c673198 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt @@ -23,7 +23,10 @@ import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService import im.vector.matrix.android.internal.crypto.api.CryptoApi +import im.vector.matrix.android.internal.crypto.crosssigning.ComputeTrustTask +import im.vector.matrix.android.internal.crypto.crosssigning.DefaultComputeTrustTask import im.vector.matrix.android.internal.crypto.crosssigning.DefaultCrossSigningService +import im.vector.matrix.android.internal.crypto.crosssigning.ShieldTrustUpdater import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.tasks.CreateKeysBackupVersionTask import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultCreateKeysBackupVersionTask @@ -137,15 +140,6 @@ internal abstract class CryptoModule { return RealmClearCacheTask(realmConfiguration) } - @JvmStatic - @Provides - fun providesCryptoStore(@CryptoDatabase - realmConfiguration: RealmConfiguration, credentials: Credentials): IMXCryptoStore { - return RealmCryptoStore( - realmConfiguration, - credentials) - } - @JvmStatic @Provides @SessionScope @@ -249,4 +243,10 @@ internal abstract class CryptoModule { @Binds abstract fun bindCrossSigningService(crossSigningService: DefaultCrossSigningService): CrossSigningService + + @Binds + abstract fun bindCryptoStore(realmCryptoStore: RealmCryptoStore): IMXCryptoStore + + @Binds + abstract fun bindComputeShieldTrustTask(defaultShieldTrustUpdater: DefaultComputeTrustTask): ComputeTrustTask } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ComputeTrustTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ComputeTrustTask.kt new file mode 100644 index 0000000000..b7eba11103 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ComputeTrustTask.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package im.vector.matrix.android.internal.crypto.crosssigning + +import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel +import im.vector.matrix.android.api.extensions.orFalse +import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo +import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore +import im.vector.matrix.android.internal.task.Task +import javax.inject.Inject + +internal interface ComputeTrustTask : Task { + data class Params( + val userList: List + ) +} + +internal class DefaultComputeTrustTask @Inject constructor( + val cryptoStore: IMXCryptoStore +) : ComputeTrustTask { + + override suspend fun execute(params: ComputeTrustTask.Params): RoomEncryptionTrustLevel { + val userIds = params.userList + val allTrusted = userIds + .filter { getUserCrossSigningKeys(it)?.isTrusted() == true } + + val allUsersAreVerified = userIds.size == allTrusted.size + + return if (allTrusted.isEmpty()) { + RoomEncryptionTrustLevel.Default + } else { + // If one of the verified user as an untrusted device -> warning + // Green if all devices of all verified users are trusted -> green + // else black + val allDevices = allTrusted.mapNotNull { + cryptoStore.getUserDeviceList(it) + }.flatten() + if (getMyCrossSigningKeys() != null) { + val hasWarning = allDevices.any { !it.trustLevel?.crossSigningVerified.orFalse() } + if (hasWarning) { + RoomEncryptionTrustLevel.Warning + } else { + if (allUsersAreVerified) RoomEncryptionTrustLevel.Trusted else RoomEncryptionTrustLevel.Default + } + } else { + val hasWarningLegacy = allDevices.any { !it.isVerified } + if (hasWarningLegacy) { + RoomEncryptionTrustLevel.Warning + } else { + if (allUsersAreVerified) RoomEncryptionTrustLevel.Trusted else RoomEncryptionTrustLevel.Default + } + } + } + } + + private fun getUserCrossSigningKeys(otherUserId: String): MXCrossSigningInfo? { + return cryptoStore.getCrossSigningInfo(otherUserId) + } + + private fun getMyCrossSigningKeys(): MXCrossSigningInfo? { + return cryptoStore.getMyCrossSigningInfo() + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt index 4632a05552..a7ad76e163 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt @@ -20,7 +20,6 @@ import androidx.lifecycle.LiveData import dagger.Lazy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel -import im.vector.matrix.android.api.extensions.orFalse import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo import im.vector.matrix.android.api.util.Optional @@ -39,9 +38,8 @@ import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.JsonCanonicalizer -import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.withoutPrefix -import kotlinx.coroutines.CoroutineScope +import org.greenrobot.eventbus.EventBus import org.matrix.olm.OlmPkSigning import org.matrix.olm.OlmUtility import timber.log.Timber @@ -56,9 +54,9 @@ internal class DefaultCrossSigningService @Inject constructor( private val deviceListManager: DeviceListManager, private val uploadSigningKeysTask: UploadSigningKeysTask, private val uploadSignaturesTask: UploadSignaturesTask, - private val cryptoCoroutineScope: CoroutineScope, - private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val taskExecutor: TaskExecutor) : CrossSigningService, DeviceListManager.UserDevicesUpdateListener { + private val computeTrustTask: ComputeTrustTask, + private val taskExecutor: TaskExecutor, + val eventBus: EventBus) : CrossSigningService, DeviceListManager.UserDevicesUpdateListener { private var olmUtility: OlmUtility? = null @@ -630,13 +628,14 @@ internal class DefaultCrossSigningService @Inject constructor( // In this case it will change my MSK trust, and should then re-trigger a check of all other user trust setUserKeysAsTrusted(otherUserId, checkSelfTrust().isVerified()) } + + eventBus.post(CryptoToSessionUserTrustChange(users)) } } private fun setUserKeysAsTrusted(otherUserId: String, trusted: Boolean) { val currentTrust = cryptoStore.getCrossSigningInfo(otherUserId)?.isTrusted() cryptoStore.setUserKeysAsTrusted(otherUserId, trusted) - // If it's me, recheck trust of all users and devices? val users = ArrayList() if (otherUserId == userId && currentTrust != trusted) { @@ -655,36 +654,7 @@ internal class DefaultCrossSigningService @Inject constructor( } } - override fun getTrustLevelForUsers(userIds: List): RoomEncryptionTrustLevel { - val allTrusted = userIds - .filter { getUserCrossSigningKeys(it)?.isTrusted() == true } - - val allUsersAreVerified = userIds.size == allTrusted.size - - return if (allTrusted.isEmpty()) { - RoomEncryptionTrustLevel.Default - } else { - // If one of the verified user as an untrusted device -> warning - // Green if all devices of all verified users are trusted -> green - // else black - val allDevices = allTrusted.mapNotNull { - cryptoStore.getUserDeviceList(it) - }.flatten() - if (getMyCrossSigningKeys() != null) { - val hasWarning = allDevices.any { !it.trustLevel?.crossSigningVerified.orFalse() } - if (hasWarning) { - RoomEncryptionTrustLevel.Warning - } else { - if (allUsersAreVerified) RoomEncryptionTrustLevel.Trusted else RoomEncryptionTrustLevel.Default - } - } else { - val hasWarningLegacy = allDevices.any { !it.isVerified } - if (hasWarningLegacy) { - RoomEncryptionTrustLevel.Warning - } else { - if (allUsersAreVerified) RoomEncryptionTrustLevel.Trusted else RoomEncryptionTrustLevel.Default - } - } - } + override suspend fun getTrustLevelForUsers(userIds: List): RoomEncryptionTrustLevel { + return computeTrustTask.execute(ComputeTrustTask.Params(userIds)) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/SessionToCryptoRoomMembersUpdate.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/SessionToCryptoRoomMembersUpdate.kt new file mode 100644 index 0000000000..0ecc9d30ba --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/SessionToCryptoRoomMembersUpdate.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package im.vector.matrix.android.internal.crypto.crosssigning + +data class SessionToCryptoRoomMembersUpdate( + val encryptedRoomMembersUpdate: String, + val userList: List +) + +data class CryptoToSessionUserTrustChange( + val userList: List +) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt new file mode 100644 index 0000000000..313681592f --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package im.vector.matrix.android.internal.crypto.crosssigning + +import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity +import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityFields +import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.di.CryptoDatabase +import im.vector.matrix.android.internal.di.SessionDatabase +import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater +import im.vector.matrix.android.internal.task.TaskExecutor +import im.vector.matrix.android.internal.util.createBackgroundHandler +import io.realm.Realm +import io.realm.RealmConfiguration +import kotlinx.coroutines.launch +import org.greenrobot.eventbus.EventBus +import org.greenrobot.eventbus.Subscribe +import java.util.concurrent.atomic.AtomicReference +import javax.inject.Inject + +internal class ShieldTrustUpdater @Inject constructor( + val eventBus: EventBus, + private val computeTrustTask: ComputeTrustTask, + val taskExecutor: TaskExecutor, + @CryptoDatabase val cryptoRealmConfiguration: RealmConfiguration, + @SessionDatabase val sessionRealmConfiguration: RealmConfiguration, + val roomSummaryUpdater: RoomSummaryUpdater +) { + + companion object { + private val BACKGROUND_HANDLER = createBackgroundHandler("SHIELD_CRYPTO_DB_THREAD") + } + + private val backgroundCryptoRealm = AtomicReference() + private val backgroundSessionRealm = AtomicReference() + +// private var cryptoDevicesResult: RealmResults? = null + +// private val cryptoDeviceChangeListener = object : OrderedRealmCollectionChangeListener> { +// override fun onChange(t: RealmResults, changeSet: OrderedCollectionChangeSet) { +// val grouped = t.groupBy { it.userId } +// onCryptoDevicesChange(grouped.keys.mapNotNull { it }) +// } +// } + + fun start() { + eventBus.register(this) + BACKGROUND_HANDLER.post { + val cryptoRealm = Realm.getInstance(cryptoRealmConfiguration) + backgroundCryptoRealm.set(cryptoRealm) +// cryptoDevicesResult = cryptoRealm.where().findAll() +// cryptoDevicesResult?.addChangeListener(cryptoDeviceChangeListener) + + backgroundSessionRealm.set(Realm.getInstance(sessionRealmConfiguration)) + } + } + + fun stop() { + eventBus.unregister(this) + BACKGROUND_HANDLER.post { + // cryptoDevicesResult?.removeAllChangeListeners() + backgroundCryptoRealm.getAndSet(null).also { + it?.close() + } + backgroundSessionRealm.getAndSet(null).also { + it?.close() + } + } + } + + @Subscribe + fun onRoomMemberChange(update: SessionToCryptoRoomMembersUpdate) { + taskExecutor.executorScope.launch { + val updatedTrust = computeTrustTask.execute(ComputeTrustTask.Params(update.userList)) + // We need to send that back to session base + + BACKGROUND_HANDLER.post { + backgroundSessionRealm.get().executeTransaction { realm -> + roomSummaryUpdater.updateShieldTrust(realm, update.encryptedRoomMembersUpdate, updatedTrust) + } + } + } + } + + @Subscribe + fun onTrustUpdate(update: CryptoToSessionUserTrustChange) { + onCryptoDevicesChange(update.userList) + } + + private fun onCryptoDevicesChange(users: List) { + BACKGROUND_HANDLER.post { + val impactedRoomsId = backgroundSessionRealm.get().where(RoomMemberSummaryEntity::class.java) + .`in`(RoomMemberSummaryEntityFields.USER_ID, users.toTypedArray()) + .findAll() + .map { it.roomId } + .distinct() + + val map = HashMap>() + impactedRoomsId.forEach { roomId -> + RoomMemberSummaryEntity.where(backgroundSessionRealm.get(), roomId).findAll()?.let { results -> + map[roomId] = results.map { it.userId } + } + } + + map.forEach { entry -> + val roomId = entry.key + val userList = entry.value + taskExecutor.executorScope.launch { + val updatedTrust = computeTrustTask.execute(ComputeTrustTask.Params(userList)) + BACKGROUND_HANDLER.post { + backgroundSessionRealm.get().executeTransaction { realm -> + roomSummaryUpdater.updateShieldTrust(realm, roomId, updatedTrust) + } + } + } + } + + } + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt index 51adc46900..00a496cae4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt @@ -61,6 +61,7 @@ import im.vector.matrix.android.internal.crypto.store.db.query.delete import im.vector.matrix.android.internal.crypto.store.db.query.get import im.vector.matrix.android.internal.crypto.store.db.query.getById import im.vector.matrix.android.internal.crypto.store.db.query.getOrCreate +import im.vector.matrix.android.internal.di.CryptoDatabase import im.vector.matrix.android.internal.session.SessionScope import io.realm.Realm import io.realm.RealmConfiguration @@ -70,11 +71,13 @@ import io.realm.kotlin.where import org.matrix.olm.OlmAccount import org.matrix.olm.OlmException import timber.log.Timber +import javax.inject.Inject import kotlin.collections.set @SessionScope -internal class RealmCryptoStore(private val realmConfiguration: RealmConfiguration, - private val credentials: Credentials) : IMXCryptoStore { +internal class RealmCryptoStore @Inject constructor( + @CryptoDatabase private val realmConfiguration: RealmConfiguration, + private val credentials: Credentials) : IMXCryptoStore { /* ========================================================================================== * Memory cache, to correctly release JNI objects @@ -403,14 +406,14 @@ internal class RealmCryptoStore(private val realmConfiguration: RealmConfigurati { realm: Realm -> realm .where() - .`in`(UserEntityFields.USER_ID, userIds.toTypedArray()) + .`in`(UserEntityFields.USER_ID, userIds.distinct().toTypedArray()) }, { entity -> entity.devices.map { CryptoMapper.mapToModel(it) } } ) return Transformations.map(liveData) { - it.firstOrNull() ?: emptyList() + it.flatten() } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomMemberSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomMemberSummaryMapper.kt index 5e8db4cf84..470772a40e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomMemberSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomMemberSummaryMapper.kt @@ -26,8 +26,7 @@ internal object RoomMemberSummaryMapper { userId = roomMemberSummaryEntity.userId, avatarUrl = roomMemberSummaryEntity.avatarUrl, displayName = roomMemberSummaryEntity.displayName, - membership = roomMemberSummaryEntity.membership, - userEncryptionTrustLevel = null + membership = roomMemberSummaryEntity.membership ) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt index 896f994c99..1089e3b5c2 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt @@ -75,7 +75,8 @@ internal class RoomSummaryMapper @Inject constructor( aliases = roomSummaryEntity.aliases.toList(), isEncrypted = roomSummaryEntity.isEncrypted, typingRoomMemberIds = roomSummaryEntity.typingUserIds.toList(), - breadcrumbsIndex = roomSummaryEntity.breadcrumbsIndex + breadcrumbsIndex = roomSummaryEntity.breadcrumbsIndex, + roomEncryptionTrustLevel = roomSummaryEntity.roomEncryptionTrustLevel ) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt index c56e9ba10e..c4ebe3cbaa 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt @@ -16,6 +16,7 @@ package im.vector.matrix.android.internal.database.model +import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.VersioningState @@ -47,7 +48,8 @@ internal open class RoomSummaryEntity( // this is required for querying var flatAliases: String = "", var isEncrypted: Boolean = false, - var typingUserIds: RealmList = RealmList() + var typingUserIds: RealmList = RealmList(), + var roomEncryptionTrustLevelStr: String? = null ) : RealmObject() { private var membershipStr: String = Membership.NONE.name @@ -68,5 +70,19 @@ internal open class RoomSummaryEntity( versioningStateStr = value.name } + var roomEncryptionTrustLevel: RoomEncryptionTrustLevel? + get() { + return roomEncryptionTrustLevelStr?.let { + try { + RoomEncryptionTrustLevel.valueOf(it) + } catch (failure: Throwable) { + null + } + } + } + set(value) { + roomEncryptionTrustLevelStr = value?.name + } + companion object } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt index 537bc63355..77cd3685d7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt @@ -43,6 +43,7 @@ import im.vector.matrix.android.api.session.sync.SyncState import im.vector.matrix.android.api.session.user.UserService import im.vector.matrix.android.internal.auth.SessionParamsStore import im.vector.matrix.android.internal.crypto.DefaultCryptoService +import im.vector.matrix.android.internal.crypto.crosssigning.ShieldTrustUpdater import im.vector.matrix.android.internal.database.LiveEntityObserver import im.vector.matrix.android.internal.di.SessionId import im.vector.matrix.android.internal.di.WorkManagerProvider @@ -89,7 +90,8 @@ internal class DefaultSession @Inject constructor( private val sessionParamsStore: SessionParamsStore, private val contentUploadProgressTracker: ContentUploadStateTracker, private val initialSyncProgressService: Lazy, - private val homeServerCapabilitiesService: Lazy) + private val homeServerCapabilitiesService: Lazy, + private val shieldTrustUpdater: ShieldTrustUpdater) : Session, RoomService by roomService.get(), RoomDirectoryService by roomDirectoryService.get(), @@ -119,6 +121,7 @@ internal class DefaultSession @Inject constructor( isOpen = true liveEntityObservers.forEach { it.start() } eventBus.register(this) + shieldTrustUpdater.start() } override fun requireBackgroundSync() { @@ -160,6 +163,7 @@ internal class DefaultSession @Inject constructor( isOpen = false eventBus.unregister(this) syncTaskSequencer.close() + shieldTrustUpdater.stop() } override fun getSyncStateLive(): LiveData { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt index 6a26e6d282..5df7fb5be5 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt @@ -17,6 +17,7 @@ package im.vector.matrix.android.internal.session.room import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.Membership @@ -24,6 +25,7 @@ import im.vector.matrix.android.api.session.room.model.RoomAliasesContent import im.vector.matrix.android.api.session.room.model.RoomCanonicalAliasContent import im.vector.matrix.android.api.session.room.model.RoomTopicContent import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import im.vector.matrix.android.internal.crypto.crosssigning.SessionToCryptoRoomMembersUpdate import im.vector.matrix.android.internal.database.mapper.ContentMapper import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity import im.vector.matrix.android.internal.database.model.EventEntity @@ -43,12 +45,14 @@ import im.vector.matrix.android.internal.session.sync.RoomSyncHandler import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary import im.vector.matrix.android.internal.session.sync.model.RoomSyncUnreadNotifications import io.realm.Realm +import org.greenrobot.eventbus.EventBus import javax.inject.Inject internal class RoomSummaryUpdater @Inject constructor( @UserId private val userId: String, private val roomDisplayNameResolver: RoomDisplayNameResolver, private val roomAvatarResolver: RoomAvatarResolver, + private val eventBus: EventBus, private val monarchy: Monarchy) { companion object { @@ -139,6 +143,18 @@ internal class RoomSummaryUpdater @Inject constructor( roomSummaryEntity.otherMemberIds.clear() roomSummaryEntity.otherMemberIds.addAll(otherRoomMembers) + if (roomSummaryEntity.isEncrypted) { + eventBus.post(SessionToCryptoRoomMembersUpdate(roomId, roomSummaryEntity.otherMemberIds.map { it } + userId)) + } + } + } + + fun updateShieldTrust(realm: Realm, + roomId: String, + trust: RoomEncryptionTrustLevel?) { + val roomSummaryEntity = RoomSummaryEntity.getOrCreate(realm, roomId) + if (roomSummaryEntity.isEncrypted) { + roomSummaryEntity.roomEncryptionTrustLevel = trust } } } diff --git a/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileActionItem.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileActionItem.kt index 27586fcfde..3c31c09c52 100644 --- a/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileActionItem.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileActionItem.kt @@ -38,12 +38,19 @@ abstract class ProfileActionItem : VectorEpoxyModel() lateinit var title: String @EpoxyAttribute var subtitle: String? = null + @EpoxyAttribute var iconRes: Int = 0 + @EpoxyAttribute + var tintIcon: Boolean = true + @EpoxyAttribute var editableRes: Int = R.drawable.ic_arrow_right + @EpoxyAttribute + var accessoryRes: Int = 0 + @EpoxyAttribute var editable: Boolean = true @@ -70,12 +77,23 @@ abstract class ProfileActionItem : VectorEpoxyModel() holder.subtitle.setTextOrHide(subtitle) if (iconRes != 0) { holder.icon.setImageResource(iconRes) - ImageViewCompat.setImageTintList(holder.icon, ColorStateList.valueOf(tintColor)) + if (tintIcon) { + ImageViewCompat.setImageTintList(holder.icon, ColorStateList.valueOf(tintColor)) + } else { + ImageViewCompat.setImageTintList(holder.icon, null) + } holder.icon.isVisible = true } else { holder.icon.isVisible = false } + if (accessoryRes != 0) { + holder.secondaryAccessory.setImageResource(accessoryRes) + holder.secondaryAccessory.isVisible = true + } else { + holder.secondaryAccessory.isVisible = false + } + if (editableRes != 0) { val tintColorSecondary = if (destructive) { tintColor @@ -95,5 +113,6 @@ abstract class ProfileActionItem : VectorEpoxyModel() val title by bind(R.id.actionTitle) val subtitle by bind(R.id.actionSubtitle) val editable by bind(R.id.actionEditable) + val secondaryAccessory by bind(R.id.actionSecondaryAccessory) } } diff --git a/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileItemExtensions.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileItemExtensions.kt index beea3ca620..693efc5418 100644 --- a/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileItemExtensions.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileItemExtensions.kt @@ -36,19 +36,23 @@ fun EpoxyController.buildProfileAction( subtitle: String? = null, editable: Boolean = true, @DrawableRes icon: Int = 0, + tintIcon: Boolean = true, @DrawableRes editableRes: Int? = null, destructive: Boolean = false, divider: Boolean = true, - action: ClickListener? = null + action: ClickListener? = null, + @DrawableRes accessory: Int = 0 ) { profileActionItem { iconRes(icon) + tintIcon(tintIcon) id("action_$id") subtitle(subtitle) editable(editable) editableRes?.let { editableRes(editableRes) } destructive(destructive) title(title) + accessoryRes(accessory) listener { _ -> action?.invoke() } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index c58270aff2..2bee55bce3 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -159,7 +159,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro observeMyRoomMember() room.getRoomSummaryLive() room.markAsRead(ReadService.MarkAsReadParams.READ_RECEIPT, NoOpMatrixCallback()) - room.rx(session).loadRoomMembersIfNeeded().subscribeLogError().disposeOnClear() + room.rx().loadRoomMembersIfNeeded().subscribeLogError().disposeOnClear() // Inform the SDK that the room is displayed session.onRoomDisplayed(initialState.roomId) } @@ -168,7 +168,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro val queryParams = roomMemberQueryParams { this.userId = QueryStringValue.Equals(session.myUserId, QueryStringValue.Case.SENSITIVE) } - room.rx(session) + room.rx() .liveRoomMembers(queryParams) .map { it.firstOrNull().toOptional() @@ -255,7 +255,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro } private fun observeDrafts() { - room.rx(session).liveDrafts() + room.rx().liveDrafts() .subscribe { Timber.d("Draft update --> SetState") setState { @@ -896,7 +896,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro } private fun observeRoomSummary() { - room.rx(session).liveRoomSummary() + room.rx().liveRoomSummary() .unwrap() .execute { async -> val typingRoomMembers = @@ -914,7 +914,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro Observable .combineLatest, RoomSummary, UnreadState>( timelineEvents.observeOn(Schedulers.computation()), - room.rx(session).liveRoomSummary().unwrap(), + room.rx().liveRoomSummary().unwrap(), BiFunction { timelineEvents, roomSummary -> computeUnreadState(timelineEvents, roomSummary) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index dcaddd3c08..114d80d9af 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -134,7 +134,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted private fun observeEvent() { if (room == null) return - room.rx(session) + room.rx() .liveTimelineEvent(eventId) .unwrap() .execute { @@ -144,7 +144,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted private fun observeReactions() { if (room == null) return - room.rx(session) + room.rx() .liveAnnotationSummary(eventId) .map { annotations -> EmojiDataSource.quickEmojis.map { emoji -> diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/reactions/ViewReactionsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/reactions/ViewReactionsViewModel.kt index e3d78c27b3..05cdbc0fd8 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/reactions/ViewReactionsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/reactions/ViewReactionsViewModel.kt @@ -86,7 +86,7 @@ class ViewReactionsViewModel @AssistedInject constructor(@Assisted } private fun observeEventAnnotationSummaries() { - RxRoom(room, session) + RxRoom(room) .liveAnnotationSummary(eventId) .unwrap() .flatMapSingle { summaries -> diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt index 3108d3eafb..e5c0e743b8 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsViewModel.kt @@ -54,7 +54,7 @@ class RoomListQuickActionsViewModel @AssistedInject constructor(@Assisted initia private fun observeNotificationState() { room - .rx(session) + .rx() .liveNotificationState() .execute { copy(roomNotificationState = it) @@ -63,7 +63,7 @@ class RoomListQuickActionsViewModel @AssistedInject constructor(@Assisted initia private fun observeRoomSummary() { room - .rx(session) + .rx() .liveRoomSummary() .unwrap() .execute { diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileController.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileController.kt index c77d575f01..70c3e8add2 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileController.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileController.kt @@ -97,6 +97,7 @@ class RoomMemberProfileController @Inject constructor( dividerColor = dividerColor, editable = true, icon = icon, + tintIcon = false, divider = false, action = { callback?.onShowDeviceList() } ) diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt index 75aa0f8e5e..e44693e4d4 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -170,7 +170,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v val queryParams = roomMemberQueryParams { this.userId = QueryStringValue.Equals(initialState.userId, QueryStringValue.Case.SENSITIVE) } - room.rx(session).liveRoomMembers(queryParams) + room.rx().liveRoomMembers(queryParams) .map { it.firstOrNull()?.toMatrixItem().toOptional() } .unwrap() .execute { @@ -193,8 +193,8 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v } private fun observeRoomSummaryAndPowerLevels(room: Room) { - val roomSummaryLive = room.rx(session).liveRoomSummary().unwrap() - val powerLevelsContentLive = room.rx(session).liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, "") + val roomSummaryLive = room.rx().liveRoomSummary().unwrap() + val powerLevelsContentLive = room.rx().liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS) .mapOptional { it.content.toModel() } .unwrap() diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileController.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileController.kt index dcc0e678d1..ab1774233a 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileController.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileController.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.roomprofile import com.airbnb.epoxy.TypedEpoxyController +import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel import im.vector.riotx.R import im.vector.riotx.core.epoxy.profiles.buildProfileAction import im.vector.riotx.core.epoxy.profiles.buildProfileSection @@ -79,11 +80,13 @@ class RoomProfileController @Inject constructor( action = { callback?.onNotificationsClicked() } ) val numberOfMembers = roomSummary.joinedMembersCount ?: 0 + val hasWarning = roomSummary.isEncrypted && roomSummary.roomEncryptionTrustLevel == RoomEncryptionTrustLevel.Warning buildProfileAction( id = "member_list", title = stringProvider.getQuantityString(R.plurals.room_profile_section_more_member_list, numberOfMembers, numberOfMembers), dividerColor = dividerColor, icon = R.drawable.ic_room_profile_member_list, + accessory = R.drawable.ic_shield_warning.takeIf { hasWarning } ?: 0, action = { callback?.onMemberListClicked() } ) buildProfileAction( diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt index b0c942cbb9..6c66ac67b2 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt @@ -56,7 +56,7 @@ class RoomProfileViewModel @AssistedInject constructor(@Assisted initialState: R } private fun observeRoomSummary() { - room.rx(session).liveRoomSummary() + room.rx().liveRoomSummary() .unwrap() .execute { copy(roomSummary = it) diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListController.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListController.kt index bd3dd06bd3..d0939e939e 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListController.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListController.kt @@ -62,7 +62,7 @@ class RoomMemberListController @Inject constructor( id(roomMember.userId) matrixItem(roomMember.toMatrixItem()) avatarRenderer(avatarRenderer) - userEncryptionTrustLevel(roomMember.userEncryptionTrustLevel) + userEncryptionTrustLevel(data.trustLevelMap.invoke()?.get(roomMember.userId)) clickListener { _ -> callback?.onRoomMemberClicked(roomMember) } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt index 9bf8f88518..bf701c2be0 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt @@ -21,6 +21,8 @@ import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject +import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel +import im.vector.matrix.android.api.extensions.orFalse import im.vector.matrix.android.api.query.QueryStringValue import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.events.model.EventType @@ -31,12 +33,14 @@ import im.vector.matrix.android.api.session.room.model.PowerLevelsContent import im.vector.matrix.android.api.session.room.model.RoomMemberSummary import im.vector.matrix.android.api.session.room.powerlevels.PowerLevelsConstants import im.vector.matrix.android.api.session.room.powerlevels.PowerLevelsHelper +import im.vector.matrix.rx.asObservable import im.vector.matrix.rx.mapOptional import im.vector.matrix.rx.rx import im.vector.matrix.rx.unwrap import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel import io.reactivex.Observable +import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.functions.BiFunction class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState: RoomMemberListViewState, @@ -70,11 +74,12 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState displayName = QueryStringValue.IsNotEmpty memberships = Membership.activeMemberships() } + Observable .combineLatest, PowerLevelsContent, RoomMemberSummaries>( - room.rx(session).liveRoomMembers(roomMemberQueryParams), - room.rx(session) - .liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, "") + room.rx().liveRoomMembers(roomMemberQueryParams), + room.rx() + .liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS) .mapOptional { it.content.toModel() } .unwrap(), BiFunction { roomMembers, powerLevelsContent -> @@ -84,10 +89,35 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState .execute { async -> copy(roomMemberSummaries = async) } + + if (room.isEncrypted()) { + room.rx().liveRoomMembers(roomMemberQueryParams) + .observeOn(AndroidSchedulers.mainThread()) + .switchMap { membersSummary -> + session.getLiveCryptoDeviceInfo(membersSummary.map { it.userId }) + .asObservable() + .map { deviceList -> + // If any key change, emit the userIds list + deviceList.groupBy { it.userId }.mapValues { + val allDeviceTrusted = it.value.fold(it.value.isNotEmpty()) { prev, next -> + prev && next.trustLevel?.isCrossSigningVerified().orFalse() + } + if (session.getCrossSigningService().getUserCrossSigningKeys(it.key)?.isTrusted().orFalse()) { + if (allDeviceTrusted) RoomEncryptionTrustLevel.Trusted else RoomEncryptionTrustLevel.Warning + } else { + RoomEncryptionTrustLevel.Default + } + } + } + } + .execute { async -> + copy(trustLevelMap = async) + } + } } private fun observeRoomSummary() { - room.rx(session).liveRoomSummary() + room.rx().liveRoomSummary() .unwrap() .execute { async -> copy(roomSummary = async) diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewState.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewState.kt index 467f194597..4618a07cb0 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewState.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewState.kt @@ -20,6 +20,7 @@ import androidx.annotation.StringRes import com.airbnb.mvrx.Async import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.Uninitialized +import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel import im.vector.matrix.android.api.session.room.model.RoomMemberSummary import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.riotx.R @@ -28,7 +29,8 @@ import im.vector.riotx.features.roomprofile.RoomProfileArgs data class RoomMemberListViewState( val roomId: String, val roomSummary: Async = Uninitialized, - val roomMemberSummaries: Async = Uninitialized + val roomMemberSummaries: Async = Uninitialized, + val trustLevelMap: Async> = Uninitialized ) : MvRxState { constructor(args: RoomProfileArgs) : this(roomId = args.roomId) diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt index 58bd9f228a..f1dee87005 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt @@ -52,7 +52,7 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: } private fun observeRoomSummary() { - room.rx(session).liveRoomSummary() + room.rx().liveRoomSummary() .unwrap() .execute { async -> copy(roomSummary = async) diff --git a/vector/src/main/res/layout/item_profile_action.xml b/vector/src/main/res/layout/item_profile_action.xml index 2f43bef0a4..dfaf2daf80 100644 --- a/vector/src/main/res/layout/item_profile_action.xml +++ b/vector/src/main/res/layout/item_profile_action.xml @@ -20,7 +20,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:scaleType="center" - android:tint="?riotx_text_primary" android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -60,13 +59,26 @@ android:textSize="12sp" app:layout_constrainedWidth="true" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toStartOf="@+id/actionEditable" + app:layout_constraintEnd_toStartOf="@+id/actionSecondaryAccessory" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toEndOf="@id/actionIcon" app:layout_constraintTop_toBottomOf="@id/actionTitle" app:layout_goneMarginStart="0dp" tools:text="@string/room_profile_encrypted_subtitle" /> + + + Date: Tue, 4 Feb 2020 18:50:28 +0100 Subject: [PATCH 02/11] Fix / annoying loading to get active sessions Start with what's known locally --- .../VectorSettingsSecurityPrivacyFragment.kt | 9 +++++++++ .../features/settings/devices/DevicesViewModel.kt | 13 +++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsSecurityPrivacyFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsSecurityPrivacyFragment.kt index c30464ab77..0637d6d545 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsSecurityPrivacyFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsSecurityPrivacyFragment.kt @@ -426,6 +426,15 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( // ============================================================================================================== private fun refreshMyDevice() { + session.getUserDevices(session.myUserId).map { + DeviceInfo( + user_id = session.myUserId, + deviceId = it.deviceId, + displayName = it.displayName() + ) + }.let { + refreshCryptographyPreference(it) + } // TODO Move to a ViewModel... session.getDevicesList(object : MatrixCallback { override fun onSuccess(data: DevicesListResponse) { diff --git a/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt index 9f47bdf8f0..419b6a5492 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt @@ -115,11 +115,20 @@ class DevicesViewModel @AssistedInject constructor(@Assisted initialState: Devic * It can be any mobile devices, and any browsers. */ private fun refreshDevicesList() { - if (session.isCryptoEnabled() && !session.sessionParams.credentials.deviceId.isNullOrEmpty()) { + if (!session.sessionParams.credentials.deviceId.isNullOrEmpty()) { + // display something asap + val localKnown = session.getUserDevices(session.myUserId).map { + DeviceInfo( + user_id = session.myUserId, + deviceId = it.deviceId, + displayName = it.displayName() + ) + } + setState { copy( // Keep known list if we have it, and let refresh go in backgroung - devices = this.devices.takeIf { it is Success } ?: Loading() + devices = this.devices.takeIf { it is Success } ?: Success(localKnown) ) } From 911ff8cf162cd2e8a6f5fee5c1bb1958619e95ab Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 4 Feb 2020 18:50:36 +0100 Subject: [PATCH 03/11] cleaning (klint) --- .../matrix/android/api/session/room/model/RoomMemberSummary.kt | 2 -- .../im/vector/matrix/android/internal/crypto/CryptoModule.kt | 2 -- .../android/internal/crypto/crosssigning/ShieldTrustUpdater.kt | 1 - 3 files changed, 5 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMemberSummary.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMemberSummary.kt index 62f632b557..8641425214 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMemberSummary.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMemberSummary.kt @@ -16,8 +16,6 @@ package im.vector.matrix.android.api.session.room.model -import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel - /** * Class representing a simplified version of EventType.STATE_ROOM_MEMBER state event content */ diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt index c30c673198..782bd63408 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt @@ -19,14 +19,12 @@ package im.vector.matrix.android.internal.crypto import dagger.Binds import dagger.Module import dagger.Provides -import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService import im.vector.matrix.android.internal.crypto.api.CryptoApi import im.vector.matrix.android.internal.crypto.crosssigning.ComputeTrustTask import im.vector.matrix.android.internal.crypto.crosssigning.DefaultComputeTrustTask import im.vector.matrix.android.internal.crypto.crosssigning.DefaultCrossSigningService -import im.vector.matrix.android.internal.crypto.crosssigning.ShieldTrustUpdater import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi import im.vector.matrix.android.internal.crypto.keysbackup.tasks.CreateKeysBackupVersionTask import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultCreateKeysBackupVersionTask diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt index 313681592f..d416abe10a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt @@ -127,7 +127,6 @@ internal class ShieldTrustUpdater @Inject constructor( } } } - } } } From 75131fdf44f329c0ed64f61713274ae9aa718b3e Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 5 Feb 2020 15:38:58 +0100 Subject: [PATCH 04/11] Post merge fix --- .../src/main/java/im/vector/matrix/rx/LiveDataObservable.kt | 2 +- .../features/roommemberprofile/RoomMemberProfileViewModel.kt | 2 +- .../features/roomprofile/members/RoomMemberListViewModel.kt | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/LiveDataObservable.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/LiveDataObservable.kt index 302e775056..60ec3c8c7d 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/LiveDataObservable.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/LiveDataObservable.kt @@ -58,7 +58,7 @@ private class LiveDataObservable( } } -internal fun LiveData.asObservable(): Observable { +fun LiveData.asObservable(): Observable { return LiveDataObservable(this).observeOn(Schedulers.computation()) } diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt index e44693e4d4..2af7a6ec35 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -194,7 +194,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v private fun observeRoomSummaryAndPowerLevels(room: Room) { val roomSummaryLive = room.rx().liveRoomSummary().unwrap() - val powerLevelsContentLive = room.rx().liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS) + val powerLevelsContentLive = room.rx().liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, "") .mapOptional { it.content.toModel() } .unwrap() diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt index bf701c2be0..72b4af4474 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt @@ -42,6 +42,7 @@ import im.vector.riotx.core.platform.VectorViewModel import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.functions.BiFunction +import timber.log.Timber class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState: RoomMemberListViewState, private val roomMemberSummaryComparator: RoomMemberSummaryComparator, @@ -79,7 +80,7 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState .combineLatest, PowerLevelsContent, RoomMemberSummaries>( room.rx().liveRoomMembers(roomMemberQueryParams), room.rx() - .liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS) + .liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, "") .mapOptional { it.content.toModel() } .unwrap(), BiFunction { roomMembers, powerLevelsContent -> @@ -96,6 +97,7 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState .switchMap { membersSummary -> session.getLiveCryptoDeviceInfo(membersSummary.map { it.userId }) .asObservable() + .doOnError { Timber.e(it) } .map { deviceList -> // If any key change, emit the userIds list deviceList.groupBy { it.userId }.mapValues { From bf2e01b8c3df8a96173ca8605f3fb2a878059950 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 5 Feb 2020 16:00:35 +0100 Subject: [PATCH 05/11] More Rx startWithcallable --- .../src/main/java/im/vector/matrix/rx/RxRoom.kt | 2 +- .../src/main/java/im/vector/matrix/rx/RxSession.kt | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index 02a72777fe..193b5c3fbf 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -36,7 +36,7 @@ class RxRoom(private val room: Room) { fun liveRoomSummary(): Observable> { return room.getRoomSummaryLive() .asObservable() - .startWith(room.roomSummary().toOptional()) + .startWithCallable { room.roomSummary().toOptional() } } fun liveRoomMembers(queryParams: RoomMemberQueryParams): Observable> { diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index c43616f574..2cd2bf2dd3 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -110,12 +110,16 @@ class RxSession(private val session: Session) { } fun liveUserCryptoDevices(userId: String): Observable> { - return session.getLiveCryptoDeviceInfo(userId).asObservable() + return session.getLiveCryptoDeviceInfo(userId).asObservable().startWithCallable { + session.getCryptoDeviceInfo(userId) + } } fun liveCrossSigningInfo(userId: String): Observable> { return session.getCrossSigningService().getLiveCrossSigningKeys(userId).asObservable() - .startWith(session.getCrossSigningService().getUserCrossSigningKeys(userId).toOptional()) + .startWithCallable { + session.getCrossSigningService().getUserCrossSigningKeys(userId).toOptional() + } } } From 3e2219cbb5a6bc433ecd27794349762e630a1e9a Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 5 Feb 2020 22:11:58 +0100 Subject: [PATCH 06/11] Ignore interrupted exception in setupRx --- .../src/main/java/im/vector/riotx/core/rx/RxConfig.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt b/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt index bd87251a58..5673bb9c12 100644 --- a/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt +++ b/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt @@ -31,11 +31,14 @@ class RxConfig @Inject constructor( fun setupRxPlugin() { RxJavaPlugins.setErrorHandler { throwable -> Timber.e(throwable, "RxError") - - // Avoid crash in production, except if user wants it - if (vectorPreferences.failFast()) { - throw throwable + //is InterruptedException -> fine, some blocking code was interrupted by a dispose call + if (throwable !is InterruptedException) { + // Avoid crash in production, except if user wants it + if (vectorPreferences.failFast()) { + throw throwable + } } + } } } From d80c15f52fe4b769d73a209ec7499ce7bd1b4907 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 6 Feb 2020 10:31:21 +0100 Subject: [PATCH 07/11] Dispatch init on crypto thread to avoid blocking cold start --- .../internal/crypto/DeviceListManager.kt | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt index faf9e7e3c5..cd46cdbe36 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt @@ -27,6 +27,9 @@ import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.DownloadKeysForUsersTask import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.sync.SyncTokenStore +import im.vector.matrix.android.internal.task.TaskExecutor +import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers +import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -36,7 +39,9 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM private val olmDevice: MXOlmDevice, private val syncTokenStore: SyncTokenStore, private val credentials: Credentials, - private val downloadKeysForUsersTask: DownloadKeysForUsersTask) { + private val downloadKeysForUsersTask: DownloadKeysForUsersTask, + coroutineDispatchers: MatrixCoroutineDispatchers, + taskExecutor: TaskExecutor) { interface UserDevicesUpdateListener { fun onUsersDeviceUpdate(users: List) @@ -72,17 +77,19 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM private val notReadyToRetryHS = mutableSetOf() init { - var isUpdated = false - val deviceTrackingStatuses = cryptoStore.getDeviceTrackingStatuses().toMutableMap() - for ((userId, status) in deviceTrackingStatuses) { - if (TRACKING_STATUS_DOWNLOAD_IN_PROGRESS == status || TRACKING_STATUS_UNREACHABLE_SERVER == status) { - // if a download was in progress when we got shut down, it isn't any more. - deviceTrackingStatuses[userId] = TRACKING_STATUS_PENDING_DOWNLOAD - isUpdated = true + taskExecutor.executorScope.launch(coroutineDispatchers.crypto) { + var isUpdated = false + val deviceTrackingStatuses = cryptoStore.getDeviceTrackingStatuses().toMutableMap() + for ((userId, status) in deviceTrackingStatuses) { + if (TRACKING_STATUS_DOWNLOAD_IN_PROGRESS == status || TRACKING_STATUS_UNREACHABLE_SERVER == status) { + // if a download was in progress when we got shut down, it isn't any more. + deviceTrackingStatuses[userId] = TRACKING_STATUS_PENDING_DOWNLOAD + isUpdated = true + } + } + if (isUpdated) { + cryptoStore.saveDeviceTrackingStatuses(deviceTrackingStatuses) } - } - if (isUpdated) { - cryptoStore.saveDeviceTrackingStatuses(deviceTrackingStatuses) } } From 5c1fcc47a1a3f1d02e826639be86e944e096b903 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 6 Feb 2020 10:31:40 +0100 Subject: [PATCH 08/11] Catch all decryption fails in mapping --- .../android/internal/database/mapper/RoomSummaryMapper.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt index 1089e3b5c2..6ebd3af78d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt @@ -22,6 +22,7 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.tag.RoomTag import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult import im.vector.matrix.android.internal.database.model.RoomSummaryEntity +import timber.log.Timber import java.util.UUID import javax.inject.Inject @@ -49,7 +50,8 @@ internal class RoomSummaryMapper @Inject constructor( keysClaimed = result.claimedEd25519Key?.let { mapOf("ed25519" to it) }, forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain ) - } catch (e: MXCryptoError) { + } catch (e: Throwable) { + Timber.d(e) } } From a48bf61ad752bdae6e394925c041f4ba28b7b438 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 6 Feb 2020 11:40:44 +0100 Subject: [PATCH 09/11] quick dispatch to correct thread (will need more work) --- .../DefaultCrossSigningService.kt | 84 +++++++++++-------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt index a7ad76e163..141490643f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt @@ -36,9 +36,13 @@ import im.vector.matrix.android.internal.crypto.tasks.UploadSigningKeysTask import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor +import im.vector.matrix.android.internal.task.TaskThread import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.JsonCanonicalizer +import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.withoutPrefix +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import org.greenrobot.eventbus.EventBus import org.matrix.olm.OlmPkSigning import org.matrix.olm.OlmUtility @@ -56,6 +60,8 @@ internal class DefaultCrossSigningService @Inject constructor( private val uploadSignaturesTask: UploadSignaturesTask, private val computeTrustTask: ComputeTrustTask, private val taskExecutor: TaskExecutor, + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val cryptoCoroutineScope: CoroutineScope, val eventBus: EventBus) : CrossSigningService, DeviceListManager.UserDevicesUpdateListener { private var olmUtility: OlmUtility? = null @@ -208,6 +214,7 @@ internal class DefaultCrossSigningService @Inject constructor( cryptoStore.storePrivateKeysInfo(masterKeyPrivateKey?.toBase64NoPadding(), uskPrivateKey?.toBase64NoPadding(), sskPrivateKey?.toBase64NoPadding()) uploadSigningKeysTask.configureWith(params) { + this.executionThread = TaskThread.CRYPTO this.callback = object : MatrixCallback { override fun onSuccess(data: Unit) { Timber.i("## CrossSigning - Keys successfully uploaded") @@ -243,6 +250,7 @@ internal class DefaultCrossSigningService @Inject constructor( resetTrustOnKeyChange() uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadSignatureQueryBuilder.build())) { // this.retryCount = 3 + this.executionThread = TaskThread.CRYPTO this.callback = object : MatrixCallback { override fun onSuccess(data: Unit) { Timber.i("## CrossSigning - signatures successfully uploaded") @@ -495,6 +503,7 @@ internal class DefaultCrossSigningService @Inject constructor( .withSigningKeyInfo(otherMasterKeys.copyForSignature(userId, userPubKey, newSignature)) .build() uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadQuery)) { + this.executionThread = TaskThread.CRYPTO this.callback = callback }.executeBy(taskExecutor) } @@ -541,6 +550,7 @@ internal class DefaultCrossSigningService @Inject constructor( .withDeviceInfo(toUpload) .build() uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadQuery)) { + this.executionThread = TaskThread.CRYPTO this.callback = callback }.executeBy(taskExecutor) } @@ -607,48 +617,52 @@ internal class DefaultCrossSigningService @Inject constructor( } override fun onUsersDeviceUpdate(users: List) { - Timber.d("## CrossSigning - onUsersDeviceUpdate for ${users.size} users") - users.forEach { otherUserId -> + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { + Timber.d("## CrossSigning - onUsersDeviceUpdate for ${users.size} users") + users.forEach { otherUserId -> - checkUserTrust(otherUserId).let { - Timber.d("## CrossSigning - update trust for $otherUserId , verified=${it.isVerified()}") - setUserKeysAsTrusted(otherUserId, it.isVerified()) + checkUserTrust(otherUserId).let { + Timber.d("## CrossSigning - update trust for $otherUserId , verified=${it.isVerified()}") + setUserKeysAsTrusted(otherUserId, it.isVerified()) + } + + // TODO if my keys have changes, i should recheck all devices of all users? + val devices = cryptoStore.getUserDeviceList(otherUserId) + devices?.forEach { device -> + val updatedTrust = checkDeviceTrust(otherUserId, device.deviceId, device.trustLevel?.isLocallyVerified() ?: false) + Timber.d("## CrossSigning - update trust for device ${device.deviceId} of user $otherUserId , verified=$updatedTrust") + cryptoStore.setDeviceTrust(otherUserId, device.deviceId, updatedTrust.isCrossSignedVerified(), updatedTrust.isLocallyVerified()) + } + + if (otherUserId == userId) { + // It's me, i should check if a newly trusted device is signing my master key + // In this case it will change my MSK trust, and should then re-trigger a check of all other user trust + setUserKeysAsTrusted(otherUserId, checkSelfTrust().isVerified()) + } + + eventBus.post(CryptoToSessionUserTrustChange(users)) } - - // TODO if my keys have changes, i should recheck all devices of all users? - val devices = cryptoStore.getUserDeviceList(otherUserId) - devices?.forEach { device -> - val updatedTrust = checkDeviceTrust(otherUserId, device.deviceId, device.trustLevel?.isLocallyVerified() ?: false) - Timber.d("## CrossSigning - update trust for device ${device.deviceId} of user $otherUserId , verified=$updatedTrust") - cryptoStore.setDeviceTrust(otherUserId, device.deviceId, updatedTrust.isCrossSignedVerified(), updatedTrust.isLocallyVerified()) - } - - if (otherUserId == userId) { - // It's me, i should check if a newly trusted device is signing my master key - // In this case it will change my MSK trust, and should then re-trigger a check of all other user trust - setUserKeysAsTrusted(otherUserId, checkSelfTrust().isVerified()) - } - - eventBus.post(CryptoToSessionUserTrustChange(users)) } } private fun setUserKeysAsTrusted(otherUserId: String, trusted: Boolean) { - val currentTrust = cryptoStore.getCrossSigningInfo(otherUserId)?.isTrusted() - cryptoStore.setUserKeysAsTrusted(otherUserId, trusted) - // If it's me, recheck trust of all users and devices? - val users = ArrayList() - if (otherUserId == userId && currentTrust != trusted) { - cryptoStore.updateUsersTrust { - users.add(it) - checkUserTrust(it).isVerified() - } + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { + val currentTrust = cryptoStore.getCrossSigningInfo(otherUserId)?.isTrusted() + cryptoStore.setUserKeysAsTrusted(otherUserId, trusted) + // If it's me, recheck trust of all users and devices? + val users = ArrayList() + if (otherUserId == userId && currentTrust != trusted) { + cryptoStore.updateUsersTrust { + users.add(it) + checkUserTrust(it).isVerified() + } - users.forEach { - cryptoStore.getUserDeviceList(it)?.forEach { device -> - val updatedTrust = checkDeviceTrust(it, device.deviceId, device.trustLevel?.isLocallyVerified() ?: false) - Timber.d("## CrossSigning - update trust for device ${device.deviceId} of user $otherUserId , verified=$updatedTrust") - cryptoStore.setDeviceTrust(it, device.deviceId, updatedTrust.isCrossSignedVerified(), updatedTrust.isLocallyVerified()) + users.forEach { + cryptoStore.getUserDeviceList(it)?.forEach { device -> + val updatedTrust = checkDeviceTrust(it, device.deviceId, device.trustLevel?.isLocallyVerified() ?: false) + Timber.d("## CrossSigning - update trust for device ${device.deviceId} of user $otherUserId , verified=$updatedTrust") + cryptoStore.setDeviceTrust(it, device.deviceId, updatedTrust.isCrossSignedVerified(), updatedTrust.isLocallyVerified()) + } } } } From 1917fbcc933a3d93d0236ef21e8f7aede3f7e46e Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 6 Feb 2020 13:56:39 +0100 Subject: [PATCH 10/11] eventBus private --- .../internal/crypto/crosssigning/DefaultCrossSigningService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt index 141490643f..a927a06b25 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt @@ -62,7 +62,7 @@ internal class DefaultCrossSigningService @Inject constructor( private val taskExecutor: TaskExecutor, private val coroutineDispatchers: MatrixCoroutineDispatchers, private val cryptoCoroutineScope: CoroutineScope, - val eventBus: EventBus) : CrossSigningService, DeviceListManager.UserDevicesUpdateListener { + private val eventBus: EventBus) : CrossSigningService, DeviceListManager.UserDevicesUpdateListener { private var olmUtility: OlmUtility? = null From 5fedfd92862ebfc465600d9fcefb150931cb30b7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 6 Feb 2020 16:00:05 +0100 Subject: [PATCH 11/11] Cleanup --- .../crosssigning/CrossSigningService.kt | 3 - .../internal/crypto/DeviceListManager.kt | 2 +- .../crypto/crosssigning/ComputeTrustTask.kt | 56 ++++++++++--------- .../DefaultCrossSigningService.kt | 14 ++--- .../SessionToCryptoRoomMembersUpdate.kt | 6 +- .../crypto/crosssigning/ShieldTrustUpdater.kt | 16 +++--- .../database/mapper/RoomSummaryMapper.kt | 1 - .../session/room/RoomSummaryUpdater.kt | 2 +- .../java/im/vector/riotx/core/rx/RxConfig.kt | 3 +- 9 files changed, 47 insertions(+), 56 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt index 2b1c48174e..b7bc20a1dc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt @@ -18,7 +18,6 @@ package im.vector.matrix.android.api.session.crypto.crosssigning import androidx.lifecycle.LiveData import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel import im.vector.matrix.android.api.util.Optional import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustResult import im.vector.matrix.android.internal.crypto.crosssigning.UserTrustResult @@ -63,6 +62,4 @@ interface CrossSigningService { fun checkDeviceTrust(otherUserId: String, otherDeviceId: String, locallyTrusted: Boolean?): DeviceTrustResult - - suspend fun getTrustLevelForUsers(userIds: List): RoomEncryptionTrustLevel } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt index cd46cdbe36..04b301ba9e 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt @@ -44,7 +44,7 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM taskExecutor: TaskExecutor) { interface UserDevicesUpdateListener { - fun onUsersDeviceUpdate(users: List) + fun onUsersDeviceUpdate(userIds: List) } private val deviceChangeListeners = mutableListOf() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ComputeTrustTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ComputeTrustTask.kt index b7eba11103..207dc0b928 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ComputeTrustTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ComputeTrustTask.kt @@ -24,7 +24,7 @@ import javax.inject.Inject internal interface ComputeTrustTask : Task { data class Params( - val userList: List + val userIds: List ) } @@ -33,36 +33,38 @@ internal class DefaultComputeTrustTask @Inject constructor( ) : ComputeTrustTask { override suspend fun execute(params: ComputeTrustTask.Params): RoomEncryptionTrustLevel { - val userIds = params.userList - val allTrusted = userIds - .filter { getUserCrossSigningKeys(it)?.isTrusted() == true } + val allTrustedUserIds = params.userIds + .filter { userId -> getUserCrossSigningKeys(userId)?.isTrusted() == true } - val allUsersAreVerified = userIds.size == allTrusted.size - - return if (allTrusted.isEmpty()) { + return if (allTrustedUserIds.isEmpty()) { RoomEncryptionTrustLevel.Default } else { // If one of the verified user as an untrusted device -> warning - // Green if all devices of all verified users are trusted -> green - // else black - val allDevices = allTrusted.mapNotNull { - cryptoStore.getUserDeviceList(it) - }.flatten() - if (getMyCrossSigningKeys() != null) { - val hasWarning = allDevices.any { !it.trustLevel?.crossSigningVerified.orFalse() } - if (hasWarning) { - RoomEncryptionTrustLevel.Warning - } else { - if (allUsersAreVerified) RoomEncryptionTrustLevel.Trusted else RoomEncryptionTrustLevel.Default - } - } else { - val hasWarningLegacy = allDevices.any { !it.isVerified } - if (hasWarningLegacy) { - RoomEncryptionTrustLevel.Warning - } else { - if (allUsersAreVerified) RoomEncryptionTrustLevel.Trusted else RoomEncryptionTrustLevel.Default - } - } + // If all devices of all verified users are trusted -> green + // else -> black + allTrustedUserIds + .mapNotNull { cryptoStore.getUserDeviceList(it) } + .flatten() + .let { allDevices -> + if (getMyCrossSigningKeys() != null) { + allDevices.any { !it.trustLevel?.crossSigningVerified.orFalse() } + } else { + // Legacy method + allDevices.any { !it.isVerified } + } + } + .let { hasWarning -> + if (hasWarning) { + RoomEncryptionTrustLevel.Warning + } else { + if (params.userIds.size == allTrustedUserIds.size) { + // all users are trusted and all devices are verified + RoomEncryptionTrustLevel.Trusted + } else { + RoomEncryptionTrustLevel.Default + } + } + } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt index a927a06b25..920e5e9e4d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt @@ -19,7 +19,6 @@ package im.vector.matrix.android.internal.crypto.crosssigning import androidx.lifecycle.LiveData import dagger.Lazy import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo import im.vector.matrix.android.api.util.Optional @@ -616,11 +615,10 @@ internal class DefaultCrossSigningService @Inject constructor( } } - override fun onUsersDeviceUpdate(users: List) { + override fun onUsersDeviceUpdate(userIds: List) { cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { - Timber.d("## CrossSigning - onUsersDeviceUpdate for ${users.size} users") - users.forEach { otherUserId -> - + Timber.d("## CrossSigning - onUsersDeviceUpdate for ${userIds.size} users") + userIds.forEach { otherUserId -> checkUserTrust(otherUserId).let { Timber.d("## CrossSigning - update trust for $otherUserId , verified=${it.isVerified()}") setUserKeysAsTrusted(otherUserId, it.isVerified()) @@ -640,7 +638,7 @@ internal class DefaultCrossSigningService @Inject constructor( setUserKeysAsTrusted(otherUserId, checkSelfTrust().isVerified()) } - eventBus.post(CryptoToSessionUserTrustChange(users)) + eventBus.post(CryptoToSessionUserTrustChange(userIds)) } } } @@ -667,8 +665,4 @@ internal class DefaultCrossSigningService @Inject constructor( } } } - - override suspend fun getTrustLevelForUsers(userIds: List): RoomEncryptionTrustLevel { - return computeTrustTask.execute(ComputeTrustTask.Params(userIds)) - } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/SessionToCryptoRoomMembersUpdate.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/SessionToCryptoRoomMembersUpdate.kt index 0ecc9d30ba..04f63f945a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/SessionToCryptoRoomMembersUpdate.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/SessionToCryptoRoomMembersUpdate.kt @@ -16,10 +16,10 @@ package im.vector.matrix.android.internal.crypto.crosssigning data class SessionToCryptoRoomMembersUpdate( - val encryptedRoomMembersUpdate: String, - val userList: List + val roomId: String, + val userIds: List ) data class CryptoToSessionUserTrustChange( - val userList: List + val userIds: List ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt index d416abe10a..a49ea77da7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt @@ -32,12 +32,12 @@ import java.util.concurrent.atomic.AtomicReference import javax.inject.Inject internal class ShieldTrustUpdater @Inject constructor( - val eventBus: EventBus, + private val eventBus: EventBus, private val computeTrustTask: ComputeTrustTask, - val taskExecutor: TaskExecutor, - @CryptoDatabase val cryptoRealmConfiguration: RealmConfiguration, - @SessionDatabase val sessionRealmConfiguration: RealmConfiguration, - val roomSummaryUpdater: RoomSummaryUpdater + private val taskExecutor: TaskExecutor, + @CryptoDatabase private val cryptoRealmConfiguration: RealmConfiguration, + @SessionDatabase private val sessionRealmConfiguration: RealmConfiguration, + private val roomSummaryUpdater: RoomSummaryUpdater ) { companion object { @@ -84,12 +84,12 @@ internal class ShieldTrustUpdater @Inject constructor( @Subscribe fun onRoomMemberChange(update: SessionToCryptoRoomMembersUpdate) { taskExecutor.executorScope.launch { - val updatedTrust = computeTrustTask.execute(ComputeTrustTask.Params(update.userList)) + val updatedTrust = computeTrustTask.execute(ComputeTrustTask.Params(update.userIds)) // We need to send that back to session base BACKGROUND_HANDLER.post { backgroundSessionRealm.get().executeTransaction { realm -> - roomSummaryUpdater.updateShieldTrust(realm, update.encryptedRoomMembersUpdate, updatedTrust) + roomSummaryUpdater.updateShieldTrust(realm, update.roomId, updatedTrust) } } } @@ -97,7 +97,7 @@ internal class ShieldTrustUpdater @Inject constructor( @Subscribe fun onTrustUpdate(update: CryptoToSessionUserTrustChange) { - onCryptoDevicesChange(update.userList) + onCryptoDevicesChange(update.userIds) } private fun onCryptoDevicesChange(users: List) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt index 6ebd3af78d..617dc6acfa 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt @@ -17,7 +17,6 @@ package im.vector.matrix.android.internal.database.mapper import im.vector.matrix.android.api.session.crypto.CryptoService -import im.vector.matrix.android.api.session.crypto.MXCryptoError import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.tag.RoomTag import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt index 5df7fb5be5..fbfe2b403e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt @@ -144,7 +144,7 @@ internal class RoomSummaryUpdater @Inject constructor( roomSummaryEntity.otherMemberIds.clear() roomSummaryEntity.otherMemberIds.addAll(otherRoomMembers) if (roomSummaryEntity.isEncrypted) { - eventBus.post(SessionToCryptoRoomMembersUpdate(roomId, roomSummaryEntity.otherMemberIds.map { it } + userId)) + eventBus.post(SessionToCryptoRoomMembersUpdate(roomId, roomSummaryEntity.otherMemberIds.toList() + userId)) } } } diff --git a/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt b/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt index 5673bb9c12..73e68a6bf0 100644 --- a/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt +++ b/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt @@ -31,14 +31,13 @@ class RxConfig @Inject constructor( fun setupRxPlugin() { RxJavaPlugins.setErrorHandler { throwable -> Timber.e(throwable, "RxError") - //is InterruptedException -> fine, some blocking code was interrupted by a dispose call + // is InterruptedException -> fine, some blocking code was interrupted by a dispose call if (throwable !is InterruptedException) { // Avoid crash in production, except if user wants it if (vectorPreferences.failFast()) { throw throwable } } - } } }