diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt index 4f6382bcc5..e3f00a24b6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt @@ -42,7 +42,6 @@ import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody -import kotlin.jvm.Throws interface CryptoService { @@ -82,7 +81,9 @@ interface CryptoService { fun getDeviceTrackingStatus(userId: String): Int - fun importRoomKeys(roomKeysAsArray: ByteArray, password: String, progressListener: ProgressListener?, callback: MatrixCallback) + suspend fun importRoomKeys(roomKeysAsArray: ByteArray, + password: String, + progressListener: ProgressListener?): ImportRoomKeysResult suspend fun exportRoomKeys(password: String): ByteArray diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index 4e6ba514f8..d170ae3dd3 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -959,42 +959,37 @@ internal class DefaultCryptoService @Inject constructor( * @param roomKeysAsArray the room keys as array. * @param password the password * @param progressListener the progress listener - * @param callback the asynchronous callback. + * @return the result ImportRoomKeysResult */ - override fun importRoomKeys(roomKeysAsArray: ByteArray, - password: String, - progressListener: ProgressListener?, - callback: MatrixCallback) { - cryptoCoroutineScope.launch(coroutineDispatchers.main) { - runCatching { - withContext(coroutineDispatchers.crypto) { - Timber.v("## CRYPTO | importRoomKeys starts") + override suspend fun importRoomKeys(roomKeysAsArray: ByteArray, + password: String, + progressListener: ProgressListener?): ImportRoomKeysResult { + return withContext(coroutineDispatchers.crypto) { + Timber.v("## CRYPTO | importRoomKeys starts") - val t0 = System.currentTimeMillis() - val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password) - val t1 = System.currentTimeMillis() + val t0 = System.currentTimeMillis() + val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password) + val t1 = System.currentTimeMillis() - Timber.v("## CRYPTO | importRoomKeys : decryptMegolmKeyFile done in ${t1 - t0} ms") + Timber.v("## CRYPTO | importRoomKeys : decryptMegolmKeyFile done in ${t1 - t0} ms") - val importedSessions = MoshiProvider.providesMoshi() - .adapter>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java)) - .fromJson(roomKeys) + val importedSessions = MoshiProvider.providesMoshi() + .adapter>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java)) + .fromJson(roomKeys) - val t2 = System.currentTimeMillis() + val t2 = System.currentTimeMillis() - Timber.v("## CRYPTO | importRoomKeys : JSON parsing ${t2 - t1} ms") + Timber.v("## CRYPTO | importRoomKeys : JSON parsing ${t2 - t1} ms") - if (importedSessions == null) { - throw Exception("Error") - } + if (importedSessions == null) { + throw Exception("Error") + } - megolmSessionDataImporter.handle( - megolmSessionsData = importedSessions, - fromBackup = false, - progressListener = progressListener - ) - } - }.foldToCallback(callback) + megolmSessionDataImporter.handle( + megolmSessionsData = importedSessions, + fromBackup = false, + progressListener = progressListener + ) } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt b/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt index 3d93b26edd..50c85c3e5f 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt @@ -20,49 +20,27 @@ import android.content.Context import android.net.Uri import im.vector.app.core.intent.getMimeTypeFromUri import im.vector.app.core.resources.openResource -import im.vector.app.features.session.coroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult -import org.matrix.android.sdk.internal.extensions.foldToCallback -import org.matrix.android.sdk.internal.util.awaitCallback -import timber.log.Timber - -class KeysImporter(private val session: Session) { +import javax.inject.Inject +class KeysImporter @Inject constructor( + private val context: Context, + private val session: Session +) { /** * Import keys from provided Uri */ - fun import(context: Context, - uri: Uri, - mimetype: String?, - password: String, - callback: MatrixCallback) { - session.coroutineScope.launch(Dispatchers.Main) { - runCatching { - withContext(Dispatchers.IO) { - val resource = openResource(context, uri, mimetype ?: getMimeTypeFromUri(context, uri)) - - if (resource?.mContentStream == null) { - throw Exception("Error") - } - - val data: ByteArray - try { - data = resource.mContentStream!!.use { it.readBytes() } - } catch (e: Exception) { - Timber.e(e, "## importKeys()") - throw e - } - - awaitCallback { - session.cryptoService().importRoomKeys(data, password, null, it) - } - } - }.foldToCallback(callback) + suspend fun import(uri: Uri, + mimetype: String?, + password: String): ImportRoomKeysResult { + return withContext(Dispatchers.IO) { + val resource = openResource(context, uri, mimetype ?: getMimeTypeFromUri(context, uri)) + val stream = resource?.mContentStream ?: throw Exception("Error") + val data = stream.use { it.readBytes() } + session.cryptoService().importRoomKeys(data, password, null) } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt index 1ae434f2f5..bb946ace7d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt @@ -66,7 +66,6 @@ import me.gujun.android.span.span import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.extensions.getFingerprintHumanReadable import org.matrix.android.sdk.internal.crypto.crosssigning.isVerified -import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse import org.matrix.android.sdk.rx.SecretsSynchronisationInfo @@ -78,6 +77,7 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( private val activeSessionHolder: ActiveSessionHolder, private val pinCodeStore: PinCodeStore, private val keysExporter: KeysExporter, + private val keysImporter: KeysImporter, private val navigator: Navigator ) : VectorSettingsBaseFragment() { @@ -472,34 +472,25 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( displayLoadingView() - KeysImporter(session) - .import(requireContext(), - uri, - mimetype, - password, - object : MatrixCallback { - override fun onSuccess(data: ImportRoomKeysResult) { - if (!isAdded) { - return - } - - hideLoadingView() - - MaterialAlertDialogBuilder(thisActivity) - .setMessage(resources.getQuantityString(R.plurals.encryption_import_room_keys_success, - data.successfullyNumberOfImportedKeys, - data.successfullyNumberOfImportedKeys, - data.totalNumberOfKeys)) - .setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() } - .show() - } - - override fun onFailure(failure: Throwable) { - appContext.toast(failure.localizedMessage ?: getString(R.string.unexpected_error)) - hideLoadingView() - } - }) + lifecycleScope.launch { + val data = try { + keysImporter.import(uri, mimetype, password) + } catch (failure: Throwable) { + appContext.toast(errorFormatter.toHumanReadable(failure)) + null + } + hideLoadingView() + if (data != null) { + MaterialAlertDialogBuilder(thisActivity) + .setMessage(resources.getQuantityString(R.plurals.encryption_import_room_keys_success, + data.successfullyNumberOfImportedKeys, + data.successfullyNumberOfImportedKeys, + data.totalNumberOfKeys)) + .setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() } + .show() + } + } importDialog.dismiss() } }