mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-12-28 03:48:37 +03:00
Use ImportKeysResult to notify sessions listeners
This commit is contained in:
parent
ee6eec041a
commit
24dc52e4f6
11 changed files with 118 additions and 29 deletions
|
@ -134,6 +134,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
private val crossSigningService: CrossSigningService,
|
||||
private val verificationService: RustVerificationService,
|
||||
private val keysBackupService: RustKeyBackupService,
|
||||
private val megolmSessionImportManager: MegolmSessionImportManager,
|
||||
private val olmMachineProvider: OlmMachineProvider
|
||||
) : CryptoService {
|
||||
|
||||
|
@ -152,9 +153,6 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
private val outgoingRequestsLock: Mutex = Mutex()
|
||||
private val roomKeyShareLocks: ConcurrentHashMap<String, Mutex> = ConcurrentHashMap()
|
||||
|
||||
// TODO does this need to be concurrent?
|
||||
private val newSessionListeners = ArrayList<NewSessionListener>()
|
||||
|
||||
fun onStateEvent(roomId: String, event: Event) {
|
||||
when (event.getClearType()) {
|
||||
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
|
||||
|
@ -675,17 +673,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
roomId: String,
|
||||
sessionId: String,
|
||||
) {
|
||||
// The sender key is actually unused since it's unimportant for megolm
|
||||
// Our events don't contain the info so pass an empty string until we
|
||||
// change the listener definition
|
||||
val senderKey = ""
|
||||
|
||||
newSessionListeners.forEach {
|
||||
try {
|
||||
it.onNewSession(roomId, senderKey, sessionId)
|
||||
} catch (e: Throwable) {
|
||||
}
|
||||
}
|
||||
megolmSessionImportManager.dispatchNewSession(roomId, sessionId)
|
||||
}
|
||||
|
||||
suspend fun receiveSyncChanges(
|
||||
|
@ -886,7 +874,9 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
override suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
|
||||
password: String,
|
||||
progressListener: ProgressListener?): ImportRoomKeysResult {
|
||||
val result = olmMachine.importKeys(roomKeysAsArray, password, progressListener)
|
||||
val result = olmMachine.importKeys(roomKeysAsArray, password, progressListener).also {
|
||||
megolmSessionImportManager.dispatchKeyImportResults(it)
|
||||
}
|
||||
keysBackupService.maybeBackupKeys()
|
||||
|
||||
return result
|
||||
|
@ -1030,11 +1020,11 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
}
|
||||
|
||||
override fun addNewSessionListener(newSessionListener: NewSessionListener) {
|
||||
if (!newSessionListeners.contains(newSessionListener)) newSessionListeners.add(newSessionListener)
|
||||
megolmSessionImportManager.addListener(newSessionListener)
|
||||
}
|
||||
|
||||
override fun removeSessionListener(listener: NewSessionListener) {
|
||||
newSessionListeners.remove(listener)
|
||||
megolmSessionImportManager.removeListener(listener)
|
||||
}
|
||||
/* ==========================================================================================
|
||||
* DEBUG INFO
|
||||
|
|
|
@ -44,6 +44,7 @@ import timber.log.Timber
|
|||
import java.util.concurrent.Executors
|
||||
import javax.inject.Inject
|
||||
|
||||
@Deprecated("rust")
|
||||
@SessionScope
|
||||
internal class IncomingGossipingRequestManager @Inject constructor(
|
||||
@SessionId private val sessionId: String,
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Helper that allows listeners to be notified when a new megolm session
|
||||
* has been added to the crypto layer (could be via room keys or forward keys via sync
|
||||
* or after importing keys from key backup or manual import).
|
||||
* Can be used to refresh display when the keys are received after the message
|
||||
*/
|
||||
@SessionScope
|
||||
internal class MegolmSessionImportManager @Inject constructor(
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val cryptoCoroutineScope: CoroutineScope
|
||||
) {
|
||||
|
||||
private val newSessionsListeners = mutableListOf<NewSessionListener>()
|
||||
|
||||
fun addListener(listener: NewSessionListener) {
|
||||
synchronized(newSessionsListeners) {
|
||||
if (!newSessionsListeners.contains(listener)) {
|
||||
newSessionsListeners.add(listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeListener(listener: NewSessionListener) {
|
||||
synchronized(newSessionsListeners) {
|
||||
newSessionsListeners.remove(listener)
|
||||
}
|
||||
}
|
||||
|
||||
fun dispatchNewSession(roomId: String?, sessionId: String) {
|
||||
val copy = synchronized(newSessionsListeners) {
|
||||
newSessionsListeners.toList()
|
||||
}
|
||||
cryptoCoroutineScope.launch(coroutineDispatchers.computation) {
|
||||
copy.forEach {
|
||||
tryOrNull("Failed to dispatch new session import") {
|
||||
it.onNewSession(roomId, sessionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun dispatchKeyImportResults(result: ImportRoomKeysResult) {
|
||||
result.importedSessionInfo.forEach { (roomId, senderToSessionIdMap) ->
|
||||
senderToSessionIdMap.values.forEach { sessionList ->
|
||||
sessionList.forEach { sessionId ->
|
||||
dispatchNewSession(roomId, sessionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,5 +16,5 @@
|
|||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
interface NewSessionListener {
|
||||
fun onNewSession(roomId: String?, senderKey: String, sessionId: String)
|
||||
fun onNewSession(roomId: String?, sessionId: String)
|
||||
}
|
||||
|
|
|
@ -510,8 +510,7 @@ internal class OlmMachine(
|
|||
|
||||
val result = inner.importKeys(decodedKeys, passphrase, rustListener)
|
||||
|
||||
// TODO do we want to remove the cast here?
|
||||
ImportRoomKeysResult(result.total.toInt(), result.imported.toInt())
|
||||
ImportRoomKeysResult.fromOlm(result)
|
||||
}
|
||||
|
||||
@Throws(CryptoStoreException::class)
|
||||
|
@ -520,13 +519,14 @@ internal class OlmMachine(
|
|||
listener: ProgressListener?
|
||||
): ImportRoomKeysResult =
|
||||
withContext(Dispatchers.IO) {
|
||||
|
||||
val adapter = MoshiProvider.providesMoshi().adapter(List::class.java)
|
||||
|
||||
// If the key backup is too big we take the risk of causing OOM
|
||||
// when serializing to json
|
||||
// so let's chunk to avoid it
|
||||
var totalImported = 0L
|
||||
var accTotal = 0L
|
||||
val details = mutableMapOf<String, Map<String, List<String>>>()
|
||||
keys.chunked(500)
|
||||
.forEach { keysSlice ->
|
||||
val encodedKeys = adapter.toJson(keysSlice)
|
||||
|
@ -540,9 +540,10 @@ internal class OlmMachine(
|
|||
inner.importDecryptedKeys(encodedKeys, rustListener).let {
|
||||
totalImported += it.imported
|
||||
accTotal += it.total
|
||||
details.putAll(it.keys)
|
||||
}
|
||||
}
|
||||
ImportRoomKeysResult(totalImported.toInt(), accTotal.toInt())
|
||||
ImportRoomKeysResult(totalImported.toInt(), accTotal.toInt(), details)
|
||||
}
|
||||
|
||||
@Throws(CryptoStoreException::class)
|
||||
|
|
|
@ -72,11 +72,11 @@ internal class RoomDecryptorProvider @Inject constructor(
|
|||
val alg = when (algorithm) {
|
||||
MXCRYPTO_ALGORITHM_MEGOLM -> megolmDecryptionFactory.create().apply {
|
||||
this.newSessionListener = object : NewSessionListener {
|
||||
override fun onNewSession(roomId: String?, senderKey: String, sessionId: String) {
|
||||
override fun onNewSession(roomId: String?, sessionId: String) {
|
||||
// PR reviewer: the parameter has been renamed so is now in conflict with the parameter of getOrCreateRoomDecryptor
|
||||
newSessionListeners.forEach {
|
||||
try {
|
||||
it.onNewSession(roomId, senderKey, sessionId)
|
||||
it.onNewSession(roomId, sessionId)
|
||||
} catch (e: Throwable) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,6 +103,6 @@ internal class MegolmSessionDataImporter @Inject constructor(private val olmDevi
|
|||
|
||||
Timber.v("## importMegolmSessionsData : sessions import " + (t1 - t0) + " ms (" + megolmSessionsData.size + " sessions)")
|
||||
|
||||
return ImportRoomKeysResult(totalNumbersOfKeys, totalNumbersOfImportedKeys)
|
||||
return ImportRoomKeysResult(totalNumbersOfKeys, totalNumbersOfImportedKeys, emptyMap())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -317,7 +317,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
|||
*/
|
||||
override fun onNewSession(senderKey: String, sessionId: String) {
|
||||
Timber.tag(loggerTag.value).v("ON NEW SESSION $sessionId - $senderKey")
|
||||
newSessionListener?.onNewSession(null, senderKey, sessionId)
|
||||
newSessionListener?.onNewSession(null, sessionId)
|
||||
}
|
||||
|
||||
override fun hasKeysForKeyRequest(request: IncomingRoomKeyRequest): Boolean {
|
||||
|
|
|
@ -39,6 +39,7 @@ 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.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
|
||||
import org.matrix.android.sdk.internal.crypto.MegolmSessionData
|
||||
import org.matrix.android.sdk.internal.crypto.MegolmSessionImportManager
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachineProvider
|
||||
import org.matrix.android.sdk.internal.crypto.RequestSender
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust
|
||||
|
@ -74,6 +75,7 @@ internal class RustKeyBackupService @Inject constructor(
|
|||
olmMachineProvider: OlmMachineProvider,
|
||||
private val sender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val megolmSessionImportManager: MegolmSessionImportManager,
|
||||
private val cryptoCoroutineScope: CoroutineScope,
|
||||
) : KeysBackupService {
|
||||
companion object {
|
||||
|
@ -545,7 +547,9 @@ internal class RustKeyBackupService @Inject constructor(
|
|||
null
|
||||
}
|
||||
|
||||
val result = olmMachine.importDecryptedKeys(sessionsData, progressListener)
|
||||
val result = olmMachine.importDecryptedKeys(sessionsData, progressListener).also {
|
||||
megolmSessionImportManager.dispatchKeyImportResults(it)
|
||||
}
|
||||
|
||||
// Do not back up the key if it comes from a backup recovery
|
||||
if (backUp) {
|
||||
|
|
|
@ -16,5 +16,21 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.crypto.model
|
||||
|
||||
import uniffi.olm.KeysImportResult
|
||||
|
||||
data class ImportRoomKeysResult(val totalNumberOfKeys: Int,
|
||||
val successfullyNumberOfImportedKeys: Int)
|
||||
val successfullyNumberOfImportedKeys: Int,
|
||||
/**It's a map from room id to a map of the sender key to a list of session*/
|
||||
val importedSessionInfo: Map<String, Map<String, List<String>>>
|
||||
) {
|
||||
|
||||
companion object {
|
||||
fun fromOlm(result: KeysImportResult): ImportRoomKeysResult {
|
||||
return ImportRoomKeysResult(
|
||||
result.total.toInt(),
|
||||
result.imported.toInt(),
|
||||
result.keys
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ internal class TimelineEventDecryptor @Inject constructor(
|
|||
) {
|
||||
|
||||
private val newSessionListener = object : NewSessionListener {
|
||||
override fun onNewSession(roomId: String?, senderKey: String, sessionId: String) {
|
||||
override fun onNewSession(roomId: String?, sessionId: String) {
|
||||
synchronized(unknownSessionsFailure) {
|
||||
unknownSessionsFailure[sessionId]
|
||||
?.toList()
|
||||
|
|
Loading…
Reference in a new issue