From 553604423eaddab82cf73ad72279c9f8af677421 Mon Sep 17 00:00:00 2001 From: Valere Date: Sun, 1 Dec 2019 12:44:29 +0100 Subject: [PATCH 01/14] Support verification using room transport --- .../MessageVerificationAcceptContent.kt | 10 +++---- .../MessageVerificationCancelContent.kt | 4 +-- .../message/MessageVerificationKeyContent.kt | 10 +++---- .../MessageVerificationRequestContent.kt | 4 +-- .../model/rest/KeyVerificationAccept.kt | 2 +- .../VerificationMessageLiveObserver.kt | 30 +++++++------------ .../room/send/LocalEchoEventFactory.kt | 4 +-- .../timeline/factory/TimelineItemFactory.kt | 2 +- 8 files changed, 28 insertions(+), 38 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationAcceptContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationAcceptContent.kt index 66914374df..bda4b9f0ac 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationAcceptContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationAcceptContent.kt @@ -20,8 +20,8 @@ import com.squareup.moshi.JsonClass import im.vector.matrix.android.api.session.events.model.RelationType import im.vector.matrix.android.api.session.events.model.toContent import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent -import im.vector.matrix.android.internal.crypto.verification.VerificationInfoAcceptFactory -import im.vector.matrix.android.internal.crypto.verification.VerificationInfoAccept +import im.vector.matrix.android.internal.crypto.verification.AcceptVerifInfoFactory +import im.vector.matrix.android.internal.crypto.verification.VerifInfoAccept import timber.log.Timber @JsonClass(generateAdapter = true) @@ -32,7 +32,7 @@ internal data class MessageVerificationAcceptContent( @Json(name = "short_authentication_string") override val shortAuthenticationStrings: List?, @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?, @Json(name = "commitment") override var commitment: String? = null -) : VerificationInfoAccept { +) : VerifInfoAccept { override val transactionID: String? get() = relatesTo?.eventId @@ -52,14 +52,14 @@ internal data class MessageVerificationAcceptContent( override fun toEventContent() = this.toContent() - companion object : VerificationInfoAcceptFactory { + companion object : AcceptVerifInfoFactory { override fun create(tid: String, keyAgreementProtocol: String, hash: String, commitment: String, messageAuthenticationCode: String, - shortAuthenticationStrings: List): VerificationInfoAccept { + shortAuthenticationStrings: List): VerifInfoAccept { return MessageVerificationAcceptContent( hash, keyAgreementProtocol, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationCancelContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationCancelContent.kt index 2070845f46..08fc3cbdbb 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationCancelContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationCancelContent.kt @@ -21,7 +21,7 @@ import im.vector.matrix.android.api.session.crypto.sas.CancelCode import im.vector.matrix.android.api.session.events.model.RelationType import im.vector.matrix.android.api.session.events.model.toContent import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent -import im.vector.matrix.android.internal.crypto.verification.VerificationInfoCancel +import im.vector.matrix.android.internal.crypto.verification.VerifInfoCancel @JsonClass(generateAdapter = true) internal data class MessageVerificationCancelContent( @@ -29,7 +29,7 @@ internal data class MessageVerificationCancelContent( @Json(name = "reason") override val reason: String? = null, @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? -) : VerificationInfoCancel { +) : VerifInfoCancel { override val transactionID: String? get() = relatesTo?.eventId diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationKeyContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationKeyContent.kt index 2dacb19871..0b93e3299a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationKeyContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationKeyContent.kt @@ -20,8 +20,8 @@ import com.squareup.moshi.JsonClass import im.vector.matrix.android.api.session.events.model.RelationType import im.vector.matrix.android.api.session.events.model.toContent import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent -import im.vector.matrix.android.internal.crypto.verification.VerificationInfoKey -import im.vector.matrix.android.internal.crypto.verification.VerificationInfoKeyFactory +import im.vector.matrix.android.internal.crypto.verification.VerifInfoKey +import im.vector.matrix.android.internal.crypto.verification.KeyVerifInfoFactory import timber.log.Timber @JsonClass(generateAdapter = true) @@ -31,7 +31,7 @@ internal data class MessageVerificationKeyContent( */ @Json(name = "key") override val key: String? = null, @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? -) : VerificationInfoKey { +) : VerifInfoKey { override val transactionID: String? get() = relatesTo?.eventId @@ -46,9 +46,9 @@ internal data class MessageVerificationKeyContent( override fun toEventContent() = this.toContent() - companion object : VerificationInfoKeyFactory { + companion object : KeyVerifInfoFactory { - override fun create(tid: String, pubKey: String): VerificationInfoKey { + override fun create(tid: String, pubKey: String): VerifInfoKey { return MessageVerificationKeyContent( pubKey, RelationDefaultContent( diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt index 1f6c8158fe..afefa39847 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt @@ -21,12 +21,12 @@ import im.vector.matrix.android.api.session.events.model.Content import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent @JsonClass(generateAdapter = true) -data class MessageVerificationRequestContent( +class MessageVerificationRequestContent( @Json(name = "msgtype") override val type: String = MessageType.MSGTYPE_VERIFICATION_REQUEST, @Json(name = "body") override val body: String, @Json(name = "from_device") val fromDevice: String, @Json(name = "methods") val methods: List, - @Json(name = "to") val toUserId: String, + @Json(name = "to") val to: String, // @Json(name = "timestamp") val timestamp: Int, @Json(name = "format") val format: String? = null, @Json(name = "formatted_body") val formattedBody: String? = null, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationAccept.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationAccept.kt index ef30986124..45de68cf77 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationAccept.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationAccept.kt @@ -88,7 +88,7 @@ internal data class KeyVerificationAccept( hash: String, commitment: String, messageAuthenticationCode: String, - shortAuthenticationStrings: List): VerificationInfoAccept { + shortAuthenticationStrings: List): VerifInfoAccept { return KeyVerificationAccept().apply { this.transactionID = tid this.keyAgreementProtocol = keyAgreementProtocol 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 9a9cf9a420..2886d78d8c 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 @@ -37,13 +37,12 @@ import timber.log.Timber import java.util.* import javax.inject.Inject -internal class VerificationMessageLiveObserver @Inject constructor( - @SessionDatabase realmConfiguration: RealmConfiguration, - @UserId private val userId: String, - private val cryptoService: CryptoService, - private val sasVerificationService: DefaultSasVerificationService, - private val taskExecutor: TaskExecutor -) : RealmLiveEntityObserver(realmConfiguration) { +internal class VerificationMessageLiveObserver @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration, + @UserId private val userId: String, + private val cryptoService: CryptoService, + private val sasVerificationService: DefaultSasVerificationService, + private val taskExecutor: TaskExecutor) : + RealmLiveEntityObserver(realmConfiguration) { override val query = Monarchy.Query { EventEntity.types(it, listOf( @@ -70,23 +69,12 @@ internal class VerificationMessageLiveObserver @Inject constructor( } .toList() - // TODO use age also, ignore initial sync or back pagination? - val now = System.currentTimeMillis() - val tooInThePast = now - (10 * 60 * 1000 * 1000) - val tooInTheFuture = System.currentTimeMillis() + (5 * 60 * 1000 * 1000) - events.forEach { event -> - Timber.d("## SAS Verification live observer: received msgId: ${event.eventId} msgtype: ${event.type} from ${event.senderId}") + Timber.d("## SAS Verification live observer: received msgId: ${event.eventId} msgtype: ${event.type} from ${event.senderId}") Timber.v("## SAS Verification live observer: received msgId: $event") - // If the request is in the future by more than 5 minutes or more than 10 minutes in the past, - // the message should be ignored by the receiver. - val eventOrigin = event.originServerTs ?: -1 - if (eventOrigin < tooInThePast || eventOrigin > tooInTheFuture) { - Timber.d("## SAS Verification live observer: msgId: ${event.eventId} is out of time ^^") - return@forEach - } // decrypt if needed? + if (event.isEncrypted() && event.mxDecryptionResult == null) { // TODO use a global event decryptor? attache to session and that listen to new sessionId? // for now decrypt sync @@ -114,6 +102,8 @@ internal class VerificationMessageLiveObserver @Inject constructor( } EventType.MESSAGE -> { if (MessageType.MSGTYPE_VERIFICATION_REQUEST == event.getClearContent().toModel()?.type) { + // TODO If the request is in the future by more than 5 minutes or more than 10 minutes in the past, + // the message should be ignored by the receiver. sasVerificationService.onRoomRequestReceived(event) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt index 45172fb213..a225146d83 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt @@ -286,7 +286,7 @@ internal class LocalEchoEventFactory @Inject constructor( ) } - fun createVerificationRequest(roomId: String, fromDevice: String, toUserId: String, methods: List): Event { + fun createVerificationRequest(roomId: String, fromDevice: String, to: String, methods: List): Event { val localID = LocalEcho.createLocalEchoId() return Event( roomId = roomId, @@ -297,7 +297,7 @@ internal class LocalEchoEventFactory @Inject constructor( content = MessageVerificationRequestContent( body = stringProvider.getString(R.string.key_verification_request_fallback_message, userId), fromDevice = fromDevice, - toUserId = toUserId, + to = to, methods = methods ).toContent(), unsignedData = UnsignedData(age = null, transactionId = localID) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt index a705576234..4c36b55fef 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt @@ -72,7 +72,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me EventType.KEY_VERIFICATION_MAC -> { // These events are filtered from timeline in normal case // Only visible in developer mode - defaultItemFactory.create(event, highlight, callback) + defaultItemFactory.create(event, highlight, readMarkerVisible, callback) } // Unhandled event types (yet) From e71ad0e51521f2ae51be1ac23ecf0f465ee291cd Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 3 Dec 2019 18:24:18 +0100 Subject: [PATCH 02/14] Simple strategy to Ignore old verification messages --- .../VerificationMessageLiveObserver.kt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) 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 2886d78d8c..6e365ac838 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 @@ -69,12 +69,23 @@ internal class VerificationMessageLiveObserver @Inject constructor(@SessionDatab } .toList() + // TODO use age also, ignore initial sync or back pagination? + val now = System.currentTimeMillis() + val tooInThePast = now - (10 * 60 * 1000 * 1000) + val tooInTheFuture = System.currentTimeMillis() + (5 * 60 * 1000 * 1000) + events.forEach { event -> Timber.d("## SAS Verification live observer: received msgId: ${event.eventId} msgtype: ${event.type} from ${event.senderId}") Timber.v("## SAS Verification live observer: received msgId: $event") + // If the request is in the future by more than 5 minutes or more than 10 minutes in the past, + // the message should be ignored by the receiver. + val eventOrigin = event.originServerTs ?: -1 + if (eventOrigin < tooInThePast || eventOrigin > tooInTheFuture) { + Timber.d("## SAS Verification live observer: msgId: ${event.eventId} is out of time ^^") + return@forEach + } // decrypt if needed? - if (event.isEncrypted() && event.mxDecryptionResult == null) { // TODO use a global event decryptor? attache to session and that listen to new sessionId? // for now decrypt sync @@ -102,8 +113,6 @@ internal class VerificationMessageLiveObserver @Inject constructor(@SessionDatab } EventType.MESSAGE -> { if (MessageType.MSGTYPE_VERIFICATION_REQUEST == event.getClearContent().toModel()?.type) { - // TODO If the request is in the future by more than 5 minutes or more than 10 minutes in the past, - // the message should be ignored by the receiver. sasVerificationService.onRoomRequestReceived(event) } } From 62f0c6edc054546f684f8b4e6ae468283cde2edb Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 4 Dec 2019 18:22:01 +0100 Subject: [PATCH 03/14] Fix / Use transport to start verification --- .../room/model/message/MessageVerificationRequestContent.kt | 2 +- .../crypto/verification/DefaultSasVerificationService.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt index afefa39847..e131ba4fec 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt @@ -21,7 +21,7 @@ import im.vector.matrix.android.api.session.events.model.Content import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent @JsonClass(generateAdapter = true) -class MessageVerificationRequestContent( +data class MessageVerificationRequestContent( @Json(name = "msgtype") override val type: String = MessageType.MSGTYPE_VERIFICATION_REQUEST, @Json(name = "body") override val body: String, @Json(name = "from_device") val fromDevice: String, 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 d54ae3a22a..ed0a0638ba 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 @@ -572,7 +572,7 @@ internal class DefaultSasVerificationService @Inject constructor( transactionId, otherUserId, otherDeviceId) - tx.transport = sasTransportRoomMessageFactory.createTransport(roomId, cryptoService, tx) + tx.transport = sasTransportRoomMessageFactory.createTransport(roomId, cryptoService) addTransaction(tx) tx.start() From ea817ff1c5ae7641e3946973971922452171b101 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 5 Dec 2019 09:53:51 +0100 Subject: [PATCH 04/14] fix rebase --- .../home/room/detail/timeline/factory/TimelineItemFactory.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt index 4c36b55fef..a705576234 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt @@ -72,7 +72,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me EventType.KEY_VERIFICATION_MAC -> { // These events are filtered from timeline in normal case // Only visible in developer mode - defaultItemFactory.create(event, highlight, readMarkerVisible, callback) + defaultItemFactory.create(event, highlight, callback) } // Unhandled event types (yet) From 6da069348896ea963e84184f651172ae203ebafb Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 5 Dec 2019 10:08:27 +0100 Subject: [PATCH 05/14] Convert KeyVerificationStart to data class --- .../android/internal/crypto/model/rest/KeyVerificationStart.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationStart.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationStart.kt index e8c0334539..d1e0ff9049 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationStart.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationStart.kt @@ -41,6 +41,7 @@ data class KeyVerificationStart( return JsonCanonicalizer.getCanonicalJson(KeyVerificationStart::class.java, this) } + companion object { const val VERIF_METHOD_SAS = "m.sas.v1" } From f53b99a42305d9af1459b5a833d8c9bb759b2d37 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 5 Dec 2019 11:20:53 +0100 Subject: [PATCH 06/14] rebase --- .../android/internal/crypto/model/rest/KeyVerificationStart.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationStart.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationStart.kt index d1e0ff9049..e8c0334539 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationStart.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationStart.kt @@ -41,7 +41,6 @@ data class KeyVerificationStart( return JsonCanonicalizer.getCanonicalJson(KeyVerificationStart::class.java, this) } - companion object { const val VERIF_METHOD_SAS = "m.sas.v1" } From d0a3b4663ee15db997bafbd9278e8a1026f907bc Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 10 Dec 2019 16:37:54 +0100 Subject: [PATCH 07/14] FIx / room transport was not updating state --- .../crypto/verification/DefaultSasVerificationService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ed0a0638ba..d54ae3a22a 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 @@ -572,7 +572,7 @@ internal class DefaultSasVerificationService @Inject constructor( transactionId, otherUserId, otherDeviceId) - tx.transport = sasTransportRoomMessageFactory.createTransport(roomId, cryptoService) + tx.transport = sasTransportRoomMessageFactory.createTransport(roomId, cryptoService, tx) addTransaction(tx) tx.start() From cb4d52c9fb4c99567dfedefb7b6c773e3ab5da45 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 11 Dec 2019 14:44:31 +0100 Subject: [PATCH 08/14] Aggregate Event References for DM verifications --- .../android/api/session/events/model/Event.kt | 8 + .../api/session/events/model/UnsignedData.kt | 14 ++ .../room/model/EventAnnotationsSummary.kt | 3 +- .../room/model/ReferencesAggregatedContent.kt | 31 ++++ .../room/model/ReferencesAggregatedSummary.kt | 30 ++++ .../model/message/MessageRelationContent.kt | 2 +- .../verification/SasTransportRoomMessage.kt | 7 + .../verification/SasTransportToDevice.kt | 1 - .../VerificationMessageLiveObserver.kt | 21 ++- .../mapper/EventAnnotationsSummaryMapper.kt | 18 +++ .../internal/database/mapper/EventMapper.kt | 2 + .../model/EventAnnotationsSummaryEntity.kt | 3 +- .../internal/database/model/EventEntity.kt | 2 + .../ReferencesAggregatedSummaryEntity.kt | 31 ++++ .../database/model/SessionRealmModule.kt | 1 + ...eferencesAggregatedSummaryEntityQueries.kt | 22 +++ .../android/internal/di/MatrixModule.kt | 9 +- .../room/EventRelationsAggregationTask.kt | 141 +++++++++++++++--- .../room/EventRelationsAggregationUpdater.kt | 6 + .../internal/session/sync/RoomSyncHandler.kt | 20 ++- .../android/internal/task/TaskExecutor.kt | 1 + .../android/internal/task/TaskThread.kt | 3 +- .../util/MatrixCoroutineDispatchers.kt | 3 +- 23 files changed, 336 insertions(+), 43 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/ReferencesAggregatedContent.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/ReferencesAggregatedSummary.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/ReferencesAggregatedSummaryEntity.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt index bc6885eddc..ab39dea178 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt @@ -85,6 +85,14 @@ data class Event( @Transient var sendState: SendState = SendState.UNKNOWN + /** + The `age` value transcoded in a timestamp based on the device clock when the SDK received + the event from the home server. + Unlike `age`, this value is static. + */ + @Transient + var ageLocalTs: Long? = null + /** * Check if event is a state event. * @return true if event is state event. diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/UnsignedData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/UnsignedData.kt index 57eaa7dc76..b179cb7a31 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/UnsignedData.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/UnsignedData.kt @@ -21,9 +21,23 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class UnsignedData( + /** + * The time in milliseconds that has elapsed since the event was sent. + * This field is generated by the local homeserver, and may be incorrect if the local time on at least one of the two servers + * is out of sync, which can cause the age to either be negative or greater than it actually is. + */ @Json(name = "age") val age: Long?, + /** + * Optional. The event that redacted this event, if any. + */ @Json(name = "redacted_because") val redactedEvent: Event? = null, + /** + * The client-supplied transaction ID, if the client being given the event is the same one which sent it. + */ @Json(name = "transaction_id") val transactionId: String? = null, + /** + * Optional. The previous content for this event. If there is no previous content, this key will be missing. + */ @Json(name = "prev_content") val prevContent: Map? = null, @Json(name = "m.relations") val relations: AggregatedRelations? = null ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/EventAnnotationsSummary.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/EventAnnotationsSummary.kt index 0d403be2f4..28edfcfe04 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/EventAnnotationsSummary.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/EventAnnotationsSummary.kt @@ -18,5 +18,6 @@ package im.vector.matrix.android.api.session.room.model data class EventAnnotationsSummary( var eventId: String, var reactionsSummary: List, - var editSummary: EditAggregatedSummary? + var editSummary: EditAggregatedSummary?, + var referencesAggregatedSummary: ReferencesAggregatedSummary? = null ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/ReferencesAggregatedContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/ReferencesAggregatedContent.kt new file mode 100644 index 0000000000..ae6e52a091 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/ReferencesAggregatedContent.kt @@ -0,0 +1,31 @@ +/* + * 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.api.session.room.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * Contains an aggregated summary info of the references. + * Put pre-computed info that you want to access quickly without having + * to go through all references events + */ +@JsonClass(generateAdapter = true) +data class ReferencesAggregatedContent( + // Verification status info for m.key.verification.request msgType events + @Json(name = "verif_sum") val verificationSummary: String + // Add more fields for future summary info. +) 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 new file mode 100644 index 0000000000..fce166c37a --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/ReferencesAggregatedSummary.kt @@ -0,0 +1,30 @@ +/* + * 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.api.session.room.model + +import im.vector.matrix.android.api.session.events.model.Content + +/** + * Events can relates to other events, this object keeps a summary + * of all events that are referencing the 'eventId' event via the RelationType.REFERENCE + */ +class ReferencesAggregatedSummary( + val eventId: String, + val content: Content?, + val sourceEvents: List, + val localEchos: List +) + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageRelationContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageRelationContent.kt index ec773916fd..f65215e2bf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageRelationContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageRelationContent.kt @@ -21,6 +21,6 @@ import com.squareup.moshi.JsonClass import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent @JsonClass(generateAdapter = true) -internal data class MessageRelationContent( +data class MessageRelationContent( @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportRoomMessage.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportRoomMessage.kt index 8e956fd60e..e40e8be31f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportRoomMessage.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportRoomMessage.kt @@ -29,6 +29,7 @@ import im.vector.matrix.android.internal.crypto.tasks.SendVerificationMessageTas import im.vector.matrix.android.internal.session.room.send.SendResponse import im.vector.matrix.android.internal.task.TaskConstraints 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 timber.log.Timber import javax.inject.Inject @@ -56,6 +57,8 @@ internal class SasTransportRoomMessage( cryptoService ) ) { + callbackThread = TaskThread.DM_VERIF + executionThread = TaskThread.DM_VERIF constraints = TaskConstraints(true) callback = object : MatrixCallback { override fun onSuccess(data: SendResponse) { @@ -86,6 +89,8 @@ internal class SasTransportRoomMessage( cryptoService ) ) { + callbackThread = TaskThread.DM_VERIF + executionThread = TaskThread.DM_VERIF constraints = TaskConstraints(true) retryCount = 3 callback = object : MatrixCallback { @@ -115,6 +120,8 @@ internal class SasTransportRoomMessage( cryptoService ) ) { + callbackThread = TaskThread.DM_VERIF + executionThread = TaskThread.DM_VERIF constraints = TaskConstraints(true) retryCount = 3 } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportToDevice.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportToDevice.kt index bce23de1cd..85e9099972 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportToDevice.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportToDevice.kt @@ -61,7 +61,6 @@ internal class SasTransportToDevice( override fun onFailure(failure: Throwable) { Timber.e("## SAS verification [$tx.transactionId] failed to send toDevice in state : $tx.state") - tx.cancel(onErrorReason) } } 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 6e365ac838..2bca40c855 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 @@ -69,10 +69,12 @@ internal class VerificationMessageLiveObserver @Inject constructor(@SessionDatab } .toList() - // TODO use age also, ignore initial sync or back pagination? + // TODO ignore initial sync or back pagination? + val now = System.currentTimeMillis() - val tooInThePast = now - (10 * 60 * 1000 * 1000) - val tooInTheFuture = System.currentTimeMillis() + (5 * 60 * 1000 * 1000) + val tooInThePast = now - (10 * 60 * 1000) + val fiveMinInMs = 5 * 60 * 1000 + val tooInTheFuture = System.currentTimeMillis() + fiveMinInMs events.forEach { event -> Timber.d("## SAS Verification live observer: received msgId: ${event.eventId} msgtype: ${event.type} from ${event.senderId}") @@ -80,11 +82,18 @@ internal class VerificationMessageLiveObserver @Inject constructor(@SessionDatab // If the request is in the future by more than 5 minutes or more than 10 minutes in the past, // the message should be ignored by the receiver. - val eventOrigin = event.originServerTs ?: -1 - if (eventOrigin < tooInThePast || eventOrigin > tooInTheFuture) { - Timber.d("## SAS Verification live observer: msgId: ${event.eventId} is out of time ^^") + val ageLocalTs = event.ageLocalTs + if (ageLocalTs != null && (now - ageLocalTs) > fiveMinInMs) { + Timber.d("## SAS Verification live observer: msgId: ${event.eventId} is too old (age: ${(now - ageLocalTs)})") return@forEach + } else { + val eventOrigin = event.originServerTs ?: -1 + if (eventOrigin < tooInThePast || eventOrigin > tooInTheFuture) { + Timber.d("## SAS Verification live observer: msgId: ${event.eventId} is too old (ts: $eventOrigin") + return@forEach + } } + // decrypt if needed? if (event.isEncrypted() && event.mxDecryptionResult == null) { // TODO use a global event decryptor? attache to session and that listen to new sessionId? diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventAnnotationsSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventAnnotationsSummaryMapper.kt index 701d35926a..ccdb8fb91f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventAnnotationsSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventAnnotationsSummaryMapper.kt @@ -19,9 +19,11 @@ package im.vector.matrix.android.internal.database.mapper import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary import im.vector.matrix.android.api.session.room.model.ReactionAggregatedSummary +import im.vector.matrix.android.api.session.room.model.ReferencesAggregatedSummary import im.vector.matrix.android.internal.database.model.EditAggregatedSummaryEntity import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity import im.vector.matrix.android.internal.database.model.ReactionAggregatedSummaryEntity +import im.vector.matrix.android.internal.database.model.ReferencesAggregatedSummaryEntity import io.realm.RealmList internal object EventAnnotationsSummaryMapper { @@ -45,6 +47,14 @@ internal object EventAnnotationsSummaryMapper { it.sourceLocalEchoEvents.toList(), it.lastEditTs ) + }, + referencesAggregatedSummary = annotationsSummary.referencesSummaryEntity?.let { + ReferencesAggregatedSummary( + it.eventId, + ContentMapper.map(it.content), + it.sourceEvents.toList(), + it.sourceLocalEcho.toList() + ) } ) } @@ -75,6 +85,14 @@ internal object EventAnnotationsSummaryMapper { }) } } + eventAnnotationsSummaryEntity.referencesSummaryEntity = annotationsSummary.referencesAggregatedSummary?.let { + ReferencesAggregatedSummaryEntity( + it.eventId, + ContentMapper.map(it.content), + RealmList().apply { addAll(it.sourceEvents) }, + RealmList().apply { addAll(it.localEchos) } + ) + } return eventAnnotationsSummaryEntity } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventMapper.kt index ed5f04ef75..faac57e486 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventMapper.kt @@ -43,6 +43,7 @@ internal object EventMapper { eventEntity.redacts = event.redacts eventEntity.age = event.unsignedData?.age ?: event.originServerTs eventEntity.unsignedData = uds + eventEntity.ageLocalTs = event.ageLocalTs return eventEntity } @@ -70,6 +71,7 @@ internal object EventMapper { unsignedData = ud, redacts = eventEntity.redacts ).also { + it.ageLocalTs = eventEntity.ageLocalTs it.sendState = eventEntity.sendState eventEntity.decryptionResultJson?.let { json -> try { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventAnnotationsSummaryEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventAnnotationsSummaryEntity.kt index 523d94b770..1a4f72f0b1 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventAnnotationsSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventAnnotationsSummaryEntity.kt @@ -24,7 +24,8 @@ internal open class EventAnnotationsSummaryEntity( var eventId: String = "", var roomId: String? = null, var reactionsSummary: RealmList = RealmList(), - var editSummary: EditAggregatedSummaryEntity? = null + var editSummary: EditAggregatedSummaryEntity? = null, + var referencesSummaryEntity: ReferencesAggregatedSummaryEntity? = null ) : RealmObject() { companion object diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt index 4def7aec5d..9e3ed6a93b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt @@ -59,6 +59,8 @@ internal open class EventEntity(@Index var eventId: String = "", sendStateStr = value.name } + var ageLocalTs: Long? = null + companion object @LinkingObjects("untimelinedStateEvents") diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/ReferencesAggregatedSummaryEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/ReferencesAggregatedSummaryEntity.kt new file mode 100644 index 0000000000..1c3ea70e52 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/ReferencesAggregatedSummaryEntity.kt @@ -0,0 +1,31 @@ +/* + * 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.database.model + +import io.realm.RealmList +import io.realm.RealmObject + +internal open class ReferencesAggregatedSummaryEntity( + var eventId: String = "", + var content: String? = null, + // The list of the eventIDs used to build the summary (might be out of sync if chunked received from message chunk) + var sourceEvents: RealmList = RealmList(), + // List of transaction ids for local echos + var sourceLocalEcho: RealmList = RealmList() +) : RealmObject() { + + companion object +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/SessionRealmModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/SessionRealmModule.kt index 6059d3faf7..4a93819027 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/SessionRealmModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/SessionRealmModule.kt @@ -38,6 +38,7 @@ import io.realm.annotations.RealmModule IgnoredUserEntity::class, BreadcrumbsEntity::class, EventAnnotationsSummaryEntity::class, + ReferencesAggregatedSummaryEntity::class, ReactionAggregatedSummaryEntity::class, EditAggregatedSummaryEntity::class, PushRulesEntity::class, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt new file mode 100644 index 0000000000..9c7547b5e1 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt @@ -0,0 +1,22 @@ +package im.vector.matrix.android.internal.database.query + +import im.vector.matrix.android.internal.database.model.ReferencesAggregatedSummaryEntity +import im.vector.matrix.android.internal.database.model.ReferencesAggregatedSummaryEntityFields +import io.realm.Realm +import io.realm.RealmQuery +import io.realm.kotlin.where + +internal fun ReferencesAggregatedSummaryEntity.Companion.where(realm: Realm, eventId: String): RealmQuery { + val query = realm.where() + query.equalTo(ReferencesAggregatedSummaryEntityFields.EVENT_ID, eventId) + return query +} + +internal fun ReferencesAggregatedSummaryEntity.Companion.create(realm: Realm, txID: String): ReferencesAggregatedSummaryEntity { + return realm.createObject(ReferencesAggregatedSummaryEntity::class.java).apply { + this.eventId = txID + } +} + + + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt index c17864b82b..1cf0964e50 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt @@ -36,10 +36,11 @@ internal object MatrixModule { @MatrixScope fun providesMatrixCoroutineDispatchers(): MatrixCoroutineDispatchers { return MatrixCoroutineDispatchers(io = Dispatchers.IO, - computation = Dispatchers.Default, - main = Dispatchers.Main, - crypto = createBackgroundHandler("Crypto_Thread").asCoroutineDispatcher(), - sync = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + computation = Dispatchers.Default, + main = Dispatchers.Main, + crypto = createBackgroundHandler("Crypto_Thread").asCoroutineDispatcher(), + sync = Executors.newSingleThreadExecutor().asCoroutineDispatcher(), + dmVerif = Executors.newSingleThreadExecutor().asCoroutineDispatcher() ) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt index 3d7c5df5fc..5c38fcf797 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt @@ -19,7 +19,9 @@ 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.* +import im.vector.matrix.android.api.session.room.model.ReferencesAggregatedContent import im.vector.matrix.android.api.session.room.model.message.MessageContent +import im.vector.matrix.android.api.session.room.model.message.MessageRelationContent import im.vector.matrix.android.api.session.room.model.relation.ReactionContent import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent @@ -42,6 +44,14 @@ internal interface EventRelationsAggregationTask : Task { + EventType.REACTION -> { // we got a reaction!! Timber.v("###REACTION in room $roomId , reaction eventID ${event.eventId}") handleReaction(event, roomId, realm, userId, isLocalEcho) } - EventType.MESSAGE -> { + EventType.MESSAGE -> { if (event.unsignedData?.relations?.annotations != null) { Timber.v("###REACTION Agreggation in room $roomId for event ${event.eventId}") handleInitialAggregatedRelations(event, roomId, event.unsignedData.relations.annotations, realm) @@ -99,33 +109,49 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( } } - EventType.ENCRYPTED -> { + EventType.KEY_VERIFICATION_DONE, + EventType.KEY_VERIFICATION_CANCEL, + EventType.KEY_VERIFICATION_ACCEPT, + EventType.KEY_VERIFICATION_START, + EventType.KEY_VERIFICATION_MAC, + EventType.KEY_VERIFICATION_KEY -> { + Timber.v("## SAS REF in room $roomId for event ${event.eventId}") + event.content.toModel()?.relatesTo?.let { + if (it.type == RelationType.REFERENCE && it.eventId != null) { + handleVerification(realm, event, roomId, isLocalEcho, it.eventId, userId) + } + } + } + + EventType.ENCRYPTED -> { // Relation type is in clear val encryptedEventContent = event.content.toModel() if (encryptedEventContent?.relatesTo?.type == RelationType.REPLACE) { // we need to decrypt if needed - if (event.mxDecryptionResult == null) { - try { - val result = cryptoService.decryptEvent(event, event.roomId) - event.mxDecryptionResult = OlmDecryptionResult( - payload = result.clearEvent, - senderKey = result.senderCurve25519Key, - keysClaimed = result.claimedEd25519Key?.let { k -> mapOf("ed25519" to k) }, - forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain - ) - } catch (e: MXCryptoError) { - Timber.w("Failed to decrypt e2e replace") - // TODO -> we should keep track of this and retry, or aggregation will be broken - } - } + decryptIfNeeded(event) event.getClearContent().toModel()?.let { Timber.v("###REPLACE in room $roomId for event ${event.eventId}") // A replace! handleReplace(realm, event, it, roomId, isLocalEcho, encryptedEventContent.relatesTo.eventId) } + } else if (encryptedEventContent?.relatesTo?.type == RelationType.REFERENCE) { + decryptIfNeeded(event) + when (event.getClearType()) { + EventType.KEY_VERIFICATION_DONE, + EventType.KEY_VERIFICATION_CANCEL, + EventType.KEY_VERIFICATION_ACCEPT, + EventType.KEY_VERIFICATION_START, + EventType.KEY_VERIFICATION_MAC, + EventType.KEY_VERIFICATION_KEY -> { + Timber.v("## SAS REF in room $roomId for event ${event.eventId}") + encryptedEventContent.relatesTo.eventId?.let { + handleVerification(realm, event, roomId, isLocalEcho, it, userId) + } + } + } } } - EventType.REDACTION -> { + EventType.REDACTION -> { val eventToPrune = event.redacts?.let { EventEntity.where(realm, eventId = it).findFirst() } ?: return@forEach when (eventToPrune.type) { @@ -145,7 +171,7 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( } } } - else -> Timber.v("UnHandled event ${event.eventId}") + else -> Timber.v("UnHandled event ${event.eventId}") } } catch (t: Throwable) { Timber.e(t, "## Should not happen ") @@ -153,6 +179,23 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( } } + private fun decryptIfNeeded(event: Event) { + if (event.mxDecryptionResult == null) { + try { + val result = cryptoService.decryptEvent(event, event.roomId ?: "") + event.mxDecryptionResult = OlmDecryptionResult( + payload = result.clearEvent, + senderKey = result.senderCurve25519Key, + keysClaimed = result.claimedEd25519Key?.let { k -> mapOf("ed25519" to k) }, + forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain + ) + } catch (e: MXCryptoError) { + Timber.w("Failed to decrypt e2e replace") + // TODO -> we should keep track of this and retry, or aggregation will be broken + } + } + } + private fun handleReplace(realm: Realm, event: Event, content: MessageContent, roomId: String, isLocalEcho: Boolean, relatedEventId: String? = null) { val eventId = event.eventId ?: return val targetEventId = relatedEventId ?: content.relatesTo?.eventId ?: return @@ -228,7 +271,8 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( val eventSummary = EventAnnotationsSummaryEntity.create(realm, roomId, eventId) val sum = realm.createObject(ReactionAggregatedSummaryEntity::class.java) sum.key = it.key - sum.firstTimestamp = event.originServerTs ?: 0 // TODO how to maintain order? + sum.firstTimestamp = event.originServerTs + ?: 0 // TODO how to maintain order? sum.count = it.count eventSummary.reactionsSummary.add(sum) } else { @@ -374,4 +418,61 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( Timber.e("## Cannot find summary for key $reactionKey") } } + + private fun handleVerification(realm: Realm, event: Event, roomId: String, isLocalEcho: Boolean, relatedEventId: String, userId: String) { + val eventSummary = EventAnnotationsSummaryEntity.where(realm, relatedEventId).findFirst() + ?: EventAnnotationsSummaryEntity.create(realm, roomId, relatedEventId).apply { this.roomId = roomId } + + val verifSummary = eventSummary.referencesSummaryEntity + ?: ReferencesAggregatedSummaryEntity.create(realm, relatedEventId).also { + eventSummary.referencesSummaryEntity = it + } + + val txId = event.unsignedData?.transactionId + + if (!isLocalEcho && verifSummary.sourceLocalEcho.contains(txId)) { + // ok it has already been handled + } else { + ContentMapper.map(verifSummary.content)?.toModel() + var data = ContentMapper.map(verifSummary.content)?.toModel() + ?: ReferencesAggregatedContent(VerificationState.REQUEST.name) + // TODO ignore invalid messages? e.g a START after a CANCEL? + // i.e. never change state if already canceled/done + val newState = when (event.getClearType()) { + EventType.KEY_VERIFICATION_START -> { + VerificationState.WAITING + } + EventType.KEY_VERIFICATION_ACCEPT -> { + VerificationState.WAITING + } + EventType.KEY_VERIFICATION_KEY -> { + VerificationState.WAITING + } + EventType.KEY_VERIFICATION_MAC -> { + VerificationState.WAITING + } + EventType.KEY_VERIFICATION_CANCEL -> { + if (event.senderId == userId) { + VerificationState.CANCELED_BY_ME + } else VerificationState.CANCELED_BY_OTHER + } + EventType.KEY_VERIFICATION_DONE -> { + VerificationState.DONE + } + else -> VerificationState.REQUEST + } + + data = data.copy(verificationSummary = newState.name) + verifSummary.content = ContentMapper.map(data.toContent()) + } + + if (isLocalEcho) { + verifSummary.sourceLocalEcho.add(event.eventId) + } else { + if (verifSummary.sourceLocalEcho.contains(txId)) { + verifSummary.sourceLocalEcho.remove(txId) + } + verifSummary.sourceEvents.add(event.eventId) + } + } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationUpdater.kt index aadf1bfccf..916430877e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationUpdater.kt @@ -48,6 +48,12 @@ internal class EventRelationsAggregationUpdater @Inject constructor(@SessionData EventType.MESSAGE, EventType.REDACTION, EventType.REACTION, + EventType.KEY_VERIFICATION_DONE, + EventType.KEY_VERIFICATION_CANCEL, + EventType.KEY_VERIFICATION_ACCEPT, + EventType.KEY_VERIFICATION_START, + EventType.KEY_VERIFICATION_MAC, + EventType.KEY_VERIFICATION_KEY, EventType.ENCRYPTED) ) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt index 4a003eb7d9..649de30339 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt @@ -93,14 +93,15 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch // PRIVATE METHODS ***************************************************************************** private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy, isInitialSync: Boolean, reporter: DefaultInitialSyncProgressService?) { + val syncLocalTimeStampMillis = System.currentTimeMillis() val rooms = when (handlingStrategy) { is HandlingStrategy.JOINED -> handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_joined_rooms, 0.6f) { - handleJoinedRoom(realm, it.key, it.value, isInitialSync) + handleJoinedRoom(realm, it.key, it.value, isInitialSync, syncLocalTimeStampMillis) } is HandlingStrategy.INVITED -> handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_invited_rooms, 0.1f) { - handleInvitedRoom(realm, it.key, it.value) + handleInvitedRoom(realm, it.key, it.value, syncLocalTimeStampMillis) } is HandlingStrategy.LEFT -> { @@ -115,7 +116,8 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch private fun handleJoinedRoom(realm: Realm, roomId: String, roomSync: RoomSync, - isInitialSync: Boolean): RoomEntity { + isInitialSync: Boolean, + syncLocalTimestampMillis: Long): RoomEntity { Timber.v("Handle join sync for room $roomId") if (roomSync.ephemeral != null && roomSync.ephemeral.events.isNotEmpty()) { @@ -154,7 +156,8 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch roomEntity, roomSync.timeline.events, roomSync.timeline.prevToken, - roomSync.timeline.limited + roomSync.timeline.limited, + syncLocalTimestampMillis ) roomEntity.addOrUpdate(chunkEntity) } @@ -170,12 +173,13 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch private fun handleInvitedRoom(realm: Realm, roomId: String, - roomSync: InvitedRoomSync): RoomEntity { + roomSync: InvitedRoomSync, + syncLocalTimestampMillis: Long): RoomEntity { Timber.v("Handle invited sync for room $roomId") val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId) roomEntity.membership = Membership.INVITE if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) { - val chunkEntity = handleTimelineEvents(realm, roomEntity, roomSync.inviteState.events) + val chunkEntity = handleTimelineEvents(realm, roomEntity, roomSync.inviteState.events, syncLocalTimestampMillis = syncLocalTimestampMillis) roomEntity.addOrUpdate(chunkEntity) } val hasRoomMember = roomSync.inviteState?.events?.firstOrNull { @@ -200,7 +204,8 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch roomEntity: RoomEntity, eventList: List, prevToken: String? = null, - isLimited: Boolean = true): ChunkEntity { + isLimited: Boolean = true, + syncLocalTimestampMillis: Long): ChunkEntity { val lastChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomEntity.roomId) var stateIndexOffset = 0 val chunkEntity = if (!isLimited && lastChunk != null) { @@ -216,6 +221,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch val eventIds = ArrayList(eventList.size) for (event in eventList) { + event.ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it } event.eventId?.also { eventIds.add(it) } chunkEntity.add(roomEntity.roomId, event, PaginationDirection.FORWARDS, stateIndexOffset) // Give info to crypto module diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt index d5392779d1..fefd21b2cf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt @@ -86,5 +86,6 @@ internal class TaskExecutor @Inject constructor(private val coroutineDispatchers TaskThread.CALLER -> EmptyCoroutineContext TaskThread.CRYPTO -> coroutineDispatchers.crypto TaskThread.SYNC -> coroutineDispatchers.sync + TaskThread.DM_VERIF -> coroutineDispatchers.dmVerif } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskThread.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskThread.kt index 16ed93662c..4c24f30506 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskThread.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskThread.kt @@ -22,5 +22,6 @@ internal enum class TaskThread { IO, CALLER, CRYPTO, - SYNC + SYNC, + DM_VERIF } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/MatrixCoroutineDispatchers.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/MatrixCoroutineDispatchers.kt index 23201c084e..ce43c5ea77 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/MatrixCoroutineDispatchers.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/MatrixCoroutineDispatchers.kt @@ -23,5 +23,6 @@ internal data class MatrixCoroutineDispatchers( val computation: CoroutineDispatcher, val main: CoroutineDispatcher, val crypto: CoroutineDispatcher, - val sync: CoroutineDispatcher + val sync: CoroutineDispatcher, + val dmVerif: CoroutineDispatcher ) From cb595177a905cafd41b3bb2de226fb9b32b27f6a Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 11 Dec 2019 16:00:53 +0100 Subject: [PATCH 09/14] Fix test compilation --- .../vector/matrix/android/SingleThreadCoroutineDispatcher.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/SingleThreadCoroutineDispatcher.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/SingleThreadCoroutineDispatcher.kt index e63123f3b3..fb1faa92d4 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/SingleThreadCoroutineDispatcher.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/SingleThreadCoroutineDispatcher.kt @@ -18,5 +18,8 @@ package im.vector.matrix.android import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import kotlinx.coroutines.Dispatchers.Main +import kotlinx.coroutines.asCoroutineDispatcher +import java.util.concurrent.Executors -internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main, Main) +internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main, Main, + Executors.newSingleThreadExecutor().asCoroutineDispatcher()) From 0afcb60e7d7b279fb7928e0e952c49674094b17b Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 12 Dec 2019 14:31:01 +0100 Subject: [PATCH 10/14] fix rebase --- .../android/internal/crypto/model/rest/KeyVerificationAccept.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationAccept.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationAccept.kt index 45de68cf77..ef30986124 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationAccept.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationAccept.kt @@ -88,7 +88,7 @@ internal data class KeyVerificationAccept( hash: String, commitment: String, messageAuthenticationCode: String, - shortAuthenticationStrings: List): VerifInfoAccept { + shortAuthenticationStrings: List): VerificationInfoAccept { return KeyVerificationAccept().apply { this.transactionID = tid this.keyAgreementProtocol = keyAgreementProtocol From 35404b9a7fff510f606006c3e6e31fda4ee7d1db Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 12 Dec 2019 15:05:13 +0100 Subject: [PATCH 11/14] Fix merge --- .../model/message/MessageVerificationAcceptContent.kt | 10 +++++----- .../model/message/MessageVerificationCancelContent.kt | 4 ++-- .../model/message/MessageVerificationKeyContent.kt | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationAcceptContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationAcceptContent.kt index bda4b9f0ac..54403ab67f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationAcceptContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationAcceptContent.kt @@ -20,8 +20,8 @@ import com.squareup.moshi.JsonClass import im.vector.matrix.android.api.session.events.model.RelationType import im.vector.matrix.android.api.session.events.model.toContent import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent -import im.vector.matrix.android.internal.crypto.verification.AcceptVerifInfoFactory -import im.vector.matrix.android.internal.crypto.verification.VerifInfoAccept +import im.vector.matrix.android.internal.crypto.verification.VerificationInfoAccept +import im.vector.matrix.android.internal.crypto.verification.VerificationInfoAcceptFactory import timber.log.Timber @JsonClass(generateAdapter = true) @@ -32,7 +32,7 @@ internal data class MessageVerificationAcceptContent( @Json(name = "short_authentication_string") override val shortAuthenticationStrings: List?, @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?, @Json(name = "commitment") override var commitment: String? = null -) : VerifInfoAccept { +) : VerificationInfoAccept { override val transactionID: String? get() = relatesTo?.eventId @@ -52,14 +52,14 @@ internal data class MessageVerificationAcceptContent( override fun toEventContent() = this.toContent() - companion object : AcceptVerifInfoFactory { + companion object : VerificationInfoAcceptFactory { override fun create(tid: String, keyAgreementProtocol: String, hash: String, commitment: String, messageAuthenticationCode: String, - shortAuthenticationStrings: List): VerifInfoAccept { + shortAuthenticationStrings: List): VerificationInfoAccept { return MessageVerificationAcceptContent( hash, keyAgreementProtocol, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationCancelContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationCancelContent.kt index 08fc3cbdbb..2070845f46 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationCancelContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationCancelContent.kt @@ -21,7 +21,7 @@ import im.vector.matrix.android.api.session.crypto.sas.CancelCode import im.vector.matrix.android.api.session.events.model.RelationType import im.vector.matrix.android.api.session.events.model.toContent import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent -import im.vector.matrix.android.internal.crypto.verification.VerifInfoCancel +import im.vector.matrix.android.internal.crypto.verification.VerificationInfoCancel @JsonClass(generateAdapter = true) internal data class MessageVerificationCancelContent( @@ -29,7 +29,7 @@ internal data class MessageVerificationCancelContent( @Json(name = "reason") override val reason: String? = null, @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? -) : VerifInfoCancel { +) : VerificationInfoCancel { override val transactionID: String? get() = relatesTo?.eventId diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationKeyContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationKeyContent.kt index 0b93e3299a..2dacb19871 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationKeyContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationKeyContent.kt @@ -20,8 +20,8 @@ import com.squareup.moshi.JsonClass import im.vector.matrix.android.api.session.events.model.RelationType import im.vector.matrix.android.api.session.events.model.toContent import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent -import im.vector.matrix.android.internal.crypto.verification.VerifInfoKey -import im.vector.matrix.android.internal.crypto.verification.KeyVerifInfoFactory +import im.vector.matrix.android.internal.crypto.verification.VerificationInfoKey +import im.vector.matrix.android.internal.crypto.verification.VerificationInfoKeyFactory import timber.log.Timber @JsonClass(generateAdapter = true) @@ -31,7 +31,7 @@ internal data class MessageVerificationKeyContent( */ @Json(name = "key") override val key: String? = null, @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? -) : VerifInfoKey { +) : VerificationInfoKey { override val transactionID: String? get() = relatesTo?.eventId @@ -46,9 +46,9 @@ internal data class MessageVerificationKeyContent( override fun toEventContent() = this.toContent() - companion object : KeyVerifInfoFactory { + companion object : VerificationInfoKeyFactory { - override fun create(tid: String, pubKey: String): VerifInfoKey { + override fun create(tid: String, pubKey: String): VerificationInfoKey { return MessageVerificationKeyContent( pubKey, RelationDefaultContent( From 9842cac504951f6526b22a27b27170b052b4eff9 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 12 Dec 2019 15:29:56 +0100 Subject: [PATCH 12/14] More explicit val naming --- .../room/model/message/MessageVerificationRequestContent.kt | 2 +- .../internal/session/room/send/LocalEchoEventFactory.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt index e131ba4fec..1f6c8158fe 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageVerificationRequestContent.kt @@ -26,7 +26,7 @@ data class MessageVerificationRequestContent( @Json(name = "body") override val body: String, @Json(name = "from_device") val fromDevice: String, @Json(name = "methods") val methods: List, - @Json(name = "to") val to: String, + @Json(name = "to") val toUserId: String, // @Json(name = "timestamp") val timestamp: Int, @Json(name = "format") val format: String? = null, @Json(name = "formatted_body") val formattedBody: String? = null, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt index a225146d83..45172fb213 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt @@ -286,7 +286,7 @@ internal class LocalEchoEventFactory @Inject constructor( ) } - fun createVerificationRequest(roomId: String, fromDevice: String, to: String, methods: List): Event { + fun createVerificationRequest(roomId: String, fromDevice: String, toUserId: String, methods: List): Event { val localID = LocalEcho.createLocalEchoId() return Event( roomId = roomId, @@ -297,7 +297,7 @@ internal class LocalEchoEventFactory @Inject constructor( content = MessageVerificationRequestContent( body = stringProvider.getString(R.string.key_verification_request_fallback_message, userId), fromDevice = fromDevice, - to = to, + toUserId = toUserId, methods = methods ).toContent(), unsignedData = UnsignedData(age = null, transactionId = localID) From 975de1dbed9a4bf2101e543d6f1860911010834a Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 12 Dec 2019 18:48:57 +0100 Subject: [PATCH 13/14] Cleaning / klint --- .../api/session/room/model/ReferencesAggregatedSummary.kt | 1 - .../database/query/ReferencesAggregatedSummaryEntityQueries.kt | 3 --- 2 files changed, 4 deletions(-) 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/database/query/ReferencesAggregatedSummaryEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt index 9c7547b5e1..88f127066d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt @@ -17,6 +17,3 @@ internal fun ReferencesAggregatedSummaryEntity.Companion.create(realm: Realm, tx this.eventId = txID } } - - - From 289c03e724649dc7482c027033daea0a1e0f4aed Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 13 Dec 2019 16:37:41 +0100 Subject: [PATCH 14/14] Code review --- .../room/model/ReferencesAggregatedSummary.kt | 2 +- .../internal/database/model/EventEntity.kt | 5 ++--- .../query/EventAnnotationsSummaryEntityQuery.kt | 4 ++++ .../ReferencesAggregatedSummaryEntityQueries.kt | 16 ++++++++++++++++ .../room/EventRelationsAggregationTask.kt | 17 +++++------------ 5 files changed, 28 insertions(+), 16 deletions(-) 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 ca9d81cba1..018436ad6b 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 @@ -21,7 +21,7 @@ import im.vector.matrix.android.api.session.events.model.Content * Events can relates to other events, this object keeps a summary * of all events that are referencing the 'eventId' event via the RelationType.REFERENCE */ -class ReferencesAggregatedSummary( +data class ReferencesAggregatedSummary( val eventId: String, val content: Content?, val sourceEvents: List, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt index 9e3ed6a93b..71e787561b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt @@ -40,7 +40,8 @@ internal open class EventEntity(@Index var eventId: String = "", @Index var displayIndex: Int = 0, @Index var isUnlinked: Boolean = false, var decryptionResultJson: String? = null, - var decryptionErrorCode: String? = null + var decryptionErrorCode: String? = null, + var ageLocalTs: Long? = null ) : RealmObject() { enum class LinkFilterMode { @@ -59,8 +60,6 @@ internal open class EventEntity(@Index var eventId: String = "", sendStateStr = value.name } - var ageLocalTs: Long? = null - companion object @LinkingObjects("untimelinedStateEvents") diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventAnnotationsSummaryEntityQuery.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventAnnotationsSummaryEntityQuery.kt index 1e7a5758ad..03025cb9bb 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventAnnotationsSummaryEntityQuery.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventAnnotationsSummaryEntityQuery.kt @@ -47,3 +47,7 @@ internal fun EventAnnotationsSummaryEntity.Companion.create(realm: Realm, roomId } return obj } +internal fun EventAnnotationsSummaryEntity.Companion.getOrCreate(realm: Realm, roomId: String, eventId: String): EventAnnotationsSummaryEntity { + return EventAnnotationsSummaryEntity.where(realm, eventId).findFirst() + ?: EventAnnotationsSummaryEntity.create(realm, roomId, eventId).apply { this.roomId = roomId } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt index 88f127066d..7d2ed98232 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ReferencesAggregatedSummaryEntityQueries.kt @@ -1,3 +1,19 @@ +/* + * 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.database.query import im.vector.matrix.android.internal.database.model.ReferencesAggregatedSummaryEntity diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt index 5c38fcf797..a162849fa9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt @@ -29,6 +29,7 @@ import im.vector.matrix.android.internal.database.mapper.ContentMapper import im.vector.matrix.android.internal.database.mapper.EventMapper import im.vector.matrix.android.internal.database.model.* import im.vector.matrix.android.internal.database.query.create +import im.vector.matrix.android.internal.database.query.getOrCreate import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.util.awaitTransaction @@ -201,11 +202,7 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( val targetEventId = relatedEventId ?: content.relatesTo?.eventId ?: return val newContent = content.newContent ?: return // ok, this is a replace - var existing = EventAnnotationsSummaryEntity.where(realm, targetEventId).findFirst() - if (existing == null) { - Timber.v("###REPLACE creating new relation summary for $targetEventId") - existing = EventAnnotationsSummaryEntity.create(realm, roomId, targetEventId) - } + val existing = EventAnnotationsSummaryEntity.getOrCreate(realm, roomId, targetEventId) // we have it val existingSummary = existing.editSummary @@ -295,8 +292,7 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( val relatedEventID = content.relatesTo.eventId val reactionEventId = event.eventId Timber.v("Reaction $reactionEventId relates to $relatedEventID") - val eventSummary = EventAnnotationsSummaryEntity.where(realm, relatedEventID).findFirst() - ?: EventAnnotationsSummaryEntity.create(realm, roomId, relatedEventID).apply { this.roomId = roomId } + val eventSummary = EventAnnotationsSummaryEntity.getOrCreate(realm, roomId, relatedEventID) var sum = eventSummary.reactionsSummary.find { it.key == reaction } val txId = event.unsignedData?.transactionId @@ -420,8 +416,7 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( } private fun handleVerification(realm: Realm, event: Event, roomId: String, isLocalEcho: Boolean, relatedEventId: String, userId: String) { - val eventSummary = EventAnnotationsSummaryEntity.where(realm, relatedEventId).findFirst() - ?: EventAnnotationsSummaryEntity.create(realm, roomId, relatedEventId).apply { this.roomId = roomId } + val eventSummary = EventAnnotationsSummaryEntity.getOrCreate(realm, roomId, relatedEventId) val verifSummary = eventSummary.referencesSummaryEntity ?: ReferencesAggregatedSummaryEntity.create(realm, relatedEventId).also { @@ -469,9 +464,7 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( if (isLocalEcho) { verifSummary.sourceLocalEcho.add(event.eventId) } else { - if (verifSummary.sourceLocalEcho.contains(txId)) { - verifSummary.sourceLocalEcho.remove(txId) - } + verifSummary.sourceLocalEcho.remove(txId) verifSummary.sourceEvents.add(event.eventId) } }