diff --git a/CHANGES.md b/CHANGES.md index 5e9f9ce671..a8c366204e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ Bugfix 🐛: - Do not show long click help if only invitation are displayed - Fix emoji filtering not working - Fix issue of closing Realm in another thread (#725) + - Attempt to properly cancel the crypto module when user signs out (#724) Translations 🗣: - diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/file/FileService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/file/FileService.kt index e1694199ed..4d9cff3e92 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/file/FileService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/file/FileService.kt @@ -17,6 +17,7 @@ package im.vector.matrix.android.api.session.file import im.vector.matrix.android.api.MatrixCallback +import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt import java.io.File @@ -47,5 +48,5 @@ interface FileService { fileName: String, url: String?, elementToDecrypt: ElementToDecrypt?, - callback: MatrixCallback<File>) + callback: MatrixCallback<File>): Cancelable } 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 5a7e28b70f..a12f6e40ce 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 @@ -37,6 +37,8 @@ import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.cache.ClearCacheTask import im.vector.matrix.android.internal.session.cache.RealmClearCacheTask import io.realm.RealmConfiguration +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob import retrofit2.Retrofit import java.io.File @@ -66,6 +68,13 @@ internal abstract class CryptoModule { .build() } + @JvmStatic + @Provides + @SessionScope + fun providesCryptoCoroutineScope(): CoroutineScope { + return CoroutineScope(SupervisorJob()) + } + @JvmStatic @Provides @CryptoDatabase diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt index cf5506a443..c50b9e2e10 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt @@ -132,7 +132,8 @@ internal class DefaultCryptoService @Inject constructor( private val loadRoomMembersTask: LoadRoomMembersTask, private val monarchy: Monarchy, private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val taskExecutor: TaskExecutor + private val taskExecutor: TaskExecutor, + private val cryptoCoroutineScope: CoroutineScope ) : CryptoService { private val uiHandler = Handler(Looper.getMainLooper()) @@ -243,7 +244,8 @@ internal class DefaultCryptoService @Inject constructor( return } isStarting.set(true) - GlobalScope.launch(coroutineDispatchers.crypto) { + + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { internalStart(isInitialSync) } } @@ -269,10 +271,9 @@ internal class DefaultCryptoService @Inject constructor( isStarted.set(true) }, { - Timber.e("Start failed: $it") - delay(1000) isStarting.set(false) - internalStart(isInitialSync) + isStarted.set(false) + Timber.e(it, "Start failed") } ) } @@ -281,9 +282,12 @@ internal class DefaultCryptoService @Inject constructor( * Close the crypto */ fun close() = runBlocking(coroutineDispatchers.crypto) { + cryptoCoroutineScope.coroutineContext.cancelChildren(CancellationException("Closing crypto module")) + + outgoingRoomKeyRequestManager.stop() + olmDevice.release() cryptoStore.close() - outgoingRoomKeyRequestManager.stop() } // Aways enabled on RiotX @@ -305,19 +309,21 @@ internal class DefaultCryptoService @Inject constructor( * @param syncResponse the syncResponse */ fun onSyncCompleted(syncResponse: SyncResponse) { - GlobalScope.launch(coroutineDispatchers.crypto) { - 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() + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { + runCatching { + 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() + } } } } @@ -511,7 +517,7 @@ internal class DefaultCryptoService @Inject constructor( eventType: String, roomId: String, callback: MatrixCallback<MXEncryptEventContentResult>) { - GlobalScope.launch(coroutineDispatchers.crypto) { + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { if (!isStarted()) { Timber.v("## encryptEventContent() : wait after e2e init") internalStart(false) @@ -571,7 +577,7 @@ internal class DefaultCryptoService @Inject constructor( * @param callback the callback to return data or null */ override fun decryptEventAsync(event: Event, timeline: String, callback: MatrixCallback<MXEventDecryptionResult>) { - GlobalScope.launch { + cryptoCoroutineScope.launch { val result = runCatching { withContext(coroutineDispatchers.crypto) { internalDecryptEvent(event, timeline) @@ -621,7 +627,7 @@ internal class DefaultCryptoService @Inject constructor( * @param event the event */ fun onToDeviceEvent(event: Event) { - GlobalScope.launch(coroutineDispatchers.crypto) { + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { when (event.getClearType()) { EventType.ROOM_KEY, EventType.FORWARDED_ROOM_KEY -> { onRoomKeyEvent(event) @@ -661,7 +667,7 @@ internal class DefaultCryptoService @Inject constructor( * @param event the encryption event. */ private fun onRoomEncryptionEvent(roomId: String, event: Event) { - GlobalScope.launch(coroutineDispatchers.crypto) { + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { val params = LoadRoomMembersTask.Params(roomId) try { loadRoomMembersTask.execute(params) @@ -753,7 +759,7 @@ internal class DefaultCryptoService @Inject constructor( * @param callback the exported keys */ override fun exportRoomKeys(password: String, callback: MatrixCallback<ByteArray>) { - GlobalScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.main) { runCatching { exportRoomKeys(password, MXMegolmExportEncryption.DEFAULT_ITERATION_COUNT) }.foldToCallback(callback) @@ -791,7 +797,7 @@ internal class DefaultCryptoService @Inject constructor( password: String, progressListener: ProgressListener?, callback: MatrixCallback<ImportRoomKeysResult>) { - GlobalScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.main) { runCatching { withContext(coroutineDispatchers.crypto) { Timber.v("## importRoomKeys starts") @@ -839,7 +845,7 @@ internal class DefaultCryptoService @Inject constructor( */ fun checkUnknownDevices(userIds: List<String>, callback: MatrixCallback<Unit>) { // force the refresh to ensure that the devices list is up-to-date - GlobalScope.launch(coroutineDispatchers.crypto) { + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { runCatching { val keys = deviceListManager.downloadKeys(userIds, true) val unknownDevices = getUnknownDevices(keys) @@ -999,7 +1005,7 @@ internal class DefaultCryptoService @Inject constructor( } override fun downloadKeys(userIds: List<String>, forceDownload: Boolean, callback: MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>>) { - GlobalScope.launch(coroutineDispatchers.crypto) { + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { runCatching { deviceListManager.downloadKeys(userIds, forceDownload) }.foldToCallback(callback) 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 aeee025fdc..e8d8bf0f35 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 @@ -25,7 +25,6 @@ import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.session.SessionScope import timber.log.Timber import javax.inject.Inject -import kotlin.collections.ArrayList @SessionScope internal class IncomingRoomKeyRequestManager @Inject constructor( @@ -51,7 +50,7 @@ internal class IncomingRoomKeyRequestManager @Inject constructor( * * @param event the announcement event. */ - suspend fun onRoomKeyRequestEvent(event: Event) { + fun onRoomKeyRequestEvent(event: Event) { val roomKeyShare = event.getClearContent().toModel<RoomKeyShare>() when (roomKeyShare?.action) { RoomKeyShare.ACTION_SHARE_REQUEST -> receivedRoomKeyRequests.add(IncomingRoomKeyRequest(event)) @@ -139,7 +138,7 @@ internal class IncomingRoomKeyRequestManager @Inject constructor( if (null != receivedRoomKeyRequestCancellations) { for (request in receivedRoomKeyRequestCancellations!!) { Timber.v("## ## processReceivedRoomKeyRequests() : m.room_key_request cancellation for " + request.userId - + ":" + request.deviceId + " id " + request.requestId) + + ":" + request.deviceId + " id " + request.requestId) // we should probably only notify the app of cancellations we told it // about, but we don't currently have a record of that, so we just pass 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 433dee4fb9..5320b84b0e 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 @@ -63,6 +63,7 @@ internal class OutgoingRoomKeyRequestManager @Inject constructor( */ fun stop() { isClientRunning = false + stopTimer() } /** @@ -171,6 +172,10 @@ internal class OutgoingRoomKeyRequestManager @Inject constructor( }, SEND_KEY_REQUESTS_DELAY_MS.toLong()) } + private fun stopTimer() { + BACKGROUND_HANDLER.removeCallbacksAndMessages(null) + } + // look for and send any queued requests. Runs itself recursively until // there are no more requests, or there is an error (in which case, the // timer will be restarted before the promise resolves). 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 0230141e1b..81ac1403df 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 @@ -34,7 +34,7 @@ import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers -import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import timber.log.Timber @@ -46,8 +46,9 @@ internal class MXMegolmDecryption(private val userId: String, private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction, private val cryptoStore: IMXCryptoStore, private val sendToDeviceTask: SendToDeviceTask, - private val coroutineDispatchers: MatrixCoroutineDispatchers) - : IMXDecrypting { + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val cryptoCoroutineScope: CoroutineScope +) : IMXDecrypting { var newSessionListener: NewSessionListener? = null @@ -61,7 +62,7 @@ internal class MXMegolmDecryption(private val userId: String, return decryptEvent(event, timeline, true) } - private suspend fun decryptEvent(event: Event, timeline: String, requestKeysOnFail: Boolean): MXEventDecryptionResult { + private fun decryptEvent(event: Event, timeline: String, requestKeysOnFail: Boolean): MXEventDecryptionResult { if (event.roomId.isNullOrBlank()) { throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_FIELDS, MXCryptoError.MISSING_FIELDS_REASON) } @@ -292,7 +293,7 @@ internal class MXMegolmDecryption(private val userId: String, return } val userId = request.userId ?: return - GlobalScope.launch(coroutineDispatchers.crypto) { + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { runCatching { deviceListManager.downloadKeys(listOf(userId), false) } .mapCatching { val deviceId = request.deviceId diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt index b7329221ab..7cddd27779 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt @@ -25,17 +25,21 @@ import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers +import kotlinx.coroutines.CoroutineScope import javax.inject.Inject -internal class MXMegolmDecryptionFactory @Inject constructor(@UserId private val userId: String, - private val olmDevice: MXOlmDevice, - private val deviceListManager: DeviceListManager, - private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager, - private val messageEncrypter: MessageEncrypter, - private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction, - private val cryptoStore: IMXCryptoStore, - private val sendToDeviceTask: SendToDeviceTask, - private val coroutineDispatchers: MatrixCoroutineDispatchers) { +internal class MXMegolmDecryptionFactory @Inject constructor( + @UserId private val userId: String, + private val olmDevice: MXOlmDevice, + private val deviceListManager: DeviceListManager, + private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager, + private val messageEncrypter: MessageEncrypter, + private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction, + private val cryptoStore: IMXCryptoStore, + private val sendToDeviceTask: SendToDeviceTask, + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val cryptoCoroutineScope: CoroutineScope +) { fun create(): MXMegolmDecryption { return MXMegolmDecryption( @@ -47,6 +51,7 @@ internal class MXMegolmDecryptionFactory @Inject constructor(@UserId private val ensureOlmSessionsForDevicesAction, cryptoStore, sendToDeviceTask, - coroutineDispatchers) + coroutineDispatchers, + cryptoCoroutineScope) } } 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 b3ee138591..5e5291d600 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 @@ -59,7 +59,7 @@ import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.awaitCallback -import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.matrix.olm.OlmException @@ -102,7 +102,8 @@ internal class KeysBackup @Inject constructor( private val updateKeysBackupVersionTask: UpdateKeysBackupVersionTask, // Task executor private val taskExecutor: TaskExecutor, - private val coroutineDispatchers: MatrixCoroutineDispatchers + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val cryptoCoroutineScope: CoroutineScope ) : KeysBackupService { private val uiHandler = Handler(Looper.getMainLooper()) @@ -143,7 +144,7 @@ internal class KeysBackup @Inject constructor( override fun prepareKeysBackupVersion(password: String?, progressListener: ProgressListener?, callback: MatrixCallback<MegolmBackupCreationInfo>) { - GlobalScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.main) { runCatching { withContext(coroutineDispatchers.crypto) { val olmPkDecryption = OlmPkDecryption() @@ -233,7 +234,7 @@ internal class KeysBackup @Inject constructor( } override fun deleteBackup(version: String, callback: MatrixCallback<Unit>?) { - GlobalScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.main) { withContext(coroutineDispatchers.crypto) { // If we're currently backing up to this backup... stop. // (We start using it automatically in createKeysBackupVersion so this is symmetrical). @@ -448,7 +449,7 @@ internal class KeysBackup @Inject constructor( callback.onFailure(IllegalArgumentException("Missing element")) } else { - GlobalScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.main) { val updateKeysBackupVersionBody = withContext(coroutineDispatchers.crypto) { // Get current signatures, or create an empty set val myUserSignatures = authData.signatures?.get(userId)?.toMutableMap() @@ -523,7 +524,7 @@ internal class KeysBackup @Inject constructor( callback: MatrixCallback<Unit>) { Timber.v("trustKeysBackupVersionWithRecoveryKey: version ${keysBackupVersion.version}") - GlobalScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.main) { val isValid = withContext(coroutineDispatchers.crypto) { isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion) } @@ -543,7 +544,7 @@ internal class KeysBackup @Inject constructor( callback: MatrixCallback<Unit>) { Timber.v("trustKeysBackupVersionWithPassphrase: version ${keysBackupVersion.version}") - GlobalScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.main) { val recoveryKey = withContext(coroutineDispatchers.crypto) { recoveryKeyFromPassword(password, keysBackupVersion, null) } @@ -614,7 +615,7 @@ internal class KeysBackup @Inject constructor( callback: MatrixCallback<ImportRoomKeysResult>) { Timber.v("restoreKeysWithRecoveryKey: From backup version: ${keysVersionResult.version}") - GlobalScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.main) { runCatching { val decryption = withContext(coroutineDispatchers.crypto) { // Check if the recovery is valid before going any further @@ -695,7 +696,7 @@ internal class KeysBackup @Inject constructor( callback: MatrixCallback<ImportRoomKeysResult>) { Timber.v("[MXKeyBackup] restoreKeyBackup with password: From backup version: ${keysBackupVersion.version}") - GlobalScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.main) { runCatching { val progressListener = if (stepProgressListener != null) { object : ProgressListener { @@ -729,8 +730,8 @@ internal class KeysBackup @Inject constructor( * parameters and always returns a KeysBackupData object through the Callback */ private suspend fun getKeys(sessionId: String?, - roomId: String?, - version: String): KeysBackupData { + roomId: String?, + version: String): KeysBackupData { return if (roomId != null && sessionId != null) { // Get key for the room and for the session val data = getRoomSessionDataTask.execute(GetRoomSessionDataTask.Params(roomId, sessionId, version)) @@ -1154,7 +1155,7 @@ internal class KeysBackup @Inject constructor( keysBackupStateManager.state = KeysBackupState.BackingUp - GlobalScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.main) { withContext(coroutineDispatchers.crypto) { Timber.v("backupKeys: 2 - Encrypting keys") 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 fd7a5e8e7a..db05f473b1 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 @@ -53,10 +53,10 @@ internal class DefaultUploadKeysTask @Inject constructor(private val cryptoApi: } return executeRequest { - if (encodedDeviceId.isNullOrBlank()) { - apiCall = cryptoApi.uploadKeys(body) + apiCall = if (encodedDeviceId.isBlank()) { + cryptoApi.uploadKeys(body) } else { - apiCall = cryptoApi.uploadKeys(encodedDeviceId, body) + cryptoApi.uploadKeys(encodedDeviceId, body) } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt index e530bafb18..868d63665a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt @@ -22,12 +22,14 @@ import arrow.core.Try import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.content.ContentUrlResolver import im.vector.matrix.android.api.session.file.FileService +import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments import im.vector.matrix.android.internal.di.UserMd5 import im.vector.matrix.android.internal.extensions.foldToCallback import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.md5 +import im.vector.matrix.android.internal.util.toCancelable import im.vector.matrix.android.internal.util.writeToFile import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -55,8 +57,8 @@ internal class DefaultFileService @Inject constructor(private val context: Conte fileName: String, url: String?, elementToDecrypt: ElementToDecrypt?, - callback: MatrixCallback<File>) { - GlobalScope.launch(coroutineDispatchers.main) { + callback: MatrixCallback<File>): Cancelable { + return GlobalScope.launch(coroutineDispatchers.main) { withContext(coroutineDispatchers.io) { Try { val folder = getFolder(downloadMode, id) @@ -96,7 +98,7 @@ internal class DefaultFileService @Inject constructor(private val context: Conte } } .foldToCallback(callback) - } + }.toCancelable() } private fun getFolder(downloadMode: FileService.DownloadMode, id: String): File {