Merge pull request #1411 from vector-im/feature/attachment_e2e

Feature/attachment e2e
This commit is contained in:
Benoit Marty 2020-05-27 15:13:17 +02:00 committed by GitHub
commit 34d638da4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 12 deletions

View File

@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.database.helper
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
import im.vector.matrix.android.internal.database.model.TimelineEventEntityFields
import im.vector.matrix.android.internal.extensions.assertIsManaged
import io.realm.Realm
internal fun TimelineEventEntity.Companion.nextId(realm: Realm): Long {
@ -28,3 +29,11 @@ internal fun TimelineEventEntity.Companion.nextId(realm: Realm): Long {
currentIdNum.toLong() + 1
}
}
internal fun TimelineEventEntity.deleteOnCascade() {
assertIsManaged()
root?.deleteFromRealm()
annotations?.deleteFromRealm()
readReceipts?.deleteFromRealm()
deleteFromRealm()
}

View File

@ -28,6 +28,13 @@ internal object TimelineEventFilter {
internal const val RESPONSE = """{*"m.relates_to"*"rel_type":*"m.response"*}"""
}
/**
* To apply to Event.decryptionResultJson
*/
internal object DecryptedContent {
internal const val URL = """{*"file":*"url":*}"""
}
/**
* To apply to Event.unsigned
*/

View File

@ -21,5 +21,8 @@ import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
internal data class SendResponse(
/**
* A unique identifier for the event.
*/
@Json(name = "event_id") val eventId: String
)

View File

@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.session.room.uploads
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.crypto.CryptoService
import im.vector.matrix.android.api.session.room.uploads.GetUploadsResult
import im.vector.matrix.android.api.session.room.uploads.UploadsService
import im.vector.matrix.android.api.util.Cancelable
@ -28,7 +29,8 @@ import im.vector.matrix.android.internal.task.configureWith
internal class DefaultUploadsService @AssistedInject constructor(
@Assisted private val roomId: String,
private val taskExecutor: TaskExecutor,
private val getUploadsTask: GetUploadsTask
private val getUploadsTask: GetUploadsTask,
private val cryptoService: CryptoService
) : UploadsService {
@AssistedInject.Factory
@ -38,7 +40,7 @@ internal class DefaultUploadsService @AssistedInject constructor(
override fun getUploads(numberOfEvents: Int, since: String?, callback: MatrixCallback<GetUploadsResult>): Cancelable {
return getUploadsTask
.configureWith(GetUploadsTask.Params(roomId, numberOfEvents, since)) {
.configureWith(GetUploadsTask.Params(roomId, cryptoService.isRoomEncrypted(roomId), numberOfEvents, since)) {
this.callback = callback
}
.executeBy(taskExecutor)

View File

@ -17,12 +17,19 @@
package im.vector.matrix.android.internal.session.room.uploads
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.events.model.Event
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.message.MessageContent
import im.vector.matrix.android.api.session.room.model.message.MessageWithAttachmentContent
import im.vector.matrix.android.api.session.room.sender.SenderInfo
import im.vector.matrix.android.api.session.room.uploads.GetUploadsResult
import im.vector.matrix.android.api.session.room.uploads.UploadEvent
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.model.EventEntityFields
import im.vector.matrix.android.internal.database.query.TimelineEventFilter
import im.vector.matrix.android.internal.database.query.whereType
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.filter.FilterFactory
import im.vector.matrix.android.internal.session.room.RoomAPI
@ -38,6 +45,7 @@ internal interface GetUploadsTask : Task<GetUploadsTask.Params, GetUploadsResult
data class Params(
val roomId: String,
val isRoomEncrypted: Boolean,
val numberOfEvents: Int,
val since: String?
)
@ -51,11 +59,42 @@ internal class DefaultGetUploadsTask @Inject constructor(
: GetUploadsTask {
override suspend fun execute(params: GetUploadsTask.Params): GetUploadsResult {
val since = params.since ?: tokenStore.getLastToken() ?: throw IllegalStateException("No token available")
val result: GetUploadsResult
val events: List<Event>
val filter = FilterFactory.createUploadsFilter(params.numberOfEvents).toJSONString()
val chunk = executeRequest<PaginationResponse>(eventBus) {
apiCall = roomAPI.getRoomMessagesFrom(params.roomId, since, PaginationDirection.BACKWARDS.value, params.numberOfEvents, filter)
if (params.isRoomEncrypted) {
// Get a chunk of events from cache for e2e rooms
result = GetUploadsResult(
uploadEvents = emptyList(),
nextToken = "",
hasMore = false
)
var eventsFromRealm = emptyList<Event>()
monarchy.doWithRealm { realm ->
eventsFromRealm = EventEntity.whereType(realm, EventType.ENCRYPTED, params.roomId)
.like(EventEntityFields.DECRYPTION_RESULT_JSON, TimelineEventFilter.DecryptedContent.URL)
.findAll()
.map { it.asDomain() }
// Exclude stickers
.filter { it.getClearType() != EventType.STICKER }
}
events = eventsFromRealm
} else {
val since = params.since ?: tokenStore.getLastToken() ?: throw IllegalStateException("No token available")
val filter = FilterFactory.createUploadsFilter(params.numberOfEvents).toJSONString()
val chunk = executeRequest<PaginationResponse>(eventBus) {
apiCall = roomAPI.getRoomMessagesFrom(params.roomId, since, PaginationDirection.BACKWARDS.value, params.numberOfEvents, filter)
}
result = GetUploadsResult(
uploadEvents = emptyList(),
nextToken = chunk.end ?: "",
hasMore = chunk.hasMore()
)
events = chunk.events
}
var uploadEvents = listOf<UploadEvent>()
@ -66,7 +105,7 @@ internal class DefaultGetUploadsTask @Inject constructor(
monarchy.doWithRealm { realm ->
val roomMemberHelper = RoomMemberHelper(realm, params.roomId)
uploadEvents = chunk.events.mapNotNull { event ->
uploadEvents = events.mapNotNull { event ->
val eventId = event.eventId ?: return@mapNotNull null
val messageContent = event.getClearContent()?.toModel<MessageContent>() ?: return@mapNotNull null
val messageWithAttachmentContent = (messageContent as? MessageWithAttachmentContent) ?: return@mapNotNull null
@ -91,10 +130,6 @@ internal class DefaultGetUploadsTask @Inject constructor(
}
}
return GetUploadsResult(
uploadEvents = uploadEvents,
nextToken = chunk.end ?: "",
hasMore = chunk.hasMore()
)
return result.copy(uploadEvents = uploadEvents)
}
}

View File

@ -29,6 +29,7 @@ import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
import im.vector.matrix.android.internal.database.helper.addOrUpdate
import im.vector.matrix.android.internal.database.helper.addTimelineEvent
import im.vector.matrix.android.internal.database.helper.deleteOnCascade
import im.vector.matrix.android.internal.database.mapper.ContentMapper
import im.vector.matrix.android.internal.database.mapper.toEntity
import im.vector.matrix.android.internal.database.model.ChunkEntity
@ -272,6 +273,8 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
event.mxDecryptionResult = adapter.fromJson(json)
}
}
// Finally delete the local echo
sendingEventEntity.deleteOnCascade()
} else {
Timber.v("Can't find corresponding local echo for tx:$it")
}