forked from GitHub-Mirror/riotX-android
Crypto: continue cleaning + fix some issues.
This commit is contained in:
parent
c4d7711d2f
commit
664e5354d3
@ -92,34 +92,10 @@ interface CryptoService {
|
||||
roomId: String,
|
||||
callback: MatrixCallback<MXEncryptEventContentResult>)
|
||||
|
||||
/*
|
||||
fun start(isInitialSync: Boolean, aCallback: MatrixCallback<Unit>?)
|
||||
|
||||
fun isStarted(): Boolean
|
||||
|
||||
fun isStarting(): Boolean
|
||||
|
||||
fun close()
|
||||
|
||||
|
||||
fun getOlmDevice(): MXOlmDevice?
|
||||
|
||||
fun checkUnknownDevices(userIds: List<String>, callback: MatrixCallback<Unit>)
|
||||
|
||||
fun warnOnUnknownDevices(): Boolean
|
||||
|
||||
@Throws(MXDecryptionException::class)
|
||||
fun decryptEvent(event: Event, timelineId: String?): MXEventDecryptionResult?
|
||||
|
||||
fun resetReplayAttackCheckInTimeline(timelineId: String)
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
fun ensureOlmSessionsForUsers(users: List<String>, callback: MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>>)
|
||||
*/
|
||||
|
||||
fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult?
|
||||
|
||||
fun decryptEventAsync(event: Event, timeline: String, callback: MatrixCallback<MXEventDecryptionResult?>)
|
||||
|
||||
fun getEncryptionAlgorithm(roomId: String): String?
|
||||
|
||||
fun shouldEncryptForInvitedMembers(roomId: String): Boolean
|
||||
|
@ -23,5 +23,5 @@ import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RoomHistoryVisibilityContent(
|
||||
@Json(name = "history_visibility") val historyVisibility: RoomHistoryVisibility
|
||||
@Json(name = "history_visibility") val historyVisibility: RoomHistoryVisibility? = null
|
||||
)
|
@ -73,6 +73,7 @@ import org.matrix.olm.OlmManager
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
/**
|
||||
* A `CryptoService` class instance manages the end-to-end crypto for a session.
|
||||
@ -134,22 +135,8 @@ internal class CryptoManager(
|
||||
|
||||
// MXEncrypting instance for each room.
|
||||
private val roomEncryptors: MutableMap<String, IMXEncrypting> = HashMap()
|
||||
|
||||
// the encryption is starting
|
||||
private var isStarting = AtomicBoolean(false)
|
||||
|
||||
// tell if the crypto is started
|
||||
private var isStarted = AtomicBoolean(false)
|
||||
|
||||
// TODO
|
||||
//private val mNetworkListener = object : IMXNetworkEventListener {
|
||||
// override fun onNetworkConnectionUpdate(isConnected: Boolean) {
|
||||
// if (isConnected && !isStarted()) {
|
||||
// Timber.v("Start MXCrypto because a network connection has been retrieved ")
|
||||
// start(false, null)
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
private val isStarting = AtomicBoolean(false)
|
||||
private val isStarted = AtomicBoolean(false)
|
||||
|
||||
fun onStateEvent(roomId: String, event: Event) {
|
||||
when {
|
||||
@ -262,8 +249,6 @@ internal class CryptoManager(
|
||||
internalStart(isInitialSync)
|
||||
},
|
||||
{
|
||||
isStarting.set(false)
|
||||
isStarted.set(true)
|
||||
outgoingRoomKeyRequestManager.start()
|
||||
keysBackup.checkAndStartKeysBackup()
|
||||
if (isInitialSync) {
|
||||
@ -273,6 +258,8 @@ internal class CryptoManager(
|
||||
} else {
|
||||
incomingRoomKeyRequestManager.processReceivedRoomKeyRequests()
|
||||
}
|
||||
isStarting.set(false)
|
||||
isStarted.set(true)
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -589,13 +576,47 @@ internal class CryptoManager(
|
||||
*/
|
||||
@Throws(MXDecryptionException::class)
|
||||
override fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult? {
|
||||
return runBlocking {
|
||||
internalDecryptEvent(event, timeline).fold(
|
||||
{ throw it },
|
||||
{ it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt an event asynchronously
|
||||
*
|
||||
* @param event the raw event.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @param callback the callback to return data or null
|
||||
*/
|
||||
override fun decryptEventAsync(event: Event, timeline: String, callback: MatrixCallback<MXEventDecryptionResult?>) {
|
||||
GlobalScope.launch(EmptyCoroutineContext) {
|
||||
val result = withContext(coroutineDispatchers.crypto) {
|
||||
internalDecryptEvent(event, timeline)
|
||||
}
|
||||
result.fold(
|
||||
{ callback.onFailure(it) },
|
||||
{ callback.onSuccess(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt an event
|
||||
*
|
||||
* @param event the raw event.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @return the MXEventDecryptionResult data, or null in case of error wrapped into [Try]
|
||||
*/
|
||||
private suspend fun internalDecryptEvent(event: Event, timeline: String): Try<MXEventDecryptionResult?> {
|
||||
return Try {
|
||||
val eventContent = event.content
|
||||
if (eventContent == null) {
|
||||
Timber.e("## decryptEvent : empty event content")
|
||||
return null
|
||||
return@Try null
|
||||
}
|
||||
return runBlocking {
|
||||
withContext(coroutineDispatchers.crypto) {
|
||||
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(event.roomId, eventContent["algorithm"] as String)
|
||||
if (alg == null) {
|
||||
val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, eventContent["algorithm"] as String)
|
||||
@ -606,7 +627,6 @@ internal class CryptoManager(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset replay attack data for the given timeline.
|
||||
@ -624,11 +644,17 @@ internal class CryptoManager(
|
||||
*/
|
||||
fun onToDeviceEvent(event: Event) {
|
||||
CoroutineScope(coroutineDispatchers.crypto).launch {
|
||||
if (event.getClearType() == EventType.ROOM_KEY || event.getClearType() == EventType.FORWARDED_ROOM_KEY) {
|
||||
when (event.getClearType()) {
|
||||
EventType.ROOM_KEY, EventType.FORWARDED_ROOM_KEY -> {
|
||||
onRoomKeyEvent(event)
|
||||
} else if (event.getClearType() == EventType.ROOM_KEY_REQUEST) {
|
||||
}
|
||||
EventType.ROOM_KEY_REQUEST -> {
|
||||
incomingRoomKeyRequestManager.onRoomKeyRequestEvent(event)
|
||||
}
|
||||
else -> {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -638,7 +664,7 @@ internal class CryptoManager(
|
||||
* @param event the key event.
|
||||
*/
|
||||
private fun onRoomKeyEvent(event: Event) {
|
||||
val roomKeyContent = event.getClearContent().toModel<RoomKeyContent>()!!
|
||||
val roomKeyContent = event.getClearContent().toModel<RoomKeyContent>() ?: return
|
||||
if (TextUtils.isEmpty(roomKeyContent.roomId) || TextUtils.isEmpty(roomKeyContent.algorithm)) {
|
||||
Timber.e("## onRoomKeyEvent() : missing fields")
|
||||
return
|
||||
@ -722,7 +748,6 @@ internal class CryptoManager(
|
||||
|
||||
private fun onRoomHistoryVisibilityEvent(roomId: String, event: Event) {
|
||||
val eventContent = event.content.toModel<RoomHistoryVisibilityContent>()
|
||||
|
||||
eventContent?.historyVisibility?.let {
|
||||
cryptoStore.setShouldEncryptForInvitedMembers(roomId, it != RoomHistoryVisibility.JOINED)
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
||||
* @param timelineId the timeline identifier
|
||||
*/
|
||||
private fun addEventToPendingList(event: Event, timelineId: String) {
|
||||
val encryptedEventContent = event.content.toModel<EncryptedEventContent>()!!
|
||||
val encryptedEventContent = event.content.toModel<EncryptedEventContent>() ?: return
|
||||
val pendingEventsKey = "${encryptedEventContent.senderKey}|${encryptedEventContent.sessionId}"
|
||||
|
||||
if (!pendingEvents.containsKey(pendingEventsKey)) {
|
||||
@ -190,7 +190,7 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
||||
*/
|
||||
override fun onRoomKeyEvent(event: Event, keysBackup: KeysBackup) {
|
||||
var exportFormat = false
|
||||
val roomKeyContent = event.getClearContent().toModel<RoomKeyContent>()!!
|
||||
val roomKeyContent = event.getClearContent().toModel<RoomKeyContent>() ?: return
|
||||
|
||||
var senderKey: String? = event.getSenderKey()
|
||||
var keysClaimed: MutableMap<String, String> = HashMap()
|
||||
@ -203,11 +203,11 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
||||
if (event.getClearType() == EventType.FORWARDED_ROOM_KEY) {
|
||||
Timber.v("## onRoomKeyEvent(), forward adding key : roomId " + roomKeyContent.roomId + " sessionId " + roomKeyContent.sessionId
|
||||
+ " sessionKey " + roomKeyContent.sessionKey) // from " + event);
|
||||
val forwardedRoomKeyContent = event.getClearContent().toModel<ForwardedRoomKeyContent>()!!
|
||||
forwardingCurve25519KeyChain = if (null == forwardedRoomKeyContent.forwardingCurve25519KeyChain) {
|
||||
val forwardedRoomKeyContent = event.getClearContent().toModel<ForwardedRoomKeyContent>() ?: return
|
||||
forwardingCurve25519KeyChain = if (forwardedRoomKeyContent.forwardingCurve25519KeyChain == null) {
|
||||
ArrayList()
|
||||
} else {
|
||||
ArrayList(forwardedRoomKeyContent.forwardingCurve25519KeyChain!!)
|
||||
ArrayList(forwardedRoomKeyContent.forwardingCurve25519KeyChain)
|
||||
}
|
||||
forwardingCurve25519KeyChain.add(senderKey!!)
|
||||
|
||||
@ -262,6 +262,7 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
||||
*/
|
||||
override fun onNewSession(senderKey: String, sessionId: String) {
|
||||
//TODO see how to handle this
|
||||
Timber.v("ON NEW SESSION $sessionId - $senderKey")
|
||||
/*val k = "$senderKey|$sessionId"
|
||||
|
||||
val pending = pendingEvents[k]
|
||||
|
@ -28,29 +28,29 @@ data class EncryptedEventContent(
|
||||
* the used algorithm
|
||||
*/
|
||||
@Json(name = "algorithm")
|
||||
var algorithm: String? = null,
|
||||
val algorithm: String? = null,
|
||||
|
||||
/**
|
||||
* The encrypted event
|
||||
*/
|
||||
@Json(name = "ciphertext")
|
||||
var ciphertext: String? = null,
|
||||
val ciphertext: String? = null,
|
||||
|
||||
/**
|
||||
* The device id
|
||||
*/
|
||||
@Json(name = "device_id")
|
||||
var deviceId: String? = null,
|
||||
val deviceId: String? = null,
|
||||
|
||||
/**
|
||||
* the sender key
|
||||
*/
|
||||
@Json(name = "sender_key")
|
||||
var senderKey: String? = null,
|
||||
val senderKey: String? = null,
|
||||
|
||||
/**
|
||||
* The session id
|
||||
*/
|
||||
@Json(name = "session_id")
|
||||
var sessionId: String? = null
|
||||
val sessionId: String? = null
|
||||
)
|
@ -25,18 +25,18 @@ import com.squareup.moshi.JsonClass
|
||||
data class RoomKeyContent(
|
||||
|
||||
@Json(name = "algorithm")
|
||||
var algorithm: String? = null,
|
||||
val algorithm: String? = null,
|
||||
|
||||
@Json(name = "room_id")
|
||||
var roomId: String? = null,
|
||||
val roomId: String? = null,
|
||||
|
||||
@Json(name = "session_id")
|
||||
var sessionId: String? = null,
|
||||
val sessionId: String? = null,
|
||||
|
||||
@Json(name = "session_key")
|
||||
var sessionKey: String? = null,
|
||||
val sessionKey: String? = null,
|
||||
|
||||
// should be a Long but it is sometimes a double
|
||||
@Json(name = "chain_index")
|
||||
var chainIndex: Any? = null
|
||||
val chainIndex: Any? = null
|
||||
)
|
||||
|
@ -25,23 +25,23 @@ import com.squareup.moshi.JsonClass
|
||||
data class ForwardedRoomKeyContent(
|
||||
|
||||
@Json(name = "algorithm")
|
||||
var algorithm: String? = null,
|
||||
val algorithm: String? = null,
|
||||
|
||||
@Json(name = "room_id")
|
||||
var roomId: String? = null,
|
||||
val roomId: String? = null,
|
||||
|
||||
@Json(name = "sender_key")
|
||||
var senderKey: String? = null,
|
||||
val senderKey: String? = null,
|
||||
|
||||
@Json(name = "session_id")
|
||||
var sessionId: String? = null,
|
||||
val sessionId: String? = null,
|
||||
|
||||
@Json(name = "session_key")
|
||||
var sessionKey: String? = null,
|
||||
val sessionKey: String? = null,
|
||||
|
||||
@Json(name = "forwarding_curve25519_key_chain")
|
||||
var forwardingCurve25519KeyChain: List<String>? = null,
|
||||
val forwardingCurve25519KeyChain: List<String>? = null,
|
||||
|
||||
@Json(name = "sender_claimed_ed25519_key")
|
||||
var senderClaimedEd25519Key: String? = null
|
||||
val senderClaimedEd25519Key: String? = null
|
||||
)
|
@ -54,14 +54,14 @@ import kotlin.collections.HashMap
|
||||
* Short codes interactive verification is a more user friendly way of verifying devices
|
||||
* that is still maintaining a good level of security (alternative to the 43-character strings compare method).
|
||||
*/
|
||||
internal class DefaultSasVerificationService(private val mCredentials: Credentials,
|
||||
private val mCryptoStore: IMXCryptoStore,
|
||||
private val mMyDeviceInfoHolder: MyDeviceInfoHolder,
|
||||
internal class DefaultSasVerificationService(private val credentials: Credentials,
|
||||
private val cryptoStore: IMXCryptoStore,
|
||||
private val myDeviceInfoHolder: MyDeviceInfoHolder,
|
||||
private val deviceListManager: DeviceListManager,
|
||||
private val setDeviceVerificationAction: SetDeviceVerificationAction,
|
||||
private val mSendToDeviceTask: SendToDeviceTask,
|
||||
private val sendToDeviceTask: SendToDeviceTask,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val mTaskExecutor: TaskExecutor)
|
||||
private val taskExecutor: TaskExecutor)
|
||||
: VerificationTransaction.Listener, SasVerificationService {
|
||||
|
||||
private val uiHandler = Handler(Looper.getMainLooper())
|
||||
@ -194,11 +194,11 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia
|
||||
val tx = IncomingSASVerificationTransaction(
|
||||
this,
|
||||
setDeviceVerificationAction,
|
||||
mCredentials,
|
||||
mCryptoStore,
|
||||
mSendToDeviceTask,
|
||||
mTaskExecutor,
|
||||
mMyDeviceInfoHolder.myDevice.fingerprint()!!,
|
||||
credentials,
|
||||
cryptoStore,
|
||||
sendToDeviceTask,
|
||||
taskExecutor,
|
||||
myDeviceInfoHolder.myDevice.fingerprint()!!,
|
||||
startReq.transactionID!!,
|
||||
otherUserId)
|
||||
addTransaction(tx)
|
||||
@ -363,11 +363,11 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia
|
||||
val tx = OutgoingSASVerificationRequest(
|
||||
this,
|
||||
setDeviceVerificationAction,
|
||||
mCredentials,
|
||||
mCryptoStore,
|
||||
mSendToDeviceTask,
|
||||
mTaskExecutor,
|
||||
mMyDeviceInfoHolder.myDevice.fingerprint()!!,
|
||||
credentials,
|
||||
cryptoStore,
|
||||
sendToDeviceTask,
|
||||
taskExecutor,
|
||||
myDeviceInfoHolder.myDevice.fingerprint()!!,
|
||||
txID,
|
||||
userId,
|
||||
deviceID)
|
||||
@ -387,8 +387,8 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia
|
||||
private fun createUniqueIDForTransaction(userId: String, deviceID: String): String {
|
||||
val buff = StringBuffer()
|
||||
buff
|
||||
.append(mCredentials.userId).append("|")
|
||||
.append(mCredentials.deviceId).append("|")
|
||||
.append(credentials.userId).append("|")
|
||||
.append(credentials.deviceId).append("|")
|
||||
.append(userId).append("|")
|
||||
.append(deviceID).append("|")
|
||||
.append(UUID.randomUUID().toString())
|
||||
@ -413,7 +413,7 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia
|
||||
val contentMap = MXUsersDevicesMap<Any>()
|
||||
contentMap.setObject(cancelMessage, userId, userDevice)
|
||||
|
||||
mSendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_CANCEL, contentMap, transactionId))
|
||||
sendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_CANCEL, contentMap, transactionId))
|
||||
.dispatchTo(object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("## SAS verification [$transactionId] canceled for reason ${code.value}")
|
||||
@ -423,6 +423,6 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia
|
||||
Timber.e(failure, "## SAS verification [$transactionId] failed to cancel.")
|
||||
}
|
||||
})
|
||||
.executeBy(mTaskExecutor)
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
}
|
@ -350,6 +350,10 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
|
||||
return cryptoService.decryptEvent(event, timeline)
|
||||
}
|
||||
|
||||
override fun decryptEventAsync(event: Event, timeline: String, callback: MatrixCallback<MXEventDecryptionResult?>) {
|
||||
return cryptoService.decryptEventAsync(event, timeline, callback)
|
||||
}
|
||||
|
||||
override fun getEncryptionAlgorithm(roomId: String): String? {
|
||||
return cryptoService.getEncryptionAlgorithm(roomId)
|
||||
}
|
||||
|
@ -16,7 +16,9 @@
|
||||
|
||||
package im.vector.matrix.android.internal.session.room.timeline
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||
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.room.timeline.TimelineEvent
|
||||
import im.vector.matrix.android.internal.crypto.MXDecryptionException
|
||||
@ -44,23 +46,7 @@ internal class TimelineEventFactory(private val roomMemberExtractor: SenderRoomM
|
||||
}
|
||||
val event = eventEntity.asDomain()
|
||||
if (event.getClearType() == EventType.ENCRYPTED) {
|
||||
try {
|
||||
Timber.v("Encrypted event: try to decrypt ${event.eventId}")
|
||||
val result = if (decryptionCache.containsKey(eventEntity.localId)) {
|
||||
Timber.v("Encrypted event ${event.eventId} cached")
|
||||
decryptionCache[eventEntity.localId]
|
||||
} else {
|
||||
cryptoService.decryptEvent(event, timelineId)?.also {
|
||||
decryptionCache[eventEntity.localId] = it
|
||||
}
|
||||
}
|
||||
event.setClearData(result)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Encrypted event: decryption failed")
|
||||
if (e is MXDecryptionException) {
|
||||
event.setCryptoError(e.cryptoError)
|
||||
}
|
||||
}
|
||||
handleEncryptedEvent(event, eventEntity.localId)
|
||||
}
|
||||
return TimelineEvent(
|
||||
event,
|
||||
@ -72,6 +58,28 @@ internal class TimelineEventFactory(private val roomMemberExtractor: SenderRoomM
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleEncryptedEvent(event: Event, eventId: String) {
|
||||
Timber.v("Encrypted event: try to decrypt ${event.eventId}")
|
||||
val cachedDecryption = decryptionCache[eventId]
|
||||
if (cachedDecryption != null) {
|
||||
Timber.v("Encrypted event ${event.eventId} cached")
|
||||
event.setClearData(cachedDecryption)
|
||||
} else {
|
||||
try {
|
||||
val result = cryptoService.decryptEvent(event, timelineId)
|
||||
if (result != null) {
|
||||
decryptionCache[eventId] = result
|
||||
}
|
||||
event.setClearData(result)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "Encrypted event: decryption failed")
|
||||
if (failure is MXDecryptionException) {
|
||||
event.setCryptoError(failure.cryptoError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
senderCache.clear()
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ internal class CryptoSyncHandler(private val cryptoManager: CryptoManager,
|
||||
}
|
||||
}
|
||||
|
||||
fun onSyncCompleted(syncResponse: SyncResponse, fromToken: String?, catchingUp: Boolean) {
|
||||
fun onSyncCompleted(syncResponse: SyncResponse) {
|
||||
cryptoManager.onSyncCompleted(syncResponse)
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ internal class SyncResponseHandler(private val roomSyncHandler: RoomSyncHandler,
|
||||
userAccountDataSyncHandler.handle(syncResponse.accountData)
|
||||
}
|
||||
Timber.v("On sync completed")
|
||||
cryptoSyncHandler.onSyncCompleted(syncResponse, fromToken, isCatchingUp)
|
||||
cryptoSyncHandler.onSyncCompleted(syncResponse)
|
||||
}
|
||||
val isInitialSync = fromToken == null
|
||||
if (!cryptoManager.isStarted()) {
|
||||
|
@ -67,7 +67,7 @@ class HomeModule {
|
||||
roomHistoryVisibilityItemFactory = RoomHistoryVisibilityItemFactory(get()),
|
||||
callItemFactory = CallItemFactory(get()),
|
||||
encryptionItemFactory = EncryptionItemFactory(get()),
|
||||
encryptedItemFactory = EncryptedItemFactory(get(), get(), messageItemFactory),
|
||||
encryptedItemFactory = EncryptedItemFactory(get()),
|
||||
defaultItemFactory = DefaultItemFactory()
|
||||
)
|
||||
TimelineEventController(timelineDateFormatter, timelineItemFactory, timelineMediaSizeProvider)
|
||||
|
@ -20,29 +20,18 @@ import android.graphics.Typeface
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.style.StyleSpan
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
||||
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.room.timeline.TimelineEvent
|
||||
import im.vector.matrix.android.internal.crypto.MXDecryptionException
|
||||
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.riotredesign.core.resources.StringProvider
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem_
|
||||
|
||||
class EncryptedItemFactory(
|
||||
private val session: Session,
|
||||
private val stringProvider: StringProvider,
|
||||
private val messageItemFactory: MessageItemFactory) {
|
||||
|
||||
fun create(timelineEvent: TimelineEvent,
|
||||
nextEvent: TimelineEvent?,
|
||||
callback: TimelineEventController.Callback?): VectorEpoxyModel<*>? {
|
||||
// This class handles timeline event who haven't been successfully decrypted
|
||||
class EncryptedItemFactory(private val stringProvider: StringProvider) {
|
||||
|
||||
fun create(timelineEvent: TimelineEvent): VectorEpoxyModel<*>? {
|
||||
return when {
|
||||
EventType.ENCRYPTED == timelineEvent.root.getClearType() -> {
|
||||
val cryptoError = timelineEvent.root.mCryptoError
|
||||
@ -54,7 +43,6 @@ class EncryptedItemFactory(
|
||||
}
|
||||
|
||||
val message = stringProvider.getString(R.string.notice_crypto_unable_to_decrypt, errorDescription)
|
||||
|
||||
val spannableStr = SpannableString(message)
|
||||
spannableStr.setSpan(StyleSpan(Typeface.ITALIC), 0, message.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
// TODO This is not correct format for error, change it
|
||||
|
@ -39,8 +39,9 @@ class RoomHistoryVisibilityItemFactory(private val stringProvider: StringProvide
|
||||
}
|
||||
|
||||
private fun buildNoticeText(event: Event, senderName: String?): CharSequence? {
|
||||
val content = event.content.toModel<RoomHistoryVisibilityContent>() ?: return null
|
||||
val formattedVisibility = when (content.historyVisibility) {
|
||||
val historyVisibility = event.content.toModel<RoomHistoryVisibilityContent>()?.historyVisibility
|
||||
?: return null
|
||||
val formattedVisibility = when (historyVisibility) {
|
||||
RoomHistoryVisibility.SHARED -> stringProvider.getString(R.string.notice_room_visibility_shared)
|
||||
RoomHistoryVisibility.INVITED -> stringProvider.getString(R.string.notice_room_visibility_invited)
|
||||
RoomHistoryVisibility.JOINED -> stringProvider.getString(R.string.notice_room_visibility_joined)
|
||||
|
@ -51,7 +51,7 @@ class TimelineItemFactory(private val messageItemFactory: MessageItemFactory,
|
||||
|
||||
EventType.ENCRYPTION -> encryptionItemFactory.create(event)
|
||||
|
||||
EventType.ENCRYPTED -> encryptedItemFactory.create(event, nextEvent, callback)
|
||||
EventType.ENCRYPTED -> encryptedItemFactory.create(event)
|
||||
|
||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
EventType.STICKER,
|
||||
|
Loading…
Reference in New Issue
Block a user