Suspend: continue cleaning
This commit is contained in:
parent
ed84e38a9b
commit
91daa1ab90
@ -100,7 +100,7 @@ interface CryptoService {
|
|||||||
|
|
||||||
fun getDeviceInfo(deviceId: String, callback: MatrixCallback<DeviceInfo>)
|
fun getDeviceInfo(deviceId: String, callback: MatrixCallback<DeviceInfo>)
|
||||||
|
|
||||||
fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int
|
suspend fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int
|
||||||
|
|
||||||
fun isRoomEncrypted(roomId: String): Boolean
|
fun isRoomEncrypted(roomId: String): Boolean
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
|
|||||||
import org.matrix.android.sdk.internal.crypto.store.SavedKeyBackupKeyInfo
|
import org.matrix.android.sdk.internal.crypto.store.SavedKeyBackupKeyInfo
|
||||||
|
|
||||||
interface KeysBackupService {
|
interface KeysBackupService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the current version of the backup from the homeserver
|
* Retrieve the current version of the backup from the homeserver
|
||||||
*
|
*
|
||||||
@ -45,12 +46,12 @@ interface KeysBackupService {
|
|||||||
/**
|
/**
|
||||||
* Facility method to get the total number of locally stored keys
|
* Facility method to get the total number of locally stored keys
|
||||||
*/
|
*/
|
||||||
fun getTotalNumbersOfKeys(): Int
|
suspend fun getTotalNumbersOfKeys(): Int
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Facility method to get the number of backed up keys
|
* Facility method to get the number of backed up keys
|
||||||
*/
|
*/
|
||||||
fun getTotalNumbersOfBackedUpKeys(): Int
|
suspend fun getTotalNumbersOfBackedUpKeys(): Int
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Start to back up keys immediately.
|
// * Start to back up keys immediately.
|
||||||
@ -71,7 +72,7 @@ interface KeysBackupService {
|
|||||||
/**
|
/**
|
||||||
* Return the current progress of the backup
|
* Return the current progress of the backup
|
||||||
*/
|
*/
|
||||||
fun getBackupProgress(progressListener: ProgressListener)
|
suspend fun getBackupProgress(progressListener: ProgressListener)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get information about a backup version defined on the homeserver.
|
* Get information about a backup version defined on the homeserver.
|
||||||
@ -128,7 +129,7 @@ interface KeysBackupService {
|
|||||||
* Ask if the backup on the server contains keys that we may do not have locally.
|
* Ask if the backup on the server contains keys that we may do not have locally.
|
||||||
* This should be called when entering in the state READY_TO_BACKUP
|
* This should be called when entering in the state READY_TO_BACKUP
|
||||||
*/
|
*/
|
||||||
fun canRestoreKeys(): Boolean
|
suspend fun canRestoreKeys(): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set trust on a keys backup version.
|
* Set trust on a keys backup version.
|
||||||
@ -199,7 +200,7 @@ interface KeysBackupService {
|
|||||||
|
|
||||||
// For gossiping
|
// For gossiping
|
||||||
fun saveBackupRecoveryKey(recoveryKey: String?, version: String?)
|
fun saveBackupRecoveryKey(recoveryKey: String?, version: String?)
|
||||||
fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo?
|
suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo?
|
||||||
|
|
||||||
suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String): Boolean
|
suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String): Boolean
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
private val taskExecutor: TaskExecutor,
|
private val taskExecutor: TaskExecutor,
|
||||||
private val cryptoCoroutineScope: CoroutineScope,
|
private val cryptoCoroutineScope: CoroutineScope,
|
||||||
private val sender: RequestSender,
|
private val requestSender: RequestSender,
|
||||||
private val crossSigningService: CrossSigningService,
|
private val crossSigningService: CrossSigningService,
|
||||||
private val verificationService: RustVerificationService,
|
private val verificationService: RustVerificationService,
|
||||||
private val keysBackupService: RustKeyBackupService,
|
private val keysBackupService: RustKeyBackupService,
|
||||||
@ -248,7 +248,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int {
|
override suspend fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int {
|
||||||
return if (onlyBackedUp) {
|
return if (onlyBackedUp) {
|
||||||
keysBackupService.getTotalNumbersOfBackedUpKeys()
|
keysBackupService.getTotalNumbersOfBackedUpKeys()
|
||||||
} else {
|
} else {
|
||||||
@ -594,7 +594,6 @@ internal class DefaultCryptoService @Inject constructor(
|
|||||||
// Timber.e(throwable, "## CRYPTO | onRoomEncryptionEvent ERROR FAILED TO SETUP CRYPTO ")
|
// Timber.e(throwable, "## CRYPTO | onRoomEncryptionEvent ERROR FAILED TO SETUP CRYPTO ")
|
||||||
// } finally {
|
// } finally {
|
||||||
val userIds = getRoomUserIds(roomId)
|
val userIds = getRoomUserIds(roomId)
|
||||||
olmMachine.updateTrackedUsers(userIds)
|
|
||||||
setEncryptionInRoom(roomId, event.content?.get("algorithm")?.toString(), userIds)
|
setEncryptionInRoom(roomId, event.content?.get("algorithm")?.toString(), userIds)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
@ -758,14 +757,18 @@ internal class DefaultCryptoService @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun uploadKeys(request: Request.KeysUpload) {
|
private suspend fun uploadKeys(request: Request.KeysUpload) {
|
||||||
val response = this.sender.uploadKeys(request)
|
try {
|
||||||
this.olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_UPLOAD, response)
|
val response = requestSender.uploadKeys(request)
|
||||||
|
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_UPLOAD, response)
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO uploadKeys(): error")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun queryKeys(request: Request.KeysQuery) {
|
private suspend fun queryKeys(request: Request.KeysQuery) {
|
||||||
try {
|
try {
|
||||||
val response = this.sender.queryKeys(request)
|
val response = requestSender.queryKeys(request)
|
||||||
this.olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_QUERY, response)
|
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_QUERY, response)
|
||||||
|
|
||||||
// Update the shields!
|
// Update the shields!
|
||||||
cryptoCoroutineScope.launch {
|
cryptoCoroutineScope.launch {
|
||||||
@ -781,18 +784,38 @@ internal class DefaultCryptoService @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun sendToDevice(request: Request.ToDevice) {
|
private suspend fun sendToDevice(request: Request.ToDevice) {
|
||||||
this.sender.sendToDevice(request)
|
try {
|
||||||
|
requestSender.sendToDevice(request)
|
||||||
olmMachine.markRequestAsSent(request.requestId, RequestType.TO_DEVICE, "{}")
|
olmMachine.markRequestAsSent(request.requestId, RequestType.TO_DEVICE, "{}")
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO sendToDevice(): error")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun claimKeys(request: Request.KeysClaim) {
|
private suspend fun claimKeys(request: Request.KeysClaim) {
|
||||||
val response = this.sender.claimKeys(request)
|
try {
|
||||||
|
val response = requestSender.claimKeys(request)
|
||||||
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_CLAIM, response)
|
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_CLAIM, response)
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO claimKeys(): error")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun signatureUpload(request: Request.SignatureUpload) {
|
private suspend fun signatureUpload(request: Request.SignatureUpload) {
|
||||||
this.sender.sendSignatureUpload(request)
|
try {
|
||||||
|
requestSender.sendSignatureUpload(request)
|
||||||
olmMachine.markRequestAsSent(request.requestId, RequestType.SIGNATURE_UPLOAD, "{}")
|
olmMachine.markRequestAsSent(request.requestId, RequestType.SIGNATURE_UPLOAD, "{}")
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO signatureUpload(): error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun sendRoomMessage(request: Request.RoomMessage){
|
||||||
|
try {
|
||||||
|
requestSender.sendRoomMessage(request)
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO sendRoomMessage(): error")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun sendOutgoingRequests() {
|
private suspend fun sendOutgoingRequests() {
|
||||||
@ -822,7 +845,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||||||
}
|
}
|
||||||
is Request.RoomMessage -> {
|
is Request.RoomMessage -> {
|
||||||
async {
|
async {
|
||||||
sender.sendRoomMessage(it)
|
sendRoomMessage(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Request.SignatureUpload -> {
|
is Request.SignatureUpload -> {
|
||||||
|
@ -833,22 +833,25 @@ internal class OlmMachine(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
fun roomKeyCounts(): RoomKeyCounts {
|
suspend fun roomKeyCounts(): RoomKeyCounts {
|
||||||
// TODO convert this to a suspendable method
|
return withContext(Dispatchers.Default) {
|
||||||
return inner.roomKeyCounts()
|
inner.roomKeyCounts()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
fun getBackupKeys(): BackupKeys? {
|
suspend fun getBackupKeys(): BackupKeys? {
|
||||||
// TODO this needs to be suspendable
|
return withContext(Dispatchers.Default) {
|
||||||
return inner.getBackupKeys()
|
inner.getBackupKeys()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
fun saveRecoveryKey(key: String?, version: String?) {
|
suspend fun saveRecoveryKey(key: String?, version: String?) {
|
||||||
// TODO convert this to a suspendable method
|
withContext(Dispatchers.Default) {
|
||||||
inner.saveRecoveryKey(key, version)
|
inner.saveRecoveryKey(key, version)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
suspend fun backupRoomKeys(): Request? {
|
suspend fun backupRoomKeys(): Request? {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.internal.crypto
|
package org.matrix.android.sdk.internal.crypto
|
||||||
|
|
||||||
|
import com.squareup.moshi.Moshi
|
||||||
import com.squareup.moshi.Types
|
import com.squareup.moshi.Types
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
||||||
@ -80,6 +81,7 @@ internal class RequestSender @Inject constructor(
|
|||||||
private val getSessionsDataTask: GetSessionsDataTask,
|
private val getSessionsDataTask: GetSessionsDataTask,
|
||||||
private val getRoomSessionsDataTask: GetRoomSessionsDataTask,
|
private val getRoomSessionsDataTask: GetRoomSessionsDataTask,
|
||||||
private val getRoomSessionDataTask: GetRoomSessionDataTask,
|
private val getRoomSessionDataTask: GetRoomSessionDataTask,
|
||||||
|
private val moshi: Moshi
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val REQUEST_RETRY_COUNT = 3
|
const val REQUEST_RETRY_COUNT = 3
|
||||||
@ -97,16 +99,16 @@ internal class RequestSender @Inject constructor(
|
|||||||
suspend fun queryKeys(request: Request.KeysQuery): String {
|
suspend fun queryKeys(request: Request.KeysQuery): String {
|
||||||
val params = DownloadKeysForUsersTask.Params(request.users, null)
|
val params = DownloadKeysForUsersTask.Params(request.users, null)
|
||||||
val response = downloadKeysForUsersTask.executeRetry(params, REQUEST_RETRY_COUNT)
|
val response = downloadKeysForUsersTask.executeRetry(params, REQUEST_RETRY_COUNT)
|
||||||
val adapter = MoshiProvider.providesMoshi().adapter(KeysQueryResponse::class.java)
|
val adapter = moshi.adapter(KeysQueryResponse::class.java)
|
||||||
return adapter.toJson(response)!!
|
return adapter.toJson(response)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun uploadKeys(request: Request.KeysUpload): String {
|
suspend fun uploadKeys(request: Request.KeysUpload): String {
|
||||||
val body = MoshiProvider.providesMoshi().adapter<JsonDict>(Map::class.java).fromJson(request.body)!!
|
val body = moshi.adapter<JsonDict>(Map::class.java).fromJson(request.body)!!
|
||||||
val params = UploadKeysTask.Params(body)
|
val params = UploadKeysTask.Params(body)
|
||||||
|
|
||||||
val response = uploadKeysTask.executeRetry(params, REQUEST_RETRY_COUNT)
|
val response = uploadKeysTask.executeRetry(params, REQUEST_RETRY_COUNT)
|
||||||
val adapter = MoshiProvider.providesMoshi().adapter(KeysUploadResponse::class.java)
|
val adapter = moshi.adapter(KeysUploadResponse::class.java)
|
||||||
|
|
||||||
return adapter.toJson(response)!!
|
return adapter.toJson(response)!!
|
||||||
}
|
}
|
||||||
@ -127,7 +129,7 @@ internal class RequestSender @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun sendRoomMessage(eventType: String, roomId: String, content: String, transactionId: String): String {
|
suspend fun sendRoomMessage(eventType: String, roomId: String, content: String, transactionId: String): String {
|
||||||
val adapter = MoshiProvider.providesMoshi().adapter<Content>(Map::class.java)
|
val adapter = moshi.adapter<Content>(Map::class.java)
|
||||||
val jsonContent = adapter.fromJson(content)
|
val jsonContent = adapter.fromJson(content)
|
||||||
val event = Event(eventType, transactionId, jsonContent, roomId = roomId)
|
val event = Event(eventType, transactionId, jsonContent, roomId = roomId)
|
||||||
val params = SendVerificationMessageTask.Params(event)
|
val params = SendVerificationMessageTask.Params(event)
|
||||||
@ -143,7 +145,7 @@ internal class RequestSender @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun sendSignatureUpload(body: String) {
|
private suspend fun sendSignatureUpload(body: String) {
|
||||||
val adapter = MoshiProvider.providesMoshi().adapter<Map<String, Map<String, Any>>>(Map::class.java)
|
val adapter = moshi.adapter<Map<String, Map<String, Any>>>(Map::class.java)
|
||||||
val signatures = adapter.fromJson(body)!!
|
val signatures = adapter.fromJson(body)!!
|
||||||
val params = UploadSignaturesTask.Params(signatures)
|
val params = UploadSignaturesTask.Params(signatures)
|
||||||
this.signaturesUploadTask.executeRetry(params, REQUEST_RETRY_COUNT)
|
this.signaturesUploadTask.executeRetry(params, REQUEST_RETRY_COUNT)
|
||||||
@ -153,7 +155,7 @@ internal class RequestSender @Inject constructor(
|
|||||||
request: UploadSigningKeysRequest,
|
request: UploadSigningKeysRequest,
|
||||||
interactiveAuthInterceptor: UserInteractiveAuthInterceptor?
|
interactiveAuthInterceptor: UserInteractiveAuthInterceptor?
|
||||||
) {
|
) {
|
||||||
val adapter = MoshiProvider.providesMoshi().adapter(RestKeyInfo::class.java)
|
val adapter = moshi.adapter(RestKeyInfo::class.java)
|
||||||
val masterKey = adapter.fromJson(request.masterKey)!!.toCryptoModel()
|
val masterKey = adapter.fromJson(request.masterKey)!!.toCryptoModel()
|
||||||
val selfSigningKey = adapter.fromJson(request.selfSigningKey)!!.toCryptoModel()
|
val selfSigningKey = adapter.fromJson(request.selfSigningKey)!!.toCryptoModel()
|
||||||
val userSigningKey = adapter.fromJson(request.userSigningKey)!!.toCryptoModel()
|
val userSigningKey = adapter.fromJson(request.userSigningKey)!!.toCryptoModel()
|
||||||
@ -195,8 +197,7 @@ internal class RequestSender @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun sendToDevice(eventType: String, body: String, transactionId: String) {
|
suspend fun sendToDevice(eventType: String, body: String, transactionId: String) {
|
||||||
val adapter = MoshiProvider
|
val adapter = moshi
|
||||||
.providesMoshi()
|
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.add(CheckNumberType.JSON_ADAPTER_FACTORY)
|
.add(CheckNumberType.JSON_ADAPTER_FACTORY)
|
||||||
.build()
|
.build()
|
||||||
@ -252,7 +253,7 @@ internal class RequestSender @Inject constructor(
|
|||||||
val keys = adapter.fromJson(request.rooms)!!
|
val keys = adapter.fromJson(request.rooms)!!
|
||||||
val params = StoreSessionsDataTask.Params(request.version, KeysBackupData(keys))
|
val params = StoreSessionsDataTask.Params(request.version, KeysBackupData(keys))
|
||||||
val response = backupRoomKeysTask.executeRetry(params, REQUEST_RETRY_COUNT)
|
val response = backupRoomKeysTask.executeRetry(params, REQUEST_RETRY_COUNT)
|
||||||
val responseAdapter = MoshiProvider.providesMoshi().adapter(BackupKeysResult::class.java)
|
val responseAdapter = moshi.adapter(BackupKeysResult::class.java)
|
||||||
return responseAdapter.toJson(response)!!
|
return responseAdapter.toJson(response)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ internal class RustKeyBackupService @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canRestoreKeys(): Boolean {
|
override suspend fun canRestoreKeys(): Boolean {
|
||||||
val keyCountOnServer = keysBackupVersion?.count ?: return false
|
val keyCountOnServer = keysBackupVersion?.count ?: return false
|
||||||
val keyCountLocally = getTotalNumbersOfKeys()
|
val keyCountLocally = getTotalNumbersOfKeys()
|
||||||
|
|
||||||
@ -246,11 +246,11 @@ internal class RustKeyBackupService @Inject constructor(
|
|||||||
return keyCountLocally < keyCountOnServer
|
return keyCountLocally < keyCountOnServer
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTotalNumbersOfKeys(): Int {
|
override suspend fun getTotalNumbersOfKeys(): Int {
|
||||||
return olmMachine.roomKeyCounts().total.toInt()
|
return olmMachine.roomKeyCounts().total.toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTotalNumbersOfBackedUpKeys(): Int {
|
override suspend fun getTotalNumbersOfBackedUpKeys(): Int {
|
||||||
return olmMachine.roomKeyCounts().backedUp.toInt()
|
return olmMachine.roomKeyCounts().backedUp.toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,7 +405,7 @@ internal class RustKeyBackupService @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBackupProgress(progressListener: ProgressListener) {
|
override suspend fun getBackupProgress(progressListener: ProgressListener) {
|
||||||
val backedUpKeys = getTotalNumbersOfBackedUpKeys()
|
val backedUpKeys = getTotalNumbersOfBackedUpKeys()
|
||||||
val total = getTotalNumbersOfKeys()
|
val total = getTotalNumbersOfKeys()
|
||||||
|
|
||||||
@ -725,7 +725,7 @@ internal class RustKeyBackupService @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? {
|
override suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? {
|
||||||
val info = olmMachine.getBackupKeys() ?: return null
|
val info = olmMachine.getBackupKeys() ?: return null
|
||||||
return SavedKeyBackupKeyInfo(info.recoveryKey, info.backupVersion)
|
return SavedKeyBackupKeyInfo(info.recoveryKey, info.backupVersion)
|
||||||
}
|
}
|
||||||
|
@ -64,12 +64,12 @@ fun Session.startSyncing(context: Context) {
|
|||||||
/**
|
/**
|
||||||
* Tell is the session has unsaved e2e keys in the backup
|
* Tell is the session has unsaved e2e keys in the backup
|
||||||
*/
|
*/
|
||||||
fun Session.hasUnsavedKeys(): Boolean {
|
suspend fun Session.hasUnsavedKeys(): Boolean {
|
||||||
return cryptoService().inboundGroupSessionsCount(false) > 0 &&
|
return cryptoService().inboundGroupSessionsCount(false) > 0 &&
|
||||||
cryptoService().keysBackupService().state != KeysBackupState.ReadyToBackUp
|
cryptoService().keysBackupService().state != KeysBackupState.ReadyToBackUp
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Session.cannotLogoutSafely(): Boolean {
|
suspend fun Session.cannotLogoutSafely(): Boolean {
|
||||||
// has some encrypted chat
|
// has some encrypted chat
|
||||||
return hasUnsavedKeys() ||
|
return hasUnsavedKeys() ||
|
||||||
// has local cross signing keys
|
// has local cross signing keys
|
||||||
|
@ -26,5 +26,8 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionR
|
|||||||
data class KeysBackupSettingViewState(val keysBackupVersionTrust: Async<KeysBackupVersionTrust> = Uninitialized,
|
data class KeysBackupSettingViewState(val keysBackupVersionTrust: Async<KeysBackupVersionTrust> = Uninitialized,
|
||||||
val keysBackupState: KeysBackupState? = null,
|
val keysBackupState: KeysBackupState? = null,
|
||||||
val keysBackupVersion: KeysVersionResult? = null,
|
val keysBackupVersion: KeysVersionResult? = null,
|
||||||
|
val remainingKeysToBackup: Int = 0,
|
||||||
val deleteBackupRequest: Async<Unit> = Uninitialized) :
|
val deleteBackupRequest: Async<Unit> = Uninitialized) :
|
||||||
MavericksState
|
MavericksState
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,10 +124,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(
|
|||||||
style(ItemStyle.BIG_TEXT)
|
style(ItemStyle.BIG_TEXT)
|
||||||
hasIndeterminateProcess(true)
|
hasIndeterminateProcess(true)
|
||||||
|
|
||||||
val totalKeys = host.session.cryptoService().inboundGroupSessionsCount(false)
|
val remainingKeysToBackup = data.remainingKeysToBackup
|
||||||
val backedUpKeys = host.session.cryptoService().inboundGroupSessionsCount(true)
|
|
||||||
|
|
||||||
val remainingKeysToBackup = totalKeys - backedUpKeys
|
|
||||||
|
|
||||||
if (data.keysBackupVersionTrust()?.usable == false) {
|
if (data.keysBackupVersionTrust()?.usable == false) {
|
||||||
description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence())
|
description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence())
|
||||||
|
@ -18,7 +18,6 @@ package im.vector.app.features.crypto.keysbackup.settings
|
|||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.Loading
|
import com.airbnb.mvrx.Loading
|
||||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
import com.airbnb.mvrx.Success
|
|
||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
@ -32,7 +31,6 @@ import org.matrix.android.sdk.api.session.Session
|
|||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
||||||
import timber.log.Timber
|
|
||||||
|
|
||||||
class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialState: KeysBackupSettingViewState,
|
class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialState: KeysBackupSettingViewState,
|
||||||
session: Session
|
session: Session
|
||||||
@ -46,6 +44,7 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
|
|||||||
|
|
||||||
companion object : MavericksViewModelFactory<KeysBackupSettingsViewModel, KeysBackupSettingViewState> by hiltMavericksViewModelFactory()
|
companion object : MavericksViewModelFactory<KeysBackupSettingsViewModel, KeysBackupSettingViewState> by hiltMavericksViewModelFactory()
|
||||||
|
|
||||||
|
private val cryptoService = session.cryptoService()
|
||||||
private val keysBackupService: KeysBackupService = session.cryptoService().keysBackupService()
|
private val keysBackupService: KeysBackupService = session.cryptoService().keysBackupService()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -75,34 +74,12 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
|
|||||||
|
|
||||||
private fun getKeysBackupTrust() = withState { state ->
|
private fun getKeysBackupTrust() = withState { state ->
|
||||||
val versionResult = keysBackupService.keysBackupVersion
|
val versionResult = keysBackupService.keysBackupVersion
|
||||||
Timber.d("BACKUP: HEEEEEEE $versionResult ${state.keysBackupVersionTrust}")
|
|
||||||
|
|
||||||
if (state.keysBackupVersionTrust is Uninitialized && versionResult != null) {
|
if (state.keysBackupVersionTrust is Uninitialized && versionResult != null) {
|
||||||
setState {
|
setState { copy(deleteBackupRequest = Uninitialized) }
|
||||||
copy(
|
suspend {
|
||||||
keysBackupVersionTrust = Loading(),
|
keysBackupService.getKeysBackupTrust(versionResult)
|
||||||
deleteBackupRequest = Uninitialized
|
}.execute {
|
||||||
)
|
copy(keysBackupVersionTrust = it)
|
||||||
}
|
|
||||||
Timber.d("BACKUP: HEEEEEEE TWO")
|
|
||||||
|
|
||||||
viewModelScope.launch {
|
|
||||||
try {
|
|
||||||
val data = keysBackupService.getKeysBackupTrust(versionResult)
|
|
||||||
Timber.d("BACKUP: HEEEE suceeeded $data")
|
|
||||||
setState {
|
|
||||||
copy(
|
|
||||||
keysBackupVersionTrust = Success(data)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (failure: Throwable) {
|
|
||||||
Timber.d("BACKUP: HEEEE FAILED $failure")
|
|
||||||
setState {
|
|
||||||
copy(
|
|
||||||
keysBackupVersionTrust = Fail(failure)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,10 +96,24 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
|
|||||||
keysBackupVersion = keysBackupService.keysBackupVersion
|
keysBackupVersion = keysBackupService.keysBackupVersion
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
when (newState) {
|
||||||
|
KeysBackupState.BackingUp, KeysBackupState.WillBackUp -> updateKeysCount()
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
getKeysBackupTrust()
|
getKeysBackupTrust()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateKeysCount() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val totalKeys = cryptoService.inboundGroupSessionsCount(false)
|
||||||
|
val backedUpKeys = cryptoService.inboundGroupSessionsCount(true)
|
||||||
|
val remainingKeysToBackup = totalKeys - backedUpKeys
|
||||||
|
setState {
|
||||||
|
copy(remainingKeysToBackup = remainingKeysToBackup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun deleteCurrentBackup() {
|
private fun deleteCurrentBackup() {
|
||||||
val keysBackupService = keysBackupService
|
val keysBackupService = keysBackupService
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ class HomeDrawerFragment @Inject constructor(
|
|||||||
}
|
}
|
||||||
// Sign out
|
// Sign out
|
||||||
views.homeDrawerHeaderSignoutView.debouncedClicks {
|
views.homeDrawerHeaderSignoutView.debouncedClicks {
|
||||||
|
signout()
|
||||||
sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer)
|
sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer)
|
||||||
SignOutUiWorker(requireActivity()).perform()
|
SignOutUiWorker(requireActivity()).perform()
|
||||||
}
|
}
|
||||||
@ -118,4 +119,8 @@ class HomeDrawerFragment @Inject constructor(
|
|||||||
navigator.openDebug(requireActivity())
|
navigator.openDebug(requireActivity())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun signout() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ class SoftLogoutActivity : LoginActivity() {
|
|||||||
MainActivity.restartApp(this, MainActivityArgs())
|
MainActivity.restartApp(this, MainActivityArgs())
|
||||||
}
|
}
|
||||||
|
|
||||||
views.loginLoading.isVisible = softLogoutViewState.isLoading()
|
views.loginLoading.isVisible = softLogoutViewState.isLoading
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -34,6 +34,7 @@ import im.vector.app.features.signout.soft.epoxy.loginRedButtonItem
|
|||||||
import im.vector.app.features.signout.soft.epoxy.loginTextItem
|
import im.vector.app.features.signout.soft.epoxy.loginTextItem
|
||||||
import im.vector.app.features.signout.soft.epoxy.loginTitleItem
|
import im.vector.app.features.signout.soft.epoxy.loginTitleItem
|
||||||
import im.vector.app.features.signout.soft.epoxy.loginTitleSmallItem
|
import im.vector.app.features.signout.soft.epoxy.loginTitleSmallItem
|
||||||
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SoftLogoutController @Inject constructor(
|
class SoftLogoutController @Inject constructor(
|
||||||
@ -52,6 +53,7 @@ class SoftLogoutController @Inject constructor(
|
|||||||
|
|
||||||
override fun buildModels() {
|
override fun buildModels() {
|
||||||
val safeViewState = viewState ?: return
|
val safeViewState = viewState ?: return
|
||||||
|
if (safeViewState.hasUnsavedKeys is Incomplete) return
|
||||||
|
|
||||||
buildHeader(safeViewState)
|
buildHeader(safeViewState)
|
||||||
buildForm(safeViewState)
|
buildForm(safeViewState)
|
||||||
@ -78,7 +80,7 @@ class SoftLogoutController @Inject constructor(
|
|||||||
state.userDisplayName,
|
state.userDisplayName,
|
||||||
state.userId))
|
state.userId))
|
||||||
}
|
}
|
||||||
if (state.hasUnsavedKeys) {
|
if (state.hasUnsavedKeys().orFalse()) {
|
||||||
loginTextItem {
|
loginTextItem {
|
||||||
id("signText2")
|
id("signText2")
|
||||||
text(host.stringProvider.getString(R.string.soft_logout_signin_e2e_warning_notice))
|
text(host.stringProvider.getString(R.string.soft_logout_signin_e2e_warning_notice))
|
||||||
|
@ -32,6 +32,7 @@ import im.vector.app.features.login.AbstractLoginFragment
|
|||||||
import im.vector.app.features.login.LoginAction
|
import im.vector.app.features.login.LoginAction
|
||||||
import im.vector.app.features.login.LoginMode
|
import im.vector.app.features.login.LoginMode
|
||||||
import im.vector.app.features.login.LoginViewEvents
|
import im.vector.app.features.login.LoginViewEvents
|
||||||
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,7 +119,7 @@ class SoftLogoutFragment @Inject constructor(
|
|||||||
withState(softLogoutViewModel) { state ->
|
withState(softLogoutViewModel) { state ->
|
||||||
cleanupUi()
|
cleanupUi()
|
||||||
|
|
||||||
val messageResId = if (state.hasUnsavedKeys) {
|
val messageResId = if (state.hasUnsavedKeys().orFalse()) {
|
||||||
R.string.soft_logout_clear_data_dialog_e2e_warning_content
|
R.string.soft_logout_clear_data_dialog_e2e_warning_content
|
||||||
} else {
|
} else {
|
||||||
R.string.soft_logout_clear_data_dialog_content
|
R.string.soft_logout_clear_data_dialog_content
|
||||||
|
@ -69,7 +69,6 @@ class SoftLogoutViewModel @AssistedInject constructor(
|
|||||||
userId = userId,
|
userId = userId,
|
||||||
deviceId = session.sessionParams.deviceId.orEmpty(),
|
deviceId = session.sessionParams.deviceId.orEmpty(),
|
||||||
userDisplayName = session.getUser(userId)?.displayName ?: userId,
|
userDisplayName = session.getUser(userId)?.displayName ?: userId,
|
||||||
hasUnsavedKeys = session.hasUnsavedKeys()
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
SoftLogoutViewState(
|
SoftLogoutViewState(
|
||||||
@ -77,17 +76,25 @@ class SoftLogoutViewModel @AssistedInject constructor(
|
|||||||
userId = "",
|
userId = "",
|
||||||
deviceId = "",
|
deviceId = "",
|
||||||
userDisplayName = "",
|
userDisplayName = "",
|
||||||
hasUnsavedKeys = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
checkHasUnsavedKeys()
|
||||||
// Get the supported login flow
|
// Get the supported login flow
|
||||||
getSupportedLoginFlow()
|
getSupportedLoginFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkHasUnsavedKeys() {
|
||||||
|
suspend {
|
||||||
|
session.hasUnsavedKeys()
|
||||||
|
}.execute {
|
||||||
|
copy(hasUnsavedKeys = it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getSupportedLoginFlow() {
|
private fun getSupportedLoginFlow() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
authenticationService.cancelPendingLoginOrRegistration()
|
authenticationService.cancelPendingLoginOrRegistration()
|
||||||
|
@ -30,13 +30,12 @@ data class SoftLogoutViewState(
|
|||||||
val userId: String,
|
val userId: String,
|
||||||
val deviceId: String,
|
val deviceId: String,
|
||||||
val userDisplayName: String,
|
val userDisplayName: String,
|
||||||
val hasUnsavedKeys: Boolean,
|
val hasUnsavedKeys: Async<Boolean> = Uninitialized,
|
||||||
val enteredPassword: String = ""
|
val enteredPassword: String = ""
|
||||||
) : MavericksState {
|
) : MavericksState {
|
||||||
|
|
||||||
fun isLoading(): Boolean {
|
val isLoading: Boolean =
|
||||||
return asyncLoginAction is Loading ||
|
asyncLoginAction is Loading ||
|
||||||
// Keep loading when it is success because of the delay to switch to the next Activity
|
// Keep loading when it is success because of the delay to switch to the next Activity
|
||||||
asyncLoginAction is Success
|
asyncLoginAction is Success
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -130,14 +130,14 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS
|
|||||||
/**
|
/**
|
||||||
* Safe way to get the number of keys to backup
|
* Safe way to get the number of keys to backup
|
||||||
*/
|
*/
|
||||||
fun getNumberOfKeysToBackup(): Int {
|
private suspend fun getNumberOfKeysToBackup(): Int {
|
||||||
return session.cryptoService().inboundGroupSessionsCount(false)
|
return session.cryptoService().inboundGroupSessionsCount(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Safe way to tell if there are more keys on the server
|
* Safe way to tell if there are more keys on the server
|
||||||
*/
|
*/
|
||||||
fun canRestoreKeys(): Boolean {
|
private suspend fun canRestoreKeys(): Boolean {
|
||||||
return session.cryptoService().keysBackupService().canRestoreKeys()
|
return session.cryptoService().keysBackupService().canRestoreKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,5 +161,5 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handle(action: EmptyAction) {}
|
override fun handle(action: EmptyAction) = Unit
|
||||||
}
|
}
|
||||||
|
@ -17,17 +17,25 @@
|
|||||||
package im.vector.app.features.workers.signout
|
package im.vector.app.features.workers.signout
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.cannotLogoutSafely
|
import im.vector.app.core.extensions.cannotLogoutSafely
|
||||||
import im.vector.app.core.extensions.singletonEntryPoint
|
import im.vector.app.core.extensions.singletonEntryPoint
|
||||||
import im.vector.app.features.MainActivity
|
import im.vector.app.features.MainActivity
|
||||||
import im.vector.app.features.MainActivityArgs
|
import im.vector.app.features.MainActivityArgs
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
|
||||||
class SignOutUiWorker(private val activity: FragmentActivity) {
|
class SignOutUiWorker(private val activity: FragmentActivity) {
|
||||||
|
|
||||||
fun perform() {
|
fun perform() {
|
||||||
val session = activity.singletonEntryPoint().activeSessionHolder().getSafeActiveSession() ?: return
|
val session = activity.singletonEntryPoint().activeSessionHolder().getSafeActiveSession() ?: return
|
||||||
|
activity.lifecycleScope.perform(session)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun CoroutineScope.perform(session: Session) = launch {
|
||||||
if (session.cannotLogoutSafely()) {
|
if (session.cannotLogoutSafely()) {
|
||||||
// The backup check on logout flow has to be displayed if there are keys in the store, and the keys backup state is not Ready
|
// The backup check on logout flow has to be displayed if there are keys in the store, and the keys backup state is not Ready
|
||||||
val signOutDialog = SignOutBottomSheetDialogFragment.newInstance()
|
val signOutDialog = SignOutBottomSheetDialogFragment.newInstance()
|
||||||
|
Loading…
Reference in New Issue
Block a user