diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/ReferencesAggregatedSummary.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/ReferencesAggregatedSummary.kt index fce166c37a..ca9d81cba1 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/ReferencesAggregatedSummary.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/ReferencesAggregatedSummary.kt @@ -27,4 +27,3 @@ class ReferencesAggregatedSummary( val sourceEvents: List, val localEchos: List ) - diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt index 9149f99c17..1d50fc89fe 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt @@ -108,6 +108,7 @@ internal class DefaultSasVerificationService @Inject constructor( onRoomStartRequestReceived(event) } EventType.KEY_VERIFICATION_CANCEL -> { + // MultiSessions | ignore events if i didn't sent the start from this device, or accepted from this device onRoomCancelReceived(event) } EventType.KEY_VERIFICATION_ACCEPT -> { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationMessageLiveObserver.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationMessageLiveObserver.kt index e7a38e8908..2fee568895 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationMessageLiveObserver.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationMessageLiveObserver.kt @@ -19,14 +19,15 @@ import com.zhuinden.monarchy.Monarchy 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.events.model.EventType +import im.vector.matrix.android.api.session.events.model.LocalEcho import im.vector.matrix.android.api.session.events.model.toModel -import im.vector.matrix.android.api.session.room.model.message.MessageContent -import im.vector.matrix.android.api.session.room.model.message.MessageType +import im.vector.matrix.android.api.session.room.model.message.* import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult import im.vector.matrix.android.internal.database.RealmLiveEntityObserver import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.types +import im.vector.matrix.android.internal.di.DeviceId import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.task.TaskExecutor @@ -36,10 +37,12 @@ import io.realm.RealmResults import timber.log.Timber import java.util.* import javax.inject.Inject +import kotlin.collections.ArrayList internal class VerificationMessageLiveObserver @Inject constructor( @SessionDatabase realmConfiguration: RealmConfiguration, @UserId private val userId: String, + @DeviceId private val deviceId: String?, private val cryptoService: CryptoService, private val sasVerificationService: DefaultSasVerificationService, private val taskExecutor: TaskExecutor @@ -58,6 +61,8 @@ internal class VerificationMessageLiveObserver @Inject constructor( ) } + val transactionsHandledByOtherDevice = ArrayList() + override fun onChange(results: RealmResults, changeSet: OrderedCollectionChangeSet) { // TODO do that in a task // TODO how to ignore when it's an initial sync? @@ -65,8 +70,8 @@ internal class VerificationMessageLiveObserver @Inject constructor( .asSequence() .mapNotNull { results[it]?.asDomain() } .filterNot { - // ignore mines ^^ - it.senderId == userId + // ignore local echos + LocalEcho.isLocalEchoId(it.eventId ?: "") } .toList() @@ -112,6 +117,45 @@ internal class VerificationMessageLiveObserver @Inject constructor( } } Timber.v("## SAS Verification live observer: received msgId: ${event.eventId} type: ${event.getClearType()}") + + if (event.senderId == userId) { + // If it's send from me, we need to keep track of Requests or Start + // done from another device of mine + + if (EventType.MESSAGE == event.type) { + val msgType = event.getClearContent().toModel()?.type + if (MessageType.MSGTYPE_VERIFICATION_REQUEST == msgType) { + event.getClearContent().toModel()?.let { + if (it.fromDevice != deviceId) { + // The verification is requested from another device + Timber.v("## SAS Verification live observer: Transaction requested from other device tid:${event.eventId} ") + event.eventId?.let { txId -> transactionsHandledByOtherDevice.add(txId) } + } + } + } + } else if (EventType.KEY_VERIFICATION_START == event.type) { + event.getClearContent().toModel()?.let { + if (it.fromDevice != deviceId) { + // The verification is started from another device + Timber.v("## SAS Verification live observer: Transaction started by other device tid:${it.transactionID} ") + it.transactionID?.let { txId -> transactionsHandledByOtherDevice.add(txId) } + } + } + } else if (EventType.KEY_VERIFICATION_CANCEL == event.type || EventType.KEY_VERIFICATION_DONE == event.type) { + event.getClearContent().toModel()?.relatesTo?.eventId?.let { + transactionsHandledByOtherDevice.remove(it) + } + } + + return@forEach + } + + val relatesTo = event.getClearContent().toModel()?.relatesTo?.eventId + if (relatesTo != null && transactionsHandledByOtherDevice.contains(relatesTo)) { + // Ignore this event, it is directed to another of my devices + Timber.v("## SAS Verification live observer: Ignore Transaction handled by other device tid:$relatesTo ") + return@forEach + } when (event.getClearType()) { EventType.KEY_VERIFICATION_START, EventType.KEY_VERIFICATION_ACCEPT, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/StringQualifiers.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/StringQualifiers.kt index 0e38618590..3444a8fa70 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/StringQualifiers.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/StringQualifiers.kt @@ -25,6 +25,13 @@ import javax.inject.Qualifier @Retention(AnnotationRetention.RUNTIME) internal annotation class UserId +/** + * Used to inject the userId + */ +@Qualifier +@Retention(AnnotationRetention.RUNTIME) +internal annotation class DeviceId + /** * Used to inject the md5 of the userId */ diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt index 883fd37745..6f4136405e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt @@ -77,6 +77,13 @@ internal abstract class SessionModule { return credentials.userId } + @JvmStatic + @DeviceId + @Provides + fun providesDeviceId(credentials: Credentials): String? { + return credentials.deviceId + } + @JvmStatic @UserMd5 @Provides