Be robust if Event.type is missing (#2946)

This commit is contained in:
Benoit Marty 2021-03-02 16:14:57 +01:00
parent 32e7845c2b
commit 4e2e73637a
13 changed files with 33 additions and 24 deletions

View File

@ -11,6 +11,7 @@ Improvements 🙌:
Bugfix 🐛: Bugfix 🐛:
- Try to fix crash about UrlPreview (#2640) - Try to fix crash about UrlPreview (#2640)
- Be robust if Event.type is missing (#2946)
Translations 🗣: Translations 🗣:
- -

View File

@ -66,7 +66,7 @@ inline fun <reified T> T.toContent(): Content {
*/ */
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class Event( data class Event(
@Json(name = "type") val type: String, @Json(name = "type") val type: String? = null,
@Json(name = "event_id") val eventId: String? = null, @Json(name = "event_id") val eventId: String? = null,
@Json(name = "content") val content: Content? = null, @Json(name = "content") val content: Content? = null,
@Json(name = "prev_content") val prevContent: Content? = null, @Json(name = "prev_content") val prevContent: Content? = null,
@ -135,7 +135,7 @@ data class Event(
* @return the event type * @return the event type
*/ */
fun getClearType(): String { fun getClearType(): String {
return mxDecryptionResult?.payload?.get("type")?.toString() ?: type return mxDecryptionResult?.payload?.get("type")?.toString() ?: type ?: EventType.MISSING_TYPE
} }
/** /**

View File

@ -20,6 +20,8 @@ package org.matrix.android.sdk.api.session.events.model
* Constants defining known event types from Matrix specifications. * Constants defining known event types from Matrix specifications.
*/ */
object EventType { object EventType {
// Used when the type is missing, which should not happen
const val MISSING_TYPE = "org.matrix.android.sdk.missing_type"
const val PRESENCE = "m.presence" const val PRESENCE = "m.presence"
const val MESSAGE = "m.room.message" const val MESSAGE = "m.room.message"

View File

@ -45,7 +45,7 @@ internal class DefaultEncryptEventTask @Inject constructor(
// don't want to wait for any query // don't want to wait for any query
// if (!params.crypto.isRoomEncrypted(params.roomId)) return params.event // if (!params.crypto.isRoomEncrypted(params.roomId)) return params.event
val localEvent = params.event val localEvent = params.event
if (localEvent.eventId == null) { if (localEvent.eventId == null || localEvent.type == null) {
throw IllegalArgumentException() throw IllegalArgumentException()
} }

View File

@ -58,7 +58,7 @@ internal class DefaultSendEventTask @Inject constructor(
localId, localId,
roomId = event.roomId ?: "", roomId = event.roomId ?: "",
content = event.content, content = event.content,
eventType = event.type eventType = event.type ?: ""
) )
} }
localEchoRepository.updateSendState(localId, params.event.roomId, SendState.SENT) localEchoRepository.updateSendState(localId, params.event.roomId, SendState.SENT)

View File

@ -50,7 +50,7 @@ internal class DefaultSendVerificationMessageTask @Inject constructor(
localId, localId,
roomId = event.roomId ?: "", roomId = event.roomId ?: "",
content = event.content, content = event.content,
eventType = event.type eventType = event.type ?: ""
) )
} }
localEchoRepository.updateSendState(localId, event.roomId, SendState.SENT) localEchoRepository.updateSendState(localId, event.roomId, SendState.SENT)

View File

@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.database.mapper
import com.squareup.moshi.JsonDataException import com.squareup.moshi.JsonDataException
import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.UnsignedData import org.matrix.android.sdk.api.session.events.model.UnsignedData
import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
@ -29,8 +30,6 @@ import timber.log.Timber
internal object EventMapper { internal object EventMapper {
fun map(event: Event, roomId: String): EventEntity { fun map(event: Event, roomId: String): EventEntity {
val uds = if (event.unsignedData == null) null
else MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).toJson(event.unsignedData)
val eventEntity = EventEntity() val eventEntity = EventEntity()
// TODO change this as we shouldn't use event everywhere // TODO change this as we shouldn't use event everywhere
eventEntity.eventId = event.eventId ?: "$$roomId-${System.currentTimeMillis()}-${event.hashCode()}" eventEntity.eventId = event.eventId ?: "$$roomId-${System.currentTimeMillis()}-${event.hashCode()}"
@ -39,14 +38,16 @@ internal object EventMapper {
eventEntity.prevContent = ContentMapper.map(event.resolvedPrevContent()) eventEntity.prevContent = ContentMapper.map(event.resolvedPrevContent())
eventEntity.isUseless = IsUselessResolver.isUseless(event) eventEntity.isUseless = IsUselessResolver.isUseless(event)
eventEntity.stateKey = event.stateKey eventEntity.stateKey = event.stateKey
eventEntity.type = event.type eventEntity.type = event.type ?: EventType.MISSING_TYPE
eventEntity.sender = event.senderId eventEntity.sender = event.senderId
eventEntity.originServerTs = event.originServerTs eventEntity.originServerTs = event.originServerTs
eventEntity.redacts = event.redacts eventEntity.redacts = event.redacts
eventEntity.age = event.unsignedData?.age ?: event.originServerTs eventEntity.age = event.unsignedData?.age ?: event.originServerTs
eventEntity.unsignedData = uds eventEntity.unsignedData = event.unsignedData?.let {
MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).toJson(it)
}
eventEntity.decryptionResultJson = event.mxDecryptionResult?.let { eventEntity.decryptionResultJson = event.mxDecryptionResult?.let {
MoshiProvider.providesMoshi().adapter<OlmDecryptionResult>(OlmDecryptionResult::class.java).toJson(it) MoshiProvider.providesMoshi().adapter(OlmDecryptionResult::class.java).toJson(it)
} }
eventEntity.decryptionErrorReason = event.mCryptoErrorReason eventEntity.decryptionErrorReason = event.mCryptoErrorReason
eventEntity.decryptionErrorCode = event.mCryptoError?.name eventEntity.decryptionErrorCode = event.mCryptoError?.name

View File

@ -105,12 +105,17 @@ internal class DefaultLoadRoomMembersTask @Inject constructor(
?: realm.createObject(roomId) ?: realm.createObject(roomId)
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
for (roomMemberEvent in response.roomMemberEvents) { for (roomMemberEvent in response.roomMemberEvents) {
if (roomMemberEvent.eventId == null || roomMemberEvent.stateKey == null) { if (roomMemberEvent.eventId == null || roomMemberEvent.stateKey == null || roomMemberEvent.type == null) {
continue continue
} }
val ageLocalTs = roomMemberEvent.unsignedData?.age?.let { now - it } val ageLocalTs = roomMemberEvent.unsignedData?.age?.let { now - it }
val eventEntity = roomMemberEvent.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, EventInsertType.PAGINATION) val eventEntity = roomMemberEvent.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, EventInsertType.PAGINATION)
CurrentStateEventEntity.getOrCreate(realm, roomId, roomMemberEvent.stateKey, roomMemberEvent.type).apply { CurrentStateEventEntity.getOrCreate(
realm,
roomId,
roomMemberEvent.stateKey,
roomMemberEvent.type
).apply {
eventId = roomMemberEvent.eventId eventId = roomMemberEvent.eventId
root = eventEntity root = eventEntity
} }

View File

@ -89,7 +89,7 @@ internal class SendRelationWorker(context: Context, params: WorkerParameters)
roomId = roomId, roomId = roomId,
parentId = relatedEventId, parentId = relatedEventId,
relationType = relationType, relationType = relationType,
eventType = localEvent.type, eventType = localEvent.type!!,
content = localEvent.content content = localEvent.content
) )
} }

View File

@ -56,10 +56,10 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private
fun createLocalEcho(event: Event) { fun createLocalEcho(event: Event) {
val roomId = event.roomId ?: throw IllegalStateException("You should have set a roomId for your event") val roomId = event.roomId ?: throw IllegalStateException("You should have set a roomId for your event")
val senderId = event.senderId ?: throw IllegalStateException("You should have set a senderIf for your event") val senderId = event.senderId ?: throw IllegalStateException("You should have set a senderId for your event")
if (event.eventId == null) { event.eventId ?: throw IllegalStateException("You should have set an eventId for your event")
throw IllegalStateException("You should have set an eventId for your event") event.type ?: throw IllegalStateException("You should have set a type for your event")
}
val timelineEventEntity = realmSessionProvider.withRealm { realm -> val timelineEventEntity = realmSessionProvider.withRealm { realm ->
val eventEntity = event.toEntity(roomId, SendState.UNSENT, System.currentTimeMillis()) val eventEntity = event.toEntity(roomId, SendState.UNSENT, System.currentTimeMillis())
val roomMemberHelper = RoomMemberHelper(realm, roomId) val roomMemberHelper = RoomMemberHelper(realm, roomId)

View File

@ -198,7 +198,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
// State event // State event
if (roomSync.state?.events?.isNotEmpty() == true) { if (roomSync.state?.events?.isNotEmpty() == true) {
for (event in roomSync.state.events) { for (event in roomSync.state.events) {
if (event.eventId == null || event.stateKey == null) { if (event.eventId == null || event.stateKey == null || event.type == null) {
continue continue
} }
val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it } val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it }
@ -254,7 +254,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
roomEntity.membership = Membership.INVITE roomEntity.membership = Membership.INVITE
if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) { if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) {
roomSync.inviteState.events.forEach { event -> roomSync.inviteState.events.forEach { event ->
if (event.stateKey == null) { if (event.stateKey == null || event.type == null) {
return@forEach return@forEach
} }
val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it } val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it }
@ -281,7 +281,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
syncLocalTimestampMillis: Long): RoomEntity { syncLocalTimestampMillis: Long): RoomEntity {
val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId) val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId)
for (event in roomSync.state?.events.orEmpty()) { for (event in roomSync.state?.events.orEmpty()) {
if (event.eventId == null || event.stateKey == null) { if (event.eventId == null || event.stateKey == null || event.type == null) {
continue continue
} }
val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it } val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it }
@ -293,7 +293,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
roomMemberEventHandler.handle(realm, roomId, event) roomMemberEventHandler.handle(realm, roomId, event)
} }
for (event in roomSync.timeline?.events.orEmpty()) { for (event in roomSync.timeline?.events.orEmpty()) {
if (event.eventId == null || event.senderId == null) { if (event.eventId == null || event.senderId == null || event.type == null) {
continue continue
} }
val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it } val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it }
@ -340,7 +340,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>() val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>()
for (event in eventList) { for (event in eventList) {
if (event.eventId == null || event.senderId == null) { if (event.eventId == null || event.senderId == null || event.type == null) {
continue continue
} }
eventIds.add(event.eventId) eventIds.add(event.eventId)

View File

@ -37,7 +37,7 @@ class RoomStateListController @Inject constructor(
override fun buildModels(data: RoomDevToolViewState?) { override fun buildModels(data: RoomDevToolViewState?) {
when (data?.displayMode) { when (data?.displayMode) {
RoomDevToolViewState.Mode.StateEventList -> { RoomDevToolViewState.Mode.StateEventList -> {
val stateEventsGroups = data.stateEvents.invoke().orEmpty().groupBy { it.type } val stateEventsGroups = data.stateEvents.invoke().orEmpty().groupBy { it.getClearType() }
if (stateEventsGroups.isEmpty()) { if (stateEventsGroups.isEmpty()) {
noResultItem { noResultItem {

View File

@ -68,7 +68,7 @@ class NotifiableEventResolver @Inject constructor(private val stringProvider: St
// If the event can be displayed, display it as is // If the event can be displayed, display it as is
Timber.w("NotifiableEventResolver Received an unsupported event matching a bing rule") Timber.w("NotifiableEventResolver Received an unsupported event matching a bing rule")
// TODO Better event text display // TODO Better event text display
val bodyPreview = event.type val bodyPreview = event.type ?: EventType.MISSING_TYPE
return SimpleNotifiableEvent( return SimpleNotifiableEvent(
session.myUserId, session.myUserId,