Convert KeysImporter to coroutines

This commit is contained in:
Benoit Marty 2021-06-01 17:04:48 +02:00 committed by Benoit Marty
parent 3be95ca442
commit 04f06b2803
4 changed files with 58 additions and 93 deletions

View File

@ -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.DeviceInfo
import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse
import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody
import kotlin.jvm.Throws
interface CryptoService { interface CryptoService {
@ -82,7 +81,9 @@ interface CryptoService {
fun getDeviceTrackingStatus(userId: String): Int fun getDeviceTrackingStatus(userId: String): Int
fun importRoomKeys(roomKeysAsArray: ByteArray, password: String, progressListener: ProgressListener?, callback: MatrixCallback<ImportRoomKeysResult>) suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
password: String,
progressListener: ProgressListener?): ImportRoomKeysResult
suspend fun exportRoomKeys(password: String): ByteArray suspend fun exportRoomKeys(password: String): ByteArray

View File

@ -959,42 +959,37 @@ internal class DefaultCryptoService @Inject constructor(
* @param roomKeysAsArray the room keys as array. * @param roomKeysAsArray the room keys as array.
* @param password the password * @param password the password
* @param progressListener the progress listener * @param progressListener the progress listener
* @param callback the asynchronous callback. * @return the result ImportRoomKeysResult
*/ */
override fun importRoomKeys(roomKeysAsArray: ByteArray, override suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
password: String, password: String,
progressListener: ProgressListener?, progressListener: ProgressListener?): ImportRoomKeysResult {
callback: MatrixCallback<ImportRoomKeysResult>) { return withContext(coroutineDispatchers.crypto) {
cryptoCoroutineScope.launch(coroutineDispatchers.main) { Timber.v("## CRYPTO | importRoomKeys starts")
runCatching {
withContext(coroutineDispatchers.crypto) {
Timber.v("## CRYPTO | importRoomKeys starts")
val t0 = System.currentTimeMillis() val t0 = System.currentTimeMillis()
val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password) val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password)
val t1 = System.currentTimeMillis() 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() val importedSessions = MoshiProvider.providesMoshi()
.adapter<List<MegolmSessionData>>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java)) .adapter<List<MegolmSessionData>>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java))
.fromJson(roomKeys) .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) { if (importedSessions == null) {
throw Exception("Error") throw Exception("Error")
} }
megolmSessionDataImporter.handle( megolmSessionDataImporter.handle(
megolmSessionsData = importedSessions, megolmSessionsData = importedSessions,
fromBackup = false, fromBackup = false,
progressListener = progressListener progressListener = progressListener
) )
}
}.foldToCallback(callback)
} }
} }

View File

@ -20,49 +20,27 @@ import android.content.Context
import android.net.Uri import android.net.Uri
import im.vector.app.core.intent.getMimeTypeFromUri import im.vector.app.core.intent.getMimeTypeFromUri
import im.vector.app.core.resources.openResource import im.vector.app.core.resources.openResource
import im.vector.app.features.session.coroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
import org.matrix.android.sdk.internal.extensions.foldToCallback import javax.inject.Inject
import org.matrix.android.sdk.internal.util.awaitCallback
import timber.log.Timber
class KeysImporter(private val session: Session) {
class KeysImporter @Inject constructor(
private val context: Context,
private val session: Session
) {
/** /**
* Import keys from provided Uri * Import keys from provided Uri
*/ */
fun import(context: Context, suspend fun import(uri: Uri,
uri: Uri, mimetype: String?,
mimetype: String?, password: String): ImportRoomKeysResult {
password: String, return withContext(Dispatchers.IO) {
callback: MatrixCallback<ImportRoomKeysResult>) { val resource = openResource(context, uri, mimetype ?: getMimeTypeFromUri(context, uri))
session.coroutineScope.launch(Dispatchers.Main) { val stream = resource?.mContentStream ?: throw Exception("Error")
runCatching { val data = stream.use { it.readBytes() }
withContext(Dispatchers.IO) { session.cryptoService().importRoomKeys(data, password, null)
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<ImportRoomKeysResult> {
session.cryptoService().importRoomKeys(data, password, null, it)
}
}
}.foldToCallback(callback)
} }
} }
} }

View File

@ -66,7 +66,6 @@ import me.gujun.android.span.span
import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.extensions.getFingerprintHumanReadable import org.matrix.android.sdk.api.extensions.getFingerprintHumanReadable
import org.matrix.android.sdk.internal.crypto.crosssigning.isVerified 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.DeviceInfo
import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse
import org.matrix.android.sdk.rx.SecretsSynchronisationInfo import org.matrix.android.sdk.rx.SecretsSynchronisationInfo
@ -78,6 +77,7 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
private val activeSessionHolder: ActiveSessionHolder, private val activeSessionHolder: ActiveSessionHolder,
private val pinCodeStore: PinCodeStore, private val pinCodeStore: PinCodeStore,
private val keysExporter: KeysExporter, private val keysExporter: KeysExporter,
private val keysImporter: KeysImporter,
private val navigator: Navigator private val navigator: Navigator
) : VectorSettingsBaseFragment() { ) : VectorSettingsBaseFragment() {
@ -472,34 +472,25 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
displayLoadingView() displayLoadingView()
KeysImporter(session) lifecycleScope.launch {
.import(requireContext(), val data = try {
uri, keysImporter.import(uri, mimetype, password)
mimetype, } catch (failure: Throwable) {
password, appContext.toast(errorFormatter.toHumanReadable(failure))
object : MatrixCallback<ImportRoomKeysResult> { null
override fun onSuccess(data: ImportRoomKeysResult) { }
if (!isAdded) { hideLoadingView()
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()
}
})
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() importDialog.dismiss()
} }
} }