Crypto: continue cleaning. Need threading refactoring

This commit is contained in:
ganfra 2019-06-03 18:39:37 +02:00
parent 784d55c16c
commit 3d50393b33
30 changed files with 462 additions and 466 deletions

View File

@ -19,4 +19,4 @@ package im.vector.matrix.android
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.Dispatchers.Main

internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main, Main)
internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main)

View File

@ -135,20 +135,20 @@ data class Event(
internal fun setClearData(decryptionResult: MXEventDecryptionResult?) {
mClearEvent = null
if (decryptionResult != null) {
if (decryptionResult.mClearEvent != null) {
if (decryptionResult.clearEvent != null) {
val adapter = MoshiProvider.providesMoshi().adapter(Event::class.java)
mClearEvent = adapter.fromJsonValue(decryptionResult.mClearEvent)
mClearEvent = adapter.fromJsonValue(decryptionResult.clearEvent)

}
mClearEvent?.apply {
mSenderCurve25519Key = decryptionResult.mSenderCurve25519Key
mClaimedEd25519Key = decryptionResult.mClaimedEd25519Key
mForwardingCurve25519KeyChain = decryptionResult.mForwardingCurve25519KeyChain
mSenderCurve25519Key = decryptionResult.senderCurve25519Key
mClaimedEd25519Key = decryptionResult.claimedEd25519Key
mForwardingCurve25519KeyChain = decryptionResult.forwardingCurve25519KeyChain
try {
// Add "m.relates_to" data from e2e event to the unencrypted event
// TODO
//if (getWireContent().getAsJsonObject().has("m.relates_to")) {
// mClearEvent!!.getContentAsJsonObject()
// clearEvent!!.getContentAsJsonObject()
// .add("m.relates_to", getWireContent().getAsJsonObject().get("m.relates_to"))
//}
} catch (e: Exception) {
@ -193,7 +193,7 @@ data class Event(
}

/**
* @return the event type
* @return the event content
*/
fun getClearContent(): Content? {
return mClearEvent?.content ?: content

View File

@ -22,44 +22,40 @@ import android.os.Handler
import android.os.HandlerThread
import android.os.Looper

private const val THREAD_ENCRYPT_NAME = "Crypto_Encrypt_Thread"
private const val THREAD_DECRYPT_NAME = "Crypto_Decrypt_Thread"
private const val THREAD_CRYPTO_NAME = "Crypto_Thread"

// TODO Remove and replace by Task
internal object CryptoAsyncHelper {

private var uiHandler: Handler? = null
private var decryptBackgroundHandler: Handler? = null
private var encryptBackgroundHandler: Handler? = null
private var cryptoBackgroundHandler: Handler? = null

fun getUiHandler(): Handler {
return uiHandler
?: Handler(Looper.getMainLooper())
.also { uiHandler = it }
?: Handler(Looper.getMainLooper())
.also { uiHandler = it }
}


fun getDecryptBackgroundHandler(): Handler {
return decryptBackgroundHandler
?: createDecryptBackgroundHandler()
.also { decryptBackgroundHandler = it }
return getCryptoBackgroundHandler()
}

fun getEncryptBackgroundHandler(): Handler {
return encryptBackgroundHandler
?: createEncryptBackgroundHandler()
.also { encryptBackgroundHandler = it }
return getCryptoBackgroundHandler()
}

private fun createDecryptBackgroundHandler(): Handler {
val handlerThread = HandlerThread(THREAD_DECRYPT_NAME)
private fun getCryptoBackgroundHandler(): Handler {
return cryptoBackgroundHandler
?: createCryptoBackgroundHandler()
.also { cryptoBackgroundHandler = it }
}

private fun createCryptoBackgroundHandler(): Handler {
val handlerThread = HandlerThread(THREAD_CRYPTO_NAME)
handlerThread.start()
return Handler(handlerThread.looper)
}

private fun createEncryptBackgroundHandler(): Handler {
val handlerThread = HandlerThread(THREAD_ENCRYPT_NAME)
handlerThread.start()
return Handler(handlerThread.looper)
}

}

View File

@ -49,7 +49,6 @@ import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import im.vector.matrix.android.internal.crypto.model.event.RoomKeyContent
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
@ -488,8 +487,8 @@ internal class CryptoManager(
cryptoStore.storeRoomAlgorithm(roomId, algorithm!!)

val alg: IMXEncrypting = when (algorithm) {
MXCRYPTO_ALGORITHM_MEGOLM -> megolmEncryptionFactory.instantiate(roomId)
else -> olmEncryptionFactory.instantiate(roomId)
MXCRYPTO_ALGORITHM_MEGOLM -> megolmEncryptionFactory.create(roomId)
else -> olmEncryptionFactory.create(roomId)
}

synchronized(roomEncryptors) {
@ -544,20 +543,6 @@ internal class CryptoManager(
return if (null != map) ArrayList(map.values) else ArrayList()
}

// TODO Remove ?
/**
* Try to make sure we have established olm sessions for the given devices.
* It must be called in getCryptoHandler() thread.
* The callback is called in the UI thread.
*
* @param devicesByUser a map from userid to list of devices.
* @param callback the asynchronous callback
*/
fun ensureOlmSessionsForDevices(devicesByUser: Map<String, List<MXDeviceInfo>>,
callback: MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>>?) {
ensureOlmSessionsForDevicesAction.handle(devicesByUser, callback)
}

fun isEncryptionEnabledForInvitedUser(): Boolean {
return cryptoConfig.mEnableEncryptionForInvitedMembers
}
@ -602,7 +587,7 @@ internal class CryptoManager(
var alg = synchronized(roomEncryptors) {
roomEncryptors[roomId]
}
if (null == alg) {
if (alg == null) {
val algorithm = getEncryptionAlgorithm(roomId)
if (null != algorithm) {
if (setEncryptionInRoom(roomId, algorithm, false, userIds)) {
@ -613,7 +598,7 @@ internal class CryptoManager(
}
}

if (null != alg) {
if (alg != null) {
val t0 = System.currentTimeMillis()
Timber.v("## encryptEventContent() starts")

@ -739,7 +724,7 @@ internal class CryptoManager(
* @param event the encryption event.
*/
private fun onRoomEncryptionEvent(roomId: String, event: Event) {
CoroutineScope(coroutineDispatchers.encryption).launch {
CoroutineScope(coroutineDispatchers.crypto).launch {
val params = LoadRoomMembersTask.Params(roomId)
loadRoomMembersTask
.execute(params)

View File

@ -69,8 +69,8 @@ internal class CryptoModule {
// CryptoStore
scope(DefaultSession.SCOPE) {
RealmCryptoStore(false /* TODO*/,
get("CryptoRealmConfiguration"),
get()) as IMXCryptoStore
get("CryptoRealmConfiguration"),
get()) as IMXCryptoStore
}

scope(DefaultSession.SCOPE) {
@ -123,7 +123,7 @@ internal class CryptoModule {
}

scope(DefaultSession.SCOPE) {
EnsureOlmSessionsForDevicesAction(get(), get(), get())
EnsureOlmSessionsForDevicesAction(get(), get(), get(), get())
}

scope(DefaultSession.SCOPE) {
@ -146,7 +146,7 @@ internal class CryptoModule {
// Factories
scope(DefaultSession.SCOPE) {
MXMegolmDecryptionFactory(
get(), get(), get(), get(), get(), get(), get(), get(), get()
get(), get(), get(), get(), get(), get(), get(), get(), get(), get()
)
}

@ -164,7 +164,7 @@ internal class CryptoModule {

scope(DefaultSession.SCOPE) {
MXOlmEncryptionFactory(
get(), get(), get(), get(), get()
get(), get(), get(), get(), get(),get()
)
}

@ -217,7 +217,7 @@ internal class CryptoModule {

// Device list
scope(DefaultSession.SCOPE) {
DeviceListManager(get(), get(), get(), get(), get(), get())
DeviceListManager(get(), get(), get(), get(), get(), get(), get())
}

// Crypto tasks

View File

@ -28,7 +28,9 @@ import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import im.vector.matrix.android.internal.crypto.tasks.DownloadKeysForUsersTask
import im.vector.matrix.android.internal.session.sync.SyncTokenStore
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.TaskThread
import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import timber.log.Timber
import java.util.*

@ -38,6 +40,7 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore,
private val syncTokenStore: SyncTokenStore,
private val credentials: Credentials,
private val downloadKeysForUsersTask: DownloadKeysForUsersTask,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val taskExecutor: TaskExecutor) {

// keys in progress
@ -457,6 +460,7 @@ internal class DeviceListManager(private val cryptoStore: IMXCryptoStore,

downloadKeysForUsersTask
.configureWith(DownloadKeysForUsersTask.Params(filteredUsers, syncTokenStore.getLastToken()))
.executeOn(TaskThread.ENCRYPTION)
.dispatchTo(object : MatrixCallback<KeysQueryResponse> {
override fun onSuccess(data: KeysQueryResponse) {
CryptoAsyncHelper.getEncryptBackgroundHandler().post {

View File

@ -30,34 +30,34 @@ open class IncomingRoomKeyRequest {
/**
* The user id
*/
var mUserId: String? = null
var userId: String? = null

/**
* The device id
*/
var mDeviceId: String? = null
var deviceId: String? = null

/**
* The request id
*/
var mRequestId: String? = null
var requestId: String? = null

/**
* The request body
*/
var mRequestBody: RoomKeyRequestBody? = null
var requestBody: RoomKeyRequestBody? = null

/**
* The runnable to call to accept to share the keys
*/
@Transient
var mShare: Runnable? = null
var share: Runnable? = null

/**
* The runnable to call to ignore the key share request.
*/
@Transient
var mIgnore: Runnable? = null
var ignore: Runnable? = null

/**
* Constructor
@ -65,11 +65,11 @@ open class IncomingRoomKeyRequest {
* @param event the event
*/
constructor(event: Event) {
mUserId = event.sender
userId = event.sender
val roomKeyShareRequest = event.getClearContent().toModel<RoomKeyShareRequest>()!!
mDeviceId = roomKeyShareRequest.requestingDeviceId
mRequestId = roomKeyShareRequest.requestId
mRequestBody = if (null != roomKeyShareRequest.body) roomKeyShareRequest.body else RoomKeyRequestBody()
deviceId = roomKeyShareRequest.requestingDeviceId
requestId = roomKeyShareRequest.requestId
requestBody = if (null != roomKeyShareRequest.body) roomKeyShareRequest.body else RoomKeyRequestBody()
}

/**

View File

@ -24,6 +24,6 @@ import im.vector.matrix.android.api.session.events.model.Event
class IncomingRoomKeyRequestCancellation(event: Event) : IncomingRoomKeyRequest(event) {

init {
mRequestBody = null
requestBody = null
}
}

View File

@ -80,13 +80,13 @@ internal class IncomingRoomKeyRequestManager(

if (null != receivedRoomKeyRequests) {
for (request in receivedRoomKeyRequests!!) {
val userId = request.mUserId!!
val deviceId = request.mDeviceId
val body = request.mRequestBody
val userId = request.userId!!
val deviceId = request.deviceId
val body = request.requestBody
val roomId = body!!.roomId
val alg = body.algorithm

Timber.v("m.room_key_request from " + userId + ":" + deviceId + " for " + roomId + " / " + body.sessionId + " id " + request.mRequestId)
Timber.v("m.room_key_request from " + userId + ":" + deviceId + " for " + roomId + " / " + body.sessionId + " id " + request.requestId)

if (!TextUtils.equals(mCredentials.userId, userId)) {
// TODO: determine if we sent this device the keys already: in
@ -119,12 +119,12 @@ internal class IncomingRoomKeyRequestManager(
continue
}

request.mShare = Runnable {
request.share = Runnable {
decryptor.shareKeysWithDevice(request)
mCryptoStore.deleteIncomingRoomKeyRequest(request)
}

request.mIgnore = Runnable { mCryptoStore.deleteIncomingRoomKeyRequest(request) }
request.ignore = Runnable { mCryptoStore.deleteIncomingRoomKeyRequest(request) }

// if the device is verified already, share the keys
val device = mCryptoStore.getUserDevice(deviceId!!, userId)
@ -133,7 +133,7 @@ internal class IncomingRoomKeyRequestManager(
if (device.isVerified) {
Timber.v("## processReceivedRoomKeyRequests() : device is already verified: sharing keys")
mCryptoStore.deleteIncomingRoomKeyRequest(request)
request.mShare!!.run()
request.share!!.run()
continue
}

@ -160,8 +160,8 @@ internal class IncomingRoomKeyRequestManager(

if (null != receivedRoomKeyRequestCancellations) {
for (request in receivedRoomKeyRequestCancellations!!) {
Timber.v("## ## processReceivedRoomKeyRequests() : m.room_key_request cancellation for " + request.mUserId
+ ":" + request.mDeviceId + " id " + request.mRequestId)
Timber.v("## ## processReceivedRoomKeyRequests() : m.room_key_request cancellation for " + request.userId
+ ":" + request.deviceId + " id " + request.requestId)

// we should probably only notify the app of cancellations we told it
// about, but we don't currently have a record of that, so we just pass

View File

@ -28,23 +28,23 @@ data class MXEventDecryptionResult(
/**
* The plaintext payload for the event (typically containing "type" and "content" fields).
*/
var mClearEvent: JsonDict? = null,
var clearEvent: JsonDict? = null,

/**
* Key owned by the sender of this event.
* See MXEvent.senderKey.
*/
var mSenderCurve25519Key: String? = null,
var senderCurve25519Key: String? = null,

/**
* Ed25519 key claimed by the sender of this event.
* See MXEvent.claimedEd25519Key.
*/
var mClaimedEd25519Key: String? = null,
var claimedEd25519Key: String? = null,

/**
* List of curve25519 keys involved in telling us about the senderCurve25519Key and
* claimedEd25519Key. See MXEvent.forwardingCurve25519KeyChain.
*/
var mForwardingCurve25519KeyChain: List<String> = ArrayList()
var forwardingCurve25519KeyChain: List<String> = ArrayList()
)

View File

@ -32,25 +32,25 @@ import timber.log.Timber
import java.util.*

internal class OutgoingRoomKeyRequestManager(
private val mCryptoStore: IMXCryptoStore,
private val mSendToDeviceTask: SendToDeviceTask,
private val mTaskExecutor: TaskExecutor) {
private val cryptoStore: IMXCryptoStore,
private val sendToDeviceTask: SendToDeviceTask,
private val taskExecutor: TaskExecutor) {

// running
private var mClientRunning: Boolean = false
private var isClientRunning: Boolean = false

// transaction counter
private var mTxnCtr: Int = 0
private var txnCtr: Int = 0

// sanity check to ensure that we don't end up with two concurrent runs
// of mSendOutgoingRoomKeyRequestsTimer
private var mSendOutgoingRoomKeyRequestsRunning: Boolean = false
// of sendOutgoingRoomKeyRequestsTimer
private var sendOutgoingRoomKeyRequestsRunning: Boolean = false

/**
* Called when the client is started. Sets background processes running.
*/
fun start() {
mClientRunning = true
isClientRunning = true
startTimer()
}

@ -58,7 +58,7 @@ internal class OutgoingRoomKeyRequestManager(
* Called when the client is stopped. Stops any running background processes.
*/
fun stop() {
mClientRunning = false
isClientRunning = false
}

/**
@ -67,7 +67,7 @@ internal class OutgoingRoomKeyRequestManager(
* @return {string} a new, unique, transaction id
*/
private fun makeTxnId(): String {
return "m" + System.currentTimeMillis() + "." + mTxnCtr++
return "m" + System.currentTimeMillis() + "." + txnCtr++
}

/**
@ -83,7 +83,7 @@ internal class OutgoingRoomKeyRequestManager(
* @param recipients recipients
*/
fun sendRoomKeyRequest(requestBody: RoomKeyRequestBody?, recipients: List<Map<String, String>>) {
val req = mCryptoStore.getOrAddOutgoingRoomKeyRequest(
val req = cryptoStore.getOrAddOutgoingRoomKeyRequest(
OutgoingRoomKeyRequest(requestBody, recipients, makeTxnId(), OutgoingRoomKeyRequest.RequestState.UNSENT))


@ -117,9 +117,9 @@ internal class OutgoingRoomKeyRequestManager(
* @param andResend true to resend the key request
*/
private fun cancelRoomKeyRequest(requestBody: RoomKeyRequestBody, andResend: Boolean) {
val req = mCryptoStore.getOutgoingRoomKeyRequest(requestBody)
?: // no request was made for this key
return
val req = cryptoStore.getOutgoingRoomKeyRequest(requestBody)
?: // no request was made for this key
return

Timber.v("cancelRoomKeyRequest: requestId: " + req.mRequestId + " state: " + req.mState + " andResend: " + andResend)

@ -127,7 +127,7 @@ internal class OutgoingRoomKeyRequestManager(
// nothing to do here
} else if (req.mState === OutgoingRoomKeyRequest.RequestState.UNSENT || req.mState === OutgoingRoomKeyRequest.RequestState.FAILED) {
Timber.v("## cancelRoomKeyRequest() : deleting unnecessary room key request for $requestBody")
mCryptoStore.deleteOutgoingRoomKeyRequest(req.mRequestId)
cryptoStore.deleteOutgoingRoomKeyRequest(req.mRequestId)
} else if (req.mState === OutgoingRoomKeyRequest.RequestState.SENT) {
if (andResend) {
req.mState = OutgoingRoomKeyRequest.RequestState.CANCELLATION_PENDING_AND_WILL_RESEND
@ -135,7 +135,7 @@ internal class OutgoingRoomKeyRequestManager(
req.mState = OutgoingRoomKeyRequest.RequestState.CANCELLATION_PENDING
}
req.mCancellationTxnId = makeTxnId()
mCryptoStore.updateOutgoingRoomKeyRequest(req)
cryptoStore.updateOutgoingRoomKeyRequest(req)
sendOutgoingRoomKeyRequestCancellation(req)
}
}
@ -145,17 +145,17 @@ internal class OutgoingRoomKeyRequestManager(
* Start the background timer to send queued requests, if the timer isn't already running.
*/
private fun startTimer() {
if (mSendOutgoingRoomKeyRequestsRunning) {
if (sendOutgoingRoomKeyRequestsRunning) {
return
}

Handler().postDelayed(Runnable {
if (mSendOutgoingRoomKeyRequestsRunning) {
if (sendOutgoingRoomKeyRequestsRunning) {
Timber.v("## startTimer() : RoomKeyRequestSend already in progress!")
return@Runnable
}

mSendOutgoingRoomKeyRequestsRunning = true
sendOutgoingRoomKeyRequestsRunning = true
sendOutgoingRoomKeyRequests()
}, SEND_KEY_REQUESTS_DELAY_MS.toLong())
}
@ -164,20 +164,20 @@ internal class OutgoingRoomKeyRequestManager(
// there are no more requests, or there is an error (in which case, the
// timer will be restarted before the promise resolves).
private fun sendOutgoingRoomKeyRequests() {
if (!mClientRunning) {
mSendOutgoingRoomKeyRequestsRunning = false
if (!isClientRunning) {
sendOutgoingRoomKeyRequestsRunning = false
return
}

Timber.v("## sendOutgoingRoomKeyRequests() : Looking for queued outgoing room key requests")
val outgoingRoomKeyRequest = mCryptoStore.getOutgoingRoomKeyRequestByState(
val outgoingRoomKeyRequest = cryptoStore.getOutgoingRoomKeyRequestByState(
HashSet<OutgoingRoomKeyRequest.RequestState>(Arrays.asList<OutgoingRoomKeyRequest.RequestState>(OutgoingRoomKeyRequest.RequestState.UNSENT,
OutgoingRoomKeyRequest.RequestState.CANCELLATION_PENDING,
OutgoingRoomKeyRequest.RequestState.CANCELLATION_PENDING_AND_WILL_RESEND)))

if (null == outgoingRoomKeyRequest) {
Timber.e("## sendOutgoingRoomKeyRequests() : No more outgoing room key requests")
mSendOutgoingRoomKeyRequestsRunning = false
sendOutgoingRoomKeyRequestsRunning = false
return
}

@ -198,7 +198,7 @@ internal class OutgoingRoomKeyRequestManager(
+ " from " + request.mRecipients + " id " + request.mRequestId)

val requestMessage = RoomKeyShareRequest()
requestMessage.requestingDeviceId = mCryptoStore.getDeviceId()
requestMessage.requestingDeviceId = cryptoStore.getDeviceId()
requestMessage.requestId = request.mRequestId
requestMessage.body = request.mRequestBody

@ -208,10 +208,10 @@ internal class OutgoingRoomKeyRequestManager(
Timber.v("## sendOutgoingRoomKeyRequest() : Cannot update room key request from UNSENT as it was already updated to " + request.mState)
} else {
request.mState = state
mCryptoStore.updateOutgoingRoomKeyRequest(request)
cryptoStore.updateOutgoingRoomKeyRequest(request)
}

mSendOutgoingRoomKeyRequestsRunning = false
sendOutgoingRoomKeyRequestsRunning = false
startTimer()
}

@ -238,13 +238,13 @@ internal class OutgoingRoomKeyRequestManager(
+ " cancellation id " + request.mCancellationTxnId)

val roomKeyShareCancellation = RoomKeyShareCancellation()
roomKeyShareCancellation.requestingDeviceId = mCryptoStore.getDeviceId()
roomKeyShareCancellation.requestingDeviceId = cryptoStore.getDeviceId()
roomKeyShareCancellation.requestId = request.mCancellationTxnId

sendMessageToDevices(roomKeyShareCancellation, request.mRecipients, request.mCancellationTxnId, object : MatrixCallback<Unit> {
private fun onDone() {
mCryptoStore.deleteOutgoingRoomKeyRequest(request.mRequestId)
mSendOutgoingRoomKeyRequestsRunning = false
cryptoStore.deleteOutgoingRoomKeyRequest(request.mRequestId)
sendOutgoingRoomKeyRequestsRunning = false
startTimer()
}

@ -286,9 +286,9 @@ internal class OutgoingRoomKeyRequestManager(
contentMap.setObject(message, recipient["userId"], recipient["deviceId"]) // TODO Change this two hard coded key to something better
}

mSendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ROOM_KEY_REQUEST, contentMap, transactionId))
sendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ROOM_KEY_REQUEST, contentMap, transactionId))
.dispatchTo(callback)
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
}

companion object {

View File

@ -68,8 +68,8 @@ internal class RoomDecryptorProvider(

if (decryptingClass) {
alg = when (algorithm) {
MXCRYPTO_ALGORITHM_MEGOLM -> mMXMegolmDecryptionFactory.instantiate()
else -> mMXOlmDecryptionFactory.instantiate()
MXCRYPTO_ALGORITHM_MEGOLM -> mMXMegolmDecryptionFactory.create()
else -> mMXOlmDecryptionFactory.create()
}

if (null != alg) {

View File

@ -26,12 +26,14 @@ import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import im.vector.matrix.android.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import timber.log.Timber
import java.util.*

internal class EnsureOlmSessionsForDevicesAction(private val mOlmDevice: MXOlmDevice,
private val mClaimOneTimeKeysForUsersDeviceTask: ClaimOneTimeKeysForUsersDeviceTask,
private val mTaskExecutor: TaskExecutor) {
internal class EnsureOlmSessionsForDevicesAction(private val olmDevice: MXOlmDevice,
private val oneTimeKeysForUsersDeviceTask: ClaimOneTimeKeysForUsersDeviceTask,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val taskExecutor: TaskExecutor) {


fun handle(devicesByUser: Map<String, List<MXDeviceInfo>>, callback: MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>>?) {
@ -48,7 +50,7 @@ internal class EnsureOlmSessionsForDevicesAction(private val mOlmDevice: MXOlmDe
val deviceId = deviceInfo.deviceId
val key = deviceInfo.identityKey()

val sessionId = mOlmDevice.getSessionId(key!!)
val sessionId = olmDevice.getSessionId(key!!)

if (TextUtils.isEmpty(sessionId)) {
devicesWithoutSession.add(deviceInfo)
@ -81,7 +83,8 @@ internal class EnsureOlmSessionsForDevicesAction(private val mOlmDevice: MXOlmDe

Timber.v("## claimOneTimeKeysForUsersDevices() : $usersDevicesToClaim")

mClaimOneTimeKeysForUsersDeviceTask

oneTimeKeysForUsersDeviceTask
.configureWith(ClaimOneTimeKeysForUsersDeviceTask.Params(usersDevicesToClaim))
.dispatchTo(object : MatrixCallback<MXUsersDevicesMap<MXKey>> {
override fun onSuccess(data: MXUsersDevicesMap<MXKey>) {
@ -137,7 +140,7 @@ internal class EnsureOlmSessionsForDevicesAction(private val mOlmDevice: MXOlmDe
callback?.onFailure(failure)
}
})
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
}


@ -153,7 +156,7 @@ internal class EnsureOlmSessionsForDevicesAction(private val mOlmDevice: MXOlmDe
var errorMessage: String? = null

try {
mOlmDevice.verifySignature(deviceInfo.fingerprint()!!, oneTimeKey.signalableJSONDictionary(), signature)
olmDevice.verifySignature(deviceInfo.fingerprint()!!, oneTimeKey.signalableJSONDictionary(), signature)
isVerified = true
} catch (e: Exception) {
errorMessage = e.message
@ -161,7 +164,7 @@ internal class EnsureOlmSessionsForDevicesAction(private val mOlmDevice: MXOlmDe

// Check one-time key signature
if (isVerified) {
sessionId = mOlmDevice.createOutboundSession(deviceInfo.identityKey()!!, oneTimeKey.value)
sessionId = olmDevice.createOutboundSession(deviceInfo.identityKey()!!, oneTimeKey.value)

if (!TextUtils.isEmpty(sessionId)) {
Timber.v("## verifyKeyAndStartSession() : Started new sessionid " + sessionId

View File

@ -26,9 +26,9 @@ import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import timber.log.Timber
import java.util.*

internal class EnsureOlmSessionsForUsersAction(private val mOlmDevice: MXOlmDevice,
private val mCryptoStore: IMXCryptoStore,
private val mEnsureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction) {
internal class EnsureOlmSessionsForUsersAction(private val olmDevice: MXOlmDevice,
private val cryptoStore: IMXCryptoStore,
private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction) {

/**
* Try to make sure we have established olm sessions for the given users.
@ -46,12 +46,12 @@ internal class EnsureOlmSessionsForUsersAction(private val mOlmDevice: MXOlmDevi
for (userId in users) {
devicesByUser[userId] = ArrayList()

val devices = mCryptoStore.getUserDevices(userId)?.values ?: emptyList()
val devices = cryptoStore.getUserDevices(userId)?.values ?: emptyList()

for (device in devices) {
val key = device.identityKey()

if (TextUtils.equals(key, mOlmDevice.deviceCurve25519Key)) {
if (TextUtils.equals(key, olmDevice.deviceCurve25519Key)) {
// Don't bother setting up session to ourself
continue
}
@ -65,6 +65,6 @@ internal class EnsureOlmSessionsForUsersAction(private val mOlmDevice: MXOlmDevi
}
}

mEnsureOlmSessionsForDevicesAction.handle(devicesByUser, callback)
ensureOlmSessionsForDevicesAction.handle(devicesByUser, callback)
}
}

View File

@ -24,7 +24,13 @@ import im.vector.matrix.android.api.session.crypto.MXCryptoError
import im.vector.matrix.android.api.session.events.model.Event
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.*
import im.vector.matrix.android.internal.crypto.CryptoAsyncHelper
import im.vector.matrix.android.internal.crypto.DeviceListManager
import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequest
import im.vector.matrix.android.internal.crypto.MXDecryptionException
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
import im.vector.matrix.android.internal.crypto.MXOlmDevice
import im.vector.matrix.android.internal.crypto.OutgoingRoomKeyRequestManager
import im.vector.matrix.android.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
import im.vector.matrix.android.internal.crypto.actions.MessageEncrypter
import im.vector.matrix.android.internal.crypto.algorithms.IMXDecrypting
@ -39,27 +45,28 @@ import im.vector.matrix.android.internal.crypto.model.rest.ForwardedRoomKeyConte
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
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
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.*

internal class MXMegolmDecryption(private val mCredentials: Credentials,
private val mOlmDevice: MXOlmDevice,
private val mDeviceListManager: DeviceListManager,
private val mOutgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager,
private val mMessageEncrypter: MessageEncrypter,
private val mEnsureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
private val mCryptoStore: IMXCryptoStore,
private val mSendToDeviceTask: SendToDeviceTask,
private val mTaskExecutor: TaskExecutor)
internal class MXMegolmDecryption(private val credentials: Credentials,
private val olmDevice: MXOlmDevice,
private val deviceListManager: DeviceListManager,
private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager,
private val messageEncrypter: MessageEncrypter,
private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
private val cryptoStore: IMXCryptoStore,
private val sendToDeviceTask: SendToDeviceTask,
private val coroutineDispatchers: MatrixCoroutineDispatchers)
: IMXDecrypting {

/**
* Events which we couldn't decrypt due to unknown sessions / indexes: map from
* senderKey|sessionId to timelines to list of MatrixEvents.
*/
private var mPendingEvents: MutableMap<String /* senderKey|sessionId */, MutableMap<String /* timelineId */, MutableList<Event>>> = HashMap()
private var pendingEvents: MutableMap<String /* senderKey|sessionId */, MutableMap<String /* timelineId */, MutableList<Event>>> = HashMap()

@Throws(MXDecryptionException::class)
override fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult? {
@ -72,7 +79,7 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,
val encryptedEventContent = event.content.toModel<EncryptedEventContent>()!!
if (TextUtils.isEmpty(encryptedEventContent.senderKey) || TextUtils.isEmpty(encryptedEventContent.sessionId) || TextUtils.isEmpty(encryptedEventContent.ciphertext)) {
throw MXDecryptionException(MXCryptoError(MXCryptoError.MISSING_FIELDS_ERROR_CODE,
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_FIELDS_REASON))
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_FIELDS_REASON))
}

var eventDecryptionResult: MXEventDecryptionResult? = null
@ -80,24 +87,24 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,
var decryptGroupMessageResult: MXDecryptionResult? = null

try {
decryptGroupMessageResult = mOlmDevice.decryptGroupMessage(encryptedEventContent.ciphertext!!, event.roomId!!, timeline, encryptedEventContent.sessionId!!, encryptedEventContent.senderKey!!)
decryptGroupMessageResult = olmDevice.decryptGroupMessage(encryptedEventContent.ciphertext!!, event.roomId!!, timeline, encryptedEventContent.sessionId!!, encryptedEventContent.senderKey!!)
} catch (e: MXDecryptionException) {
cryptoError = e.cryptoError
}

// the decryption succeeds
if (null != decryptGroupMessageResult && null != decryptGroupMessageResult.mPayload && null == cryptoError) {
if (decryptGroupMessageResult?.mPayload != null && cryptoError == null) {
eventDecryptionResult = MXEventDecryptionResult()

eventDecryptionResult.mClearEvent = decryptGroupMessageResult.mPayload
eventDecryptionResult.mSenderCurve25519Key = decryptGroupMessageResult.mSenderKey
eventDecryptionResult.clearEvent = decryptGroupMessageResult.mPayload
eventDecryptionResult.senderCurve25519Key = decryptGroupMessageResult.mSenderKey

if (null != decryptGroupMessageResult.mKeysClaimed) {
eventDecryptionResult.mClaimedEd25519Key = decryptGroupMessageResult.mKeysClaimed!!["ed25519"]
eventDecryptionResult.claimedEd25519Key = decryptGroupMessageResult.mKeysClaimed!!["ed25519"]
}

eventDecryptionResult.mForwardingCurve25519KeyChain = decryptGroupMessageResult.mForwardingCurve25519KeyChain!!
} else if (null != cryptoError) {
eventDecryptionResult.forwardingCurve25519KeyChain = decryptGroupMessageResult.mForwardingCurve25519KeyChain!!
} else if (cryptoError != null) {
if (cryptoError.isOlmError) {
if (TextUtils.equals("UNKNOWN_MESSAGE_INDEX", cryptoError.message)) {
addEventToPendingList(event, timeline)
@ -120,7 +127,6 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,
requestKeysForEvent(event)
}
}

throw MXDecryptionException(cryptoError)
}

@ -141,11 +147,11 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,
val recipients = ArrayList<Map<String, String>>()

val selfMap = HashMap<String, String>()
selfMap["userId"] = mCredentials.userId // TODO Replace this hard coded keys (see OutgoingRoomKeyRequestManager)
selfMap["userId"] = credentials.userId // TODO Replace this hard coded keys (see OutgoingRoomKeyRequestManager)
selfMap["deviceId"] = "*"
recipients.add(selfMap)

if (!TextUtils.equals(sender, mCredentials.userId)) {
if (!TextUtils.equals(sender, credentials.userId)) {
val senderMap = HashMap<String, String>()
senderMap["userId"] = sender
senderMap["deviceId"] = encryptedEventContent.deviceId!!
@ -159,7 +165,7 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,
requestBody.senderKey = encryptedEventContent.senderKey
requestBody.sessionId = encryptedEventContent.sessionId

mOutgoingRoomKeyRequestManager.sendRoomKeyRequest(requestBody, recipients)
outgoingRoomKeyRequestManager.sendRoomKeyRequest(requestBody, recipients)
}

/**
@ -174,17 +180,17 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,

val k = "${encryptedEventContent.senderKey}|${encryptedEventContent.sessionId}"

if (!mPendingEvents.containsKey(k)) {
mPendingEvents[k] = HashMap()
if (!pendingEvents.containsKey(k)) {
pendingEvents[k] = HashMap()
}

if (!mPendingEvents[k]!!.containsKey(timelineId)) {
mPendingEvents[k]!!.put(timelineId, ArrayList<Event>())
if (!pendingEvents[k]!!.containsKey(timelineId)) {
pendingEvents[k]!!.put(timelineId, ArrayList<Event>())
}

if (mPendingEvents[k]!![timelineId]!!.indexOf(event) < 0) {
if (pendingEvents[k]!![timelineId]!!.indexOf(event) < 0) {
Timber.v("## addEventToPendingList() : add Event " + event.eventId + " in room id " + event.roomId)
mPendingEvents[k]!![timelineId]!!.add(event)
pendingEvents[k]!![timelineId]!!.add(event)
}
}

@ -208,7 +214,7 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,

if (event.getClearType() == EventType.FORWARDED_ROOM_KEY) {
Timber.v("## onRoomKeyEvent(), forward adding key : roomId " + roomKeyContent.roomId + " sessionId " + roomKeyContent.sessionId
+ " sessionKey " + roomKeyContent.sessionKey) // from " + event);
+ " sessionKey " + roomKeyContent.sessionKey) // from " + event);
val forwardedRoomKeyContent = event.getClearContent().toModel<ForwardedRoomKeyContent>()!!

if (null == forwardedRoomKeyContent.forwardingCurve25519KeyChain) {
@ -234,7 +240,7 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,
keysClaimed["ed25519"] = forwardedRoomKeyContent.senderClaimedEd25519Key!!
} else {
Timber.v("## onRoomKeyEvent(), Adding key : roomId " + roomKeyContent.roomId + " sessionId " + roomKeyContent.sessionId
+ " sessionKey " + roomKeyContent.sessionKey) // from " + event);
+ " sessionKey " + roomKeyContent.sessionKey) // from " + event);

if (null == senderKey) {
Timber.e("## onRoomKeyEvent() : key event has no sender key (not encrypted?)")
@ -245,7 +251,7 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,
keysClaimed = event.getKeysClaimed().toMutableMap()
}

val added = mOlmDevice.addInboundGroupSession(roomKeyContent.sessionId!!, roomKeyContent.sessionKey!!, roomKeyContent.roomId!!, senderKey, forwarding_curve25519_key_chain!!, keysClaimed, exportFormat)
val added = olmDevice.addInboundGroupSession(roomKeyContent.sessionId!!, roomKeyContent.sessionKey!!, roomKeyContent.roomId!!, senderKey, forwarding_curve25519_key_chain!!, keysClaimed, exportFormat)

if (added) {
keysBackup.maybeBackupKeys()
@ -257,7 +263,7 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,
content.sessionId = roomKeyContent.sessionId
content.senderKey = senderKey

mOutgoingRoomKeyRequestManager.cancelRoomKeyRequest(content)
outgoingRoomKeyRequestManager.cancelRoomKeyRequest(content)

onNewSession(senderKey, roomKeyContent.sessionId!!)
}
@ -272,11 +278,11 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,
override fun onNewSession(senderKey: String, sessionId: String) {
val k = "$senderKey|$sessionId"

val pending = mPendingEvents[k]
val pending = pendingEvents[k]

if (null != pending) {
// Have another go at decrypting events sent with this session.
mPendingEvents.remove(k)
pendingEvents.remove(k)

val timelineIds = pending.keys

@ -307,81 +313,81 @@ internal class MXMegolmDecryption(private val mCredentials: Credentials,
}

override fun hasKeysForKeyRequest(request: IncomingRoomKeyRequest): Boolean {
return (null != request.mRequestBody
&& mOlmDevice.hasInboundSessionKeys(request.mRequestBody!!.roomId!!, request.mRequestBody!!.senderKey!!, request.mRequestBody!!.sessionId!!))
return (null != request.requestBody
&& olmDevice.hasInboundSessionKeys(request.requestBody!!.roomId!!, request.requestBody!!.senderKey!!, request.requestBody!!.sessionId!!))
}

override fun shareKeysWithDevice(request: IncomingRoomKeyRequest) {
// sanity checks
if (request.mRequestBody == null) {
if (request.requestBody == null) {
return
}
val userId = request.userId!!
CoroutineScope(coroutineDispatchers.crypto).launch {
deviceListManager.downloadKeys(listOf(userId), false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> {
override fun onSuccess(data: MXUsersDevicesMap<MXDeviceInfo>) {
val deviceId = request.deviceId
val deviceInfo = cryptoStore.getUserDevice(deviceId!!, userId)

val userId = request.mUserId!!
if (null != deviceInfo) {
val body = request.requestBody

mDeviceListManager.downloadKeys(listOf(userId), false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> {
override fun onSuccess(data: MXUsersDevicesMap<MXDeviceInfo>) {
val deviceId = request.mDeviceId
val deviceInfo = mCryptoStore.getUserDevice(deviceId!!, userId)
val devicesByUser = HashMap<String, List<MXDeviceInfo>>()
devicesByUser[userId] = ArrayList(Arrays.asList(deviceInfo))

if (null != deviceInfo) {
val body = request.mRequestBody
ensureOlmSessionsForDevicesAction.handle(devicesByUser, object : MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>> {
override fun onSuccess(data: MXUsersDevicesMap<MXOlmSessionResult>) {
val olmSessionResult = data.getObject(deviceId, userId)

val devicesByUser = HashMap<String, List<MXDeviceInfo>>()
devicesByUser[userId] = ArrayList(Arrays.asList(deviceInfo))
if (olmSessionResult?.mSessionId == null) {
// no session with this device, probably because there
// were no one-time keys.
//
// ensureOlmSessionsForUsers has already done the logging,
// so just skip it.
return
}
Timber.v("## shareKeysWithDevice() : sharing keys for session " + body!!.senderKey + "|" + body.sessionId
+ " with device " + userId + ":" + deviceId)
val inboundGroupSession = olmDevice.getInboundGroupSession(body.sessionId, body.senderKey, body.roomId)

mEnsureOlmSessionsForDevicesAction.handle(devicesByUser, object : MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>> {
override fun onSuccess(data: MXUsersDevicesMap<MXOlmSessionResult>) {
val olmSessionResult = data.getObject(deviceId, userId)
val payloadJson = HashMap<String, Any>()
payloadJson["type"] = EventType.FORWARDED_ROOM_KEY
payloadJson["content"] = inboundGroupSession!!.exportKeys()!!

if (null == olmSessionResult || null == olmSessionResult.mSessionId) {
// no session with this device, probably because there
// were no one-time keys.
//
// ensureOlmSessionsForUsers has already done the logging,
// so just skip it.
return
val encodedPayload = messageEncrypter.encryptMessage(payloadJson, Arrays.asList(deviceInfo))
val sendToDeviceMap = MXUsersDevicesMap<Any>()
sendToDeviceMap.setObject(encodedPayload, userId, deviceId)
Timber.v("## shareKeysWithDevice() : sending to $userId:$deviceId")

val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap)
sendToDeviceTask
.execute(sendToDeviceParams)
.fold(
{
Timber.e(it, "## shareKeysWithDevice() : sendToDevice $userId:$deviceId failed")
}
, {
Timber.v("## shareKeysWithDevice() : sent to $userId:$deviceId")
}
)
}

Timber.v("## shareKeysWithDevice() : sharing keys for session " + body!!.senderKey + "|" + body.sessionId
+ " with device " + userId + ":" + deviceId)

val inboundGroupSession = mOlmDevice.getInboundGroupSession(body.sessionId, body.senderKey, body.roomId)

val payloadJson = HashMap<String, Any>()
payloadJson["type"] = EventType.FORWARDED_ROOM_KEY
payloadJson["content"] = inboundGroupSession!!.exportKeys()!!

val encodedPayload = mMessageEncrypter.encryptMessage(payloadJson, Arrays.asList(deviceInfo))
val sendToDeviceMap = MXUsersDevicesMap<Any>()
sendToDeviceMap.setObject(encodedPayload, userId, deviceId)

Timber.v("## shareKeysWithDevice() : sending to $userId:$deviceId")
mSendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap))
.dispatchTo(object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
Timber.v("## shareKeysWithDevice() : sent to $userId:$deviceId")
}

override fun onFailure(failure: Throwable) {
Timber.e(failure, "## shareKeysWithDevice() : sendToDevice $userId:$deviceId failed")
}
})
.executeBy(mTaskExecutor)
}

override fun onFailure(failure: Throwable) {
Timber.e(failure, "## shareKeysWithDevice() : ensureOlmSessionsForDevices $userId:$deviceId failed")
}
})
} else {
Timber.e("## shareKeysWithDevice() : ensureOlmSessionsForDevices $userId:$deviceId not found")
override fun onFailure(failure: Throwable) {
Timber.e(failure, "## shareKeysWithDevice() : ensureOlmSessionsForDevices $userId:$deviceId failed")
}
})
} else {
Timber.e("## shareKeysWithDevice() : ensureOlmSessionsForDevices $userId:$deviceId not found")
}
}
}

override fun onFailure(failure: Throwable) {
Timber.e(failure, "## shareKeysWithDevice() : downloadKeys $userId failed")
}
})
override fun onFailure(failure: Throwable) {
Timber.e(failure, "## shareKeysWithDevice() : downloadKeys $userId failed")
}
})
}


}
}

View File

@ -25,6 +25,7 @@ import im.vector.matrix.android.internal.crypto.actions.MessageEncrypter
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.util.MatrixCoroutineDispatchers

internal class MXMegolmDecryptionFactory(private val mCredentials: Credentials,
private val mOlmDevice: MXOlmDevice,
@ -34,9 +35,10 @@ internal class MXMegolmDecryptionFactory(private val mCredentials: Credentials,
private val mEnsureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
private val mCryptoStore: IMXCryptoStore,
private val mSendToDeviceTask: SendToDeviceTask,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val mTaskExecutor: TaskExecutor) {

fun instantiate(): MXMegolmDecryption {
fun create(): MXMegolmDecryption {
return MXMegolmDecryption(
mCredentials,
mOlmDevice,
@ -46,6 +48,6 @@ internal class MXMegolmDecryptionFactory(private val mCredentials: Credentials,
mEnsureOlmSessionsForDevicesAction,
mCryptoStore,
mSendToDeviceTask,
mTaskExecutor)
coroutineDispatchers)
}
}

View File

@ -49,36 +49,36 @@ import java.util.*

internal class MXMegolmEncryption(
// The id of the room we will be sending to.
private var mRoomId: String,
private var roomId: String,

private val olmDevice: MXOlmDevice,
private val mKeysBackup: KeysBackup,
private val mCryptoStore: IMXCryptoStore,
private val mDeviceListManager: DeviceListManager,
private val mEnsureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
private val mCredentials: Credentials,
private val mSendToDeviceTask: SendToDeviceTask,
private val mTaskExecutor: TaskExecutor,
private val mMessageEncrypter: MessageEncrypter,
private val mWarnOnUnknownDevicesRepository: WarnOnUnknownDeviceRepository
private val keysBackup: KeysBackup,
private val cryptoStore: IMXCryptoStore,
private val deviceListManager: DeviceListManager,
private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
private val credentials: Credentials,
private val sendToDeviceTask: SendToDeviceTask,
private val taskExecutor: TaskExecutor,
private val messageEncrypter: MessageEncrypter,
private val warnOnUnknownDevicesRepository: WarnOnUnknownDeviceRepository
) : IMXEncrypting {


// OutboundSessionInfo. Null if we haven't yet started setting one up. Note
// that even if this is non-null, it may not be ready for use (in which
// case outboundSession.shareOperation will be non-null.)
private var mOutboundSession: MXOutboundSessionInfo? = null
private var outboundSession: MXOutboundSessionInfo? = null

// true when there is an HTTP operation in progress
private var mShareOperationIsProgress: Boolean = false
private var shareOperationIsProgress: Boolean = false

private val mPendingEncryptions = ArrayList<MXQueuedEncryption>()
private val _pendingEncryptions = ArrayList<MXQueuedEncryption>()

// Default rotation periods
// TODO: Make it configurable via parameters
// Session rotation periods
private var mSessionRotationPeriodMsgs: Int = 100
private var mSessionRotationPeriodMs: Int = 7 * 24 * 3600 * 1000
private var sessionRotationPeriodMsgs: Int = 100
private var sessionRotationPeriodMs: Int = 7 * 24 * 3600 * 1000

/**
* @return a snapshot of the pending encryptions
@ -86,11 +86,9 @@ internal class MXMegolmEncryption(
private val pendingEncryptions: List<MXQueuedEncryption>
get() {
val list = ArrayList<MXQueuedEncryption>()

synchronized(mPendingEncryptions) {
list.addAll(mPendingEncryptions)
synchronized(_pendingEncryptions) {
list.addAll(_pendingEncryptions)
}

return list
}

@ -102,12 +100,12 @@ internal class MXMegolmEncryption(
// It will be processed when everything is set up
val queuedEncryption = MXQueuedEncryption()

queuedEncryption.mEventContent = eventContent
queuedEncryption.mEventType = eventType
queuedEncryption.mApiCallback = callback
queuedEncryption.eventContent = eventContent
queuedEncryption.eventType = eventType
queuedEncryption.apiCallback = callback

synchronized(mPendingEncryptions) {
mPendingEncryptions.add(queuedEncryption)
synchronized(_pendingEncryptions) {
_pendingEncryptions.add(queuedEncryption)
}

val t0 = System.currentTimeMillis()
@ -124,11 +122,11 @@ internal class MXMegolmEncryption(
val queuedEncryptions = pendingEncryptions

for (queuedEncryption in queuedEncryptions) {
queuedEncryption.mApiCallback?.onFailure(failure)
queuedEncryption.apiCallback?.onFailure(failure)
}

synchronized(mPendingEncryptions) {
mPendingEncryptions.removeAll(queuedEncryptions)
synchronized(_pendingEncryptions) {
_pendingEncryptions.removeAll(queuedEncryptions)
}
}

@ -162,10 +160,10 @@ internal class MXMegolmEncryption(
val keysClaimedMap = HashMap<String, String>()
keysClaimedMap["ed25519"] = olmDevice.deviceEd25519Key!!

olmDevice.addInboundGroupSession(sessionId!!, olmDevice.getSessionKey(sessionId)!!, mRoomId, olmDevice.deviceCurve25519Key!!,
ArrayList(), keysClaimedMap, false)
olmDevice.addInboundGroupSession(sessionId!!, olmDevice.getSessionKey(sessionId)!!, roomId, olmDevice.deviceCurve25519Key!!,
ArrayList(), keysClaimedMap, false)

mKeysBackup.maybeBackupKeys()
keysBackup.maybeBackupKeys()

return MXOutboundSessionInfo(sessionId)
}
@ -177,18 +175,18 @@ internal class MXMegolmEncryption(
* @param callback the asynchronous callback.
*/
private fun ensureOutboundSession(devicesInRoom: MXUsersDevicesMap<MXDeviceInfo>, callback: MatrixCallback<MXOutboundSessionInfo>?) {
var session = mOutboundSession
var session = outboundSession

if (null == session
// Need to make a brand new session?
|| session.needsRotation(mSessionRotationPeriodMsgs, mSessionRotationPeriodMs)
// Determine if we have shared with anyone we shouldn't have
|| session.sharedWithTooManyDevices(devicesInRoom)) {
// Need to make a brand new session?
|| session.needsRotation(sessionRotationPeriodMsgs, sessionRotationPeriodMs)
// Determine if we have shared with anyone we shouldn't have
|| session.sharedWithTooManyDevices(devicesInRoom)) {
session = prepareNewSessionInRoom()
mOutboundSession = session
outboundSession = session
}

if (mShareOperationIsProgress) {
if (shareOperationIsProgress) {
Timber.v("## ensureOutboundSessionInRoom() : already in progress")
// Key share already in progress
return
@ -218,7 +216,7 @@ internal class MXMegolmEncryption(

shareKey(fSession, shareMap, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
mShareOperationIsProgress = false
shareOperationIsProgress = false
callback?.onSuccess(fSession)
}

@ -226,7 +224,7 @@ internal class MXMegolmEncryption(
Timber.e("## ensureOutboundSessionInRoom() : shareKey onFailure")

callback?.onFailure(failure)
mShareOperationIsProgress = false
shareOperationIsProgress = false
}
})

@ -303,7 +301,7 @@ internal class MXMegolmEncryption(

val submap = HashMap<String, Any>()
submap["algorithm"] = MXCRYPTO_ALGORITHM_MEGOLM
submap["room_id"] = mRoomId
submap["room_id"] = roomId
submap["session_id"] = session.mSessionId
submap["session_key"] = sessionKey!!
submap["chain_index"] = chainIndex
@ -315,10 +313,10 @@ internal class MXMegolmEncryption(
val t0 = System.currentTimeMillis()
Timber.v("## shareUserDevicesKey() : starts")

mEnsureOlmSessionsForDevicesAction.handle(devicesByUser, object : MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>> {
ensureOlmSessionsForDevicesAction.handle(devicesByUser, object : MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>> {
override fun onSuccess(data: MXUsersDevicesMap<MXOlmSessionResult>) {
Timber.v("## shareUserDevicesKey() : ensureOlmSessionsForDevices succeeds after "
+ (System.currentTimeMillis() - t0) + " ms")
+ (System.currentTimeMillis() - t0) + " ms")
val contentMap = MXUsersDevicesMap<Any>()

var haveTargets = false
@ -348,7 +346,7 @@ internal class MXMegolmEncryption(

Timber.v("## shareUserDevicesKey() : Sharing keys with device $userId:$deviceID")
//noinspection ArraysAsListWithZeroOrOneArgument,ArraysAsListWithZeroOrOneArgument
contentMap.setObject(mMessageEncrypter.encryptMessage(payload, Arrays.asList(sessionResult.mDevice)), userId, deviceID)
contentMap.setObject(messageEncrypter.encryptMessage(payload, Arrays.asList(sessionResult.mDevice)), userId, deviceID)
haveTargets = true
}
}
@ -357,11 +355,11 @@ internal class MXMegolmEncryption(
val t0 = System.currentTimeMillis()
Timber.v("## shareUserDevicesKey() : has target")

mSendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ENCRYPTED, contentMap))
sendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ENCRYPTED, contentMap))
.dispatchTo(object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
Timber.v("## shareUserDevicesKey() : sendToDevice succeeds after "
+ (System.currentTimeMillis() - t0) + " ms")
+ (System.currentTimeMillis() - t0) + " ms")

// Add the devices we have shared with to session.sharedWithDevices.
// we deliberately iterate over devicesByUser (ie, the devices we
@ -387,7 +385,7 @@ internal class MXMegolmEncryption(
callback?.onFailure(failure)
}
})
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
} else {
Timber.v("## shareUserDevicesKey() : no need to sharekey")

@ -416,9 +414,9 @@ internal class MXMegolmEncryption(
for (queuedEncryption in queuedEncryptions) {
val payloadJson = HashMap<String, Any>()

payloadJson["room_id"] = mRoomId
payloadJson["type"] = queuedEncryption.mEventType!!
payloadJson["content"] = queuedEncryption.mEventContent!!
payloadJson["room_id"] = roomId
payloadJson["type"] = queuedEncryption.eventType!!
payloadJson["content"] = queuedEncryption.eventContent!!

// Get canonical Json from

@ -433,15 +431,15 @@ internal class MXMegolmEncryption(

// Include our device ID so that recipients can send us a
// m.new_device message if they don't have our session key.
map["device_id"] = mCredentials.deviceId!!
map["device_id"] = credentials.deviceId!!

CryptoAsyncHelper.getUiHandler().post { queuedEncryption.mApiCallback?.onSuccess(map) }
CryptoAsyncHelper.getUiHandler().post { queuedEncryption.apiCallback?.onSuccess(map) }

session.mUseCount++
}

synchronized(mPendingEncryptions) {
mPendingEncryptions.removeAll(queuedEncryptions)
synchronized(_pendingEncryptions) {
_pendingEncryptions.removeAll(queuedEncryptions)
}
}
}
@ -458,10 +456,10 @@ internal class MXMegolmEncryption(
// have a list of the user's devices, then we already share an e2e room
// with them, which means that they will have announced any new devices via
// an m.new_device.
mDeviceListManager.downloadKeys(userIds, false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> {
deviceListManager.downloadKeys(userIds, false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> {
override fun onSuccess(data: MXUsersDevicesMap<MXDeviceInfo>) {
val encryptToVerifiedDevicesOnly = mCryptoStore.getGlobalBlacklistUnverifiedDevices()
|| mCryptoStore.getRoomsListBlacklistUnverifiedDevices().contains(mRoomId)
val encryptToVerifiedDevicesOnly = cryptoStore.getGlobalBlacklistUnverifiedDevices()
|| cryptoStore.getRoomsListBlacklistUnverifiedDevices().contains(roomId)

val devicesInRoom = MXUsersDevicesMap<MXDeviceInfo>()
val unknownDevices = MXUsersDevicesMap<MXDeviceInfo>()
@ -472,7 +470,7 @@ internal class MXMegolmEncryption(
for (deviceId in deviceIds!!) {
val deviceInfo = data.getObject(deviceId, userId)

if (mWarnOnUnknownDevicesRepository.warnOnUnknownDevices() && deviceInfo!!.isUnknown) {
if (warnOnUnknownDevicesRepository.warnOnUnknownDevices() && deviceInfo!!.isUnknown) {
// The device is not yet known by the user
unknownDevices.setObject(deviceInfo, userId, deviceId)
continue
@ -501,7 +499,7 @@ internal class MXMegolmEncryption(
// if so, warn the user so they can verify or ignore.
if (unknownDevices.map.isNotEmpty()) {
callback.onFailure(Failure.CryptoError(MXCryptoError(MXCryptoError.UNKNOWN_DEVICES_CODE,
MXCryptoError.UNABLE_TO_ENCRYPT, MXCryptoError.UNKNOWN_DEVICES_REASON, unknownDevices)))
MXCryptoError.UNABLE_TO_ENCRYPT, MXCryptoError.UNKNOWN_DEVICES_REASON, unknownDevices)))
} else {
callback.onSuccess(devicesInRoom)
}

View File

@ -40,10 +40,9 @@ internal class MXMegolmEncryptionFactory(
private val mMessageEncrypter: MessageEncrypter,
private val mWarnOnUnknownDevicesRepository: WarnOnUnknownDeviceRepository) {

fun instantiate(roomId: String): MXMegolmEncryption {
fun create(roomId: String): MXMegolmEncryption {
return MXMegolmEncryption(
roomId,

olmDevice,
mKeysBackup,
mCryptoStore,

View File

@ -18,7 +18,6 @@
package im.vector.matrix.android.internal.crypto.algorithms.olm

import android.text.TextUtils
import com.squareup.moshi.Json
import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.api.session.crypto.MXCryptoError
import im.vector.matrix.android.api.session.events.model.Event
@ -144,9 +143,9 @@ internal class MXOlmDecryption(
}

val result = MXEventDecryptionResult()
result.mClearEvent = payload
result.mSenderCurve25519Key = olmEventContent.senderKey
result.mClaimedEd25519Key = olmPayloadContent.keys!!.get("ed25519")
result.clearEvent = payload
result.senderCurve25519Key = olmEventContent.senderKey
result.claimedEd25519Key = olmPayloadContent.keys!!.get("ed25519")

return result
}

View File

@ -22,7 +22,7 @@ import im.vector.matrix.android.internal.crypto.MXOlmDevice
internal class MXOlmDecryptionFactory(private val mOlmDevice: MXOlmDevice,
private val mCredentials: Credentials) {

fun instantiate(): MXOlmDecryption {
fun create(): MXOlmDecryption {
return MXOlmDecryption(
mOlmDevice,
mCredentials)

View File

@ -31,19 +31,21 @@ import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import java.util.*

internal class MXOlmEncryption(
private var mRoomId: String,

private val mOlmDevice: MXOlmDevice,
private val mCryptoStore: IMXCryptoStore,
private val mMessageEncrypter: MessageEncrypter,
private val mDeviceListManager: DeviceListManager,
private val mEnsureOlmSessionsForUsersAction: EnsureOlmSessionsForUsersAction)
private var roomId: String,
private val olmDevice: MXOlmDevice,
private val cryptoStore: IMXCryptoStore,
private val messageEncrypter: MessageEncrypter,
private val deviceListManager: DeviceListManager,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val ensureOlmSessionsForUsersAction: EnsureOlmSessionsForUsersAction)
: IMXEncrypting {


override fun encryptEventContent(eventContent: Content,
eventType: String,
userIds: List<String>,
@ -51,40 +53,42 @@ internal class MXOlmEncryption(
// pick the list of recipients based on the membership list.
//
// TODO: there is a race condition here! What if a new user turns up
ensureSession(userIds, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
val deviceInfos = ArrayList<MXDeviceInfo>()
CoroutineScope(coroutineDispatchers.crypto).launch {
ensureSession(userIds, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
val deviceInfos = ArrayList<MXDeviceInfo>()

for (userId in userIds) {
val devices = mCryptoStore.getUserDevices(userId)?.values ?: emptyList()
for (userId in userIds) {
val devices = cryptoStore.getUserDevices(userId)?.values ?: emptyList()

for (device in devices) {
val key = device.identityKey()
for (device in devices) {
val key = device.identityKey()

if (TextUtils.equals(key, mOlmDevice.deviceCurve25519Key)) {
// Don't bother setting up session to ourself
continue
if (TextUtils.equals(key, olmDevice.deviceCurve25519Key)) {
// Don't bother setting up session to ourself
continue
}

if (device.isBlocked) {
// Don't bother setting up sessions with blocked users
continue
}

deviceInfos.add(device)
}

if (device.isBlocked) {
// Don't bother setting up sessions with blocked users
continue
}

deviceInfos.add(device)
}

val messageMap = HashMap<String, Any>()
messageMap["room_id"] = roomId
messageMap["type"] = eventType
messageMap["content"] = eventContent

messageEncrypter.encryptMessage(messageMap, deviceInfos)

callback.onSuccess(messageMap.toContent()!!)
}

val messageMap = HashMap<String, Any>()
messageMap["room_id"] = mRoomId
messageMap["type"] = eventType
messageMap["content"] = eventContent

mMessageEncrypter.encryptMessage(messageMap, deviceInfos)

callback.onSuccess(messageMap.toContent()!!)
}
})
})
}
}

/**
@ -94,10 +98,10 @@ internal class MXOlmEncryption(
* @param callback the asynchronous callback
*/
private fun ensureSession(users: List<String>, callback: MatrixCallback<Unit>?) {
mDeviceListManager.downloadKeys(users, false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> {
deviceListManager.downloadKeys(users, false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> {

override fun onSuccess(data: MXUsersDevicesMap<MXDeviceInfo>) {
mEnsureOlmSessionsForUsersAction.handle(users, object : MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>> {
ensureOlmSessionsForUsersAction.handle(users, object : MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>> {
override fun onSuccess(data: MXUsersDevicesMap<MXOlmSessionResult>) {
callback?.onSuccess(Unit)
}

View File

@ -21,21 +21,23 @@ import im.vector.matrix.android.internal.crypto.MXOlmDevice
import im.vector.matrix.android.internal.crypto.actions.EnsureOlmSessionsForUsersAction
import im.vector.matrix.android.internal.crypto.actions.MessageEncrypter
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers

internal class MXOlmEncryptionFactory(private val mOlmDevice: MXOlmDevice,
private val mCryptoStore: IMXCryptoStore,
private val mMessageEncrypter: MessageEncrypter,
private val mDeviceListManager: DeviceListManager,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val mEnsureOlmSessionsForUsersAction: EnsureOlmSessionsForUsersAction) {

fun instantiate(roomId: String): MXOlmEncryption {
fun create(roomId: String): MXOlmEncryption {
return MXOlmEncryption(
roomId,

mOlmDevice,
mCryptoStore,
mMessageEncrypter,
mDeviceListManager,
coroutineDispatchers,
mEnsureOlmSessionsForUsersAction)
}
}

View File

@ -64,34 +64,34 @@ import kotlin.collections.HashMap
* to the user's homeserver.
*/
internal class KeysBackup(
private val mCredentials: Credentials,
private val mCryptoStore: IMXCryptoStore,
private val mOlmDevice: MXOlmDevice,
private val mObjectSigner: ObjectSigner,
private val credentials: Credentials,
private val cryptoStore: IMXCryptoStore,
private val olmDevice: MXOlmDevice,
private val objectSigner: ObjectSigner,
// Actions
private val mMegolmSessionDataImporter: MegolmSessionDataImporter,
private val megolmSessionDataImporter: MegolmSessionDataImporter,
// Tasks
private val mCreateKeysBackupVersionTask: CreateKeysBackupVersionTask,
private val mDeleteBackupTask: DeleteBackupTask,
private val mDeleteRoomSessionDataTask: DeleteRoomSessionDataTask,
private val mDeleteRoomSessionsDataTask: DeleteRoomSessionsDataTask,
private val mDeleteSessionDataTask: DeleteSessionsDataTask,
private val mGetKeysBackupLastVersionTask: GetKeysBackupLastVersionTask,
private val mGetKeysBackupVersionTask: GetKeysBackupVersionTask,
private val mGetRoomSessionDataTask: GetRoomSessionDataTask,
private val mGetRoomSessionsDataTask: GetRoomSessionsDataTask,
private val mGetSessionsDataTask: GetSessionsDataTask,
private val mStoreRoomSessionDataTask: StoreRoomSessionDataTask,
private val mStoreSessionsDataTask: StoreRoomSessionsDataTask,
private val mStoreSessionDataTask: StoreSessionsDataTask,
private val mUpdateKeysBackupVersionTask: UpdateKeysBackupVersionTask,
private val createKeysBackupVersionTask: CreateKeysBackupVersionTask,
private val deleteBackupTask: DeleteBackupTask,
private val deleteRoomSessionDataTask: DeleteRoomSessionDataTask,
private val deleteRoomSessionsDataTask: DeleteRoomSessionsDataTask,
private val deleteSessionDataTask: DeleteSessionsDataTask,
private val getKeysBackupLastVersionTask: GetKeysBackupLastVersionTask,
private val getKeysBackupVersionTask: GetKeysBackupVersionTask,
private val getRoomSessionDataTask: GetRoomSessionDataTask,
private val getRoomSessionsDataTask: GetRoomSessionsDataTask,
private val getSessionsDataTask: GetSessionsDataTask,
private val storeRoomSessionDataTask: StoreRoomSessionDataTask,
private val storeSessionsDataTask: StoreRoomSessionsDataTask,
private val storeSessionDataTask: StoreSessionsDataTask,
private val updateKeysBackupVersionTask: UpdateKeysBackupVersionTask,
// Task executor
private val mTaskExecutor: TaskExecutor
private val taskExecutor: TaskExecutor
) : KeysBackupService {

private val mUIHandler = Handler(Looper.getMainLooper())
private val uiHandler = Handler(Looper.getMainLooper())

private val mKeysBackupStateManager = KeysBackupStateManager(mUIHandler)
private val keysBackupStateManager = KeysBackupStateManager(uiHandler)

// The backup version
override var mKeysBackupVersion: KeysVersionResult? = null
@ -107,23 +107,23 @@ internal class KeysBackup(
private var mKeysBackupStateListener: KeysBackupService.KeysBackupStateListener? = null

override val isEnabled: Boolean
get() = mKeysBackupStateManager.isEnabled
get() = keysBackupStateManager.isEnabled

override val isStucked: Boolean
get() = mKeysBackupStateManager.isStucked
get() = keysBackupStateManager.isStucked

override val state: KeysBackupState
get() = mKeysBackupStateManager.state
get() = keysBackupStateManager.state

override val currentBackupVersion: String?
get() = mKeysBackupVersion?.version

override fun addListener(listener: KeysBackupService.KeysBackupStateListener) {
mKeysBackupStateManager.addListener(listener)
keysBackupStateManager.addListener(listener)
}

override fun removeListener(listener: KeysBackupService.KeysBackupStateListener) {
mKeysBackupStateManager.removeListener(listener)
keysBackupStateManager.removeListener(listener)
}

/**
@ -153,7 +153,7 @@ internal class KeysBackup(
} else {
object : ProgressListener {
override fun onProgress(progress: Int, total: Int) {
mUIHandler.post {
uiHandler.post {
try {
progressListener.onProgress(progress, total)
} catch (e: Exception) {
@ -176,7 +176,7 @@ internal class KeysBackup(

val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, megolmBackupAuthData.signalableJSONDictionary())

megolmBackupAuthData.signatures = mObjectSigner.signObject(canonicalJson)
megolmBackupAuthData.signatures = objectSigner.signObject(canonicalJson)


val megolmBackupCreationInfo = MegolmBackupCreationInfo()
@ -184,11 +184,11 @@ internal class KeysBackup(
megolmBackupCreationInfo.authData = megolmBackupAuthData
megolmBackupCreationInfo.recoveryKey = computeRecoveryKey(olmPkDecryption.privateKey())

mUIHandler.post { callback.onSuccess(megolmBackupCreationInfo) }
uiHandler.post { callback.onSuccess(megolmBackupCreationInfo) }
} catch (e: OlmException) {
Timber.e(e, "OlmException")

mUIHandler.post { callback.onFailure(e) }
uiHandler.post { callback.onFailure(e) }
}
}
}
@ -206,14 +206,14 @@ internal class KeysBackup(
createKeysBackupVersionBody.authData = MoshiProvider.providesMoshi().adapter(Map::class.java)
.fromJson(keysBackupCreationInfo.authData?.toJsonString()) as Map<String, Any>?

mKeysBackupStateManager.state = KeysBackupState.Enabling
keysBackupStateManager.state = KeysBackupState.Enabling

mCreateKeysBackupVersionTask
createKeysBackupVersionTask
.configureWith(createKeysBackupVersionBody)
.dispatchTo(object : MatrixCallback<KeysVersion> {
override fun onSuccess(info: KeysVersion) {
// Reset backup markers.
mCryptoStore.resetBackupMarkers()
cryptoStore.resetBackupMarkers()

val keyBackupVersion = KeysVersionResult()
keyBackupVersion.algorithm = createKeysBackupVersionBody.algorithm
@ -230,11 +230,11 @@ internal class KeysBackup(
}

override fun onFailure(failure: Throwable) {
mKeysBackupStateManager.state = KeysBackupState.Disabled
keysBackupStateManager.state = KeysBackupState.Disabled
callback.onFailure(failure)
}
})
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
}

/**
@ -251,10 +251,10 @@ internal class KeysBackup(
if (mKeysBackupVersion != null && version == mKeysBackupVersion!!.version) {
resetKeysBackupData()
mKeysBackupVersion = null
mKeysBackupStateManager.state = KeysBackupState.Unknown
keysBackupStateManager.state = KeysBackupState.Unknown
}

mDeleteBackupTask.configureWith(DeleteBackupTask.Params(version))
deleteBackupTask.configureWith(DeleteBackupTask.Params(version))
.dispatchTo(object : MatrixCallback<Unit> {
private fun eventuallyRestartBackup() {
// Do not stay in KeysBackupState.Unknown but check what is available on the homeserver
@ -266,16 +266,16 @@ internal class KeysBackup(
override fun onSuccess(data: Unit) {
eventuallyRestartBackup()

mUIHandler.post { callback?.onSuccess(Unit) }
uiHandler.post { callback?.onSuccess(Unit) }
}

override fun onFailure(failure: Throwable) {
eventuallyRestartBackup()

mUIHandler.post { callback?.onFailure(failure) }
uiHandler.post { callback?.onFailure(failure) }
}
})
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
}
}

@ -287,7 +287,7 @@ internal class KeysBackup(
// Server contains more keys than locally
val totalNumberOfKeysLocally = getTotalNumbersOfKeys()

val keysBackupData = mCryptoStore.getKeysBackupData()
val keysBackupData = cryptoStore.getKeysBackupData()

val totalNumberOfKeysServer = keysBackupData?.backupLastServerNumberOfKeys ?: -1
val hashServer = keysBackupData?.backupLastServerHash
@ -310,7 +310,7 @@ internal class KeysBackup(
* Facility method to get the total number of locally stored keys
*/
override fun getTotalNumbersOfKeys(): Int {
return mCryptoStore.inboundGroupSessionsCount(false)
return cryptoStore.inboundGroupSessionsCount(false)

}

@ -318,7 +318,7 @@ internal class KeysBackup(
* Facility method to get the number of backed up keys
*/
override fun getTotalNumbersOfBackedUpKeys(): Int {
return mCryptoStore.inboundGroupSessionsCount(true)
return cryptoStore.inboundGroupSessionsCount(true)
}

/**
@ -370,7 +370,7 @@ internal class KeysBackup(
}
}

mKeysBackupStateManager.addListener(mKeysBackupStateListener!!)
keysBackupStateManager.addListener(mKeysBackupStateListener!!)

backupKeys()
}
@ -396,7 +396,7 @@ internal class KeysBackup(
.configureWith(keysBackupVersion)
.dispatchTo(callback)
.executeOn(TaskThread.COMPUTATION)
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
}

/**
@ -408,7 +408,7 @@ internal class KeysBackup(
*/
@WorkerThread
private fun getKeysBackupTrustBg(keysBackupVersion: KeysVersionResult): KeysBackupVersionTrust {
val myUserId = mCredentials.userId
val myUserId = credentials.userId

val keysBackupVersionTrust = KeysBackupVersionTrust()
val authData = keysBackupVersion.getAuthDataAsMegolmBackupAuthData()
@ -437,7 +437,7 @@ internal class KeysBackup(

var device: MXDeviceInfo? = null
if (deviceId != null) {
device = mCryptoStore.getUserDevice(deviceId, myUserId)
device = cryptoStore.getUserDevice(deviceId, myUserId)

var isSignatureValid = false

@ -445,7 +445,7 @@ internal class KeysBackup(
Timber.v("getKeysBackupTrust: Signature from unknown device $deviceId")
} else {
try {
mOlmDevice.verifySignature(device.fingerprint()!!, authData.signalableJSONDictionary(), mySigs[keyId] as String)
olmDevice.verifySignature(device.fingerprint()!!, authData.signalableJSONDictionary(), mySigs[keyId] as String)
isSignatureValid = true
} catch (e: OlmException) {
Timber.v("getKeysBackupTrust: Bad signature from device " + device.deviceId + " " + e.localizedMessage)
@ -481,7 +481,7 @@ internal class KeysBackup(
Timber.v("trustKeyBackupVersion: $trust, version ${keysBackupVersion.version}")

CryptoAsyncHelper.getDecryptBackgroundHandler().post {
val myUserId = mCredentials.userId
val myUserId = credentials.userId

// Get auth data to update it
val authData = getMegolmBackupAuthData(keysBackupVersion)
@ -489,7 +489,7 @@ internal class KeysBackup(
if (authData == null) {
Timber.w("trustKeyBackupVersion:trust: Key backup is missing required data")

mUIHandler.post {
uiHandler.post {
callback.onFailure(IllegalArgumentException("Missing element"))
}

@ -503,14 +503,14 @@ internal class KeysBackup(
// Add current device signature
val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, authData.signalableJSONDictionary())

val deviceSignatures = mObjectSigner.signObject(canonicalJson)
val deviceSignatures = objectSigner.signObject(canonicalJson)

deviceSignatures[myUserId]?.forEach { entry ->
myUserSignatures[entry.key] = entry.value
}
} else {
// Remove current device signature
myUserSignatures.remove("ed25519:${mCredentials.deviceId}")
myUserSignatures.remove("ed25519:${credentials.deviceId}")
}

// Create an updated version of KeysVersionResult
@ -532,7 +532,7 @@ internal class KeysBackup(
updateKeysBackupVersionBody.authData = adapter.fromJson(newMegolmBackupAuthData.toJsonString()) as Map<String, Any>?

// And send it to the homeserver
mUpdateKeysBackupVersionTask
updateKeysBackupVersionTask
.configureWith(UpdateKeysBackupVersionTask.Params(keysBackupVersion.version!!, updateKeysBackupVersionBody))
.dispatchTo(object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
@ -547,18 +547,18 @@ internal class KeysBackup(

checkAndStartWithKeysBackupVersion(newKeysBackupVersion)

mUIHandler.post {
uiHandler.post {
callback.onSuccess(data)
}
}

override fun onFailure(failure: Throwable) {
mUIHandler.post {
uiHandler.post {
callback.onFailure(failure)
}
}
})
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
}
}

@ -578,7 +578,7 @@ internal class KeysBackup(
if (!isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion)) {
Timber.w("trustKeyBackupVersionWithRecoveryKey: Invalid recovery key.")

mUIHandler.post {
uiHandler.post {
callback.onFailure(IllegalArgumentException("Invalid recovery key or password"))
}
return@post
@ -606,7 +606,7 @@ internal class KeysBackup(
if (recoveryKey == null) {
Timber.w("trustKeysBackupVersionWithPassphrase: Key backup is missing required data")

mUIHandler.post {
uiHandler.post {
callback.onFailure(IllegalArgumentException("Missing element"))
}

@ -652,7 +652,7 @@ internal class KeysBackup(
backupAllGroupSessionsCallback = null

mKeysBackupStateListener?.let {
mKeysBackupStateManager.removeListener(it)
keysBackupStateManager.removeListener(it)
}

mKeysBackupStateListener = null
@ -663,10 +663,10 @@ internal class KeysBackup(
*/
override fun getBackupProgress(progressListener: ProgressListener) {
CryptoAsyncHelper.getDecryptBackgroundHandler().post {
val backedUpKeys = mCryptoStore.inboundGroupSessionsCount(true)
val total = mCryptoStore.inboundGroupSessionsCount(false)
val backedUpKeys = cryptoStore.inboundGroupSessionsCount(true)
val total = cryptoStore.inboundGroupSessionsCount(false)

mUIHandler.post { progressListener.onProgress(backedUpKeys, total) }
uiHandler.post { progressListener.onProgress(backedUpKeys, total) }
}
}

@ -692,7 +692,7 @@ internal class KeysBackup(
// Check if the recovery is valid before going any further
if (!isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysVersionResult)) {
Timber.e("restoreKeysWithRecoveryKey: Invalid recovery key for this keys version")
mUIHandler.post { callback.onFailure(InvalidParameterException("Invalid recovery key")) }
uiHandler.post { callback.onFailure(InvalidParameterException("Invalid recovery key")) }
return@Runnable
}

@ -701,12 +701,12 @@ internal class KeysBackup(
if (decryption == null) {
// This should not happen anymore
Timber.e("restoreKeysWithRecoveryKey: Invalid recovery key. Error")
mUIHandler.post { callback.onFailure(InvalidParameterException("Invalid recovery key")) }
uiHandler.post { callback.onFailure(InvalidParameterException("Invalid recovery key")) }
return@Runnable
}

if (stepProgressListener != null) {
mUIHandler.post { stepProgressListener.onStepProgress(StepProgressListener.Step.DownloadingKey) }
uiHandler.post { stepProgressListener.onStepProgress(StepProgressListener.Step.DownloadingKey) }
}

// Get backed up keys from the homeserver
@ -749,7 +749,7 @@ internal class KeysBackup(
null
}

mMegolmSessionDataImporter.handle(sessionsData, !backUp, progressListener, object : MatrixCallback<ImportRoomKeysResult> {
megolmSessionDataImporter.handle(sessionsData, !backUp, progressListener, object : MatrixCallback<ImportRoomKeysResult> {
override fun onSuccess(data: ImportRoomKeysResult) {
// Do not back up the key if it comes from a backup recovery
if (backUp) {
@ -766,7 +766,7 @@ internal class KeysBackup(
}

override fun onFailure(failure: Throwable) {
mUIHandler.post { callback.onFailure(failure) }
uiHandler.post { callback.onFailure(failure) }
}
})
})
@ -794,7 +794,7 @@ internal class KeysBackup(
val progressListener = if (stepProgressListener != null) {
object : ProgressListener {
override fun onProgress(progress: Int, total: Int) {
mUIHandler.post {
uiHandler.post {
stepProgressListener.onStepProgress(StepProgressListener.Step.ComputingKey(progress, total))
}
}
@ -806,7 +806,7 @@ internal class KeysBackup(
val recoveryKey = recoveryKeyFromPassword(password, keysBackupVersion, progressListener)

if (recoveryKey == null) {
mUIHandler.post {
uiHandler.post {
Timber.v("backupKeys: Invalid configuration")
callback.onFailure(IllegalStateException("Invalid configuration"))
}
@ -828,7 +828,7 @@ internal class KeysBackup(
callback: MatrixCallback<KeysBackupData>) {
if (roomId != null && sessionId != null) {
// Get key for the room and for the session
mGetRoomSessionDataTask
getRoomSessionDataTask
.configureWith(GetRoomSessionDataTask.Params(roomId, sessionId, version))
.dispatchTo(object : MatrixCallback<KeyBackupData> {
override fun onSuccess(data: KeyBackupData) {
@ -847,10 +847,10 @@ internal class KeysBackup(
callback.onFailure(failure)
}
})
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
} else if (roomId != null) {
// Get all keys for the room
mGetRoomSessionsDataTask
getRoomSessionsDataTask
.configureWith(GetRoomSessionsDataTask.Params(roomId, version))
.dispatchTo(object : MatrixCallback<RoomKeysBackupData> {
override fun onSuccess(data: RoomKeysBackupData) {
@ -866,13 +866,13 @@ internal class KeysBackup(
callback.onFailure(failure)
}
})
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
} else {
// Get all keys
mGetSessionsDataTask
getSessionsDataTask
.configureWith(GetSessionsDataTask.Params(version))
.dispatchTo(callback)
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
}
}

@ -908,14 +908,14 @@ internal class KeysBackup(
checkAndStartKeysBackup()
}
state == KeysBackupState.ReadyToBackUp -> {
mKeysBackupStateManager.state = KeysBackupState.WillBackUp
keysBackupStateManager.state = KeysBackupState.WillBackUp

// Wait between 0 and 10 seconds, to avoid backup requests from
// different clients hitting the server all at the same time when a
// new key is sent
val delayInMs = mRandom.nextInt(KEY_BACKUP_WAITING_TIME_TO_SEND_KEY_BACKUP_MILLIS).toLong()

mUIHandler.postDelayed({ backupKeys() }, delayInMs)
uiHandler.postDelayed({ backupKeys() }, delayInMs)
}
else -> {
Timber.v("maybeBackupKeys: Skip it because state: $state")
@ -932,7 +932,7 @@ internal class KeysBackup(
*/
override fun getVersion(version: String,
callback: MatrixCallback<KeysVersionResult?>) {
mGetKeysBackupVersionTask
getKeysBackupVersionTask
.configureWith(version)
.dispatchTo(object : MatrixCallback<KeysVersionResult> {
override fun onSuccess(data: KeysVersionResult) {
@ -950,7 +950,7 @@ internal class KeysBackup(
}
}
})
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
}

/**
@ -960,7 +960,7 @@ internal class KeysBackup(
* @param callback onSuccess(null) will be called if there is no backup on the server
*/
override fun getCurrentVersion(callback: MatrixCallback<KeysVersionResult?>) {
mGetKeysBackupLastVersionTask
getKeysBackupLastVersionTask
.configureWith(Unit)
.dispatchTo(object : MatrixCallback<KeysVersionResult> {
override fun onSuccess(data: KeysVersionResult) {
@ -978,7 +978,7 @@ internal class KeysBackup(
}
}
})
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
}

/**
@ -1002,7 +1002,7 @@ internal class KeysBackup(
callback.onSuccess(false)
resetKeysBackupData()
mKeysBackupVersion = null
mKeysBackupStateManager.state = KeysBackupState.Disabled
keysBackupStateManager.state = KeysBackupState.Disabled
}
} else {
if (localBackupVersion == null) {
@ -1047,7 +1047,7 @@ internal class KeysBackup(
}

mKeysBackupVersion = null
mKeysBackupStateManager.state = KeysBackupState.CheckingBackUpOnHomeserver
keysBackupStateManager.state = KeysBackupState.CheckingBackUpOnHomeserver

getCurrentVersion(object : MatrixCallback<KeysVersionResult?> {
override fun onSuccess(data: KeysVersionResult?) {
@ -1056,7 +1056,7 @@ internal class KeysBackup(

override fun onFailure(failure: Throwable) {
Timber.e(failure, "checkAndStartKeysBackup: Failed to get current version")
mKeysBackupStateManager.state = KeysBackupState.Unknown
keysBackupStateManager.state = KeysBackupState.Unknown
}
})
}
@ -1069,12 +1069,12 @@ internal class KeysBackup(
if (keyBackupVersion == null) {
Timber.v("checkAndStartWithKeysBackupVersion: Found no key backup version on the homeserver")
resetKeysBackupData()
mKeysBackupStateManager.state = KeysBackupState.Disabled
keysBackupStateManager.state = KeysBackupState.Disabled
} else {
getKeysBackupTrust(keyBackupVersion, object : MatrixCallback<KeysBackupVersionTrust> {

override fun onSuccess(data: KeysBackupVersionTrust) {
val versionInStore = mCryptoStore.getKeyBackupVersion()
val versionInStore = cryptoStore.getKeyBackupVersion()

if (data.usable) {
Timber.v("checkAndStartWithKeysBackupVersion: Found usable key backup. version: " + keyBackupVersion.version)
@ -1093,7 +1093,7 @@ internal class KeysBackup(
resetKeysBackupData()
}

mKeysBackupStateManager.state = KeysBackupState.NotTrusted
keysBackupStateManager.state = KeysBackupState.NotTrusted
}
}

@ -1213,7 +1213,7 @@ internal class KeysBackup(

if (retrievedMegolmBackupAuthData != null) {
mKeysBackupVersion = keysVersionResult
mCryptoStore.setKeyBackupVersion(keysVersionResult.version)
cryptoStore.setKeyBackupVersion(keysVersionResult.version)

onServerDataRetrieved(keysVersionResult.count, keysVersionResult.hash)

@ -1223,20 +1223,20 @@ internal class KeysBackup(
}
} catch (e: OlmException) {
Timber.e(e, "OlmException")
mKeysBackupStateManager.state = KeysBackupState.Disabled
keysBackupStateManager.state = KeysBackupState.Disabled
return
}

mKeysBackupStateManager.state = KeysBackupState.ReadyToBackUp
keysBackupStateManager.state = KeysBackupState.ReadyToBackUp

maybeBackupKeys()
} else {
Timber.e("Invalid authentication data")
mKeysBackupStateManager.state = KeysBackupState.Disabled
keysBackupStateManager.state = KeysBackupState.Disabled
}
} else {
Timber.e("Invalid authentication data")
mKeysBackupStateManager.state = KeysBackupState.Disabled
keysBackupStateManager.state = KeysBackupState.Disabled
}
}

@ -1244,7 +1244,7 @@ internal class KeysBackup(
* Update the DB with data fetch from the server
*/
private fun onServerDataRetrieved(count: Int?, hash: String?) {
mCryptoStore.setKeysBackupData(KeysBackupDataEntity()
cryptoStore.setKeysBackupData(KeysBackupDataEntity()
.apply {
backupLastServerNumberOfKeys = count
backupLastServerHash = hash
@ -1260,12 +1260,12 @@ internal class KeysBackup(
private fun resetKeysBackupData() {
resetBackupAllGroupSessionsListeners()

mCryptoStore.setKeyBackupVersion(null)
mCryptoStore.setKeysBackupData(null)
cryptoStore.setKeyBackupVersion(null)
cryptoStore.setKeysBackupData(null)
mBackupKey = null

// Reset backup markers
mCryptoStore.resetBackupMarkers()
cryptoStore.resetBackupMarkers()
}

/**
@ -1291,20 +1291,20 @@ internal class KeysBackup(
}

// Get a chunk of keys to backup
val sessions = mCryptoStore.inboundGroupSessionsToBackup(KEY_BACKUP_SEND_KEYS_MAX_COUNT)
val sessions = cryptoStore.inboundGroupSessionsToBackup(KEY_BACKUP_SEND_KEYS_MAX_COUNT)

Timber.v("backupKeys: 1 - " + sessions.size + " sessions to back up")

if (sessions.isEmpty()) {
// Backup is up to date
mKeysBackupStateManager.state = KeysBackupState.ReadyToBackUp
keysBackupStateManager.state = KeysBackupState.ReadyToBackUp

backupAllGroupSessionsCallback?.onSuccess(Unit)
resetBackupAllGroupSessionsListeners()
return
}

mKeysBackupStateManager.state = KeysBackupState.BackingUp
keysBackupStateManager.state = KeysBackupState.BackingUp

CryptoAsyncHelper.getEncryptBackgroundHandler().post {
Timber.v("backupKeys: 2 - Encrypting keys")
@ -1332,25 +1332,25 @@ internal class KeysBackup(
Timber.v("backupKeys: 4 - Sending request")

// Make the request
mStoreSessionDataTask
storeSessionDataTask
.configureWith(StoreSessionsDataTask.Params(mKeysBackupVersion!!.version!!, keysBackupData))
.dispatchTo(object : MatrixCallback<BackupKeysResult> {
override fun onSuccess(data: BackupKeysResult) {
mUIHandler.post {
uiHandler.post {
Timber.v("backupKeys: 5a - Request complete")

// Mark keys as backed up
mCryptoStore.markBackupDoneForInboundGroupSessions(sessions)
cryptoStore.markBackupDoneForInboundGroupSessions(sessions)

if (sessions.size < KEY_BACKUP_SEND_KEYS_MAX_COUNT) {
Timber.v("backupKeys: All keys have been backed up")
onServerDataRetrieved(data.count, data.hash)

// Note: Changing state will trigger the call to backupAllGroupSessionsCallback.onSuccess()
mKeysBackupStateManager.state = KeysBackupState.ReadyToBackUp
keysBackupStateManager.state = KeysBackupState.ReadyToBackUp
} else {
Timber.v("backupKeys: Continue to back up keys")
mKeysBackupStateManager.state = KeysBackupState.WillBackUp
keysBackupStateManager.state = KeysBackupState.WillBackUp

backupKeys()
}
@ -1359,14 +1359,14 @@ internal class KeysBackup(

override fun onFailure(failure: Throwable) {
if (failure is Failure.ServerError) {
mUIHandler.post {
uiHandler.post {
Timber.e(failure, "backupKeys: backupKeys failed.")

when (failure.error.code) {
MatrixError.NOT_FOUND,
MatrixError.WRONG_ROOM_KEYS_VERSION -> {
// Backup has been deleted on the server, or we are not using the last backup version
mKeysBackupStateManager.state = KeysBackupState.WrongBackUpVersion
keysBackupStateManager.state = KeysBackupState.WrongBackUpVersion
backupAllGroupSessionsCallback?.onFailure(failure)
resetBackupAllGroupSessionsListeners()
resetKeysBackupData()
@ -1376,24 +1376,24 @@ internal class KeysBackup(
checkAndStartKeysBackup()
}
else -> // Come back to the ready state so that we will retry on the next received key
mKeysBackupStateManager.state = KeysBackupState.ReadyToBackUp
keysBackupStateManager.state = KeysBackupState.ReadyToBackUp
}
}
} else {
mUIHandler.post {
uiHandler.post {
backupAllGroupSessionsCallback?.onFailure(failure)
resetBackupAllGroupSessionsListeners()

Timber.e("backupKeys: backupKeys failed.")

// Retry a bit later
mKeysBackupStateManager.state = KeysBackupState.ReadyToBackUp
keysBackupStateManager.state = KeysBackupState.ReadyToBackUp
maybeBackupKeys()
}
}
}
})
.executeBy(mTaskExecutor)
.executeBy(taskExecutor)
}
}

@ -1401,7 +1401,7 @@ internal class KeysBackup(
@WorkerThread
fun encryptGroupSession(session: MXOlmInboundGroupSession2): KeyBackupData {
// Gather information for each key
val device = mCryptoStore.deviceWithIdentityKey(session.mSenderKey!!)
val device = cryptoStore.deviceWithIdentityKey(session.mSenderKey!!)

// Build the m.megolm_backup.v1.curve25519-aes-sha2 data as defined at
// https://github.com/uhoreg/matrix-doc/blob/e2e_backup/proposals/1219-storing-megolm-keys-serverside.md#mmegolm_backupv1curve25519-aes-sha2-key-format
@ -1496,5 +1496,5 @@ internal class KeysBackup(
* DEBUG INFO
* ========================================================================================== */

override fun toString() = "KeysBackup for ${mCredentials.userId}"
override fun toString() = "KeysBackup for ${credentials.userId}"
}

View File

@ -24,11 +24,11 @@ class MXQueuedEncryption {
/**
* The data to encrypt.
*/
var mEventContent: Content? = null
var mEventType: String? = null
var eventContent: Content? = null
var eventType: String? = null

/**
* the asynchronous callback
*/
var mApiCallback: MatrixCallback<Content>? = null
var apiCallback: MatrixCallback<Content>? = null
}

View File

@ -666,18 +666,18 @@ internal class RealmCryptoStore(private val enableFileEncryption: Boolean = fals
doRealmTransaction(realmConfiguration) {
// Delete any previous store request with the same parameters
it.where<IncomingRoomKeyRequestEntity>()
.equalTo(IncomingRoomKeyRequestEntityFields.USER_ID, incomingRoomKeyRequest.mUserId)
.equalTo(IncomingRoomKeyRequestEntityFields.DEVICE_ID, incomingRoomKeyRequest.mDeviceId)
.equalTo(IncomingRoomKeyRequestEntityFields.REQUEST_ID, incomingRoomKeyRequest.mRequestId)
.equalTo(IncomingRoomKeyRequestEntityFields.USER_ID, incomingRoomKeyRequest.userId)
.equalTo(IncomingRoomKeyRequestEntityFields.DEVICE_ID, incomingRoomKeyRequest.deviceId)
.equalTo(IncomingRoomKeyRequestEntityFields.REQUEST_ID, incomingRoomKeyRequest.requestId)
.findAll()
.deleteAllFromRealm()

// Then store it
it.createObject(IncomingRoomKeyRequestEntity::class.java).apply {
userId = incomingRoomKeyRequest.mUserId
deviceId = incomingRoomKeyRequest.mDeviceId
requestId = incomingRoomKeyRequest.mRequestId
putRequestBody(incomingRoomKeyRequest.mRequestBody)
userId = incomingRoomKeyRequest.userId
deviceId = incomingRoomKeyRequest.deviceId
requestId = incomingRoomKeyRequest.requestId
putRequestBody(incomingRoomKeyRequest.requestBody)
}
}
}
@ -685,9 +685,9 @@ internal class RealmCryptoStore(private val enableFileEncryption: Boolean = fals
override fun deleteIncomingRoomKeyRequest(incomingRoomKeyRequest: IncomingRoomKeyRequest) {
doRealmTransaction(realmConfiguration) {
it.where<IncomingRoomKeyRequestEntity>()
.equalTo(IncomingRoomKeyRequestEntityFields.USER_ID, incomingRoomKeyRequest.mUserId)
.equalTo(IncomingRoomKeyRequestEntityFields.DEVICE_ID, incomingRoomKeyRequest.mDeviceId)
.equalTo(IncomingRoomKeyRequestEntityFields.REQUEST_ID, incomingRoomKeyRequest.mRequestId)
.equalTo(IncomingRoomKeyRequestEntityFields.USER_ID, incomingRoomKeyRequest.userId)
.equalTo(IncomingRoomKeyRequestEntityFields.DEVICE_ID, incomingRoomKeyRequest.deviceId)
.equalTo(IncomingRoomKeyRequestEntityFields.REQUEST_ID, incomingRoomKeyRequest.requestId)
.findAll()
.deleteAllFromRealm()
}

View File

@ -33,10 +33,10 @@ internal open class IncomingRoomKeyRequestEntity(

fun toIncomingRoomKeyRequest(): IncomingRoomKeyRequest {
return IncomingRoomKeyRequest().apply {
mRequestId = requestId
mUserId = userId
mDeviceId = deviceId
mRequestBody = RoomKeyRequestBody().apply {
requestId = requestId
userId = userId
deviceId = deviceId
requestBody = RoomKeyRequestBody().apply {
algorithm = requestBodyAlgorithm
roomId = requestBodyRoomId
senderKey = requestBodySenderKey

View File

@ -38,8 +38,7 @@ class MatrixModule(private val context: Context) {
MatrixCoroutineDispatchers(io = Dispatchers.IO,
computation = Dispatchers.IO,
main = Dispatchers.Main,
encryption = Executors.newSingleThreadExecutor().asCoroutineDispatcher(),
decryption = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
crypto = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
)
}


View File

@ -68,8 +68,8 @@ internal class TaskExecutor(private val coroutineDispatchers: MatrixCoroutineDis
TaskThread.COMPUTATION -> coroutineDispatchers.computation
TaskThread.IO -> coroutineDispatchers.io
TaskThread.CALLER -> EmptyCoroutineContext
TaskThread.ENCRYPTION -> coroutineDispatchers.encryption
TaskThread.DECRYPTION -> coroutineDispatchers.decryption
TaskThread.ENCRYPTION -> coroutineDispatchers.crypto
TaskThread.DECRYPTION -> coroutineDispatchers.crypto
}



View File

@ -22,6 +22,5 @@ internal data class MatrixCoroutineDispatchers(
val io: CoroutineDispatcher,
val computation: CoroutineDispatcher,
val main: CoroutineDispatcher,
val decryption: CoroutineDispatcher,
val encryption: CoroutineDispatcher
val crypto: CoroutineDispatcher
)

View File

@ -70,11 +70,11 @@ class EncryptedItemFactory(
if (decrypted == null) {
return null
}
if (decrypted.mClearEvent == null) {
if (decrypted.clearEvent == null) {
return null
}
val adapter = MoshiProvider.providesMoshi().adapter(Event::class.java)
val clearEvent = adapter.fromJsonValue(decrypted.mClearEvent) ?: return null
val clearEvent = adapter.fromJsonValue(decrypted.clearEvent) ?: return null
val decryptedTimelineEvent = timelineEvent.copy(root = clearEvent)

// Success