From de4662b9d51734e4236e7203e642a3b47aa66801 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 17 May 2019 15:05:07 +0200 Subject: [PATCH] Remove all async thread --- .../api/session/crypto/CryptoService.kt | 14 +- .../internal/crypto/CryptoAsyncHelper.kt | 1 + .../android/internal/crypto/CryptoManager.kt | 943 +++++++----------- .../internal/crypto/DeviceListManager.kt | 21 +- .../crypto/IncomingRoomKeyRequestManager.kt | 43 +- .../crypto/MXOutgoingRoomKeyRequestManager.kt | 65 +- .../algorithms/megolm/MXMegolmEncryption.kt | 228 ++--- .../crypto/store/db/RealmCryptoStore.kt | 4 - .../DefaultSasVerificationService.kt | 44 +- .../SASVerificationTransaction.kt | 28 +- .../internal/session/DefaultSession.kt | 28 +- .../VectorSettingsPreferencesFragment.kt | 41 +- 12 files changed, 558 insertions(+), 902 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt index 073aac61..7e58fafe 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt @@ -43,11 +43,11 @@ interface CryptoService { fun getKeysBackupService(): KeysBackupService - fun isRoomBlacklistUnverifiedDevices(roomId: String, callback: MatrixCallback?) + fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean fun setWarnOnUnknownDevices(warn: Boolean) - fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String, callback: MatrixCallback) + fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String) fun getUserDevices(userId: String): MutableList @@ -57,11 +57,11 @@ interface CryptoService { fun getMyDevice(): MXDeviceInfo - fun getGlobalBlacklistUnverifiedDevices(callback: MatrixCallback?) + fun getGlobalBlacklistUnverifiedDevices() : Boolean - fun setGlobalBlacklistUnverifiedDevices(block: Boolean, callback: MatrixCallback?) + fun setGlobalBlacklistUnverifiedDevices(block: Boolean) - fun setRoomUnBlacklistUnverifiedDevices(roomId: String, callback: MatrixCallback) + fun setRoomUnBlacklistUnverifiedDevices(roomId: String) fun getDeviceTrackingStatus(userId: String): Int @@ -69,9 +69,9 @@ interface CryptoService { fun exportRoomKeys(password: String, callback: MatrixCallback) - fun setRoomBlacklistUnverifiedDevices(roomId: String, callback: MatrixCallback) + fun setRoomBlacklistUnverifiedDevices(roomId: String) - fun getDeviceInfo(userId: String, deviceId: String?, callback: MatrixCallback) + fun getDeviceInfo(userId: String, deviceId: String?): MXDeviceInfo? fun reRequestRoomKeyForEvent(event: Event) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoAsyncHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoAsyncHelper.kt index 42e97d30..7e9e71ad 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoAsyncHelper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoAsyncHelper.kt @@ -25,6 +25,7 @@ import android.os.Looper private const val THREAD_ENCRYPT_NAME = "Crypto_Encrypt_Thread" private const val THREAD_DECRYPT_NAME = "Crypto_Decrypt_Thread" +// TODO Remove and replace by Task internal object CryptoAsyncHelper { private var uiHandler: Handler? = null 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 904ff9cd..89aaa974 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 @@ -20,8 +20,6 @@ package im.vector.matrix.android.internal.crypto import android.content.Context import android.os.Handler -import android.os.HandlerThread -import android.os.Looper import android.text.TextUtils import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.data.Credentials @@ -58,7 +56,6 @@ import im.vector.matrix.android.internal.util.convertToUTF8 import org.matrix.olm.OlmManager import timber.log.Timber import java.util.* -import java.util.concurrent.CountDownLatch /** * A `MXCrypto` class instance manages the end-to-end crypto for a MXSession instance. @@ -110,11 +107,10 @@ internal class CryptoManager( private val mTaskExecutor: TaskExecutor ) : KeysBackup.KeysBackupCryptoListener, DefaultSasVerificationService.SasCryptoListener, - DeviceListManager.DeviceListCryptoListener, CryptoService { // MXEncrypting instance for each room. - private val mRoomEncryptors: MutableMap + private val mRoomEncryptors: MutableMap = HashMap() // Our device keys /** @@ -128,16 +124,6 @@ internal class CryptoManager( // tell if the crypto is started private var mIsStarted: Boolean = false - // the crypto background threads - private var mEncryptingHandlerThread: HandlerThread? = null - private var mEncryptingHandler: Handler? = null - - private var mDecryptingHandlerThread: HandlerThread? = null - private var mDecryptingHandler: Handler? = null - - // the UI thread - private val mUIHandler: Handler - // TODO //private val mNetworkListener = object : IMXNetworkEventListener { // override fun onNetworkConnectionUpdate(isConnected: Boolean) { @@ -165,32 +151,6 @@ internal class CryptoManager( // Set of parameters used to configure/customize the end-to-end crypto. private var mCryptoConfig: MXCryptoConfig? = null - /** - * @return the encrypting thread handler - */ - // mEncryptingHandlerThread was not yet ready - // fail to get the handler - // might happen if the thread is not yet ready - val encryptingThreadHandler: Handler - get() { - if (null == mEncryptingHandler) { - mEncryptingHandler = Handler(mEncryptingHandlerThread!!.looper) - } - return if (null == mEncryptingHandler) { - mUIHandler - } else mEncryptingHandler!! - } - - /** - * Tells whether the client should ever send encrypted messages to unverified devices. - * The default value is false. - * This function must be called in the getEncryptingThreadHandler() thread. - * - * @return true to unilaterally blacklist all unverified devices. - */ - val globalBlacklistUnverifiedDevices: Boolean - get() = mCryptoStore.getGlobalBlacklistUnverifiedDevices() - init { if (null != cryptoConfig) { mCryptoConfig = cryptoConfig @@ -199,8 +159,6 @@ internal class CryptoManager( mCryptoConfig = MXCryptoConfig() } - mRoomEncryptors = HashMap() // TODO Merge with declaration - var deviceId = mCredentials.deviceId // deviceId should always be defined val refreshDevicesList = !TextUtils.isEmpty(deviceId) @@ -255,26 +213,14 @@ internal class CryptoManager( this.mCryptoStore.storeUserDevices(mCredentials.userId, myDevices) - mEncryptingHandlerThread = HandlerThread("MXCrypto_encrypting_" + mCredentials.userId, Thread.MIN_PRIORITY) - mEncryptingHandlerThread!!.start() - - mDecryptingHandlerThread = HandlerThread("MXCrypto_decrypting_" + mCredentials.userId, Thread.MIN_PRIORITY) - mDecryptingHandlerThread!!.start() - - mUIHandler = Handler(Looper.getMainLooper()) - if (refreshDevicesList) { // ensure to have the up-to-date devices list // got some issues when upgrading from Riot < 0.6.4 deviceListManager.handleDeviceListsChanges(listOf(mCredentials.userId), null) } - mOutgoingRoomKeyRequestManager.setWorkingHandler(encryptingThreadHandler) - mIncomingRoomKeyRequestManager.setEncryptingThreadHandler(encryptingThreadHandler) - mKeysBackup.setCryptoInternalListener(this) mSasVerificationService.setCryptoInternalListener(this) - deviceListManager.setCryptoInternalListener(this) } override fun setDeviceName(deviceId: String, deviceName: String, callback: MatrixCallback) { @@ -306,33 +252,10 @@ internal class CryptoManager( .executeBy(mTaskExecutor) } - /** - * @return the decrypting thread handler - */ - fun getDecryptingThreadHandler(): Handler { - // mDecryptingHandlerThread was not yet ready - if (null == mDecryptingHandler) { - mDecryptingHandler = Handler(mDecryptingHandlerThread!!.looper) - } - - // fail to get the handler - // might happen if the thread is not yet ready - return if (null == mDecryptingHandler) { - mUIHandler - } else mDecryptingHandler!! - } - override fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int { return mCryptoStore.inboundGroupSessionsCount(onlyBackedUp) } - /** - * @return true if this instance has been released - */ - override fun hasBeenReleased(): Boolean { - return null == mOlmDevice - } - /** * Provides the tracking status * @@ -395,114 +318,78 @@ internal class CryptoManager( // Open the store mCryptoStore.open() - encryptingThreadHandler.post { - uploadDeviceKeys(object : MatrixCallback { - private fun onError() { - mUIHandler.postDelayed({ - if (!isStarted()) { - mIsStarting = false - start(isInitialSync, null) - } - }, 1000) - } + uploadDeviceKeys(object : MatrixCallback { + private fun onError() { + Handler().postDelayed({ + if (!isStarted()) { + mIsStarting = false + start(isInitialSync, null) + } + }, 1000) + } - override fun onSuccess(data: KeysUploadResponse) { - encryptingThreadHandler.post { - if (!hasBeenReleased()) { - Timber.d("###########################################################") - Timber.d("uploadDeviceKeys done for " + mCredentials.userId) - Timber.d(" - device id : " + mCredentials.deviceId) - Timber.d(" - ed25519 : " + mOlmDevice.deviceEd25519Key) - Timber.d(" - curve25519 : " + mOlmDevice.deviceCurve25519Key) - Timber.d(" - oneTimeKeys: " + mOneTimeKeysManager.mLastPublishedOneTimeKeys) - Timber.d("") + override fun onSuccess(data: KeysUploadResponse) { + Timber.d("###########################################################") + Timber.d("uploadDeviceKeys done for " + mCredentials.userId) + Timber.d(" - device id : " + mCredentials.deviceId) + Timber.d(" - ed25519 : " + mOlmDevice.deviceEd25519Key) + Timber.d(" - curve25519 : " + mOlmDevice.deviceCurve25519Key) + Timber.d(" - oneTimeKeys: " + mOneTimeKeysManager.mLastPublishedOneTimeKeys) + Timber.d("") - encryptingThreadHandler.post { - mOneTimeKeysManager.maybeUploadOneTimeKeys(object : MatrixCallback { - override fun onSuccess(data: Unit) { - encryptingThreadHandler.post { - // TODO - //if (null != mNetworkConnectivityReceiver) { - // mNetworkConnectivityReceiver!!.removeEventListener(mNetworkListener) - //} + mOneTimeKeysManager.maybeUploadOneTimeKeys(object : MatrixCallback { + override fun onSuccess(data: Unit) { + // TODO + //if (null != mNetworkConnectivityReceiver) { + // mNetworkConnectivityReceiver!!.removeEventListener(mNetworkListener) + //} - mIsStarting = false - mIsStarted = true + mIsStarting = false + mIsStarted = true - mOutgoingRoomKeyRequestManager.start() + mOutgoingRoomKeyRequestManager.start() - mKeysBackup.checkAndStartKeysBackup() + mKeysBackup.checkAndStartKeysBackup() - synchronized(mInitializationCallbacks) { - for (callback in mInitializationCallbacks) { - mUIHandler.post { callback.onSuccess(Unit) } - } - mInitializationCallbacks.clear() - } - - if (isInitialSync) { - encryptingThreadHandler.post { - // refresh the devices list for each known room members - deviceListManager.invalidateAllDeviceLists() - deviceListManager.refreshOutdatedDeviceLists() - } - } else { - encryptingThreadHandler.post { - mIncomingRoomKeyRequestManager.processReceivedRoomKeyRequests() - - } - } - } - } - - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## start failed") - onError() - } - }) + synchronized(mInitializationCallbacks) { + for (callback in mInitializationCallbacks) { + callback.onSuccess(Unit) } + mInitializationCallbacks.clear() + } + + if (isInitialSync) { + // refresh the devices list for each known room members + deviceListManager.invalidateAllDeviceLists() + deviceListManager.refreshOutdatedDeviceLists() + } else { + mIncomingRoomKeyRequestManager.processReceivedRoomKeyRequests() } } - } - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## start failed") - onError() - } - }) - } + override fun onFailure(failure: Throwable) { + Timber.e(failure, "## start failed") + onError() + } + }) + } + + override fun onFailure(failure: Throwable) { + Timber.e(failure, "## start failed") + onError() + } + }) } /** * Close the crypto */ fun close() { - if (null != mEncryptingHandlerThread) { - encryptingThreadHandler.post { - mOlmDevice.release() + mOlmDevice.release() - // Do not reset My Device - // mMyDevice = null; + mCryptoStore.close() - mCryptoStore.close() - // Do not reset Crypto store - // mCryptoStore = null; - - if (null != mEncryptingHandlerThread) { - mEncryptingHandlerThread!!.quit() - mEncryptingHandlerThread = null - } - - mOutgoingRoomKeyRequestManager.stop() - } - - getDecryptingThreadHandler().post { - if (null != mDecryptingHandlerThread) { - mDecryptingHandlerThread!!.quit() - mDecryptingHandlerThread = null - } - } - } + mOutgoingRoomKeyRequestManager.stop() } override fun isCryptoEnabled(): Boolean { @@ -532,42 +419,24 @@ internal class CryptoManager( * @param isCatchingUp true if there is a catch-up in progress. */ fun onSyncCompleted(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean) { - encryptingThreadHandler.post { - if (null != syncResponse.deviceLists) { - deviceListManager.handleDeviceListsChanges(syncResponse.deviceLists.changed, syncResponse.deviceLists.left) - } - - if (null != syncResponse.deviceOneTimeKeysCount) { - val currentCount = syncResponse.deviceOneTimeKeysCount.signedCurve25519 ?: 0 - mOneTimeKeysManager.updateOneTimeKeyCount(currentCount) - } - - if (isStarted()) { - // Make sure we process to-device messages before generating new one-time-keys #2782 - deviceListManager.refreshOutdatedDeviceLists() - } - - if (!isCatchingUp && isStarted()) { - mOneTimeKeysManager.maybeUploadOneTimeKeys() - - mIncomingRoomKeyRequestManager.processReceivedRoomKeyRequests() - } + if (null != syncResponse.deviceLists) { + deviceListManager.handleDeviceListsChanges(syncResponse.deviceLists.changed, syncResponse.deviceLists.left) } - } - /** - * Get the stored device keys for a user. - * - * @param userId the user to list keys for. - * @param callback the asynchronous callback - */ - fun getUserDevices(userId: String, callback: MatrixCallback>?) { - encryptingThreadHandler.post { - val list = getUserDevices(userId) + if (null != syncResponse.deviceOneTimeKeysCount) { + val currentCount = syncResponse.deviceOneTimeKeysCount.signedCurve25519 ?: 0 + mOneTimeKeysManager.updateOneTimeKeyCount(currentCount) + } - if (null != callback) { - mUIHandler.post { callback.onSuccess(list) } - } + if (isStarted()) { + // Make sure we process to-device messages before generating new one-time-keys #2782 + deviceListManager.refreshOutdatedDeviceLists() + } + + if (!isCatchingUp && isStarted()) { + mOneTimeKeysManager.maybeUploadOneTimeKeys() + + mIncomingRoomKeyRequestManager.processReceivedRoomKeyRequests() } } @@ -579,16 +448,10 @@ internal class CryptoManager( * @return the device info, or null if not found / unsupported algorithm / crypto released */ override fun deviceWithIdentityKey(senderKey: String, algorithm: String): MXDeviceInfo? { - return if (!hasBeenReleased()) { - if (!TextUtils.equals(algorithm, MXCRYPTO_ALGORITHM_MEGOLM) && !TextUtils.equals(algorithm, MXCRYPTO_ALGORITHM_OLM)) { - // We only deal in olm keys - null - } else mCryptoStore.deviceWithIdentityKey(senderKey) - - // Find in the crypto store - } else null - - // The store is released + return if (!TextUtils.equals(algorithm, MXCRYPTO_ALGORITHM_MEGOLM) && !TextUtils.equals(algorithm, MXCRYPTO_ALGORITHM_OLM)) { + // We only deal in olm keys + null + } else mCryptoStore.deviceWithIdentityKey(senderKey) } /** @@ -598,17 +461,11 @@ internal class CryptoManager( * @param deviceId the device id * @param callback the asynchronous callback */ - override fun getDeviceInfo(userId: String, deviceId: String?, callback: MatrixCallback) { - getDecryptingThreadHandler().post { - val di: MXDeviceInfo? - - if (!TextUtils.isEmpty(userId) && !TextUtils.isEmpty(deviceId)) { - di = mCryptoStore.getUserDevice(deviceId!!, userId) - } else { - di = null - } - - mUIHandler.post { callback.onSuccess(di) } + override fun getDeviceInfo(userId: String, deviceId: String?): MXDeviceInfo? { + return if (!TextUtils.isEmpty(userId) && !TextUtils.isEmpty(deviceId)) { + mCryptoStore.getUserDevice(deviceId!!, userId) + } else { + null } } @@ -619,54 +476,48 @@ internal class CryptoManager( * @param callback the asynchronous callback */ override fun setDevicesKnown(devices: List, callback: MatrixCallback?) { - if (hasBeenReleased()) { - return - } - encryptingThreadHandler.post { - // build a devices map - val devicesIdListByUserId = HashMap>() + // build a devices map + val devicesIdListByUserId = HashMap>() - for (di in devices) { - var deviceIdsList: MutableList? = devicesIdListByUserId[di.userId]?.toMutableList() + for (di in devices) { + var deviceIdsList: MutableList? = devicesIdListByUserId[di.userId]?.toMutableList() - if (null == deviceIdsList) { - deviceIdsList = ArrayList() - devicesIdListByUserId[di.userId] = deviceIdsList - } - deviceIdsList.add(di.deviceId) + if (null == deviceIdsList) { + deviceIdsList = ArrayList() + devicesIdListByUserId[di.userId] = deviceIdsList } + deviceIdsList.add(di.deviceId) + } - val userIds = devicesIdListByUserId.keys + val userIds = devicesIdListByUserId.keys - for (userId in userIds) { - val storedDeviceIDs = mCryptoStore.getUserDevices(userId) + for (userId in userIds) { + val storedDeviceIDs = mCryptoStore.getUserDevices(userId) - // sanity checks - if (null != storedDeviceIDs) { - var isUpdated = false - val deviceIds = devicesIdListByUserId[userId] + // sanity checks + if (null != storedDeviceIDs) { + var isUpdated = false + val deviceIds = devicesIdListByUserId[userId] - for (deviceId in deviceIds!!) { - val device = storedDeviceIDs[deviceId] + for (deviceId in deviceIds!!) { + val device = storedDeviceIDs[deviceId] - // 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 - isUpdated = true - } - } - - if (isUpdated) { - mCryptoStore.storeUserDevices(userId, storedDeviceIDs) + // 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 + isUpdated = true } } - } - if (null != callback) { - mUIHandler.post { callback.onSuccess(Unit) } + if (isUpdated) { + mCryptoStore.storeUserDevices(userId, storedDeviceIDs) + } } } + + + callback?.onSuccess(Unit) } /** @@ -677,35 +528,26 @@ internal class CryptoManager( * @param userId the owner of the device * @param callback the asynchronous callback */ - override fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String, callback: MatrixCallback) { - if (hasBeenReleased()) { + override fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String) { + val device = mCryptoStore.getUserDevice(deviceId, userId) + + // Sanity check + if (null == device) { + Timber.w("## setDeviceVerification() : Unknown device $userId:$deviceId") return } - encryptingThreadHandler.post(Runnable { - val device = mCryptoStore.getUserDevice(deviceId, userId) + if (device.mVerified != verificationStatus) { + device.mVerified = verificationStatus + mCryptoStore.storeUserDevice(userId, device) - // Sanity check - if (null == device) { - Timber.e("## setDeviceVerification() : Unknown device $userId:$deviceId") - mUIHandler.post { callback.onSuccess(Unit) } - return@Runnable + if (userId == mCredentials.userId) { + // If one of the user's own devices is being marked as verified / unverified, + // check the key backup status, since whether or not we use this depends on + // whether it has a signature from a verified device + mKeysBackup.checkAndStartKeysBackup() } - - if (device.mVerified != verificationStatus) { - device.mVerified = verificationStatus - mCryptoStore.storeUserDevice(userId, device) - - if (userId == mCredentials.userId) { - // If one of the user's own devices is being marked as verified / unverified, - // check the key backup status, since whether or not we use this depends on - // whether it has a signature from a verified device - mKeysBackup.checkAndStartKeysBackup() - } - } - - mUIHandler.post { callback.onSuccess(Unit) } - }) + } } /** @@ -719,10 +561,6 @@ internal class CryptoManager( * @return true if the operation succeeds. */ private fun setEncryptionInRoom(roomId: String, algorithm: String?, inhibitDeviceQuery: Boolean, membersId: List): Boolean { - if (hasBeenReleased()) { - return false - } - // 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 = mCryptoStore.getRoomAlgorithm(roomId) @@ -891,9 +729,7 @@ internal class CryptoManager( } if (devicesWithoutSession.size == 0) { - if (null != callback) { - mUIHandler.post { callback.onSuccess(results) } - } + callback?.onSuccess(results) return } @@ -918,56 +754,50 @@ internal class CryptoManager( .configureWith(ClaimOneTimeKeysForUsersDeviceTask.Params(usersDevicesToClaim)) .dispatchTo(object : MatrixCallback> { override fun onSuccess(data: MXUsersDevicesMap) { - encryptingThreadHandler.post { - try { - Timber.d("## claimOneTimeKeysForUsersDevices() : keysClaimResponse.oneTimeKeys: $data") + try { + Timber.d("## claimOneTimeKeysForUsersDevices() : keysClaimResponse.oneTimeKeys: $data") - for (userId in userIds) { - val deviceInfos = devicesByUser[userId] + for (userId in userIds) { + val deviceInfos = devicesByUser[userId] - for (deviceInfo in deviceInfos!!) { + for (deviceInfo in deviceInfos!!) { - var oneTimeKey: MXKey? = null + var oneTimeKey: MXKey? = null - val deviceIds = data.getUserDeviceIds(userId) + val deviceIds = data.getUserDeviceIds(userId) - if (null != deviceIds) { - for (deviceId in deviceIds) { - val olmSessionResult = results.getObject(deviceId, userId) + if (null != deviceIds) { + for (deviceId in deviceIds) { + val olmSessionResult = results.getObject(deviceId, userId) - if (null != olmSessionResult!!.mSessionId) { - // We already have a result for this device - continue - } - - val key = data.getObject(deviceId, userId) - - if (TextUtils.equals(key!!.type, oneTimeKeyAlgorithm)) { - oneTimeKey = key - } - - if (null == oneTimeKey) { - Timber.d("## ensureOlmSessionsForDevices() : No one-time keys " + oneTimeKeyAlgorithm - + " for device " + userId + " : " + deviceId) - continue - } - - // Update the result for this device in results - olmSessionResult.mSessionId = verifyKeyAndStartSession(oneTimeKey, userId, deviceInfo) + if (null != olmSessionResult!!.mSessionId) { + // We already have a result for this device + continue } + + val key = data.getObject(deviceId, userId) + + if (TextUtils.equals(key!!.type, oneTimeKeyAlgorithm)) { + oneTimeKey = key + } + + if (null == oneTimeKey) { + Timber.d("## ensureOlmSessionsForDevices() : No one-time keys " + oneTimeKeyAlgorithm + + " for device " + userId + " : " + deviceId) + continue + } + + // Update the result for this device in results + olmSessionResult.mSessionId = verifyKeyAndStartSession(oneTimeKey, userId, deviceInfo) } } } - } catch (e: Exception) { - Timber.e(e, "## ensureOlmSessionsForDevices() " + e.message) - } - - if (!hasBeenReleased()) { - if (null != callback) { - mUIHandler.post { callback.onSuccess(results) } - } } + } catch (e: Exception) { + Timber.e(e, "## ensureOlmSessionsForDevices() " + e.message) } + + callback?.onSuccess(results) } override fun onFailure(failure: Throwable) { @@ -1060,51 +890,47 @@ internal class CryptoManager( // just as you are sending a secret message? - encryptingThreadHandler.post { - var alg: IMXEncrypting? + var alg: IMXEncrypting? - synchronized(mRoomEncryptors) { - alg = mRoomEncryptors[room.roomId] - } + synchronized(mRoomEncryptors) { + alg = mRoomEncryptors[room.roomId] + } - if (null == alg) { - val algorithm = room.encryptionAlgorithm() + if (null == alg) { + val algorithm = room.encryptionAlgorithm() - if (null != algorithm) { - if (setEncryptionInRoom(room.roomId, algorithm, false, userIds)) { - synchronized(mRoomEncryptors) { - alg = mRoomEncryptors[room.roomId] - } + if (null != algorithm) { + if (setEncryptionInRoom(room.roomId, algorithm, false, userIds)) { + synchronized(mRoomEncryptors) { + alg = mRoomEncryptors[room.roomId] } } } + } - if (null != alg) { - val t0 = System.currentTimeMillis() - Timber.d("## encryptEventContent() starts") + if (null != alg) { + val t0 = System.currentTimeMillis() + Timber.d("## encryptEventContent() starts") - alg!!.encryptEventContent(eventContent, eventType, userIds, object : MatrixCallback { - override fun onSuccess(data: Content) { - Timber.d("## encryptEventContent() : succeeds after " + (System.currentTimeMillis() - t0) + " ms") + alg!!.encryptEventContent(eventContent, eventType, userIds, object : MatrixCallback { + override fun onSuccess(data: Content) { + Timber.d("## encryptEventContent() : succeeds after " + (System.currentTimeMillis() - t0) + " ms") - callback.onSuccess(MXEncryptEventContentResult(data, EventType.ENCRYPTED)) - } - - override fun onFailure(failure: Throwable) { - callback.onFailure(failure) - } - }) - } else { - val algorithm = room.encryptionAlgorithm() - val reason = String.format(MXCryptoError.UNABLE_TO_ENCRYPT_REASON, - algorithm ?: MXCryptoError.NO_MORE_ALGORITHM_REASON) - Timber.e("## encryptEventContent() : $reason") - - mUIHandler.post { - callback.onFailure(Failure.CryptoError(MXCryptoError(MXCryptoError.UNABLE_TO_ENCRYPT_ERROR_CODE, - MXCryptoError.UNABLE_TO_ENCRYPT, reason))) + callback.onSuccess(MXEncryptEventContentResult(data, EventType.ENCRYPTED)) } - } + + override fun onFailure(failure: Throwable) { + callback.onFailure(failure) + } + }) + } else { + val algorithm = room.encryptionAlgorithm() + 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))) } } @@ -1125,36 +951,26 @@ internal class CryptoManager( } val results = ArrayList() - val lock = CountDownLatch(1) val exceptions = ArrayList() - getDecryptingThreadHandler().post { - var result: MXEventDecryptionResult? = null - val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(this, event.roomId, eventContent["algorithm"] as String) + var result: MXEventDecryptionResult? = null + val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(this, event.roomId, eventContent["algorithm"] as String) - if (null == alg) { - 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))) - } else { - try { - result = alg.decryptEvent(event, timeline) - } catch (decryptionException: MXDecryptionException) { - exceptions.add(decryptionException) - } - - if (null != result) { - results.add(result) - } + if (null == alg) { + 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))) + } else { + try { + result = alg.decryptEvent(event, timeline) + } catch (decryptionException: MXDecryptionException) { + exceptions.add(decryptionException) } - lock.countDown() - } - try { - lock.await() - } catch (e: Exception) { - Timber.e(e, "## decryptEvent() : failed") + if (null != result) { + results.add(result) + } } if (!exceptions.isEmpty()) { @@ -1164,7 +980,6 @@ internal class CryptoManager( return if (!results.isEmpty()) { results[0] } else null - } /** @@ -1173,7 +988,7 @@ internal class CryptoManager( * @param timelineId the timeline id */ fun resetReplayAttackCheckInTimeline(timelineId: String) { - getDecryptingThreadHandler().post { mOlmDevice.resetReplayAttackCheckInTimeline(timelineId) } + mOlmDevice.resetReplayAttackCheckInTimeline(timelineId) } /** @@ -1185,11 +1000,6 @@ internal class CryptoManager( * @return the content for an m.room.encrypted event. */ fun encryptMessage(payloadFields: Map, deviceInfos: List): EncryptedMessage { - if (hasBeenReleased()) { - // Empty object - return EncryptedMessage() - } - val deviceInfoParticipantKey = HashMap() val participantKeys = ArrayList() @@ -1254,13 +1064,9 @@ internal class CryptoManager( */ fun onToDeviceEvent(event: Event) { if (event.type == EventType.ROOM_KEY || event.type == EventType.FORWARDED_ROOM_KEY) { - getDecryptingThreadHandler().post { - onRoomKeyEvent(event) - } + onRoomKeyEvent(event) } else if (event.type == EventType.ROOM_KEY_REQUEST) { - encryptingThreadHandler.post { - mIncomingRoomKeyRequestManager.onRoomKeyRequestEvent(event) - } + mIncomingRoomKeyRequestManager.onRoomKeyRequestEvent(event) } } @@ -1314,7 +1120,7 @@ internal class CryptoManager( room.getJoinedRoomMemberIds() } - encryptingThreadHandler.post { setEncryptionInRoom(roomId, eventContent!!["algorithm"] as String, true, userIds) } + setEncryptionInRoom(roomId, eventContent!!["algorithm"] as String, true, userIds) } /** @@ -1342,20 +1148,18 @@ internal class CryptoManager( if (null != roomMember) { val membership = roomMember.membership - encryptingThreadHandler.post { - if (membership == Membership.JOIN) { - // make sure we are tracking the deviceList for this user. - deviceListManager.startTrackingDeviceList(Arrays.asList(userId)) - } else if (membership == Membership.INVITE - && room.shouldEncryptForInvitedMembers() - && mCryptoConfig!!.mEnableEncryptionForInvitedMembers) { - // track the deviceList for this invited user. - // Caution: there's a big edge case here in that federated servers do not - // know what other servers are in the room at the time they've been invited. - // They therefore will not send device updates if a user logs in whilst - // their state is invite. - deviceListManager.startTrackingDeviceList(Arrays.asList(userId)) - } + if (membership == Membership.JOIN) { + // make sure we are tracking the deviceList for this user. + deviceListManager.startTrackingDeviceList(Arrays.asList(userId)) + } else if (membership == Membership.INVITE + && room.shouldEncryptForInvitedMembers() + && mCryptoConfig!!.mEnableEncryptionForInvitedMembers) { + // track the deviceList for this invited user. + // Caution: there's a big edge case here in that federated servers do not + // know what other servers are in the room at the time they've been invited. + // They therefore will not send device updates if a user logs in whilst + // their state is invite. + deviceListManager.startTrackingDeviceList(Arrays.asList(userId)) } } } @@ -1402,34 +1206,32 @@ internal class CryptoManager( fun exportRoomKeys(password: String, anIterationCount: Int, callback: MatrixCallback) { val iterationCount = Math.max(0, anIterationCount) - getDecryptingThreadHandler().post(Runnable { - val exportedSessions = ArrayList() + val exportedSessions = ArrayList() - val inboundGroupSessions = mCryptoStore.getInboundGroupSessions() + val inboundGroupSessions = mCryptoStore.getInboundGroupSessions() - for (session in inboundGroupSessions) { - val megolmSessionData = session.exportKeys() + for (session in inboundGroupSessions) { + val megolmSessionData = session.exportKeys() - if (null != megolmSessionData) { - exportedSessions.add(megolmSessionData) - } + if (null != megolmSessionData) { + exportedSessions.add(megolmSessionData) } + } - val encryptedRoomKeys: ByteArray + val encryptedRoomKeys: ByteArray - try { - val moshi = MoshiProvider.providesMoshi() - val adapter = moshi.adapter(List::class.java) + try { + val moshi = MoshiProvider.providesMoshi() + val adapter = moshi.adapter(List::class.java) - encryptedRoomKeys = MXMegolmExportEncryption - .encryptMegolmKeyFile(adapter.toJson(exportedSessions), password, iterationCount) - } catch (e: Exception) { - callback.onFailure(e) - return@Runnable - } + encryptedRoomKeys = MXMegolmExportEncryption + .encryptMegolmKeyFile(adapter.toJson(exportedSessions), password, iterationCount) + } catch (e: Exception) { + callback.onFailure(e) + return + } - mUIHandler.post { callback.onSuccess(encryptedRoomKeys) } - }) + callback.onSuccess(encryptedRoomKeys) } /** @@ -1444,42 +1246,40 @@ internal class CryptoManager( password: String, progressListener: ProgressListener?, callback: MatrixCallback) { - getDecryptingThreadHandler().post(Runnable { - Timber.d("## importRoomKeys starts") + Timber.d("## importRoomKeys starts") - val t0 = System.currentTimeMillis() - val roomKeys: String + val t0 = System.currentTimeMillis() + val roomKeys: String - try { - roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password) - } catch (e: Exception) { - mUIHandler.post { callback.onFailure(e) } - return@Runnable - } + try { + roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password) + } catch (e: Exception) { + callback.onFailure(e) + return + } - val importedSessions: List + val importedSessions: List - val t1 = System.currentTimeMillis() + val t1 = System.currentTimeMillis() - Timber.d("## importRoomKeys : decryptMegolmKeyFile done in " + (t1 - t0) + " ms") + Timber.d("## importRoomKeys : decryptMegolmKeyFile done in " + (t1 - t0) + " ms") - try { - val moshi = MoshiProvider.providesMoshi() - val adapter = moshi.adapter(List::class.java) - val list = adapter.fromJson(roomKeys) - importedSessions = list as List - } catch (e: Exception) { - Timber.e(e, "## importRoomKeys failed") - mUIHandler.post { callback.onFailure(e) } - return@Runnable - } + try { + val moshi = MoshiProvider.providesMoshi() + val adapter = moshi.adapter(List::class.java) + val list = adapter.fromJson(roomKeys) + importedSessions = list as List + } catch (e: Exception) { + Timber.e(e, "## importRoomKeys failed") + callback.onFailure(e) + return + } - val t2 = System.currentTimeMillis() + val t2 = System.currentTimeMillis() - Timber.d("## importRoomKeys : JSON parsing " + (t2 - t1) + " ms") + Timber.d("## importRoomKeys : JSON parsing " + (t2 - t1) + " ms") - importMegolmSessionsData(importedSessions, true, progressListener, callback) - }) + importMegolmSessionsData(importedSessions, true, progressListener, callback) } /** @@ -1494,76 +1294,74 @@ internal class CryptoManager( backUpKeys: Boolean, progressListener: ProgressListener?, callback: MatrixCallback) { - getDecryptingThreadHandler().post { - val t0 = System.currentTimeMillis() + val t0 = System.currentTimeMillis() - val totalNumbersOfKeys = megolmSessionsData.size - var cpt = 0 - var lastProgress = 0 - var totalNumbersOfImportedKeys = 0 + val totalNumbersOfKeys = megolmSessionsData.size + var cpt = 0 + var lastProgress = 0 + var totalNumbersOfImportedKeys = 0 + + if (progressListener != null) { + progressListener.onProgress(0, 100) + } + + val sessions = mOlmDevice.importInboundGroupSessions(megolmSessionsData) + + for (megolmSessionData in megolmSessionsData) { + cpt++ + + + val decrypting = roomDecryptorProvider.getOrCreateRoomDecryptor(this, megolmSessionData.roomId, megolmSessionData.algorithm) + + if (null != decrypting) { + try { + val sessionId = megolmSessionData.sessionId + Timber.d("## importRoomKeys retrieve mSenderKey " + megolmSessionData.senderKey + " sessionId " + sessionId) + + totalNumbersOfImportedKeys++ + + // cancel any outstanding room key requests for this session + val roomKeyRequestBody = RoomKeyRequestBody() + + roomKeyRequestBody.algorithm = megolmSessionData.algorithm + roomKeyRequestBody.roomId = megolmSessionData.roomId + roomKeyRequestBody.senderKey = megolmSessionData.senderKey + roomKeyRequestBody.sessionId = megolmSessionData.sessionId + + cancelRoomKeyRequest(roomKeyRequestBody) + + // Have another go at decrypting events sent with this session + decrypting.onNewSession(megolmSessionData.senderKey!!, sessionId!!) + } catch (e: Exception) { + Timber.e(e, "## importRoomKeys() : onNewSession failed") + } + } if (progressListener != null) { - mUIHandler.post { progressListener.onProgress(0, 100) } - } + val progress = 100 * cpt / totalNumbersOfKeys - val sessions = mOlmDevice.importInboundGroupSessions(megolmSessionsData) + if (lastProgress != progress) { + lastProgress = progress - for (megolmSessionData in megolmSessionsData) { - cpt++ - - - val decrypting = roomDecryptorProvider.getOrCreateRoomDecryptor(this, megolmSessionData.roomId, megolmSessionData.algorithm) - - if (null != decrypting) { - try { - val sessionId = megolmSessionData.sessionId - Timber.d("## importRoomKeys retrieve mSenderKey " + megolmSessionData.senderKey + " sessionId " + sessionId) - - totalNumbersOfImportedKeys++ - - // cancel any outstanding room key requests for this session - val roomKeyRequestBody = RoomKeyRequestBody() - - roomKeyRequestBody.algorithm = megolmSessionData.algorithm - roomKeyRequestBody.roomId = megolmSessionData.roomId - roomKeyRequestBody.senderKey = megolmSessionData.senderKey - roomKeyRequestBody.sessionId = megolmSessionData.sessionId - - cancelRoomKeyRequest(roomKeyRequestBody) - - // Have another go at decrypting events sent with this session - decrypting.onNewSession(megolmSessionData.senderKey!!, sessionId!!) - } catch (e: Exception) { - Timber.e(e, "## importRoomKeys() : onNewSession failed") - } - } - - if (progressListener != null) { - val progress = 100 * cpt / totalNumbersOfKeys - - if (lastProgress != progress) { - lastProgress = progress - - mUIHandler.post { progressListener.onProgress(progress, 100) } - } + progressListener.onProgress(progress, 100) } } - - // Do not back up the key if it comes from a backup recovery - if (backUpKeys) { - mKeysBackup.maybeBackupKeys() - } else { - mCryptoStore.markBackupDoneForInboundGroupSessions(sessions) - } - - val t1 = System.currentTimeMillis() - - Timber.d("## importMegolmSessionsData : sessions import " + (t1 - t0) + " ms (" + megolmSessionsData.size + " sessions)") - - val finalTotalNumbersOfImportedKeys = totalNumbersOfImportedKeys - - mUIHandler.post { callback.onSuccess(ImportRoomKeysResult(totalNumbersOfKeys, finalTotalNumbersOfImportedKeys)) } } + + // Do not back up the key if it comes from a backup recovery + if (backUpKeys) { + mKeysBackup.maybeBackupKeys() + } else { + mCryptoStore.markBackupDoneForInboundGroupSessions(sessions) + } + + val t1 = System.currentTimeMillis() + + Timber.d("## importMegolmSessionsData : sessions import " + (t1 - t0) + " ms (" + megolmSessionsData.size + " sessions)") + + val finalTotalNumbersOfImportedKeys = totalNumbersOfImportedKeys + + callback.onSuccess(ImportRoomKeysResult(totalNumbersOfKeys, finalTotalNumbersOfImportedKeys)) } /** @@ -1621,44 +1419,31 @@ internal class CryptoManager( * If true, it overrides the per-room settings. * * @param block true to unilaterally blacklist all - * @param callback the asynchronous callback. */ - override fun setGlobalBlacklistUnverifiedDevices(block: Boolean, callback: MatrixCallback?) { - encryptingThreadHandler.post { - mCryptoStore.setGlobalBlacklistUnverifiedDevices(block) - mUIHandler.post { - callback?.onSuccess(Unit) - } - } + override fun setGlobalBlacklistUnverifiedDevices(block: Boolean) { + mCryptoStore.setGlobalBlacklistUnverifiedDevices(block) } /** * Tells whether the client should ever send encrypted messages to unverified devices. * The default value is false. - * messages to unverified devices. + * This function must be called in the getEncryptingThreadHandler() thread. * - * @param callback the asynchronous callback + * @return true to unilaterally blacklist all unverified devices. */ - override fun getGlobalBlacklistUnverifiedDevices(callback: MatrixCallback?) { - encryptingThreadHandler.post { - if (null != callback) { - val status = globalBlacklistUnverifiedDevices - - mUIHandler.post { callback.onSuccess(status) } - } - } + override fun getGlobalBlacklistUnverifiedDevices(): Boolean { + return mCryptoStore.getGlobalBlacklistUnverifiedDevices() } /** * Tells whether the client should encrypt messages only for the verified devices * in this room. * The default value is false. - * This function must be called in the getEncryptingThreadHandler() thread. * * @param roomId the room id * @return true if the client should encrypt messages only for the verified devices. */ - fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean { + override fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean { return if (null != roomId) { mCryptoStore.getRoomsListBlacklistUnverifiedDevices().contains(roomId) } else { @@ -1666,59 +1451,31 @@ internal class CryptoManager( } } - /** - * Tells whether the client should encrypt messages only for the verified devices - * in this room. - * The default value is false. - * This function must be called in the getEncryptingThreadHandler() thread. - * - * @param roomId the room id - * @param callback the asynchronous callback - */ - override fun isRoomBlacklistUnverifiedDevices(roomId: String, callback: MatrixCallback?) { - encryptingThreadHandler.post { - val status = isRoomBlacklistUnverifiedDevices(roomId) - - mUIHandler.post { - callback?.onSuccess(status) - } - } - } - /** * Manages the room black-listing for unverified devices. * * @param roomId the room id * @param add true to add the room id to the list, false to remove it. - * @param callback the asynchronous callback */ - private fun setRoomBlacklistUnverifiedDevices(roomId: String, add: Boolean, callback: MatrixCallback?) { + private fun setRoomBlacklistUnverifiedDevices(roomId: String, add: Boolean) { val room = mRoomService.getRoom(roomId) // sanity check if (null == room) { - mUIHandler.post { callback!!.onSuccess(Unit) } - return } - encryptingThreadHandler.post { - val roomIds = mCryptoStore.getRoomsListBlacklistUnverifiedDevices().toMutableList() + val roomIds = mCryptoStore.getRoomsListBlacklistUnverifiedDevices().toMutableList() - if (add) { - if (!roomIds.contains(roomId)) { - roomIds.add(roomId) - } - } else { - roomIds.remove(roomId) - } - - mCryptoStore.setRoomsListBlacklistUnverifiedDevices(roomIds) - - mUIHandler.post { - callback?.onSuccess(Unit) + if (add) { + if (!roomIds.contains(roomId)) { + roomIds.add(roomId) } + } else { + roomIds.remove(roomId) } + + mCryptoStore.setRoomsListBlacklistUnverifiedDevices(roomIds) } @@ -1728,8 +1485,8 @@ internal class CryptoManager( * @param roomId the room id * @param callback the asynchronous callback */ - override fun setRoomBlacklistUnverifiedDevices(roomId: String, callback: MatrixCallback) { - setRoomBlacklistUnverifiedDevices(roomId, true, callback) + override fun setRoomBlacklistUnverifiedDevices(roomId: String) { + setRoomBlacklistUnverifiedDevices(roomId, true) } /** @@ -1738,8 +1495,8 @@ internal class CryptoManager( * @param roomId the room id * @param callback the asynchronous callback */ - override fun setRoomUnBlacklistUnverifiedDevices(roomId: String, callback: MatrixCallback) { - setRoomBlacklistUnverifiedDevices(roomId, false, callback) + override fun setRoomUnBlacklistUnverifiedDevices(roomId: String) { + setRoomBlacklistUnverifiedDevices(roomId, false) } /** @@ -1749,7 +1506,7 @@ internal class CryptoManager( * @param recipients recipients */ fun requestRoomKey(requestBody: RoomKeyRequestBody, recipients: List>) { - encryptingThreadHandler.post { mOutgoingRoomKeyRequestManager.sendRoomKeyRequest(requestBody, recipients) } + mOutgoingRoomKeyRequestManager.sendRoomKeyRequest(requestBody, recipients) } /** @@ -1758,7 +1515,7 @@ internal class CryptoManager( * @param requestBody requestBody */ override fun cancelRoomKeyRequest(requestBody: RoomKeyRequestBody) { - encryptingThreadHandler.post { mOutgoingRoomKeyRequestManager.cancelRoomKeyRequest(requestBody) } + mOutgoingRoomKeyRequestManager.cancelRoomKeyRequest(requestBody) } /** @@ -1773,16 +1530,14 @@ internal class CryptoManager( val senderKey = wireContent["sender_key"].toString() val sessionId = wireContent["session_id"].toString() - encryptingThreadHandler.post { - val requestBody = RoomKeyRequestBody() + val requestBody = RoomKeyRequestBody() - requestBody.roomId = event.roomId - requestBody.algorithm = algorithm - requestBody.senderKey = senderKey - requestBody.sessionId = sessionId + requestBody.roomId = event.roomId + requestBody.algorithm = algorithm + requestBody.senderKey = senderKey + requestBody.sessionId = sessionId - mOutgoingRoomKeyRequestManager.resendRoomKeyRequest(requestBody) - } + mOutgoingRoomKeyRequestManager.resendRoomKeyRequest(requestBody) } /** 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 e6201217..06c9804e 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 @@ -55,9 +55,6 @@ internal class DeviceListManager(private val mCryptoStore: IMXCryptoStore, // tells if there is a download keys request in progress private var mIsDownloadingKeys = false - // Internal listener - private lateinit var mCryptoListener: DeviceListCryptoListener - /** * Creator * @@ -330,13 +327,12 @@ internal class DeviceListManager(private val mCryptoStore: IMXCryptoStore, } } - if (!mCryptoListener.hasBeenReleased()) { - val callback = promise.mCallback + val callback = promise.mCallback - if (null != callback) { - CryptoAsyncHelper.getUiHandler().post { callback.onSuccess(usersDevicesInfoMap) } - } + if (null != callback) { + CryptoAsyncHelper.getUiHandler().post { callback.onSuccess(usersDevicesInfoMap) } } + promisesToRemove.add(promise) } } @@ -703,15 +699,6 @@ internal class DeviceListManager(private val mCryptoStore: IMXCryptoStore, }) } - fun setCryptoInternalListener(listener: DeviceListCryptoListener) { - mCryptoListener = listener - } - - - interface DeviceListCryptoListener { - fun hasBeenReleased(): Boolean - } - 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 d70e103b..d3b81731 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 @@ -16,21 +16,20 @@ package im.vector.matrix.android.internal.crypto -import android.os.Handler import android.text.TextUtils import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.session.crypto.keyshare.RoomKeysRequestListener import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.toModel -import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyShare +import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import timber.log.Timber import java.util.* internal class IncomingRoomKeyRequestManager( - val mCredentials: Credentials, - val mCryptoStore: IMXCryptoStore, - val mRoomDecryptorProvider: RoomDecryptorProvider) { + private val mCredentials: Credentials, + private val mCryptoStore: IMXCryptoStore, + private val mRoomDecryptorProvider: RoomDecryptorProvider) { // list of IncomingRoomKeyRequests/IncomingRoomKeyRequestCancellations @@ -39,7 +38,7 @@ internal class IncomingRoomKeyRequestManager( private val mReceivedRoomKeyRequestCancellations = ArrayList() // the listeners - val mRoomKeysRequestListeners: MutableSet = HashSet() + val mRoomKeysRequestListeners: MutableSet = HashSet() init { mReceivedRoomKeyRequests.addAll(mCryptoStore.getPendingIncomingRoomKeyRequests()) @@ -52,27 +51,19 @@ internal class IncomingRoomKeyRequestManager( * @param event the announcement event. */ fun onRoomKeyRequestEvent(event: Event) { - val roomKeyShare = event.content.toModel()!! + val roomKeyShare = event.content.toModel() - if (null != roomKeyShare.action) { - when (roomKeyShare.action) { - RoomKeyShare.ACTION_SHARE_REQUEST -> synchronized(mReceivedRoomKeyRequests) { - mReceivedRoomKeyRequests.add(IncomingRoomKeyRequest(event)) - } - RoomKeyShare.ACTION_SHARE_CANCELLATION -> synchronized(mReceivedRoomKeyRequestCancellations) { - mReceivedRoomKeyRequestCancellations.add(IncomingRoomKeyRequestCancellation(event)) - } - else -> Timber.e("## onRoomKeyRequestEvent() : unsupported action " + roomKeyShare.action!!) + when (roomKeyShare?.action) { + RoomKeyShare.ACTION_SHARE_REQUEST -> synchronized(mReceivedRoomKeyRequests) { + mReceivedRoomKeyRequests.add(IncomingRoomKeyRequest(event)) } + RoomKeyShare.ACTION_SHARE_CANCELLATION -> synchronized(mReceivedRoomKeyRequestCancellations) { + mReceivedRoomKeyRequestCancellations.add(IncomingRoomKeyRequestCancellation(event)) + } + else -> Timber.e("## onRoomKeyRequestEvent() : unsupported action " + roomKeyShare?.action) } } - private lateinit var encryptingThreadHandler: Handler - - fun setEncryptingThreadHandler(encryptingThreadHandler: Handler) { - this.encryptingThreadHandler = encryptingThreadHandler - } - /** * Process any m.room_key_request events which were queued up during the * current sync. @@ -129,13 +120,11 @@ internal class IncomingRoomKeyRequestManager( } request.mShare = Runnable { - encryptingThreadHandler.post { - decryptor.shareKeysWithDevice(request) - mCryptoStore.deleteIncomingRoomKeyRequest(request) - } + decryptor.shareKeysWithDevice(request) + mCryptoStore.deleteIncomingRoomKeyRequest(request) } - request.mIgnore = Runnable { encryptingThreadHandler.post { mCryptoStore.deleteIncomingRoomKeyRequest(request) } } + request.mIgnore = Runnable { mCryptoStore.deleteIncomingRoomKeyRequest(request) } // if the device is verified already, share the keys val device = mCryptoStore.getUserDevice(deviceId!!, userId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOutgoingRoomKeyRequestManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOutgoingRoomKeyRequestManager.kt index a56f2cb6..ce186c44 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOutgoingRoomKeyRequestManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOutgoingRoomKeyRequestManager.kt @@ -20,11 +20,11 @@ package im.vector.matrix.android.internal.crypto import android.os.Handler import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.events.model.EventType -import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyShareCancellation 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.configureWith @@ -36,9 +36,6 @@ internal class MXOutgoingRoomKeyRequestManager( private val mSendToDeviceTask: SendToDeviceTask, private val mTaskExecutor: TaskExecutor) { - // working handler (should not be the UI thread) - private lateinit var mWorkingHandler: Handler - // running var mClientRunning: Boolean = false @@ -49,10 +46,6 @@ internal class MXOutgoingRoomKeyRequestManager( // of mSendOutgoingRoomKeyRequestsTimer private var mSendOutgoingRoomKeyRequestsRunning: Boolean = false - fun setWorkingHandler(encryptingThreadHandler: Handler) { - mWorkingHandler = encryptingThreadHandler - } - /** * Called when the client is started. Sets background processes running. */ @@ -90,14 +83,12 @@ internal class MXOutgoingRoomKeyRequestManager( * @param recipients recipients */ fun sendRoomKeyRequest(requestBody: RoomKeyRequestBody?, recipients: List>) { - mWorkingHandler.post { - val req = mCryptoStore.getOrAddOutgoingRoomKeyRequest( - OutgoingRoomKeyRequest(requestBody, recipients, makeTxnId(), OutgoingRoomKeyRequest.RequestState.UNSENT)) + val req = mCryptoStore.getOrAddOutgoingRoomKeyRequest( + OutgoingRoomKeyRequest(requestBody, recipients, makeTxnId(), OutgoingRoomKeyRequest.RequestState.UNSENT)) - if (req!!.mState === OutgoingRoomKeyRequest.RequestState.UNSENT) { - startTimer() - } + if (req!!.mState === OutgoingRoomKeyRequest.RequestState.UNSENT) { + startTimer() } } @@ -154,21 +145,19 @@ internal class MXOutgoingRoomKeyRequestManager( * Start the background timer to send queued requests, if the timer isn't already running. */ private fun startTimer() { - mWorkingHandler.post(Runnable { + if (mSendOutgoingRoomKeyRequestsRunning) { + return + } + + Handler().postDelayed(Runnable { if (mSendOutgoingRoomKeyRequestsRunning) { + Timber.d("## startTimer() : RoomKeyRequestSend already in progress!") return@Runnable } - mWorkingHandler.postDelayed(Runnable { - if (mSendOutgoingRoomKeyRequestsRunning) { - Timber.d("## startTimer() : RoomKeyRequestSend already in progress!") - return@Runnable - } - - mSendOutgoingRoomKeyRequestsRunning = true - sendOutgoingRoomKeyRequests() - }, SEND_KEY_REQUESTS_DELAY_MS.toLong()) - }) + mSendOutgoingRoomKeyRequestsRunning = true + sendOutgoingRoomKeyRequests() + }, SEND_KEY_REQUESTS_DELAY_MS.toLong()) } // look for and send any queued requests. Runs itself recursively until @@ -215,17 +204,15 @@ internal class MXOutgoingRoomKeyRequestManager( sendMessageToDevices(requestMessage, request.mRecipients, request.mRequestId, object : MatrixCallback { private fun onDone(state: OutgoingRoomKeyRequest.RequestState) { - mWorkingHandler.post { - if (request.mState !== OutgoingRoomKeyRequest.RequestState.UNSENT) { - Timber.d("## sendOutgoingRoomKeyRequest() : Cannot update room key request from UNSENT as it was already updated to " + request.mState) - } else { - request.mState = state - mCryptoStore.updateOutgoingRoomKeyRequest(request) - } - - mSendOutgoingRoomKeyRequestsRunning = false - startTimer() + if (request.mState !== OutgoingRoomKeyRequest.RequestState.UNSENT) { + Timber.d("## sendOutgoingRoomKeyRequest() : Cannot update room key request from UNSENT as it was already updated to " + request.mState) + } else { + request.mState = state + mCryptoStore.updateOutgoingRoomKeyRequest(request) } + + mSendOutgoingRoomKeyRequestsRunning = false + startTimer() } override fun onSuccess(data: Unit) { @@ -256,11 +243,9 @@ internal class MXOutgoingRoomKeyRequestManager( sendMessageToDevices(roomKeyShareCancellation, request.mRecipients, request.mCancellationTxnId, object : MatrixCallback { private fun onDone() { - mWorkingHandler.post { - mCryptoStore.deleteOutgoingRoomKeyRequest(request.mRequestId) - mSendOutgoingRoomKeyRequestsRunning = false - startTimer() - } + mCryptoStore.deleteOutgoingRoomKeyRequest(request.mRequestId) + mSendOutgoingRoomKeyRequestsRunning = false + startTimer() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt index 7b596fa7..e598f6a3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt @@ -154,10 +154,8 @@ internal class MXMegolmEncryption : IMXEncrypting { override fun onSuccess(devicesInRoom: MXUsersDevicesMap) { ensureOutboundSession(devicesInRoom, object : MatrixCallback { override fun onSuccess(data: MXOutboundSessionInfo) { - mCrypto!!.encryptingThreadHandler.post { - Timber.d("## encryptEventContent () processPendingEncryptions after " + (System.currentTimeMillis() - t0) + "ms") - processPendingEncryptions(data) - } + Timber.d("## encryptEventContent () processPendingEncryptions after " + (System.currentTimeMillis() - t0) + "ms") + processPendingEncryptions(data) } override fun onFailure(failure: Throwable) { @@ -178,12 +176,12 @@ internal class MXMegolmEncryption : IMXEncrypting { * @return the session description */ private fun prepareNewSessionInRoom(): MXOutboundSessionInfo { - val sessionId = olmDevice!!.createOutboundGroupSession() + val sessionId = olmDevice.createOutboundGroupSession() val keysClaimedMap = HashMap() keysClaimedMap["ed25519"] = olmDevice.deviceEd25519Key!! - olmDevice.addInboundGroupSession(sessionId!!, olmDevice.getSessionKey(sessionId)!!, mRoomId!!, olmDevice.deviceCurve25519Key!!, + olmDevice.addInboundGroupSession(sessionId!!, olmDevice.getSessionKey(sessionId)!!, mRoomId, olmDevice.deviceCurve25519Key!!, ArrayList(), keysClaimedMap, false) mKeysBackup.maybeBackupKeys() @@ -296,12 +294,10 @@ internal class MXMegolmEncryption : IMXEncrypting { Timber.d("## shareKey() ; userId $userIds") shareUserDevicesKey(session, subMap, object : MatrixCallback { override fun onSuccess(data: Unit) { - mCrypto!!.encryptingThreadHandler.post { - for (userId in userIds) { - devicesByUsers.remove(userId) - } - shareKey(session, devicesByUsers, callback) + for (userId in userIds) { + devicesByUsers.remove(userId) } + shareKey(session, devicesByUsers, callback) } override fun onFailure(failure: Throwable) { @@ -326,7 +322,7 @@ internal class MXMegolmEncryption : IMXEncrypting { val submap = HashMap() submap["algorithm"] = MXCRYPTO_ALGORITHM_MEGOLM - submap["room_id"] = mRoomId!! + submap["room_id"] = mRoomId submap["session_id"] = session.mSessionId submap["session_key"] = sessionKey!! submap["chain_index"] = chainIndex @@ -338,88 +334,84 @@ internal class MXMegolmEncryption : IMXEncrypting { val t0 = System.currentTimeMillis() Timber.d("## shareUserDevicesKey() : starts") - mCrypto!!.ensureOlmSessionsForDevices(devicesByUser, object : MatrixCallback> { - override fun onSuccess(results: MXUsersDevicesMap) { - mCrypto!!.encryptingThreadHandler.post { - Timber.d("## shareUserDevicesKey() : ensureOlmSessionsForDevices succeeds after " - + (System.currentTimeMillis() - t0) + " ms") - val contentMap = MXUsersDevicesMap() + mCrypto.ensureOlmSessionsForDevices(devicesByUser, object : MatrixCallback> { + override fun onSuccess(data: MXUsersDevicesMap) { + Timber.d("## shareUserDevicesKey() : ensureOlmSessionsForDevices succeeds after " + + (System.currentTimeMillis() - t0) + " ms") + val contentMap = MXUsersDevicesMap() - var haveTargets = false - val userIds = results.userIds + var haveTargets = false + val userIds = data.userIds - for (userId in userIds) { - val devicesToShareWith = devicesByUser[userId] + for (userId in userIds) { + val devicesToShareWith = devicesByUser[userId] - for ((deviceID) in devicesToShareWith!!) { + for ((deviceID) in devicesToShareWith!!) { - val sessionResult = results.getObject(deviceID, userId) + val sessionResult = data.getObject(deviceID, userId) - if (null == sessionResult || null == sessionResult.mSessionId) { - // no session with this device, probably because there - // were no one-time keys. - // - // we could send them a to_device message anyway, as a - // signal that they have missed out on the key sharing - // message because of the lack of keys, but there's not - // much point in that really; it will mostly serve to clog - // up to_device inboxes. - // - // ensureOlmSessionsForUsers has already done the logging, - // so just skip it. - continue - } - - Timber.d("## shareUserDevicesKey() : Sharing keys with device $userId:$deviceID") - //noinspection ArraysAsListWithZeroOrOneArgument,ArraysAsListWithZeroOrOneArgument - contentMap.setObject(mCrypto!!.encryptMessage(payload, Arrays.asList(sessionResult.mDevice)), userId, deviceID) - haveTargets = true + if (null == sessionResult || null == sessionResult.mSessionId) { + // no session with this device, probably because there + // were no one-time keys. + // + // we could send them a to_device message anyway, as a + // signal that they have missed out on the key sharing + // message because of the lack of keys, but there's not + // much point in that really; it will mostly serve to clog + // up to_device inboxes. + // + // ensureOlmSessionsForUsers has already done the logging, + // so just skip it. + continue } + + Timber.d("## shareUserDevicesKey() : Sharing keys with device $userId:$deviceID") + //noinspection ArraysAsListWithZeroOrOneArgument,ArraysAsListWithZeroOrOneArgument + contentMap.setObject(mCrypto.encryptMessage(payload, Arrays.asList(sessionResult.mDevice)), userId, deviceID) + haveTargets = true } + } - if (haveTargets && !mCrypto!!.hasBeenReleased()) { - val t0 = System.currentTimeMillis() - Timber.d("## shareUserDevicesKey() : has target") + if (haveTargets) { + val t0 = System.currentTimeMillis() + Timber.d("## shareUserDevicesKey() : has target") - mSendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ENCRYPTED, contentMap)) - .dispatchTo(object : MatrixCallback { - override fun onSuccess(data: Unit) { - mCrypto!!.encryptingThreadHandler.post { - Timber.d("## shareUserDevicesKey() : sendToDevice succeeds after " - + (System.currentTimeMillis() - t0) + " ms") + mSendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ENCRYPTED, contentMap)) + .dispatchTo(object : MatrixCallback { + override fun onSuccess(data: Unit) { + Timber.d("## shareUserDevicesKey() : sendToDevice succeeds after " + + (System.currentTimeMillis() - t0) + " ms") - // Add the devices we have shared with to session.sharedWithDevices. - // we deliberately iterate over devicesByUser (ie, the devices we - // attempted to share with) rather than the contentMap (those we did - // share with), because we don't want to try to claim a one-time-key - // for dead devices on every message. - for (userId in devicesByUser.keys) { - val devicesToShareWith = devicesByUser[userId] + // Add the devices we have shared with to session.sharedWithDevices. + // we deliberately iterate over devicesByUser (ie, the devices we + // attempted to share with) rather than the contentMap (those we did + // share with), because we don't want to try to claim a one-time-key + // for dead devices on every message. + for (userId in devicesByUser.keys) { + val devicesToShareWith = devicesByUser[userId] - for ((deviceId) in devicesToShareWith!!) { - session.mSharedWithDevices.setObject(chainIndex, userId, deviceId) - } - } - - CryptoAsyncHelper.getUiHandler().post { - callback?.onSuccess(Unit) - } + for ((deviceId) in devicesToShareWith!!) { + session.mSharedWithDevices.setObject(chainIndex, userId, deviceId) } } - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## shareUserDevicesKey() : sendToDevice") - - callback?.onFailure(failure) + CryptoAsyncHelper.getUiHandler().post { + callback?.onSuccess(Unit) } - }) - .executeBy(mTaskExecutor) - } else { - Timber.d("## shareUserDevicesKey() : no need to sharekey") + } - if (null != callback) { - CryptoAsyncHelper.getUiHandler().post { callback.onSuccess(Unit) } - } + override fun onFailure(failure: Throwable) { + Timber.e(failure, "## shareUserDevicesKey() : sendToDevice") + + callback?.onFailure(failure) + } + }) + .executeBy(mTaskExecutor) + } else { + Timber.d("## shareUserDevicesKey() : no need to sharekey") + + if (null != callback) { + CryptoAsyncHelper.getUiHandler().post { callback.onSuccess(Unit) } } } } @@ -443,7 +435,7 @@ internal class MXMegolmEncryption : IMXEncrypting { for (queuedEncryption in queuedEncryptions) { val payloadJson = HashMap() - payloadJson["room_id"] = mRoomId!! + payloadJson["room_id"] = mRoomId payloadJson["type"] = queuedEncryption.mEventType!! payloadJson["content"] = queuedEncryption.mEventContent!! @@ -487,54 +479,50 @@ internal class MXMegolmEncryption : IMXEncrypting { // with them, which means that they will have announced any new devices via // an m.new_device. mDeviceListManager.downloadKeys(userIds, false, object : MatrixCallback> { - override fun onSuccess(devices: MXUsersDevicesMap) { - mCrypto!!.encryptingThreadHandler.post { - val encryptToVerifiedDevicesOnly = mCrypto!!.globalBlacklistUnverifiedDevices || mCrypto!!.isRoomBlacklistUnverifiedDevices(mRoomId) + override fun onSuccess(data: MXUsersDevicesMap) { + val encryptToVerifiedDevicesOnly = mCrypto.getGlobalBlacklistUnverifiedDevices() || mCrypto.isRoomBlacklistUnverifiedDevices(mRoomId) - val devicesInRoom = MXUsersDevicesMap() - val unknownDevices = MXUsersDevicesMap() + val devicesInRoom = MXUsersDevicesMap() + val unknownDevices = MXUsersDevicesMap() - val userIds = devices.userIds + for (userId in data.userIds) { + val deviceIds = data.getUserDeviceIds(userId) - for (userId in userIds) { - val deviceIds = devices.getUserDeviceIds(userId) + for (deviceId in deviceIds!!) { + val deviceInfo = data.getObject(deviceId, userId) - for (deviceId in deviceIds!!) { - val deviceInfo = devices.getObject(deviceId, userId) - - if (mCrypto!!.warnOnUnknownDevices() && deviceInfo!!.isUnknown) { - // The device is not yet known by the user - unknownDevices.setObject(deviceInfo, userId, deviceId) - continue - } - - if (deviceInfo!!.isBlocked) { - // Remove any blocked devices - continue - } - - if (!deviceInfo.isVerified && encryptToVerifiedDevicesOnly) { - continue - } - - if (TextUtils.equals(deviceInfo.identityKey(), olmDevice.deviceCurve25519Key)) { - // Don't bother sending to ourself - continue - } - - devicesInRoom.setObject(deviceInfo, userId, deviceId) + if (mCrypto.warnOnUnknownDevices() && deviceInfo!!.isUnknown) { + // The device is not yet known by the user + unknownDevices.setObject(deviceInfo, userId, deviceId) + continue } + + if (deviceInfo!!.isBlocked) { + // Remove any blocked devices + continue + } + + if (!deviceInfo.isVerified && encryptToVerifiedDevicesOnly) { + continue + } + + if (TextUtils.equals(deviceInfo.identityKey(), olmDevice.deviceCurve25519Key)) { + // Don't bother sending to ourself + continue + } + + devicesInRoom.setObject(deviceInfo, userId, deviceId) } + } - CryptoAsyncHelper.getUiHandler().post { - // Check if any of these devices are not yet known to the user. - // if so, warn the user so they can verify or ignore. - if (0 != unknownDevices.map.size) { - callback.onFailure(Failure.CryptoError(MXCryptoError(MXCryptoError.UNKNOWN_DEVICES_CODE, - MXCryptoError.UNABLE_TO_ENCRYPT, MXCryptoError.UNKNOWN_DEVICES_REASON, unknownDevices))) - } else { - callback.onSuccess(devicesInRoom) - } + CryptoAsyncHelper.getUiHandler().post { + // Check if any of these devices are not yet known to the user. + // if so, warn the user so they can verify or ignore. + if (0 != unknownDevices.map.size) { + callback.onFailure(Failure.CryptoError(MXCryptoError(MXCryptoError.UNKNOWN_DEVICES_CODE, + MXCryptoError.UNABLE_TO_ENCRYPT, MXCryptoError.UNKNOWN_DEVICES_REASON, unknownDevices))) + } else { + callback.onSuccess(devicesInRoom) } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt index 5eaad8d8..826fcaf4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt @@ -701,8 +701,4 @@ internal class RealmCryptoStore(private val enableFileEncryption: Boolean = fals } .toMutableList() } - - companion object { - private const val LOG_TAG = "RealmCryptoStore" - } } \ No newline at end of file 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 f4598fcb..85648b84 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 @@ -29,10 +29,10 @@ import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.internal.crypto.CryptoAsyncHelper import im.vector.matrix.android.internal.crypto.DeviceListManager -import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore 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.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 @@ -59,9 +59,10 @@ 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 + CryptoAsyncHelper.getDecryptBackgroundHandler().post { + // TODO We are already in a BG thread when (event.type) { - EventType.KEY_VERIFICATION_START -> { + EventType.KEY_VERIFICATION_START -> { onStartRequestReceived(event) } EventType.KEY_VERIFICATION_CANCEL -> { @@ -70,13 +71,13 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia EventType.KEY_VERIFICATION_ACCEPT -> { onAcceptReceived(event) } - EventType.KEY_VERIFICATION_KEY -> { + EventType.KEY_VERIFICATION_KEY -> { onKeyReceived(event) } - EventType.KEY_VERIFICATION_MAC -> { + EventType.KEY_VERIFICATION_MAC -> { onMacReceived(event) } - else -> { + else -> { //ignore } } @@ -131,24 +132,15 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia override fun markedLocallyAsManuallyVerified(userId: String, deviceID: String) { mCryptoListener.setDeviceVerification(MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED, deviceID, - userId, - object : MatrixCallback { - override fun onSuccess(data: Unit) { - uiHandler.post { - listeners.forEach { - try { - it.markedAsManuallyVerified(userId, deviceID) - } catch (e: Throwable) { - Timber.e(e, "## Error while notifying listeners") - } - } - } - } + userId) - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## Manual verification failed in state") - } - }) + listeners.forEach { + try { + it.markedAsManuallyVerified(userId, deviceID) + } catch (e: Throwable) { + Timber.e(e, "## Error while notifying listeners") + } + } } private fun onStartRequestReceived(event: Event) { @@ -435,12 +427,12 @@ internal class DefaultSasVerificationService(private val mCredentials: Credentia mCryptoListener = listener } - fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String, callback: MatrixCallback) { - mCryptoListener.setDeviceVerification(verificationStatus, deviceId, userId, callback) + fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String) { + mCryptoListener.setDeviceVerification(verificationStatus, deviceId, userId) } interface SasCryptoListener { - fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String, callback: MatrixCallback) + fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String) fun getMyDevice(): MXDeviceInfo } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASVerificationTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASVerificationTransaction.kt index 332dcb3a..9f92d4e0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASVerificationTransaction.kt @@ -239,33 +239,15 @@ internal abstract class SASVerificationTransaction( setDeviceVerified( otherDeviceId ?: "", - otherUserId, - success = { - state = SasVerificationTxState.Verified - }, - error = { - //mmm what to do?, looks like this is never called - } - ) + otherUserId) + + state = SasVerificationTxState.Verified } - private fun setDeviceVerified(deviceId: String, userId: String, success: () -> Unit, error: () -> Unit) { + private fun setDeviceVerified(deviceId: String, userId: String) { mSasVerificationService.setDeviceVerification(MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED, deviceId, - userId, - object : MatrixCallback { - - override fun onSuccess(data: Unit) { - //We good - Timber.d("## SAS verification complete and device status updated for id:$transactionId") - success() - } - - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## SAS verification [$transactionId] failed in state : $state") - error() - } - }) + userId) } override fun cancel() { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt index 3ebc200a..166ca029 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt @@ -257,16 +257,16 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi return cryptoService.getKeysBackupService() } - override fun isRoomBlacklistUnverifiedDevices(roomId: String, callback: MatrixCallback?) { - cryptoService.isRoomBlacklistUnverifiedDevices(roomId, callback) + override fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean { + return cryptoService.isRoomBlacklistUnverifiedDevices(roomId) } override fun setWarnOnUnknownDevices(warn: Boolean) { cryptoService.setWarnOnUnknownDevices(warn) } - override fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String, callback: MatrixCallback) { - cryptoService.setDeviceVerification(verificationStatus, deviceId, userId, callback) + override fun setDeviceVerification(verificationStatus: Int, deviceId: String, userId: String) { + cryptoService.setDeviceVerification(verificationStatus, deviceId, userId) } override fun getUserDevices(userId: String): MutableList { @@ -293,16 +293,16 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi return cryptoService.inboundGroupSessionsCount(onlyBackedUp) } - override fun getGlobalBlacklistUnverifiedDevices(callback: MatrixCallback?) { - cryptoService.getGlobalBlacklistUnverifiedDevices(callback) + override fun getGlobalBlacklistUnverifiedDevices(): Boolean { + return cryptoService.getGlobalBlacklistUnverifiedDevices() } - override fun setGlobalBlacklistUnverifiedDevices(block: Boolean, callback: MatrixCallback?) { - cryptoService.setGlobalBlacklistUnverifiedDevices(block, callback) + override fun setGlobalBlacklistUnverifiedDevices(block: Boolean) { + cryptoService.setGlobalBlacklistUnverifiedDevices(block) } - override fun setRoomUnBlacklistUnverifiedDevices(roomId: String, callback: MatrixCallback) { - cryptoService.setRoomUnBlacklistUnverifiedDevices(roomId, callback) + override fun setRoomUnBlacklistUnverifiedDevices(roomId: String) { + cryptoService.setRoomUnBlacklistUnverifiedDevices(roomId) } override fun getDeviceTrackingStatus(userId: String): Int { @@ -317,12 +317,12 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi cryptoService.exportRoomKeys(password, callback) } - override fun setRoomBlacklistUnverifiedDevices(roomId: String, callback: MatrixCallback) { - cryptoService.setRoomBlacklistUnverifiedDevices(roomId, callback) + override fun setRoomBlacklistUnverifiedDevices(roomId: String) { + cryptoService.setRoomBlacklistUnverifiedDevices(roomId) } - override fun getDeviceInfo(userId: String, deviceId: String?, callback: MatrixCallback) { - cryptoService.getDeviceInfo(userId, deviceId, callback) + override fun getDeviceInfo(userId: String, deviceId: String?): MXDeviceInfo? { + return cryptoService.getDeviceInfo(userId, deviceId) } override fun reRequestRoomKeyForEvent(event: Event) { diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt index b32e250b..5d95ec45 100755 --- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt @@ -47,7 +47,6 @@ import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.extensions.getFingerprintHumanReadable import im.vector.matrix.android.api.extensions.sortByLastSeen import im.vector.matrix.android.api.session.Session -import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse import im.vector.riotredesign.R @@ -2210,42 +2209,26 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref // crypto section: device key (fingerprint) if (!TextUtils.isEmpty(deviceId) && !TextUtils.isEmpty(userId)) { - mSession.getDeviceInfo(userId, deviceId, object : MatrixCallback { - override fun onSuccess(data: MXDeviceInfo?) { - if (null != data && !TextUtils.isEmpty(data.fingerprint()) && null != activity) { - cryptoInfoTextPreference.summary = data.getFingerprintHumanReadable() + val deviceInfo = mSession.getDeviceInfo(userId, deviceId) - cryptoInfoTextPreference.setOnPreferenceClickListener { - data.fingerprint()?.let { - copyToClipboard(requireActivity(), it) - } - true - } + if (null != deviceInfo && !TextUtils.isEmpty(deviceInfo.fingerprint())) { + cryptoInfoTextPreference.summary = deviceInfo.getFingerprintHumanReadable() + + cryptoInfoTextPreference.setOnPreferenceClickListener { + deviceInfo.fingerprint()?.let { + copyToClipboard(requireActivity(), it) } + true } - }) + } } sendToUnverifiedDevicesPref.isChecked = false - mSession.getGlobalBlacklistUnverifiedDevices(object : MatrixCallback { - override fun onSuccess(data: Boolean) { - sendToUnverifiedDevicesPref.isChecked = data - } - }) + sendToUnverifiedDevicesPref.isChecked = mSession.getGlobalBlacklistUnverifiedDevices() sendToUnverifiedDevicesPref.onPreferenceClickListener = Preference.OnPreferenceClickListener { - mSession.getGlobalBlacklistUnverifiedDevices(object : MatrixCallback { - override fun onSuccess(data: Boolean) { - if (sendToUnverifiedDevicesPref.isChecked != data) { - mSession.setGlobalBlacklistUnverifiedDevices(sendToUnverifiedDevicesPref.isChecked, object : MatrixCallback { - override fun onSuccess(data: Unit) { - - } - }) - } - } - }) + mSession.setGlobalBlacklistUnverifiedDevices(sendToUnverifiedDevicesPref.isChecked) true } @@ -2871,8 +2854,6 @@ if (sharedDataItems.isNotEmpty() && thisActivity != null) { * ========================================================================================== */ companion object { - private val LOG_TAG = VectorSettingsPreferencesFragment::class.java.simpleName - // arguments indexes private const val ARG_MATRIX_ID = "VectorSettingsPreferencesFragment.ARG_MATRIX_ID"