diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakeGetContextOfEventTask.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakeGetContextOfEventTask.kt index cdd0bdcd8c..c2d325496a 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakeGetContextOfEventTask.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakeGetContextOfEventTask.kt @@ -25,7 +25,7 @@ import kotlin.random.Random internal class FakeGetContextOfEventTask(private val tokenChunkEventPersistor: TokenChunkEventPersistor) : GetContextOfEventTask { - override fun execute(params: GetContextOfEventTask.Params): Try { + override suspend fun execute(params: GetContextOfEventTask.Params): Try { val fakeEvents = RoomDataHelper.createFakeListOfEvents(30) val tokenChunkEvent = FakeTokenChunkEvent( Random.nextLong(System.currentTimeMillis()).toString(), diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakePaginationTask.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakePaginationTask.kt index 3a0e72a007..a0bc1f7415 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakePaginationTask.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/FakePaginationTask.kt @@ -23,7 +23,7 @@ import kotlin.random.Random internal class FakePaginationTask(private val tokenChunkEventPersistor: TokenChunkEventPersistor) : PaginationTask { - override fun execute(params: PaginationTask.Params): Try { + override suspend fun execute(params: PaginationTask.Params): Try { val fakeEvents = RoomDataHelper.createFakeListOfEvents(30) val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong(System.currentTimeMillis()).toString(), fakeEvents) return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, params.direction) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt index aab717ad57..84885e9e51 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt @@ -21,6 +21,8 @@ package im.vector.matrix.android.internal.crypto import android.content.Context import android.os.Handler import android.text.TextUtils +import arrow.core.Try +import arrow.instances.`try`.applicativeError.handleError import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.data.Credentials @@ -66,14 +68,16 @@ import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersTas import im.vector.matrix.android.internal.session.room.members.RoomMembers import im.vector.matrix.android.internal.session.sync.model.SyncResponse 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 im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import org.matrix.olm.OlmManager import timber.log.Timber import java.util.* +import java.util.concurrent.atomic.AtomicBoolean /** * A `CryptoService` class instance manages the end-to-end crypto for a session. @@ -137,10 +141,10 @@ internal class CryptoManager( private val roomEncryptors: MutableMap = HashMap() // the encryption is starting - private var isStarting: Boolean = false + private var isStarting = AtomicBoolean(false) // tell if the crypto is started - private var isStarted: Boolean = false + private var isStarted = AtomicBoolean(false) // TODO //private val mNetworkListener = object : IMXNetworkEventListener { @@ -220,7 +224,7 @@ internal class CryptoManager( * @return true if the crypto is started */ fun isStarted(): Boolean { - return isStarted + return isStarted.get() } /** @@ -229,7 +233,7 @@ internal class CryptoManager( * @return true if the crypto is starting */ fun isStarting(): Boolean { - return isStarting + return isStarting.get() } /** @@ -241,7 +245,7 @@ internal class CryptoManager( * @param isInitialSync true if it starts from an initial sync */ fun start(isInitialSync: Boolean) { - if (isStarting) { + if (isStarting.get()) { return } @@ -254,65 +258,43 @@ internal class CryptoManager( // return //} - isStarting = true - + isStarting.set(true) // Open the store cryptoStore.open() - - uploadDeviceKeys(object : MatrixCallback { - private fun onError() { - Handler().postDelayed({ - if (!isStarted()) { - isStarting = false - start(isInitialSync) - } - }, 1000) - } - - override fun onSuccess(data: KeysUploadResponse) { - Timber.v("###########################################################") - Timber.v("uploadDeviceKeys done for " + credentials.userId) - Timber.v(" - device id : " + credentials.deviceId) - Timber.v(" - ed25519 : " + olmDevice.deviceEd25519Key) - Timber.v(" - curve25519 : " + olmDevice.deviceCurve25519Key) - Timber.v(" - oneTimeKeys: " + oneTimeKeysUploader.mLastPublishedOneTimeKeys) - Timber.v("") - - oneTimeKeysUploader.maybeUploadOneTimeKeys(object : MatrixCallback { - override fun onSuccess(data: Unit) { - // TODO - //if (null != mNetworkConnectivityReceiver) { - // mNetworkConnectivityReceiver!!.removeEventListener(mNetworkListener) - //} - - isStarting = false - isStarted = true - - outgoingRoomKeyRequestManager.start() - - keysBackup.checkAndStartKeysBackup() - - if (isInitialSync) { - // refresh the devices list for each known room members - deviceListManager.invalidateAllDeviceLists() - deviceListManager.refreshOutdatedDeviceLists() - } else { - incomingRoomKeyRequestManager.processReceivedRoomKeyRequests() - } + CoroutineScope(coroutineDispatchers.crypto).launch { + uploadDeviceKeys() + .flatMap { + oneTimeKeysUploader.maybeUploadOneTimeKeys() } - - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## start failed") - onError() + .handleError { + Handler().postDelayed( + { + if (!isStarted()) { + isStarting.set(false) + start(isInitialSync) + } + }, 1000 + ) } - }) - } - - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## start failed") - onError() - } - }) + .fold( + { + Timber.e("Start failed: $it") + }, + { + isStarting.set(false) + isStarted.set(true) + outgoingRoomKeyRequestManager.start() + keysBackup.checkAndStartKeysBackup() + if (isInitialSync) { + // refresh the devices list for each known room members + deviceListManager.invalidateAllDeviceLists() + deviceListManager.refreshOutdatedDeviceLists() + } else { + incomingRoomKeyRequestManager.processReceivedRoomKeyRequests() + } + } + ) + } } /** @@ -320,9 +302,7 @@ internal class CryptoManager( */ fun close() { olmDevice.release() - cryptoStore.close() - outgoingRoomKeyRequestManager.stop() } @@ -351,19 +331,20 @@ internal class CryptoManager( * @param syncResponse the syncResponse */ fun onSyncCompleted(syncResponse: SyncResponse) { - if (syncResponse.deviceLists != null) { - deviceListManager.handleDeviceListsChanges(syncResponse.deviceLists.changed, syncResponse.deviceLists.left) - } - if (syncResponse.deviceOneTimeKeysCount != null) { - val currentCount = syncResponse.deviceOneTimeKeysCount.signedCurve25519 ?: 0 - oneTimeKeysUploader.updateOneTimeKeyCount(currentCount) - } - - if (isStarted()) { - // Make sure we process to-device messages before generating new one-time-keys #2782 - deviceListManager.refreshOutdatedDeviceLists() - oneTimeKeysUploader.maybeUploadOneTimeKeys() - incomingRoomKeyRequestManager.processReceivedRoomKeyRequests() + CoroutineScope(coroutineDispatchers.crypto).launch { + if (syncResponse.deviceLists != null) { + deviceListManager.handleDeviceListsChanges(syncResponse.deviceLists.changed, syncResponse.deviceLists.left) + } + if (syncResponse.deviceOneTimeKeysCount != null) { + val currentCount = syncResponse.deviceOneTimeKeysCount.signedCurve25519 ?: 0 + oneTimeKeysUploader.updateOneTimeKeyCount(currentCount) + } + if (isStarted()) { + // Make sure we process to-device messages before generating new one-time-keys #2782 + deviceListManager.refreshOutdatedDeviceLists() + oneTimeKeysUploader.maybeUploadOneTimeKeys() + incomingRoomKeyRequestManager.processReceivedRoomKeyRequests() + } } } @@ -398,7 +379,7 @@ internal class CryptoManager( /** * Set the devices as known * - * @param devices the devices. Note that the mVerified member of the devices in this list will not be updated by this method. + * @param devices the devices. Note that the verified member of the devices in this list will not be updated by this method. * @param callback the asynchronous callback */ override fun setDevicesKnown(devices: List, callback: MatrixCallback?) { @@ -431,7 +412,7 @@ internal class CryptoManager( // assume if the device is either verified or blocked // it means that the device is known if (null != device && device.isUnknown) { - device.mVerified = MXDeviceInfo.DEVICE_VERIFICATION_UNVERIFIED + device.verified = MXDeviceInfo.DEVICE_VERIFICATION_UNVERIFIED isUpdated = true } } @@ -459,7 +440,6 @@ internal class CryptoManager( /** * Configure a room to use encryption. - * This method must be called in getEncryptingThreadHandler * * @param roomId the room id to enable encryption in. * @param algorithm the encryption config for the room. @@ -467,7 +447,7 @@ internal class CryptoManager( * @param membersId list of members to start tracking their devices * @return true if the operation succeeds. */ - private fun setEncryptionInRoom(roomId: String, algorithm: String?, inhibitDeviceQuery: Boolean, membersId: List): Boolean { + private suspend fun setEncryptionInRoom(roomId: String, algorithm: String?, inhibitDeviceQuery: Boolean, membersId: List): Boolean { // If we already have encryption in this room, we should ignore this event // (for now at least. Maybe we should alert the user somehow?) val existingAlgorithm = cryptoStore.getRoomAlgorithm(roomId) @@ -578,49 +558,47 @@ internal class CryptoManager( // wait that the crypto is really started if (!isStarted()) { Timber.v("## encryptEventContent() : wait after e2e init") - start(false) return } - - val userIds = getRoomUserIds(roomId) - var alg = synchronized(roomEncryptors) { - roomEncryptors[roomId] - } - if (alg == null) { - val algorithm = getEncryptionAlgorithm(roomId) - if (null != algorithm) { - if (setEncryptionInRoom(roomId, algorithm, false, userIds)) { - synchronized(roomEncryptors) { - alg = roomEncryptors[roomId] + CoroutineScope(coroutineDispatchers.crypto).launch { + val userIds = getRoomUserIds(roomId) + var alg = synchronized(roomEncryptors) { + roomEncryptors[roomId] + } + if (alg == null) { + val algorithm = getEncryptionAlgorithm(roomId) + if (algorithm != null) { + if (setEncryptionInRoom(roomId, algorithm, false, userIds)) { + synchronized(roomEncryptors) { + alg = roomEncryptors[roomId] + } } } } - } + val safeAlgorithm = alg + if (safeAlgorithm != null) { + val t0 = System.currentTimeMillis() + Timber.v("## encryptEventContent() starts") + safeAlgorithm.encryptEventContent(eventContent, eventType, userIds, object : MatrixCallback { + override fun onSuccess(data: Content) { + Timber.v("## encryptEventContent() : succeeds after " + (System.currentTimeMillis() - t0) + " ms") + callback.onSuccess(MXEncryptEventContentResult(data, EventType.ENCRYPTED)) + } - if (alg != null) { - val t0 = System.currentTimeMillis() - Timber.v("## encryptEventContent() starts") + override fun onFailure(failure: Throwable) { + callback.onFailure(failure) + } + }) + } else { + val algorithm = getEncryptionAlgorithm(roomId) + val reason = String.format(MXCryptoError.UNABLE_TO_ENCRYPT_REASON, + algorithm ?: MXCryptoError.NO_MORE_ALGORITHM_REASON) + Timber.e("## encryptEventContent() : $reason") - alg!!.encryptEventContent(eventContent, eventType, userIds, object : MatrixCallback { - override fun onSuccess(data: Content) { - Timber.v("## encryptEventContent() : succeeds after " + (System.currentTimeMillis() - t0) + " ms") - - callback.onSuccess(MXEncryptEventContentResult(data, EventType.ENCRYPTED)) - } - - override fun onFailure(failure: Throwable) { - callback.onFailure(failure) - } - }) - } else { - val algorithm = getEncryptionAlgorithm(roomId) - val reason = String.format(MXCryptoError.UNABLE_TO_ENCRYPT_REASON, - algorithm ?: MXCryptoError.NO_MORE_ALGORITHM_REASON) - Timber.e("## encryptEventContent() : $reason") - - callback.onFailure(Failure.CryptoError(MXCryptoError(MXCryptoError.UNABLE_TO_ENCRYPT_ERROR_CODE, - MXCryptoError.UNABLE_TO_ENCRYPT, reason))) + callback.onFailure(Failure.CryptoError(MXCryptoError(MXCryptoError.UNABLE_TO_ENCRYPT_ERROR_CODE, + MXCryptoError.UNABLE_TO_ENCRYPT, reason))) + } } } @@ -633,43 +611,23 @@ internal class CryptoManager( */ @Throws(MXDecryptionException::class) override fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult? { - val eventContent = event.content //wireEventContent? - - if (null == eventContent) { + val eventContent = event.content + if (eventContent == null) { Timber.e("## decryptEvent : empty event content") return null } - - val results = ArrayList() - val exceptions = ArrayList() - - var result: MXEventDecryptionResult? = null val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(event.roomId, eventContent["algorithm"] as String) - - if (null == alg) { + if (alg == null) { val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, eventContent["algorithm"] as String) Timber.e("## decryptEvent() : $reason") - exceptions.add(MXDecryptionException(MXCryptoError(MXCryptoError.UNABLE_TO_DECRYPT_ERROR_CODE, - MXCryptoError.UNABLE_TO_DECRYPT, reason))) + throw MXDecryptionException(MXCryptoError(MXCryptoError.UNABLE_TO_DECRYPT_ERROR_CODE, MXCryptoError.UNABLE_TO_DECRYPT, reason)) } else { - try { - result = alg.decryptEvent(event, timeline) - } catch (decryptionException: MXDecryptionException) { - exceptions.add(decryptionException) - } - - if (null != result) { - results.add(result) // TODO simplify + return runBlocking { + withContext(coroutineDispatchers.crypto) { + alg.decryptEvent(event, timeline) + } } } - - if (!exceptions.isEmpty()) { - throw exceptions[0] - } - - return if (!results.isEmpty()) { - results[0] - } else null } /** @@ -687,16 +645,17 @@ internal class CryptoManager( * @param event the event */ fun onToDeviceEvent(event: Event) { - if (event.getClearType() == EventType.ROOM_KEY || event.getClearType() == EventType.FORWARDED_ROOM_KEY) { - onRoomKeyEvent(event) - } else if (event.getClearType() == EventType.ROOM_KEY_REQUEST) { - incomingRoomKeyRequestManager.onRoomKeyRequestEvent(event) + CoroutineScope(coroutineDispatchers.crypto).launch { + if (event.getClearType() == EventType.ROOM_KEY || event.getClearType() == EventType.FORWARDED_ROOM_KEY) { + onRoomKeyEvent(event) + } else if (event.getClearType() == EventType.ROOM_KEY_REQUEST) { + incomingRoomKeyRequestManager.onRoomKeyRequestEvent(event) + } } } /** * Handle a key event. - * This method must be called on getDecryptingThreadHandler() thread. * * @param event the key event. */ @@ -798,25 +757,17 @@ internal class CryptoManager( /** * Upload my user's device keys. - * This method must called on getEncryptingThreadHandler() thread. - * The callback will called on UI thread. - * - * @param callback the asynchronous callback */ - private fun uploadDeviceKeys(callback: MatrixCallback) { + private suspend fun uploadDeviceKeys(): Try { // Prepare the device keys data to send // Sign it val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, getMyDevice().signalableJSONDictionary()) - getMyDevice().signatures = objectSigner.signObject(canonicalJson) // For now, we set the device id explicitly, as we may not be using the // same one as used in login. - uploadKeysTask - .configureWith(UploadKeysTask.Params(getMyDevice().toDeviceKeys(), null, getMyDevice().deviceId)) - .executeOn(TaskThread.ENCRYPTION) - .dispatchTo(callback) - .executeBy(taskExecutor) + val uploadDeviceKeysParams = UploadKeysTask.Params(getMyDevice().toDeviceKeys(), null, getMyDevice().deviceId) + return uploadKeysTask.execute(uploadDeviceKeysParams) } /** @@ -934,24 +885,24 @@ internal class CryptoManager( */ fun checkUnknownDevices(userIds: List, callback: MatrixCallback) { // force the refresh to ensure that the devices list is up-to-date - deviceListManager.downloadKeys(userIds, true, object : MatrixCallback> { - override fun onSuccess(data: MXUsersDevicesMap) { - val unknownDevices = getUnknownDevices(data) - - if (unknownDevices.map.isEmpty()) { - callback.onSuccess(Unit) - } else { - // trigger an an unknown devices exception - callback.onFailure( - Failure.CryptoError(MXCryptoError(MXCryptoError.UNKNOWN_DEVICES_CODE, - MXCryptoError.UNABLE_TO_ENCRYPT, MXCryptoError.UNKNOWN_DEVICES_REASON, unknownDevices))) - } - } - - override fun onFailure(failure: Throwable) { - callback.onFailure(failure) - } - }) + CoroutineScope(coroutineDispatchers.crypto).launch { + deviceListManager + .downloadKeys(userIds, true) + .fold( + { callback.onFailure(it) }, + { + val unknownDevices = getUnknownDevices(it) + if (unknownDevices.map.isEmpty()) { + callback.onSuccess(Unit) + } else { + // trigger an an unknown devices exception + callback.onFailure( + Failure.CryptoError(MXCryptoError(MXCryptoError.UNKNOWN_DEVICES_CODE, + MXCryptoError.UNABLE_TO_ENCRYPT, MXCryptoError.UNKNOWN_DEVICES_REASON, unknownDevices))) + } + } + ) + } } /** @@ -1091,7 +1042,6 @@ internal class CryptoManager( */ private fun getUnknownDevices(devicesInRoom: MXUsersDevicesMap): MXUsersDevicesMap { val unknownDevices = MXUsersDevicesMap() - val userIds = devicesInRoom.userIds for (userId in userIds) { val deviceIds = devicesInRoom.getUserDeviceIds(userId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt index f1b14e5b8f..6a55914fe9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt @@ -19,7 +19,11 @@ package im.vector.matrix.android.internal.crypto import android.content.Context import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.session.crypto.CryptoService -import im.vector.matrix.android.internal.crypto.actions.* +import im.vector.matrix.android.internal.crypto.actions.EnsureOlmSessionsForDevicesAction +import im.vector.matrix.android.internal.crypto.actions.EnsureOlmSessionsForUsersAction +import im.vector.matrix.android.internal.crypto.actions.MegolmSessionDataImporter +import im.vector.matrix.android.internal.crypto.actions.MessageEncrypter +import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction import im.vector.matrix.android.internal.crypto.algorithms.megolm.MXMegolmDecryptionFactory import im.vector.matrix.android.internal.crypto.algorithms.megolm.MXMegolmEncryptionFactory import im.vector.matrix.android.internal.crypto.algorithms.olm.MXOlmDecryptionFactory @@ -27,14 +31,56 @@ import im.vector.matrix.android.internal.crypto.algorithms.olm.MXOlmEncryptionFa import im.vector.matrix.android.internal.crypto.api.CryptoApi import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi -import im.vector.matrix.android.internal.crypto.keysbackup.tasks.* +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.CreateKeysBackupVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultCreateKeysBackupVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteBackupTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetKeysBackupLastVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetKeysBackupVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultStoreRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultStoreRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultStoreSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultUpdateKeysBackupVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteBackupTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetKeysBackupLastVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetKeysBackupVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask import im.vector.matrix.android.internal.crypto.repository.WarnOnUnknownDeviceRepository import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreMigration import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule import im.vector.matrix.android.internal.crypto.store.db.hash -import im.vector.matrix.android.internal.crypto.tasks.* +import im.vector.matrix.android.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultClaimOneTimeKeysForUsersDevice +import im.vector.matrix.android.internal.crypto.tasks.DefaultDeleteDeviceTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultDownloadKeysForUsers +import im.vector.matrix.android.internal.crypto.tasks.DefaultGetDevicesTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultGetKeyChangesTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultSendToDeviceTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultSetDeviceNameTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultUploadKeysTask +import im.vector.matrix.android.internal.crypto.tasks.DeleteDeviceTask +import im.vector.matrix.android.internal.crypto.tasks.DownloadKeysForUsersTask +import im.vector.matrix.android.internal.crypto.tasks.GetDevicesTask +import im.vector.matrix.android.internal.crypto.tasks.GetKeyChangesTask +import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask +import im.vector.matrix.android.internal.crypto.tasks.SetDeviceNameTask +import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService import im.vector.matrix.android.internal.session.DefaultSession import io.realm.RealmConfiguration @@ -109,7 +155,7 @@ internal class CryptoModule { // OneTimeKeysUploader scope(DefaultSession.SCOPE) { - OneTimeKeysUploader(get(), get(), get(), get(), get()) + OneTimeKeysUploader(get(), get(), get(), get()) } // Actions @@ -164,7 +210,7 @@ internal class CryptoModule { scope(DefaultSession.SCOPE) { MXOlmEncryptionFactory( - get(), get(), get(), get(), get(),get() + get(), get(), get(), get(), get(), get() ) } @@ -217,7 +263,7 @@ internal class CryptoModule { // Device list scope(DefaultSession.SCOPE) { - DeviceListManager(get(), get(), get(), get(), get(), get(), get()) + DeviceListManager(get(), get(), get(), get(), get()) } // Crypto tasks @@ -319,7 +365,7 @@ internal class CryptoModule { * ========================================================================================== */ scope(DefaultSession.SCOPE) { - DefaultSasVerificationService(get(), get(), get(), get(), get(), get(), get()) + DefaultSasVerificationService(get(), get(), get(), get(), get(), get(), get(), get()) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt index 129e53e2ac..45b786a446 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DeviceListManager.kt @@ -18,19 +18,15 @@ package im.vector.matrix.android.internal.crypto import android.text.TextUtils -import im.vector.matrix.android.api.MatrixCallback +import arrow.core.Try +import arrow.instances.`try`.applicativeError.handleError import im.vector.matrix.android.api.MatrixPatterns import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap -import im.vector.matrix.android.internal.crypto.model.rest.KeysQueryResponse import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.DownloadKeysForUsersTask import im.vector.matrix.android.internal.session.sync.SyncTokenStore -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 im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import timber.log.Timber import java.util.* @@ -39,59 +35,22 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, private val olmDevice: MXOlmDevice, private val syncTokenStore: SyncTokenStore, private val credentials: Credentials, - private val downloadKeysForUsersTask: DownloadKeysForUsersTask, - private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val taskExecutor: TaskExecutor) { - - // keys in progress - private val userKeyDownloadsInProgress = HashSet() + private val downloadKeysForUsersTask: DownloadKeysForUsersTask) { // HS not ready for retry private val notReadyToRetryHS = HashSet() - // indexed by UserId - private val pendingDownloadKeysRequestToken = HashMap() - - // pending queues list - private val downloadKeysQueues = ArrayList() - - // tells if there is a download keys request in progress - private var isDownloadingKeys = false - - /** - * Creator - * - * @param userIds the user ids list - * @param callback the asynchronous callback - */ - internal inner class DownloadKeysPromise(userIds: List, - val callback: MatrixCallback>?) { - // list of remain pending device keys - val mPendingUserIdsList: MutableList - - // the unfiltered user ids list - val mUserIdsList: List - - init { - mPendingUserIdsList = ArrayList(userIds) - mUserIdsList = ArrayList(userIds) - } - } - init { var isUpdated = false - val deviceTrackingStatuses = cryptoStore.getDeviceTrackingStatuses().toMutableMap() for (userId in deviceTrackingStatuses.keys) { val status = deviceTrackingStatuses[userId]!! - if (TRACKING_STATUS_DOWNLOAD_IN_PROGRESS == status || TRACKING_STATUS_UNREACHABLE_SERVER == status) { // if a download was in progress when we got shut down, it isn't any more. deviceTrackingStatuses.put(userId, TRACKING_STATUS_PENDING_DOWNLOAD) isUpdated = true } } - if (isUpdated) { cryptoStore.saveDeviceTrackingStatuses(deviceTrackingStatuses) } @@ -120,43 +79,6 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, return res } - /** - * Add a download keys promise - * - * @param userIds the user ids list - * @param callback the asynchronous callback - * @return the filtered user ids list i.e the one which require a remote request - */ - private fun addDownloadKeysPromise(userIds: MutableList?, callback: MatrixCallback>?): MutableList? { - if (null != userIds) { - val filteredUserIds = ArrayList() - val invalidUserIds = ArrayList() - - for (userId in userIds) { - if (MatrixPatterns.isUserId(userId)) { - filteredUserIds.add(userId) - } else { - Timber.e("## userId " + userId + "is not a valid user id") - invalidUserIds.add(userId) - } - } - - synchronized(userKeyDownloadsInProgress) { - filteredUserIds.removeAll(userKeyDownloadsInProgress) - userKeyDownloadsInProgress.addAll(userIds) - // got some email addresses instead of matrix ids - userKeyDownloadsInProgress.removeAll(invalidUserIds) - userIds.removeAll(invalidUserIds) - } - - downloadKeysQueues.add(DownloadKeysPromise(userIds, callback)) - - return filteredUserIds - } else { - return null - } - } - /** * Clear the unavailable server lists */ @@ -180,7 +102,7 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, for (userId in userIds) { if (!deviceTrackingStatuses.containsKey(userId) || TRACKING_STATUS_NOT_TRACKED == deviceTrackingStatuses[userId]) { Timber.v("## startTrackingDeviceList() : Now tracking device list for $userId") - deviceTrackingStatuses.put(userId, TRACKING_STATUS_PENDING_DOWNLOAD) + deviceTrackingStatuses[userId] = TRACKING_STATUS_PENDING_DOWNLOAD isUpdated = true } } @@ -202,24 +124,20 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, val deviceTrackingStatuses = cryptoStore.getDeviceTrackingStatuses().toMutableMap() if (changed?.isNotEmpty() == true) { - clearUnavailableServersList() - for (userId in changed) { if (deviceTrackingStatuses.containsKey(userId)) { Timber.v("## invalidateUserDeviceList() : Marking device list outdated for $userId") - deviceTrackingStatuses.put(userId, TRACKING_STATUS_PENDING_DOWNLOAD) + deviceTrackingStatuses[userId] = TRACKING_STATUS_PENDING_DOWNLOAD isUpdated = true } } } if (left?.isNotEmpty() == true) { - clearUnavailableServersList() - for (userId in left) { if (deviceTrackingStatuses.containsKey(userId)) { Timber.v("## invalidateUserDeviceList() : No longer tracking device list for $userId") - deviceTrackingStatuses.put(userId, TRACKING_STATUS_NOT_TRACKED) + deviceTrackingStatuses[userId] = TRACKING_STATUS_NOT_TRACKED isUpdated = true } } @@ -243,21 +161,12 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, * * @param userIds the user ids list */ - private fun onKeysDownloadFailed(userIds: List?) { - if (null != userIds) { - synchronized(userKeyDownloadsInProgress) { - val deviceTrackingStatuses = cryptoStore.getDeviceTrackingStatuses().toMutableMap() - - for (userId in userIds) { - userKeyDownloadsInProgress.remove(userId) - deviceTrackingStatuses.put(userId, TRACKING_STATUS_PENDING_DOWNLOAD) - } - - cryptoStore.saveDeviceTrackingStatuses(deviceTrackingStatuses) - } + private fun onKeysDownloadFailed(userIds: List) { + val deviceTrackingStatuses = cryptoStore.getDeviceTrackingStatuses().toMutableMap() + for (userId in userIds) { + deviceTrackingStatuses[userId] = TRACKING_STATUS_PENDING_DOWNLOAD } - - isDownloadingKeys = false + cryptoStore.saveDeviceTrackingStatuses(deviceTrackingStatuses) } /** @@ -266,23 +175,19 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, * @param userIds the userIds list * @param failures the failure map. */ - private fun onKeysDownloadSucceed(userIds: List?, failures: Map>?) { - if (null != failures) { + private fun onKeysDownloadSucceed(userIds: List, failures: Map>?): MXUsersDevicesMap { + if (failures != null) { val keys = failures.keys - for (k in keys) { val value = failures[k] - if (value!!.containsKey("status")) { val statusCodeAsVoid = value["status"] var statusCode = 0 - if (statusCodeAsVoid is Double) { statusCode = statusCodeAsVoid.toInt() } else if (statusCodeAsVoid is Int) { statusCode = statusCodeAsVoid.toInt() } - if (statusCode == 503) { synchronized(notReadyToRetryHS) { notReadyToRetryHS.add(k) @@ -291,65 +196,33 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, } } } - val deviceTrackingStatuses = cryptoStore.getDeviceTrackingStatuses().toMutableMap() - - if (null != userIds) { - if (downloadKeysQueues.size > 0) { - val promisesToRemove = ArrayList() - - for (promise in downloadKeysQueues) { - promise.mPendingUserIdsList.removeAll(userIds) - - if (promise.mPendingUserIdsList.size == 0) { - // private members - val usersDevicesInfoMap = MXUsersDevicesMap() - - for (userId in promise.mUserIdsList) { - val devices = cryptoStore.getUserDevices(userId) - if (null == devices) { - if (canRetryKeysDownload(userId)) { - deviceTrackingStatuses.put(userId, TRACKING_STATUS_PENDING_DOWNLOAD) - Timber.e("failed to retry the devices of $userId : retry later") - } else { - if (deviceTrackingStatuses.containsKey(userId) && TRACKING_STATUS_DOWNLOAD_IN_PROGRESS == deviceTrackingStatuses[userId]) { - deviceTrackingStatuses.put(userId, TRACKING_STATUS_UNREACHABLE_SERVER) - Timber.e("failed to retry the devices of $userId : the HS is not available") - } - } - } else { - if (deviceTrackingStatuses.containsKey(userId) && TRACKING_STATUS_DOWNLOAD_IN_PROGRESS == deviceTrackingStatuses[userId]) { - // we didn't get any new invalidations since this download started: - // this user's device list is now up to date. - deviceTrackingStatuses.put(userId, TRACKING_STATUS_UP_TO_DATE) - Timber.v("Device list for $userId now up to date") - } - - // And the response result - usersDevicesInfoMap.setObjects(devices, userId) - } - } - - val callback = promise.callback - - if (null != callback) { - CryptoAsyncHelper.getUiHandler().post { callback.onSuccess(usersDevicesInfoMap) } - } - - promisesToRemove.add(promise) + val usersDevicesInfoMap = MXUsersDevicesMap() + for (userId in userIds) { + val devices = cryptoStore.getUserDevices(userId) + if (null == devices) { + if (canRetryKeysDownload(userId)) { + deviceTrackingStatuses[userId] = TRACKING_STATUS_PENDING_DOWNLOAD + Timber.e("failed to retry the devices of $userId : retry later") + } else { + if (deviceTrackingStatuses.containsKey(userId) && TRACKING_STATUS_DOWNLOAD_IN_PROGRESS == deviceTrackingStatuses[userId]) { + deviceTrackingStatuses[userId] = TRACKING_STATUS_UNREACHABLE_SERVER + Timber.e("failed to retry the devices of $userId : the HS is not available") } } - downloadKeysQueues.removeAll(promisesToRemove) + } else { + if (deviceTrackingStatuses.containsKey(userId) && TRACKING_STATUS_DOWNLOAD_IN_PROGRESS == deviceTrackingStatuses[userId]) { + // we didn't get any new invalidations since this download started: + // this user's device list is now up to date. + deviceTrackingStatuses[userId] = TRACKING_STATUS_UP_TO_DATE + Timber.v("Device list for $userId now up to date") + } + // And the response result + usersDevicesInfoMap.setObjects(devices, userId) } - - for (userId in userIds) { - userKeyDownloadsInProgress.remove(userId) - } - - cryptoStore.saveDeviceTrackingStatuses(deviceTrackingStatuses) } - - isDownloadingKeys = false + cryptoStore.saveDeviceTrackingStatuses(deviceTrackingStatuses) + return usersDevicesInfoMap } /** @@ -361,31 +234,27 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, * @param forceDownload Always download the keys even if cached. * @param callback the asynchronous callback */ - fun downloadKeys(userIds: List?, forceDownload: Boolean, callback: MatrixCallback>?) { + suspend fun downloadKeys(userIds: List?, forceDownload: Boolean): Try> { Timber.v("## downloadKeys() : forceDownload $forceDownload : $userIds") - // Map from userid -> deviceid -> DeviceInfo val stored = MXUsersDevicesMap() // List of user ids we need to download keys for val downloadUsers = ArrayList() - if (null != userIds) { if (forceDownload) { downloadUsers.addAll(userIds) } else { for (userId in userIds) { val status = cryptoStore.getDeviceTrackingStatus(userId, TRACKING_STATUS_NOT_TRACKED) - // downloading keys ->the keys download won't be triggered twice but the callback requires the dedicated keys // not yet retrieved - if (userKeyDownloadsInProgress.contains(userId) || TRACKING_STATUS_UP_TO_DATE != status && TRACKING_STATUS_UNREACHABLE_SERVER != status) { + if (TRACKING_STATUS_UP_TO_DATE != status && TRACKING_STATUS_UNREACHABLE_SERVER != status) { downloadUsers.add(userId) } else { val devices = cryptoStore.getUserDevices(userId) - // should always be true - if (null != devices) { + if (devices != null) { stored.setObjects(devices, userId) } else { downloadUsers.add(userId) @@ -394,31 +263,18 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, } } } - - if (0 == downloadUsers.size) { + return if (downloadUsers.isEmpty()) { Timber.v("## downloadKeys() : no new user device") - - if (null != callback) { - CryptoAsyncHelper.getUiHandler().post { callback.onSuccess(stored) } - } + Try.just(stored) } else { Timber.v("## downloadKeys() : starts") val t0 = System.currentTimeMillis() - - doKeyDownloadForUsers(downloadUsers, object : MatrixCallback> { - override fun onSuccess(data: MXUsersDevicesMap) { - Timber.v("## downloadKeys() : doKeyDownloadForUsers succeeds after " + (System.currentTimeMillis() - t0) + " ms") - - data.addEntriesFromMap(stored) - - callback?.onSuccess(data) - } - - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## downloadKeys() : doKeyDownloadForUsers onFailure") - callback?.onFailure(failure) - } - }) + doKeyDownloadForUsers(downloadUsers) + .flatMap { + Timber.v("## downloadKeys() : doKeyDownloadForUsers succeeds after " + (System.currentTimeMillis() - t0) + " ms") + it.addEntriesFromMap(stored) + Try.just(it) + } } } @@ -430,134 +286,61 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, * @param downloadUsers the user ids list * @param callback the asynchronous callback */ - private fun doKeyDownloadForUsers(downloadUsers: MutableList, callback: MatrixCallback>?) { + private suspend fun doKeyDownloadForUsers(downloadUsers: MutableList): Try> { Timber.v("## doKeyDownloadForUsers() : doKeyDownloadForUsers $downloadUsers") - // get the user ids which did not already trigger a keys download - val filteredUsers = addDownloadKeysPromise(downloadUsers, callback) - - // if there is no new keys request - if (0 == filteredUsers!!.size) { + val filteredUsers = downloadUsers.filter { MatrixPatterns.isUserId(it) } + if (filteredUsers.isEmpty()) { // trigger nothing - return + return Try.just(MXUsersDevicesMap()) } + val params = DownloadKeysForUsersTask.Params(filteredUsers, syncTokenStore.getLastToken()) + return downloadKeysForUsersTask.execute(params) + .map { response -> + Timber.v("## doKeyDownloadForUsers() : Got keys for " + filteredUsers.size + " users") + for (userId in filteredUsers) { + val devices = response.deviceKeys?.get(userId) + Timber.v("## doKeyDownloadForUsers() : Got keys for $userId : $devices") + if (devices != null) { + val mutableDevices = HashMap(devices) + val deviceIds = ArrayList(mutableDevices.keys) + for (deviceId in deviceIds) { + // Get the potential previously store device keys for this device + val previouslyStoredDeviceKeys = cryptoStore.getUserDevice(deviceId, userId) + val deviceInfo = mutableDevices[deviceId] - // sanity check - //if (null == mxSession.dataHandler || null == mxSession.dataHandler.store) { - // return - //} - - isDownloadingKeys = true - - // track the race condition while sending requests - // we defines a tag for each request - // and test if the response is the latest request one - val downloadToken = filteredUsers.hashCode().toString() + " " + System.currentTimeMillis() - - for (userId in filteredUsers) { - pendingDownloadKeysRequestToken[userId] = downloadToken - } - - downloadKeysForUsersTask - .configureWith(DownloadKeysForUsersTask.Params(filteredUsers, syncTokenStore.getLastToken())) - .executeOn(TaskThread.ENCRYPTION) - .dispatchTo(object : MatrixCallback { - override fun onSuccess(data: KeysQueryResponse) { - CryptoAsyncHelper.getEncryptBackgroundHandler().post { - Timber.v("## doKeyDownloadForUsers() : Got keys for " + filteredUsers.size + " users") - val userIdsList = ArrayList(filteredUsers) - - for (userId in userIdsList) { - // test if the response is the latest request one - if (!TextUtils.equals(pendingDownloadKeysRequestToken[userId], downloadToken)) { - Timber.e("## doKeyDownloadForUsers() : Another update in the queue for " - + userId + " not marking up-to-date") - filteredUsers.remove(userId) - } else { - val devices = data.deviceKeys!![userId] - - Timber.v("## doKeyDownloadForUsers() : Got keys for $userId : $devices") - - if (null != devices) { - val mutableDevices = HashMap(devices) - val deviceIds = ArrayList(mutableDevices.keys) - - for (deviceId in deviceIds) { - // the user has been logged out - // TODO - //if (null == cryptoStore) { - // break - //} - - // Get the potential previously store device keys for this device - val previouslyStoredDeviceKeys = cryptoStore.getUserDevice(deviceId, userId) - val deviceInfo = mutableDevices[deviceId] - - // in some race conditions (like unit tests) - // the self device must be seen as verified - if (TextUtils.equals(deviceInfo!!.deviceId, credentials.deviceId) && TextUtils.equals(userId, credentials.userId)) { - deviceInfo.mVerified = MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED - } - - // Validate received keys - if (!validateDeviceKeys(deviceInfo, userId, deviceId, previouslyStoredDeviceKeys)) { - // New device keys are not valid. Do not store them - mutableDevices.remove(deviceId) - - if (null != previouslyStoredDeviceKeys) { - // But keep old validated ones if any - mutableDevices[deviceId] = previouslyStoredDeviceKeys - } - } else if (null != previouslyStoredDeviceKeys) { - // The verified status is not sync'ed with hs. - // This is a client side information, valid only for this client. - // So, transfer its previous value - mutableDevices[deviceId]!!.mVerified = previouslyStoredDeviceKeys.mVerified - } - } - - // Update the store - // Note that devices which aren't in the response will be removed from the stores - cryptoStore.storeUserDevices(userId, mutableDevices) + // in some race conditions (like unit tests) + // the self device must be seen as verified + if (TextUtils.equals(deviceInfo!!.deviceId, credentials.deviceId) && TextUtils.equals(userId, credentials.userId)) { + deviceInfo.verified = MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED + } + // Validate received keys + if (!validateDeviceKeys(deviceInfo, userId, deviceId, previouslyStoredDeviceKeys)) { + // New device keys are not valid. Do not store them + mutableDevices.remove(deviceId) + if (null != previouslyStoredDeviceKeys) { + // But keep old validated ones if any + mutableDevices[deviceId] = previouslyStoredDeviceKeys } - - // the response is the latest request one - pendingDownloadKeysRequestToken.remove(userId) + } else if (null != previouslyStoredDeviceKeys) { + // The verified status is not sync'ed with hs. + // This is a client side information, valid only for this client. + // So, transfer its previous value + mutableDevices[deviceId]!!.verified = previouslyStoredDeviceKeys.verified } } - - onKeysDownloadSucceed(filteredUsers, data.failures) + // Update the store + // Note that devices which aren't in the response will be removed from the stores + cryptoStore.storeUserDevices(userId, mutableDevices) } } - - private fun onFailed() { - CryptoAsyncHelper.getEncryptBackgroundHandler().post { - val userIdsList = ArrayList(filteredUsers) - - // test if the response is the latest request one - for (userId in userIdsList) { - if (!TextUtils.equals(pendingDownloadKeysRequestToken[userId], downloadToken)) { - Timber.e("## doKeyDownloadForUsers() : Another update in the queue for $userId not marking up-to-date") - filteredUsers.remove(userId) - } else { - // the response is the latest request one - pendingDownloadKeysRequestToken.remove(userId) - } - } - - onKeysDownloadFailed(filteredUsers) - } - } - - override fun onFailure(failure: Throwable) { - Timber.e(failure, "##doKeyDownloadForUsers() : onNetworkError") - - onFailed() - - callback?.onFailure(failure) - } - }) - .executeBy(taskExecutor) + onKeysDownloadSucceed(filteredUsers, response.failures) + } + .handleError { + Timber.e(it, "##doKeyDownloadForUsers(): error") + onKeysDownloadFailed(filteredUsers) + throw it + } } /** @@ -631,7 +414,7 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, if (!isVerified) { Timber.e("## validateDeviceKeys() : Unable to verify signature on device " + userId + ":" - + deviceKeys.deviceId + " with error " + errorMessage) + + deviceKeys.deviceId + " with error " + errorMessage) return false } @@ -642,8 +425,8 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, // // Should we warn the user about it somehow? Timber.e("## validateDeviceKeys() : WARNING:Ed25519 key for device " + userId + ":" - + deviceKeys.deviceId + " has changed : " - + previouslyStoredDeviceKeys.fingerprint() + " -> " + signKey) + + deviceKeys.deviceId + " has changed : " + + previouslyStoredDeviceKeys.fingerprint() + " -> " + signKey) Timber.e("## validateDeviceKeys() : $previouslyStoredDeviceKeys -> $deviceKeys") Timber.e("## validateDeviceKeys() : " + previouslyStoredDeviceKeys.keys + " -> " + deviceKeys.keys) @@ -659,7 +442,7 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, * Start device queries for any users who sent us an m.new_device recently * This method must be called on getEncryptingThreadHandler() thread. */ - fun refreshOutdatedDeviceLists() { + suspend fun refreshOutdatedDeviceLists() { val users = ArrayList() val deviceTrackingStatuses = cryptoStore.getDeviceTrackingStatuses().toMutableMap() @@ -674,33 +457,24 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore, return } - if (isDownloadingKeys) { - // request already in progress - do nothing. (We will automatically - // make another request if there are more users with outdated - // device lists when the current request completes). - return - } - // update the statuses for (userId in users) { val status = deviceTrackingStatuses[userId] - if (null != status && TRACKING_STATUS_PENDING_DOWNLOAD == status) { deviceTrackingStatuses.put(userId, TRACKING_STATUS_DOWNLOAD_IN_PROGRESS) } } cryptoStore.saveDeviceTrackingStatuses(deviceTrackingStatuses) - - doKeyDownloadForUsers(users, object : MatrixCallback> { - override fun onSuccess(data: MXUsersDevicesMap) { - CryptoAsyncHelper.getEncryptBackgroundHandler().post { Timber.v("## refreshOutdatedDeviceLists() : done") } - } - - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## refreshOutdatedDeviceLists() : ERROR updating device keys for users $users") - } - }) + doKeyDownloadForUsers(users) + .fold( + { + Timber.e(it, "## refreshOutdatedDeviceLists() : ERROR updating device keys for users $users") + }, + { + Timber.v("## refreshOutdatedDeviceLists() : done") + } + ) } companion object { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt index 1575eb3e63..7444eaaf33 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt @@ -133,7 +133,7 @@ internal class IncomingRoomKeyRequestManager( if (device.isVerified) { Timber.v("## processReceivedRoomKeyRequests() : device is already verified: sharing keys") mCryptoStore.deleteIncomingRoomKeyRequest(request) - request.share!!.run() + request.share?.run() continue } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt index c24fed74af..ef57e8ee27 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt @@ -38,7 +38,7 @@ internal class MXOlmDevice( /** * The store where crypto data is saved. */ - private val mStore: IMXCryptoStore) { + private val store: IMXCryptoStore) { /** * @return the Curve25519 key for the account. @@ -53,16 +53,16 @@ internal class MXOlmDevice( private set // The OLM lib account instance. - private var mOlmAccount: OlmAccount? = null + private var olmAccount: OlmAccount? = null // The OLM lib utility instance. - private var mOlmUtility: OlmUtility? = null + private var olmUtility: OlmUtility? = null // The outbound group session. // They are not stored in 'store' to avoid to remember to which devices we sent the session key. // Plus, in cryptography, it is good to refresh sessions from time to time. // The key is the session id, the value the outbound group session. - private val mOutboundGroupSessionStore: MutableMap = HashMap() + private val outboundGroupSessionStore: MutableMap = HashMap() // Store a set of decrypted message indexes for each group session. // This partially mitigates a replay attack where a MITM resends a group @@ -76,25 +76,25 @@ internal class MXOlmDevice( // The first level keys are timeline ids. // The second level keys are strings of form "||" // Values are true. - private val mInboundGroupSessionMessageIndexes: MutableMap> = HashMap() + private val inboundGroupSessionMessageIndexes: MutableMap> = HashMap() /** * inboundGroupSessionWithId error */ - private var mInboundGroupSessionWithIdError: MXCryptoError? = null + private var inboundGroupSessionWithIdError: MXCryptoError? = null init { // Retrieve the account from the store - mOlmAccount = mStore.getAccount() + olmAccount = store.getAccount() - if (null == mOlmAccount) { + if (null == olmAccount) { Timber.v("MXOlmDevice : create a new olm account") // Else, create it try { - mOlmAccount = OlmAccount() - mStore.storeAccount(mOlmAccount!!) + olmAccount = OlmAccount() + store.storeAccount(olmAccount!!) } catch (e: Exception) { - Timber.e(e, "MXOlmDevice : cannot initialize mOlmAccount") + Timber.e(e, "MXOlmDevice : cannot initialize olmAccount") } } else { @@ -102,20 +102,20 @@ internal class MXOlmDevice( } try { - mOlmUtility = OlmUtility() + olmUtility = OlmUtility() } catch (e: Exception) { Timber.e(e, "## MXOlmDevice : OlmUtility failed with error") - mOlmUtility = null + olmUtility = null } try { - deviceCurve25519Key = mOlmAccount!!.identityKeys()[OlmAccount.JSON_KEY_IDENTITY_KEY] + deviceCurve25519Key = olmAccount!!.identityKeys()[OlmAccount.JSON_KEY_IDENTITY_KEY] } catch (e: Exception) { Timber.e(e, "## MXOlmDevice : cannot find " + OlmAccount.JSON_KEY_IDENTITY_KEY + " with error") } try { - deviceEd25519Key = mOlmAccount!!.identityKeys()[OlmAccount.JSON_KEY_FINGER_PRINT_KEY] + deviceEd25519Key = olmAccount!!.identityKeys()[OlmAccount.JSON_KEY_FINGER_PRINT_KEY] } catch (e: Exception) { Timber.e(e, "## MXOlmDevice : cannot find " + OlmAccount.JSON_KEY_FINGER_PRINT_KEY + " with error") } @@ -126,7 +126,7 @@ internal class MXOlmDevice( */ fun getOneTimeKeys(): Map>? { try { - return mOlmAccount!!.oneTimeKeys() + return olmAccount!!.oneTimeKeys() } catch (e: Exception) { Timber.e(e, "## getOneTimeKeys() : failed") } @@ -138,14 +138,14 @@ internal class MXOlmDevice( * @return The maximum number of one-time keys the olm account can store. */ fun getMaxNumberOfOneTimeKeys(): Long { - return mOlmAccount?.maxOneTimeKeys() ?: -1 + return olmAccount?.maxOneTimeKeys() ?: -1 } /** * Release the instance */ fun release() { - mOlmAccount?.releaseAccount() + olmAccount?.releaseAccount() } /** @@ -156,7 +156,7 @@ internal class MXOlmDevice( */ fun signMessage(message: String): String? { try { - return mOlmAccount!!.signMessage(message) + return olmAccount!!.signMessage(message) } catch (e: Exception) { Timber.e(e, "## signMessage() : failed") } @@ -169,8 +169,8 @@ internal class MXOlmDevice( */ fun markKeysAsPublished() { try { - mOlmAccount!!.markOneTimeKeysAsPublished() - mStore.storeAccount(mOlmAccount!!) + olmAccount!!.markOneTimeKeysAsPublished() + store.storeAccount(olmAccount!!) } catch (e: Exception) { Timber.e(e, "## markKeysAsPublished() : failed") } @@ -183,8 +183,8 @@ internal class MXOlmDevice( */ fun generateOneTimeKeys(numKeys: Int) { try { - mOlmAccount!!.generateOneTimeKeys(numKeys) - mStore.storeAccount(mOlmAccount!!) + olmAccount!!.generateOneTimeKeys(numKeys) + store.storeAccount(olmAccount!!) } catch (e: Exception) { Timber.e(e, "## generateOneTimeKeys() : failed") } @@ -204,7 +204,7 @@ internal class MXOlmDevice( try { olmSession = OlmSession() - olmSession.initOutboundSession(mOlmAccount!!, theirIdentityKey, theirOneTimeKey) + olmSession.initOutboundSession(olmAccount!!, theirIdentityKey, theirOneTimeKey) val mxOlmSession = MXOlmSession(olmSession, 0) @@ -213,7 +213,7 @@ internal class MXOlmDevice( // this session mxOlmSession.onMessageReceived() - mStore.storeSession(mxOlmSession, theirIdentityKey) + store.storeSession(mxOlmSession, theirIdentityKey) val sessionIdentifier = olmSession.sessionIdentifier() @@ -246,7 +246,7 @@ internal class MXOlmDevice( try { try { olmSession = OlmSession() - olmSession.initInboundSessionFrom(mOlmAccount!!, theirDeviceIdentityKey, ciphertext) + olmSession.initInboundSessionFrom(olmAccount!!, theirDeviceIdentityKey, ciphertext) } catch (e: Exception) { Timber.e(e, "## createInboundSession() : the session creation failed") return null @@ -255,15 +255,15 @@ internal class MXOlmDevice( Timber.v("## createInboundSession() : sessionId: " + olmSession.sessionIdentifier()) try { - mOlmAccount!!.removeOneTimeKeys(olmSession) - mStore.storeAccount(mOlmAccount!!) + olmAccount!!.removeOneTimeKeys(olmSession) + store.storeAccount(olmAccount!!) } catch (e: Exception) { Timber.e(e, "## createInboundSession() : removeOneTimeKeys failed") } Timber.v("## createInboundSession() : ciphertext: $ciphertext") try { - val sha256 = mOlmUtility!!.sha256(URLEncoder.encode(ciphertext, "utf-8")) + val sha256 = olmUtility!!.sha256(URLEncoder.encode(ciphertext, "utf-8")) Timber.v("## createInboundSession() :ciphertext: SHA256:" + sha256) } catch (e: Exception) { Timber.e(e, "## createInboundSession() :ciphertext: cannot encode ciphertext") @@ -282,7 +282,7 @@ internal class MXOlmDevice( // This counts as a received message: set last received message time to now mxOlmSession.onMessageReceived() - mStore.storeSession(mxOlmSession, theirDeviceIdentityKey) + store.storeSession(mxOlmSession, theirDeviceIdentityKey) } catch (e: Exception) { Timber.e(e, "## createInboundSession() : decryptMessage failed") } @@ -316,7 +316,7 @@ internal class MXOlmDevice( * @return a list of known session ids for the device. */ fun getSessionIds(theirDeviceIdentityKey: String): Set? { - return mStore.getDeviceSessionIds(theirDeviceIdentityKey) + return store.getDeviceSessionIds(theirDeviceIdentityKey) } /** @@ -326,7 +326,7 @@ internal class MXOlmDevice( * @return the session id, or null if no established session. */ fun getSessionId(theirDeviceIdentityKey: String): String? { - return mStore.getLastUsedSessionId(theirDeviceIdentityKey) + return store.getLastUsedSessionId(theirDeviceIdentityKey) } /** @@ -348,7 +348,7 @@ internal class MXOlmDevice( //Timber.v("## encryptMessage() : payloadString: " + payloadString); olmMessage = mxOlmSession.olmSession.encryptMessage(payloadString) - mStore.storeSession(mxOlmSession, theirDeviceIdentityKey) + store.storeSession(mxOlmSession, theirDeviceIdentityKey) res = HashMap() res["body"] = olmMessage.mCipherText @@ -384,7 +384,7 @@ internal class MXOlmDevice( try { payloadString = mxOlmSession.olmSession.decryptMessage(olmMessage) mxOlmSession.onMessageReceived() - mStore.storeSession(mxOlmSession, theirDeviceIdentityKey) + store.storeSession(mxOlmSession, theirDeviceIdentityKey) } catch (e: Exception) { Timber.e(e, "## decryptMessage() : decryptMessage failed " + e.message) } @@ -424,7 +424,7 @@ internal class MXOlmDevice( var session: OlmOutboundGroupSession? = null try { session = OlmOutboundGroupSession() - mOutboundGroupSessionStore[session.sessionIdentifier()] = session + outboundGroupSessionStore[session.sessionIdentifier()] = session return session.sessionIdentifier() } catch (e: Exception) { Timber.e(e, "createOutboundGroupSession " + e.message) @@ -444,7 +444,7 @@ internal class MXOlmDevice( fun getSessionKey(sessionId: String): String? { if (!TextUtils.isEmpty(sessionId)) { try { - return mOutboundGroupSessionStore[sessionId]!!.sessionKey() + return outboundGroupSessionStore[sessionId]!!.sessionKey() } catch (e: Exception) { Timber.e(e, "## getSessionKey() : failed " + e.message) } @@ -461,7 +461,7 @@ internal class MXOlmDevice( */ fun getMessageIndex(sessionId: String): Int { return if (!TextUtils.isEmpty(sessionId)) { - mOutboundGroupSessionStore[sessionId]!!.messageIndex() + outboundGroupSessionStore[sessionId]!!.messageIndex() } else 0 } @@ -475,7 +475,7 @@ internal class MXOlmDevice( fun encryptGroupMessage(sessionId: String, payloadString: String): String? { if (!TextUtils.isEmpty(sessionId) && !TextUtils.isEmpty(payloadString)) { try { - return mOutboundGroupSessionStore[sessionId]!!.encryptMessage(payloadString) + return outboundGroupSessionStore[sessionId]!!.encryptMessage(payloadString) } catch (e: Exception) { Timber.e(e, "## encryptGroupMessage() : failed " + e.message) } @@ -547,7 +547,7 @@ internal class MXOlmDevice( session.mKeysClaimed = keysClaimed session.mForwardingCurve25519KeyChain = forwardingCurve25519KeyChain - mStore.storeInboundGroupSessions(listOf(session)) + store.storeInboundGroupSessions(listOf(session)) return true } @@ -609,7 +609,7 @@ internal class MXOlmDevice( sessions.add(session) } - mStore.storeInboundGroupSessions(sessions) + store.storeInboundGroupSessions(sessions) return sessions } @@ -622,7 +622,7 @@ internal class MXOlmDevice( */ fun removeInboundGroupSession(sessionId: String?, sessionKey: String?) { if (null != sessionId && null != sessionKey) { - mStore.removeInboundGroupSession(sessionId, sessionKey) + store.removeInboundGroupSession(sessionId, sessionKey) } } @@ -660,41 +660,41 @@ internal class MXOlmDevice( if (null != decryptResult) { if (null != timeline) { - if (!mInboundGroupSessionMessageIndexes.containsKey(timeline)) { - mInboundGroupSessionMessageIndexes[timeline] = HashMap() + if (!inboundGroupSessionMessageIndexes.containsKey(timeline)) { + inboundGroupSessionMessageIndexes[timeline] = HashMap() } val messageIndexKey = senderKey + "|" + sessionId + "|" + decryptResult.mIndex - if (null != mInboundGroupSessionMessageIndexes[timeline]!![messageIndexKey]) { + if (null != inboundGroupSessionMessageIndexes[timeline]!![messageIndexKey]) { val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex) Timber.e("## decryptGroupMessage() : $reason") throw MXDecryptionException(MXCryptoError(MXCryptoError.DUPLICATED_MESSAGE_INDEX_ERROR_CODE, MXCryptoError.UNABLE_TO_DECRYPT, reason)) } - mInboundGroupSessionMessageIndexes[timeline]!!.put(messageIndexKey, true) + inboundGroupSessionMessageIndexes[timeline]!!.put(messageIndexKey, true) } - mStore.storeInboundGroupSessions(listOf(session)) + store.storeInboundGroupSessions(listOf(session)) try { val adapter = MoshiProvider.providesMoshi().adapter(JSON_DICT_PARAMETERIZED_TYPE) val payloadString = convertFromUTF8(decryptResult.mDecryptedMessage) val payload = adapter.fromJson(payloadString) - result.mPayload = payload + result.payload = payload } catch (e: Exception) { Timber.e(e, "## decryptGroupMessage() : RLEncoder.encode failed " + e.message) return null } - if (null == result.mPayload) { + if (null == result.payload) { Timber.e("## decryptGroupMessage() : fails to parse the payload") return null } - result.mKeysClaimed = session.mKeysClaimed - result.mSenderKey = senderKey - result.mForwardingCurve25519KeyChain = session.mForwardingCurve25519KeyChain + result.keysClaimed = session.mKeysClaimed + result.senderKey = senderKey + result.forwardingCurve25519KeyChain = session.mForwardingCurve25519KeyChain } else { Timber.e("## decryptGroupMessage() : failed to decode the message") throw MXDecryptionException(MXCryptoError(MXCryptoError.OLM_ERROR_CODE, errorMessage, null)) @@ -707,7 +707,7 @@ internal class MXOlmDevice( } } else { Timber.e("## decryptGroupMessage() : Cannot retrieve inbound group session $sessionId") - throw MXDecryptionException(mInboundGroupSessionWithIdError) + throw MXDecryptionException(inboundGroupSessionWithIdError) } return result @@ -720,7 +720,7 @@ internal class MXOlmDevice( */ fun resetReplayAttackCheckInTimeline(timeline: String?) { if (null != timeline) { - mInboundGroupSessionMessageIndexes.remove(timeline) + inboundGroupSessionMessageIndexes.remove(timeline) } } @@ -737,7 +737,7 @@ internal class MXOlmDevice( @Throws(Exception::class) fun verifySignature(key: String, jsonDictionary: Map, signature: String) { // Check signature on the canonical version of the JSON - mOlmUtility!!.verifyEd25519Signature(signature, key, MoshiProvider.getCanonicalJson>(Map::class.java, jsonDictionary)) + olmUtility!!.verifyEd25519Signature(signature, key, MoshiProvider.getCanonicalJson>(Map::class.java, jsonDictionary)) } /** @@ -747,7 +747,7 @@ internal class MXOlmDevice( * @return the base64-encoded hash value. */ fun sha256(message: String): String { - return mOlmUtility!!.sha256(convertToUTF8(message)) + return olmUtility!!.sha256(convertToUTF8(message)) } /** @@ -760,14 +760,14 @@ internal class MXOlmDevice( private fun getSessionForDevice(theirDeviceIdentityKey: String, sessionId: String): MXOlmSession? { // sanity check return if (!TextUtils.isEmpty(theirDeviceIdentityKey) && !TextUtils.isEmpty(sessionId)) { - mStore.getDeviceSession(sessionId, theirDeviceIdentityKey) + store.getDeviceSession(sessionId, theirDeviceIdentityKey) } else null } /** * Extract an InboundGroupSession from the session store and do some check. - * mInboundGroupSessionWithIdError describes the failure reason. + * inboundGroupSessionWithIdError describes the failure reason. * * @param roomId the room where the session is used. * @param sessionId the session identifier. @@ -775,9 +775,9 @@ internal class MXOlmDevice( * @return the inbound group session. */ fun getInboundGroupSession(sessionId: String?, senderKey: String?, roomId: String?): MXOlmInboundGroupSession2? { - mInboundGroupSessionWithIdError = null + inboundGroupSessionWithIdError = null - val session = mStore.getInboundGroupSession(sessionId!!, senderKey!!) + val session = store.getInboundGroupSession(sessionId!!, senderKey!!) if (null != session) { // Check that the room id matches the original one for the session. This stops @@ -785,13 +785,13 @@ internal class MXOlmDevice( if (!TextUtils.equals(roomId, session.mRoomId)) { val errorDescription = String.format(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_REASON, roomId, session.mRoomId) Timber.e("## getInboundGroupSession() : $errorDescription") - mInboundGroupSessionWithIdError = MXCryptoError(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE, - MXCryptoError.UNABLE_TO_DECRYPT, errorDescription) + inboundGroupSessionWithIdError = MXCryptoError(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE, + MXCryptoError.UNABLE_TO_DECRYPT, errorDescription) } } else { Timber.e("## getInboundGroupSession() : Cannot retrieve inbound group session $sessionId") - mInboundGroupSessionWithIdError = MXCryptoError(MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE, - MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_REASON, null) + inboundGroupSessionWithIdError = MXCryptoError(MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE, + MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_REASON, null) } return session } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MyDeviceInfoHolder.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MyDeviceInfoHolder.kt index 0eb376f611..80e03f5d09 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MyDeviceInfoHolder.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MyDeviceInfoHolder.kt @@ -50,7 +50,7 @@ internal class MyDeviceInfoHolder( myDevice.keys = keys myDevice.algorithms = MXCryptoAlgorithms.supportedAlgorithms() - myDevice.mVerified = MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED + myDevice.verified = MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED // Add our own deviceinfo to the store val endToEndDevicesForUser = cryptoStore.getUserDevices(credentials.userId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt index 02754cddbb..5ec8e84a4f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt @@ -16,15 +16,13 @@ package im.vector.matrix.android.internal.crypto -import im.vector.matrix.android.api.MatrixCallback +import arrow.core.Try +import arrow.instances.`try`.applicativeError.handleError import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.internal.crypto.model.MXKey import im.vector.matrix.android.internal.crypto.model.rest.KeysUploadResponse import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask import im.vector.matrix.android.internal.di.MoshiProvider -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 org.matrix.olm.OlmAccount import timber.log.Timber import java.util.* @@ -33,15 +31,13 @@ internal class OneTimeKeysUploader( private val mCredentials: Credentials, private val mOlmDevice: MXOlmDevice, private val mObjectSigner: ObjectSigner, - private val mUploadKeysTask: UploadKeysTask, - private val mTaskExecutor: TaskExecutor + private val mUploadKeysTask: UploadKeysTask ) { // tell if there is a OTK check in progress private var mOneTimeKeyCheckInProgress = false // last OTK check timestamp private var mLastOneTimeKeyCheck: Long = 0 - private var mOneTimeKeyCount: Int? = null var mLastPublishedOneTimeKeys: Map>? = null @@ -60,23 +56,17 @@ internal class OneTimeKeysUploader( /** * Check if the OTK must be uploaded. - * - * @param callback the asynchronous callback */ - fun maybeUploadOneTimeKeys(callback: MatrixCallback? = null) { + suspend fun maybeUploadOneTimeKeys(): Try { if (mOneTimeKeyCheckInProgress) { - callback?.onSuccess(Unit) - return + return Try.just(Unit) } - if (System.currentTimeMillis() - mLastOneTimeKeyCheck < ONE_TIME_KEY_UPLOAD_PERIOD) { // we've done a key upload recently. - callback?.onSuccess(Unit) - return + return Try.just(Unit) } mLastOneTimeKeyCheck = System.currentTimeMillis() - mOneTimeKeyCheckInProgress = true // We then check how many keys we can store in the Account object. @@ -89,44 +79,34 @@ internal class OneTimeKeysUploader( // discard the oldest private keys first. This will eventually clean // out stale private keys that won't receive a message. val keyLimit = Math.floor(maxOneTimeKeys / 2.0).toInt() - - if (null != mOneTimeKeyCount) { - uploadOTK(mOneTimeKeyCount!!, keyLimit, callback) + if (mOneTimeKeyCount != null) { + return uploadOTK(mOneTimeKeyCount!!, keyLimit) } else { // ask the server how many keys we have - mUploadKeysTask - .configureWith(UploadKeysTask.Params(null, null, mCredentials.deviceId!!)) - .executeOn(TaskThread.ENCRYPTION) - .dispatchTo(object : MatrixCallback { - - override fun onSuccess(data: KeysUploadResponse) { - // We need to keep a pool of one time public keys on the server so that - // other devices can start conversations with us. But we can only store - // a finite number of private keys in the olm Account object. - // To complicate things further then can be a delay between a device - // claiming a public one time key from the server and it sending us a - // message. We need to keep the corresponding private key locally until - // we receive the message. - // But that message might never arrive leaving us stuck with duff - // private keys clogging up our local storage. - // So we need some kind of engineering compromise to balance all of - // these factors. - // TODO Why we do not set mOneTimeKeyCount here? - // TODO This is not needed anymore, see https://github.com/matrix-org/matrix-js-sdk/pull/493 (TODO on iOS also) - val keyCount = data.oneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE) - uploadOTK(keyCount, keyLimit, callback) - } - - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## uploadKeys() : failed") - - mOneTimeKeyCount = null - mOneTimeKeyCheckInProgress = false - - callback?.onFailure(failure) - } - }) - .executeBy(mTaskExecutor) + val uploadKeysParams = UploadKeysTask.Params(null, null, mCredentials.deviceId!!) + return mUploadKeysTask.execute(uploadKeysParams) + .flatMap { + // We need to keep a pool of one time public keys on the server so that + // other devices can start conversations with us. But we can only store + // a finite number of private keys in the olm Account object. + // To complicate things further then can be a delay between a device + // claiming a public one time key from the server and it sending us a + // message. We need to keep the corresponding private key locally until + // we receive the message. + // But that message might never arrive leaving us stuck with duff + // private keys clogging up our local storage. + // So we need some kind of engineering compromise to balance all of + // these factors. + // TODO Why we do not set mOneTimeKeyCount here? + // TODO This is not needed anymore, see https://github.com/matrix-org/matrix-js-sdk/pull/493 (TODO on iOS also) + val keyCount = it.oneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE) + uploadOTK(keyCount, keyLimit) + } + .handleError { + Timber.e(it, "## uploadKeys() : failed") + mOneTimeKeyCount = null + mOneTimeKeyCheckInProgress = false + } } } @@ -135,42 +115,40 @@ internal class OneTimeKeysUploader( * * @param keyCount the key count * @param keyLimit the limit - * @param callback the asynchronous callback */ - private fun uploadOTK(keyCount: Int, keyLimit: Int, callback: MatrixCallback?) { - uploadLoop(keyCount, keyLimit, object : MatrixCallback { - private fun uploadKeysDone(errorMessage: String?) { - if (null != errorMessage) { - Timber.e("## maybeUploadOneTimeKeys() : failed $errorMessage") + private suspend fun uploadOTK(keyCount: Int, keyLimit: Int): Try { + return uploadLoop(keyCount, keyLimit) + } + + /** + * OTK upload loop + * + * @param keyCount the number of key to generate + * @param keyLimit the limit + */ + private suspend fun uploadLoop(keyCount: Int, keyLimit: Int): Try { + if (keyLimit <= keyCount) { + // If we don't need to generate any more keys then we are done. + return Try.just(Unit) + } + + val keysThisLoop = Math.min(keyLimit - keyCount, ONE_TIME_KEY_GENERATION_MAX_NUMBER) + mOlmDevice.generateOneTimeKeys(keysThisLoop) + return uploadOneTimeKeys() + .flatMap { + if (it.hasOneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE)) { + uploadLoop(it.oneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE), keyLimit) + } else { + Timber.e("## uploadLoop() : response for uploading keys does not contain one_time_key_counts.signed_curve25519") + Try.raise(Exception("response for uploading keys does not contain one_time_key_counts.signed_curve25519")) + } } - mOneTimeKeyCount = null - mOneTimeKeyCheckInProgress = false - } - - override fun onSuccess(data: Unit) { - Timber.v("## maybeUploadOneTimeKeys() : succeeded") - uploadKeysDone(null) - - callback?.onSuccess(Unit) - } - - override fun onFailure(failure: Throwable) { - uploadKeysDone(failure.message) - - callback?.onFailure(failure) - } - }) - } /** * Upload my user's one time keys. - * This method must called on getEncryptingThreadHandler() thread. - * The callback will called on UI thread. - * - * @param callback the asynchronous callback */ - private fun uploadOneTimeKeys(callback: MatrixCallback?) { + private suspend fun uploadOneTimeKeys(): Try { val oneTimeKeys = mOlmDevice.getOneTimeKeys() val oneTimeJson = HashMap() @@ -192,57 +170,14 @@ internal class OneTimeKeysUploader( // For now, we set the device id explicitly, as we may not be using the // same one as used in login. - mUploadKeysTask - .configureWith(UploadKeysTask.Params(null, oneTimeJson, mCredentials.deviceId!!)) - .executeOn(TaskThread.ENCRYPTION) - .dispatchTo(object : MatrixCallback { - override fun onSuccess(data: KeysUploadResponse) { - mLastPublishedOneTimeKeys = oneTimeKeys - mOlmDevice.markKeysAsPublished() - - callback?.onSuccess(data) - } - - override fun onFailure(failure: Throwable) { - callback?.onFailure(failure) - } - }) - .executeBy(mTaskExecutor) - } - - /** - * OTK upload loop - * - * @param keyCount the number of key to generate - * @param keyLimit the limit - * @param callback the asynchronous callback - */ - private fun uploadLoop(keyCount: Int, keyLimit: Int, callback: MatrixCallback) { - if (keyLimit <= keyCount) { - // If we don't need to generate any more keys then we are done. - callback.onSuccess(Unit) - return - } - - val keysThisLoop = Math.min(keyLimit - keyCount, ONE_TIME_KEY_GENERATION_MAX_NUMBER) - - mOlmDevice.generateOneTimeKeys(keysThisLoop) - - uploadOneTimeKeys(object : MatrixCallback { - override fun onSuccess(data: KeysUploadResponse) { - if (data.hasOneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE)) { - uploadLoop(data.oneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE), keyLimit, callback) - } else { - Timber.e("## uploadLoop() : response for uploading keys does not contain one_time_key_counts.signed_curve25519") - callback.onFailure( - Exception("response for uploading keys does not contain one_time_key_counts.signed_curve25519")) + val uploadParams = UploadKeysTask.Params(null, oneTimeJson, mCredentials.deviceId!!) + return mUploadKeysTask + .execute(uploadParams) + .map { + mLastPublishedOneTimeKeys = oneTimeKeys + mOlmDevice.markKeysAsPublished() + it } - } - - override fun onFailure(failure: Throwable) { - callback.onFailure(failure) - } - }) } companion object { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt index fb3eea8c47..c87c798fc1 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt @@ -27,6 +27,7 @@ import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyShareRequest import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask 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 java.util.* @@ -87,7 +88,7 @@ internal class OutgoingRoomKeyRequestManager( OutgoingRoomKeyRequest(requestBody, recipients, makeTxnId(), OutgoingRoomKeyRequest.RequestState.UNSENT)) - if (req!!.mState === OutgoingRoomKeyRequest.RequestState.UNSENT) { + if (req?.mState == OutgoingRoomKeyRequest.RequestState.UNSENT) { startTimer() } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/RoomDecryptorProvider.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/RoomDecryptorProvider.kt index 647a74b4b9..4561428b96 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/RoomDecryptorProvider.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/RoomDecryptorProvider.kt @@ -24,12 +24,12 @@ import timber.log.Timber import java.util.* internal class RoomDecryptorProvider( - private val mMXOlmDecryptionFactory: MXOlmDecryptionFactory, - private val mMXMegolmDecryptionFactory: MXMegolmDecryptionFactory + private val olmDecryptionFactory: MXOlmDecryptionFactory, + private val megolmDecryptionFactory: MXMegolmDecryptionFactory ) { // A map from algorithm to MXDecrypting instance, for each room - private val mRoomDecryptors: MutableMap> = HashMap() + private val roomDecryptors: MutableMap> = HashMap() /** * Get a decryptor for a given room and algorithm. @@ -43,44 +43,36 @@ internal class RoomDecryptorProvider( */ fun getOrCreateRoomDecryptor(roomId: String?, algorithm: String?): IMXDecrypting? { // sanity check - if (TextUtils.isEmpty(algorithm)) { + if (algorithm.isNullOrEmpty() || roomId.isNullOrEmpty()) { Timber.e("## getRoomDecryptor() : null algorithm") return null } - var alg: IMXDecrypting? = null - - if (!TextUtils.isEmpty(roomId)) { - synchronized(mRoomDecryptors) { - if (!mRoomDecryptors.containsKey(roomId)) { - mRoomDecryptors[roomId!!] = HashMap() - } - - alg = mRoomDecryptors[roomId]!![algorithm] + var alg: IMXDecrypting? + synchronized(roomDecryptors) { + if (!roomDecryptors.containsKey(roomId)) { + roomDecryptors[roomId!!] = HashMap() } - if (null != alg) { - return alg - } + alg = roomDecryptors[roomId]!![algorithm] + } + if (alg != null) { + return alg } - val decryptingClass = MXCryptoAlgorithms.hasDecryptorClassForAlgorithm(algorithm) - if (decryptingClass) { alg = when (algorithm) { - MXCRYPTO_ALGORITHM_MEGOLM -> mMXMegolmDecryptionFactory.create() - else -> mMXOlmDecryptionFactory.create() + MXCRYPTO_ALGORITHM_MEGOLM -> megolmDecryptionFactory.create() + else -> olmDecryptionFactory.create() } - if (null != alg) { if (!TextUtils.isEmpty(roomId)) { - synchronized(mRoomDecryptors) { - mRoomDecryptors[roomId]!!.put(algorithm!!, alg!!) + synchronized(roomDecryptors) { + roomDecryptors[roomId]!!.put(algorithm!!, alg!!) } } } } - return alg } @@ -88,7 +80,6 @@ internal class RoomDecryptorProvider( if (roomId == null || algorithm == null) { return null } - - return mRoomDecryptors[roomId]?.get(algorithm) + return roomDecryptors[roomId]?.get(algorithm) } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt index b47619aab3..189cf94c5c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt @@ -18,7 +18,11 @@ package im.vector.matrix.android.internal.crypto.actions import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.listeners.ProgressListener -import im.vector.matrix.android.internal.crypto.* +import im.vector.matrix.android.internal.crypto.CryptoAsyncHelper +import im.vector.matrix.android.internal.crypto.MXOlmDevice +import im.vector.matrix.android.internal.crypto.MegolmSessionData +import im.vector.matrix.android.internal.crypto.OutgoingRoomKeyRequestManager +import im.vector.matrix.android.internal.crypto.RoomDecryptorProvider import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore @@ -53,7 +57,6 @@ internal class MegolmSessionDataImporter(private val mOlmDevice: MXOlmDevice, progressListener.onProgress(0, 100) } } - val sessions = mOlmDevice.importInboundGroupSessions(megolmSessionsData) for (megolmSessionData in megolmSessionsData) { @@ -65,7 +68,7 @@ internal class MegolmSessionDataImporter(private val mOlmDevice: MXOlmDevice, if (null != decrypting) { try { val sessionId = megolmSessionData.sessionId - Timber.v("## importRoomKeys retrieve mSenderKey " + megolmSessionData.senderKey + " sessionId " + sessionId) + Timber.v("## importRoomKeys retrieve senderKey " + megolmSessionData.senderKey + " sessionId " + sessionId) totalNumbersOfImportedKeys++ diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt index e55aac9a74..ce55c062fc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/SetDeviceVerificationAction.kt @@ -34,8 +34,8 @@ internal class SetDeviceVerificationAction(private val mCryptoStore: IMXCryptoSt return } - if (device.mVerified != verificationStatus) { - device.mVerified = verificationStatus + if (device.verified != verificationStatus) { + device.verified = verificationStatus mCryptoStore.storeUserDevice(userId, device) if (userId == mCredentials.userId) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/MXDecryptionResult.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/MXDecryptionResult.kt index 2cf7973c92..cb1e1f708c 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/MXDecryptionResult.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/MXDecryptionResult.kt @@ -25,21 +25,21 @@ data class MXDecryptionResult( /** * The decrypted payload (with properties 'type', 'content') */ - var mPayload: JsonDict? = null, + var payload: JsonDict? = null, /** * keys that the sender of the event claims ownership of: * map from key type to base64-encoded key. */ - var mKeysClaimed: Map? = null, + var keysClaimed: Map? = null, /** * The curve25519 key that the sender of the event is known to have ownership of. */ - var mSenderKey: String? = null, + var senderKey: String? = null, /** * Devices which forwarded this session to us (normally empty). */ - var mForwardingCurve25519KeyChain: List? = null + var forwardingCurve25519KeyChain: List? = null ) \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt index 969f2aea86..016eccf74f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt @@ -74,7 +74,6 @@ internal class MXMegolmDecryption(private val credentials: Credentials, } @Throws(MXDecryptionException::class) - private fun decryptEvent(event: Event, timeline: String, requestKeysOnFail: Boolean): MXEventDecryptionResult? { val encryptedEventContent = event.content.toModel()!! if (TextUtils.isEmpty(encryptedEventContent.senderKey) || TextUtils.isEmpty(encryptedEventContent.sessionId) || TextUtils.isEmpty(encryptedEventContent.ciphertext)) { @@ -93,17 +92,17 @@ internal class MXMegolmDecryption(private val credentials: Credentials, } // the decryption succeeds - if (decryptGroupMessageResult?.mPayload != null && cryptoError == null) { + if (decryptGroupMessageResult?.payload != null && cryptoError == null) { eventDecryptionResult = MXEventDecryptionResult() - eventDecryptionResult.clearEvent = decryptGroupMessageResult.mPayload - eventDecryptionResult.senderCurve25519Key = decryptGroupMessageResult.mSenderKey + eventDecryptionResult.clearEvent = decryptGroupMessageResult.payload + eventDecryptionResult.senderCurve25519Key = decryptGroupMessageResult.senderKey - if (null != decryptGroupMessageResult.mKeysClaimed) { - eventDecryptionResult.claimedEd25519Key = decryptGroupMessageResult.mKeysClaimed!!["ed25519"] + if (null != decryptGroupMessageResult.keysClaimed) { + eventDecryptionResult.claimedEd25519Key = decryptGroupMessageResult.keysClaimed!!["ed25519"] } - eventDecryptionResult.forwardingCurve25519KeyChain = decryptGroupMessageResult.mForwardingCurve25519KeyChain!! + eventDecryptionResult.forwardingCurve25519KeyChain = decryptGroupMessageResult.forwardingCurve25519KeyChain!! } else if (cryptoError != null) { if (cryptoError.isOlmError) { if (TextUtils.equals("UNKNOWN_MESSAGE_INDEX", cryptoError.message)) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt index 46ebbcf9f7..d47b1b8bf3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt @@ -387,7 +387,7 @@ internal class KeysBackup( callback: MatrixCallback) { // TODO Validate with François that this is correct object : Task { - override fun execute(params: KeysVersionResult): Try { + override suspend fun execute(params: KeysVersionResult): Try { return Try { getKeysBackupTrustBg(params) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt index 2053f56e85..e63201bd4e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt @@ -30,7 +30,7 @@ internal class DefaultCreateKeysBackupVersionTask(private val roomKeysApi: RoomK : CreateKeysBackupVersionTask { - override fun execute(params: CreateKeysBackupVersionBody): Try { + override suspend fun execute(params: CreateKeysBackupVersionBody): Try { return executeRequest { apiCall = roomKeysApi.createKeysBackupVersion(params) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt index 472d88461d..34d183a17a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteBackupTask.kt @@ -32,7 +32,7 @@ internal interface DeleteBackupTask : Task { internal class DefaultDeleteBackupTask(private val roomKeysApi: RoomKeysApi) : DeleteBackupTask { - override fun execute(params: DeleteBackupTask.Params): Try { + override suspend fun execute(params: DeleteBackupTask.Params): Try { return executeRequest { apiCall = roomKeysApi.deleteBackup( params.version) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt index 01c59e8fe3..e80e160bdf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt @@ -33,7 +33,7 @@ internal interface DeleteRoomSessionDataTask : Task { + override suspend fun execute(params: DeleteRoomSessionDataTask.Params): Try { return executeRequest { apiCall = roomKeysApi.deleteRoomSessionData( params.roomId, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt index 79061f493f..25e930f427 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt @@ -32,7 +32,7 @@ internal interface DeleteRoomSessionsDataTask : Task { + override suspend fun execute(params: DeleteRoomSessionsDataTask.Params): Try { return executeRequest { apiCall = roomKeysApi.deleteRoomSessionsData( params.roomId, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteSessionsDataTask.kt index 8fbd995740..1580849ade 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/DeleteSessionsDataTask.kt @@ -31,7 +31,7 @@ internal interface DeleteSessionsDataTask : Task { + override suspend fun execute(params: DeleteSessionsDataTask.Params): Try { return executeRequest { apiCall = roomKeysApi.deleteSessionsData( params.version) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt index ff09a9399a..eb5d8899ba 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt @@ -29,7 +29,7 @@ internal class DefaultGetKeysBackupLastVersionTask(private val roomKeysApi: Room : GetKeysBackupLastVersionTask { - override fun execute(params: Unit): Try { + override suspend fun execute(params: Unit): Try { return executeRequest { apiCall = roomKeysApi.getKeysBackupLastVersion() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt index becdf7a459..209c8136b9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt @@ -29,7 +29,7 @@ internal class DefaultGetKeysBackupVersionTask(private val roomKeysApi: RoomKeys : GetKeysBackupVersionTask { - override fun execute(params: String): Try { + override suspend fun execute(params: String): Try { return executeRequest { apiCall = roomKeysApi.getKeysBackupVersion(params) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt index ef28efd419..849e37ebcf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt @@ -34,7 +34,7 @@ internal interface GetRoomSessionDataTask : Task { + override suspend fun execute(params: GetRoomSessionDataTask.Params): Try { return executeRequest { apiCall = roomKeysApi.getRoomSessionData( params.roomId, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt index 7858c687a4..e67e2bc3f7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt @@ -34,7 +34,7 @@ internal interface GetRoomSessionsDataTask : Task { + override suspend fun execute(params: GetRoomSessionsDataTask.Params): Try { return executeRequest { apiCall = roomKeysApi.getRoomSessionsData( params.roomId, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetSessionsDataTask.kt index 67b1878807..b2f3005bd6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/GetSessionsDataTask.kt @@ -32,7 +32,7 @@ internal interface GetSessionsDataTask : Task { + override suspend fun execute(params: GetSessionsDataTask.Params): Try { return executeRequest { apiCall = roomKeysApi.getSessionsData( params.version) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt index 1c81f691fe..e7452b0e15 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt @@ -36,7 +36,7 @@ internal interface StoreRoomSessionDataTask : Task { + override suspend fun execute(params: StoreRoomSessionDataTask.Params): Try { return executeRequest { apiCall = roomKeysApi.storeRoomSessionData( params.roomId, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt index 09b9c0b0e1..29ab818ddf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt @@ -35,7 +35,7 @@ internal interface StoreRoomSessionsDataTask : Task { + override suspend fun execute(params: StoreRoomSessionsDataTask.Params): Try { return executeRequest { apiCall = roomKeysApi.storeRoomSessionsData( params.roomId, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt index 736bfab007..c5b39d2dae 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt @@ -34,7 +34,7 @@ internal interface StoreSessionsDataTask : Task { + override suspend fun execute(params: StoreSessionsDataTask.Params): Try { return executeRequest { apiCall = roomKeysApi.storeSessionsData( params.version, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt index ffede6ab1b..e2605bfbaf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt @@ -34,7 +34,7 @@ internal class DefaultUpdateKeysBackupVersionTask(private val roomKeysApi: RoomK : UpdateKeysBackupVersionTask { - override fun execute(params: UpdateKeysBackupVersionTask.Params): Try { + override suspend fun execute(params: UpdateKeysBackupVersionTask.Params): Try { return executeRequest { apiCall = roomKeysApi.updateKeysBackupVersion(params.version, params.keysBackupVersionBody) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/MXDeviceInfo.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/MXDeviceInfo.kt index 28bcba6102..4d92089afa 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/MXDeviceInfo.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/MXDeviceInfo.kt @@ -69,7 +69,7 @@ data class MXDeviceInfo( /** * Verification state of this device. */ - var mVerified: Int = DEVICE_VERIFICATION_UNKNOWN + var verified: Int = DEVICE_VERIFICATION_UNKNOWN ) : Serializable { /** * Tells if the device is unknown @@ -77,7 +77,7 @@ data class MXDeviceInfo( * @return true if the device is unknown */ val isUnknown: Boolean - get() = mVerified == DEVICE_VERIFICATION_UNKNOWN + get() = verified == DEVICE_VERIFICATION_UNKNOWN /** * Tells if the device is verified. @@ -85,7 +85,7 @@ data class MXDeviceInfo( * @return true if the device is verified */ val isVerified: Boolean - get() = mVerified == DEVICE_VERIFICATION_VERIFIED + get() = verified == DEVICE_VERIFICATION_VERIFIED /** * Tells if the device is unverified. @@ -93,7 +93,7 @@ data class MXDeviceInfo( * @return true if the device is unverified */ val isUnverified: Boolean - get() = mVerified == DEVICE_VERIFICATION_UNVERIFIED + get() = verified == DEVICE_VERIFICATION_UNVERIFIED /** * Tells if the device is blocked. @@ -101,7 +101,7 @@ data class MXDeviceInfo( * @return true if the device is blocked */ val isBlocked: Boolean - get() = mVerified == DEVICE_VERIFICATION_BLOCKED + get() = verified == DEVICE_VERIFICATION_BLOCKED /** * @return the fingerprint diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt index 06e979b465..bab1211145 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt @@ -37,7 +37,7 @@ internal interface ClaimOneTimeKeysForUsersDeviceTask : Task> { + override suspend fun execute(params: ClaimOneTimeKeysForUsersDeviceTask.Params): Try> { val body = KeysClaimBody(oneTimeKeys = params.usersDevicesKeyTypesMap.map) return executeRequest { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DeleteDeviceTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DeleteDeviceTask.kt index 4630bd93a0..0fb9ad0f15 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DeleteDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DeleteDeviceTask.kt @@ -32,7 +32,7 @@ internal interface DeleteDeviceTask : Task { internal class DefaultDeleteDeviceTask(private val cryptoApi: CryptoApi) : DeleteDeviceTask { - override fun execute(params: DeleteDeviceTask.Params): Try { + override suspend fun execute(params: DeleteDeviceTask.Params): Try { return executeRequest { apiCall = cryptoApi.deleteDevice(params.deviceId, DeleteDeviceParams()) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt index 22c552b415..a8da9eab5f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt @@ -36,7 +36,7 @@ internal interface DownloadKeysForUsersTask : Task { + override suspend fun execute(params: DownloadKeysForUsersTask.Params): Try { val downloadQuery = HashMap>() if (null != params.userIds) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetDevicesTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetDevicesTask.kt index b7c706d256..7d634ab5d0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetDevicesTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetDevicesTask.kt @@ -27,7 +27,7 @@ internal interface GetDevicesTask : Task internal class DefaultGetDevicesTask(private val cryptoApi: CryptoApi) : GetDevicesTask { - override fun execute(params: Unit): Try { + override suspend fun execute(params: Unit): Try { return executeRequest { apiCall = cryptoApi.getDevices() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt index e4f9f7ae11..937607d95d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/GetKeyChangesTask.kt @@ -34,7 +34,7 @@ internal interface GetKeyChangesTask : Task { + override suspend fun execute(params: GetKeyChangesTask.Params): Try { return executeRequest { apiCall = cryptoApi.getKeyChanges(params.from, params.to) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SendToDeviceTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SendToDeviceTask.kt index c9a99f8aa3..89417b087c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SendToDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SendToDeviceTask.kt @@ -38,7 +38,7 @@ internal interface SendToDeviceTask : Task { internal class DefaultSendToDeviceTask(private val cryptoApi: CryptoApi) : SendToDeviceTask { - override fun execute(params: SendToDeviceTask.Params): Try { + override suspend fun execute(params: SendToDeviceTask.Params): Try { val sendToDeviceBody = SendToDeviceBody() sendToDeviceBody.messages = params.contentMap.map diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt index aba5b5c7f6..22daf51775 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/SetDeviceNameTask.kt @@ -35,7 +35,7 @@ internal interface SetDeviceNameTask : Task { internal class DefaultSetDeviceNameTask(private val cryptoApi: CryptoApi) : SetDeviceNameTask { - override fun execute(params: SetDeviceNameTask.Params): Try { + override suspend fun execute(params: SetDeviceNameTask.Params): Try { val body = UpdateDeviceInfoBody( displayName = if (TextUtils.isEmpty(params.deviceName)) "" else params.deviceName ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt index e985032a57..067f8ff789 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/UploadKeysTask.kt @@ -39,7 +39,7 @@ internal interface UploadKeysTask : Task { + override suspend fun execute(params: UploadKeysTask.Params): Try { val encodedDeviceId = convertToUTF8(params.deviceId) val body = KeysUploadBody() 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 2ce0005900..0f39f479a0 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 @@ -33,11 +33,18 @@ import im.vector.matrix.android.internal.crypto.MyDeviceInfoHolder import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap -import im.vector.matrix.android.internal.crypto.model.rest.* +import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationAccept +import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationCancel +import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationKey +import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationMac +import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith +import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import timber.log.Timber import java.util.* import kotlin.collections.HashMap @@ -53,6 +60,7 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia private val deviceListManager: DeviceListManager, private val setDeviceVerificationAction: SetDeviceVerificationAction, private val mSendToDeviceTask: SendToDeviceTask, + private val coroutineDispatchers: MatrixCoroutineDispatchers, private val mTaskExecutor: TaskExecutor) : VerificationTransaction.Listener, SasVerificationService { @@ -63,8 +71,7 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia // Event received from the sync fun onToDeviceEvent(event: Event) { - CryptoAsyncHelper.getDecryptBackgroundHandler().post { - // TODO We are already in a BG thread + CoroutineScope(coroutineDispatchers.crypto).launch { when (event.getClearType()) { EventType.KEY_VERIFICATION_START -> { onStartRequestReceived(event) @@ -131,8 +138,8 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia override fun markedLocallyAsManuallyVerified(userId: String, deviceID: String) { setDeviceVerificationAction.handle(MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED, - deviceID, - userId) + deviceID, + userId) listeners.forEach { try { @@ -143,7 +150,7 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia } } - private fun onStartRequestReceived(event: Event) { + private suspend fun onStartRequestReceived(event: Event) { val startReq = event.getClearContent().toModel()!! val otherUserId = event.sender @@ -199,7 +206,7 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia } else { Timber.e("## SAS onStartRequestReceived - unknown method ${startReq.method}") cancelTransaction(tid, otherUserId, startReq.fromDevice - ?: event.getSenderKey()!!, CancelCode.UnknownMethod) + ?: event.getSenderKey()!!, CancelCode.UnknownMethod) } } }, @@ -208,30 +215,24 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia }) } - private fun checkKeysAreDownloaded(otherUserId: String, - startReq: KeyVerificationStart, - success: (MXUsersDevicesMap) -> Unit, - error: () -> Unit) { - deviceListManager.downloadKeys(listOf(otherUserId), true, object : MatrixCallback> { - override fun onFailure(failure: Throwable) { - CryptoAsyncHelper.getDecryptBackgroundHandler().post { - error() - } - } - - override fun onSuccess(data: MXUsersDevicesMap) { - CryptoAsyncHelper.getDecryptBackgroundHandler().post { - if (data.getUserDeviceIds(otherUserId).contains(startReq.fromDevice)) { - success(data) - } else { - error() - } - } - } - }) + private suspend fun checkKeysAreDownloaded(otherUserId: String, + startReq: KeyVerificationStart, + success: (MXUsersDevicesMap) -> Unit, + error: () -> Unit) { + deviceListManager.downloadKeys(listOf(otherUserId), true) + .fold( + { error() }, + { + if (it != null && it.getUserDeviceIds(otherUserId).contains(startReq.fromDevice)) { + success(it) + } else { + error() + } + } + ) } - private fun onCancelReceived(event: Event) { + private suspend fun onCancelReceived(event: Event) { Timber.v("## SAS onCancelReceived") val cancelReq = event.getClearContent().toModel()!! @@ -254,7 +255,7 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia } } - private fun onAcceptReceived(event: Event) { + private suspend fun onAcceptReceived(event: Event) { val acceptReq = event.getClearContent().toModel()!! if (!acceptReq.isValid()) { @@ -278,7 +279,7 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia } - private fun onKeyReceived(event: Event) { + private suspend fun onKeyReceived(event: Event) { val keyReq = event.getClearContent().toModel()!! if (!keyReq.isValid()) { @@ -299,7 +300,7 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia } } - private fun onMacReceived(event: Event) { + private suspend fun onMacReceived(event: Event) { val macReq = event.getClearContent().toModel()!! if (!macReq.isValid()) { @@ -398,9 +399,9 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia override fun transactionUpdated(tx: VerificationTransaction) { dispatchTxUpdated(tx) if (tx is SASVerificationTransaction - && (tx.state == SasVerificationTxState.Cancelled - || tx.state == SasVerificationTxState.OnCancelled - || tx.state == SasVerificationTxState.Verified) + && (tx.state == SasVerificationTxState.Cancelled + || tx.state == SasVerificationTxState.OnCancelled + || tx.state == SasVerificationTxState.Verified) ) { //remove this.removeTransaction(tx.otherUserId, tx.transactionId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt index 4fdddf8153..f1e927f029 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/cache/RealmClearCacheTask.kt @@ -25,7 +25,7 @@ internal interface ClearCacheTask : Task internal class RealmClearCacheTask(val realmConfiguration: RealmConfiguration) : ClearCacheTask { - override fun execute(params: Unit): Try { + override suspend fun execute(params: Unit): Try { return Try { val realm = Realm.getInstance(realmConfiguration) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt index c5ef1a3583..ab826805c3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt @@ -38,7 +38,7 @@ internal class DefaultSaveFilterTask(private val sessionParams: SessionParams, private val filterRepository: FilterRepository ) : SaveFilterTask { - override fun execute(params: SaveFilterTask.Params): Try { + override suspend fun execute(params: SaveFilterTask.Params): Try { return executeRequest { // TODO auto retry apiCall = filterAPI.uploadFilter(sessionParams.credentials.userId, params.filter) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt index b49f004fc4..0785c33472 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/DefaultGetGroupDataTask.kt @@ -43,7 +43,7 @@ internal class DefaultGetGroupDataTask( private val monarchy: Monarchy ) : GetGroupDataTask { - override fun execute(params: GetGroupDataTask.Params): Try { + override suspend fun execute(params: GetGroupDataTask.Params): Try { val groupId = params.groupId return Try.monad().binding { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt index 4e931dcdad..34960493f6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt @@ -17,6 +17,7 @@ package im.vector.matrix.android.internal.session.group import android.content.Context +import androidx.work.CoroutineWorker import androidx.work.Worker import androidx.work.WorkerParameters import arrow.core.Try @@ -27,7 +28,7 @@ import org.koin.standalone.inject internal class GetGroupDataWorker(context: Context, workerParameters: WorkerParameters -) : Worker(context, workerParameters), MatrixKoinComponent { +) : CoroutineWorker(context, workerParameters), MatrixKoinComponent { @JsonClass(generateAdapter = true) internal data class Params( @@ -36,7 +37,7 @@ internal class GetGroupDataWorker(context: Context, private val getGroupDataTask by inject() - override fun doWork(): Result { + override suspend fun doWork(): Result { val params = WorkerParamsFactory.fromData(inputData) ?: return Result.failure() @@ -47,7 +48,7 @@ internal class GetGroupDataWorker(context: Context, return if (isSuccessful) Result.success() else Result.retry() } - private fun fetchGroupData(groupId: String): Try { + private suspend fun fetchGroupData(groupId: String): Try { return getGroupDataTask.execute(GetGroupDataTask.Params(groupId)) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt index b3aa137a03..45accb2ef9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/create/CreateRoomTask.kt @@ -41,7 +41,7 @@ internal class DefaultCreateRoomTask(private val roomAPI: RoomAPI, private val realmConfiguration: RealmConfiguration) : CreateRoomTask { - override fun execute(params: CreateRoomParams): Try { + override suspend fun execute(params: CreateRoomParams): Try { return executeRequest { apiCall = roomAPI.createRoom(params) }.flatMap { createRoomResponse -> diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/invite/InviteTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/invite/InviteTask.kt index 1086c6b5d9..d3a67dd2e5 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/invite/InviteTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/invite/InviteTask.kt @@ -31,7 +31,7 @@ internal interface InviteTask : Task { internal class DefaultInviteTask(private val roomAPI: RoomAPI) : InviteTask { - override fun execute(params: InviteTask.Params): Try { + override suspend fun execute(params: InviteTask.Params): Try { return executeRequest { val body = InviteBody(params.userId) apiCall = roomAPI.invite(params.roomId, body) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersTask.kt index c421b3bd3d..425f9fc1da 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersTask.kt @@ -44,7 +44,7 @@ internal class DefaultLoadRoomMembersTask(private val roomAPI: RoomAPI, private val roomSummaryUpdater: RoomSummaryUpdater ) : LoadRoomMembersTask { - override fun execute(params: LoadRoomMembersTask.Params): Try { + override suspend fun execute(params: LoadRoomMembersTask.Params): Try { return if (areAllMembersAlreadyLoaded(params.roomId)) { Try.just(true) } else { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt index fa57577c24..0592077eaf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt @@ -50,7 +50,7 @@ internal class DefaultSetReadMarkersTask(private val roomAPI: RoomAPI, private val monarchy: Monarchy ) : SetReadMarkersTask { - override fun execute(params: SetReadMarkersTask.Params): Try { + override suspend fun execute(params: SetReadMarkersTask.Params): Try { val markers = HashMap() if (params.fullyReadEventId != null && MatrixPatterns.isEventId(params.fullyReadEventId)) { markers[READ_MARKER] = params.fullyReadEventId diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt index 1d84bd9cb3..b6d3a74868 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt @@ -30,7 +30,7 @@ internal interface SendStateTask : Task { } internal class DefaultSendStateTask(private val roomAPI: RoomAPI) : SendStateTask { - override fun execute(params: SendStateTask.Params): Try { + override suspend fun execute(params: SendStateTask.Params): Try { return executeRequest { apiCall = roomAPI.sendStateEvent(params.roomId, params.eventType, params.body) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt index 4f93dc364e..5d72ac3344 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultGetContextOfEventTask.kt @@ -36,7 +36,7 @@ internal class DefaultGetContextOfEventTask(private val roomAPI: RoomAPI, private val tokenChunkEventPersistor: TokenChunkEventPersistor ) : GetContextOfEventTask { - override fun execute(params: GetContextOfEventTask.Params): Try { + override suspend fun execute(params: GetContextOfEventTask.Params): Try { val filter = filterRepository.getRoomFilter() return executeRequest { apiCall = roomAPI.getContextOfEvent(params.roomId, params.eventId, 0, filter) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultPaginationTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultPaginationTask.kt index 12c1e361fa..02a3ac3967 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultPaginationTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultPaginationTask.kt @@ -39,7 +39,7 @@ internal class DefaultPaginationTask(private val roomAPI: RoomAPI, private val tokenChunkEventPersistor: TokenChunkEventPersistor ) : PaginationTask { - override fun execute(params: PaginationTask.Params): Try { + override suspend fun execute(params: PaginationTask.Params): Try { val filter = filterRepository.getRoomFilter() return executeRequest { apiCall = roomAPI.getRoomMessagesFrom(params.roomId, params.from, params.direction.value, params.limit, filter) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt index 46d5d0ddb5..ae575d68c0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventTask.kt @@ -30,7 +30,7 @@ internal class GetEventTask(private val roomAPI: RoomAPI val eventId: String ) - override fun execute(params: Params): Try { + override suspend fun execute(params: Params): Try { return executeRequest { apiCall = roomAPI.getEvent(params.roomId, params.eventId) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt index 84cb1f2d38..5fa09b9aa7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt @@ -27,7 +27,7 @@ internal interface SignOutTask : Task internal class DefaultSignOutTask(private val signOutAPI: SignOutAPI, private val sessionParamsStore: SessionParamsStore) : SignOutTask { - override fun execute(params: Unit): Try { + override suspend fun execute(params: Unit): Try { return executeRequest { apiCall = signOutAPI.signOut() }.flatMap { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt index e24f0e0bb6..d6877e03a0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt @@ -37,7 +37,6 @@ internal class CryptoSyncHandler(private val cryptoManager: CryptoManager, toDevice.events?.forEach { event -> // Decrypt event if necessary decryptEvent(event, null) - if (TextUtils.equals(event.getClearType(), EventType.MESSAGE) && event.mClearEvent?.content?.toModel()?.type == "m.bad.encrypted") { Timber.e("## handleToDeviceEvent() : Warning: Unable to decrypt to-device event : " + event.content) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt index 9e6d65a55a..1f09f4c611 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt @@ -40,7 +40,7 @@ internal class DefaultSyncTask(private val syncAPI: SyncAPI, ) : SyncTask { - override fun execute(params: SyncTask.Params): Try { + override suspend fun execute(params: SyncTask.Params): Try { val requestParams = HashMap() var timeout = 0 if (params.token != null) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt index 4197156d9d..e2e423cde6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UpdateUserTask.kt @@ -35,7 +35,7 @@ internal interface UpdateUserTask : Task { internal class DefaultUpdateUserTask(private val monarchy: Monarchy) : UpdateUserTask { - override fun execute(params: UpdateUserTask.Params): Try { + override suspend fun execute(params: UpdateUserTask.Params): Try { return monarchy.tryTransactionSync { realm -> params.eventIds.forEach { eventId -> val event = EventEntity.where(realm, eventId).findFirst()?.asDomain() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt index d84bed2d74..153bd97c43 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt @@ -34,7 +34,7 @@ internal data class ConfigurableTask( ) : Task { - override fun execute(params: PARAMS): Try { + override suspend fun execute(params: PARAMS): Try { return task.execute(params) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/Task.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/Task.kt index 7a2184c425..81a2add8d7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/Task.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/Task.kt @@ -20,7 +20,7 @@ import arrow.core.Try internal interface Task { - fun execute(params: PARAMS): Try + suspend fun execute(params: PARAMS): Try } 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 54344d8c91..7823c076d4 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 @@ -68,8 +68,7 @@ internal class TaskExecutor(private val coroutineDispatchers: MatrixCoroutineDis TaskThread.COMPUTATION -> coroutineDispatchers.computation TaskThread.IO -> coroutineDispatchers.io TaskThread.CALLER -> EmptyCoroutineContext - TaskThread.ENCRYPTION -> coroutineDispatchers.crypto - TaskThread.DECRYPTION -> coroutineDispatchers.crypto + TaskThread.CRYPTO -> coroutineDispatchers.crypto } 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 b7cc212a46..fc0180c953 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 @@ -21,6 +21,5 @@ internal enum class TaskThread { COMPUTATION, IO, CALLER, - ENCRYPTION, - DECRYPTION + CRYPTO } \ No newline at end of file