WIP
This commit is contained in:
parent
6d8000b957
commit
52d9adad70
|
@ -22,12 +22,15 @@ import im.vector.matrix.android.api.listeners.ProgressListener
|
|||
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupService
|
||||
import im.vector.matrix.android.api.session.crypto.keyshare.RoomKeysRequestListener
|
||||
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationService
|
||||
import im.vector.matrix.android.api.session.events.model.Content
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.Room
|
||||
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
||||
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.rest.RoomKeyRequestBody
|
||||
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||
|
||||
interface CryptoService {
|
||||
|
||||
|
@ -57,7 +60,7 @@ interface CryptoService {
|
|||
|
||||
fun getMyDevice(): MXDeviceInfo
|
||||
|
||||
fun getGlobalBlacklistUnverifiedDevices() : Boolean
|
||||
fun getGlobalBlacklistUnverifiedDevices(): Boolean
|
||||
|
||||
fun setGlobalBlacklistUnverifiedDevices(block: Boolean)
|
||||
|
||||
|
@ -83,6 +86,13 @@ interface CryptoService {
|
|||
|
||||
fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int
|
||||
|
||||
fun isRoomEncrypted(roomId: String): Boolean
|
||||
|
||||
fun encryptEventContent(eventContent: Content,
|
||||
eventType: String,
|
||||
room: Room,
|
||||
callback: MatrixCallback<MXEncryptEventContentResult>)
|
||||
|
||||
/*
|
||||
fun start(isInitialSync: Boolean, aCallback: MatrixCallback<Unit>?)
|
||||
|
||||
|
@ -92,14 +102,6 @@ interface CryptoService {
|
|||
|
||||
fun close()
|
||||
|
||||
fun encryptEventContent(eventContent: Content,
|
||||
eventType: String,
|
||||
room: Room,
|
||||
callback: MatrixCallback<MXEncryptEventContentResult>)
|
||||
|
||||
fun onToDeviceEvent(event: Event)
|
||||
|
||||
fun onSyncCompleted(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean)
|
||||
|
||||
fun getOlmDevice(): MXOlmDevice?
|
||||
|
||||
|
@ -118,4 +120,8 @@ interface CryptoService {
|
|||
*/
|
||||
|
||||
fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult?
|
||||
|
||||
fun getEncryptionAlgorithm(roomId: String): String?
|
||||
|
||||
fun shouldEncryptForInvitedMembers(roomId: String): Boolean
|
||||
}
|
|
@ -16,16 +16,11 @@
|
|||
|
||||
package im.vector.matrix.android.api.session.room.crypto
|
||||
|
||||
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||
|
||||
interface RoomCryptoService {
|
||||
|
||||
// TODO
|
||||
fun isEncrypted(): Boolean = false
|
||||
fun isEncrypted(): Boolean
|
||||
|
||||
// TODO
|
||||
fun encryptionAlgorithm(): String? = MXCRYPTO_ALGORITHM_MEGOLM
|
||||
fun encryptionAlgorithm(): String?
|
||||
|
||||
// TODO
|
||||
fun shouldEncryptForInvitedMembers(): Boolean = false
|
||||
fun shouldEncryptForInvitedMembers(): Boolean
|
||||
}
|
|
@ -54,18 +54,4 @@ interface RoomMembersService {
|
|||
*/
|
||||
fun invite(userId: String, callback: MatrixCallback<Unit>)
|
||||
|
||||
/**
|
||||
* Return all the roomMembers ids which are joined or invited to the room
|
||||
*
|
||||
* @return a roomMember id list of joined or invited members.
|
||||
*/
|
||||
fun getActiveRoomMemberIds(): List<String>
|
||||
|
||||
/**
|
||||
* Return all the roomMembers ids which are joined to the room
|
||||
*
|
||||
* @return a roomMember id list of joined members.
|
||||
*/
|
||||
fun getJoinedRoomMemberIds(): List<String>
|
||||
|
||||
}
|
|
@ -35,8 +35,8 @@ 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.api.session.room.Room
|
||||
import im.vector.matrix.android.api.session.room.RoomService
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibilityContent
|
||||
import im.vector.matrix.android.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
|
||||
import im.vector.matrix.android.internal.crypto.actions.MegolmSessionDataImporter
|
||||
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
|
||||
|
@ -97,8 +97,6 @@ internal class CryptoManager(
|
|||
private val mIncomingRoomKeyRequestManager: IncomingRoomKeyRequestManager,
|
||||
//
|
||||
private val mOutgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager,
|
||||
// Room service
|
||||
private val mRoomService: RoomService,
|
||||
// Olm Manager
|
||||
private val mOlmManager: OlmManager,
|
||||
// Actions
|
||||
|
@ -140,11 +138,23 @@ internal class CryptoManager(
|
|||
// }
|
||||
//}
|
||||
|
||||
fun onLiveEvent(roomId: String, event: Event) {
|
||||
fun onStateEvent(roomId: String, event: Event) {
|
||||
if (event.type == EventType.ENCRYPTION) {
|
||||
onRoomEncryptionEvent(roomId, event)
|
||||
// TODO Remove onRoomEncryptionEvent(roomId, event)
|
||||
} else if (event.type == EventType.STATE_ROOM_MEMBER) {
|
||||
onRoomMembershipEvent(roomId, event)
|
||||
} else if (event.type == EventType.STATE_HISTORY_VISIBILITY) {
|
||||
onRoomHistoryVisibilityEvent(roomId, event)
|
||||
}
|
||||
}
|
||||
|
||||
fun onLiveEvent(roomId: String, event: Event) {
|
||||
if (event.type == EventType.ENCRYPTION) {
|
||||
// TODO Remove onRoomEncryptionEvent(roomId, event)
|
||||
} else if (event.type == EventType.STATE_ROOM_MEMBER) {
|
||||
onRoomMembershipEvent(roomId, event)
|
||||
} else if (event.type == EventType.STATE_HISTORY_VISIBILITY) {
|
||||
onRoomHistoryVisibilityEvent(roomId, event)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,21 +532,15 @@ internal class CryptoManager(
|
|||
* @param roomId the room id
|
||||
* @return true if the room is encrypted
|
||||
*/
|
||||
fun isRoomEncrypted(roomId: String?): Boolean {
|
||||
var res = false
|
||||
override fun isRoomEncrypted(roomId: String): Boolean {
|
||||
var res: Boolean
|
||||
|
||||
if (null != roomId) {
|
||||
synchronized(mRoomEncryptors) {
|
||||
res = mRoomEncryptors.containsKey(roomId)
|
||||
synchronized(mRoomEncryptors) {
|
||||
res = mRoomEncryptors.containsKey(roomId)
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
val room = mRoomService.getRoom(roomId)
|
||||
|
||||
if (null != room) {
|
||||
res = room.isEncrypted()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
res = !mCryptoStore.getRoomAlgorithm(roomId).isNullOrBlank()
|
||||
}
|
||||
|
||||
return res
|
||||
|
@ -564,6 +568,26 @@ internal class CryptoManager(
|
|||
mEnsureOlmSessionsForDevicesAction.handle(devicesByUser, callback)
|
||||
}
|
||||
|
||||
fun isEncryptionEnabledForInvitedUser(): Boolean {
|
||||
return mCryptoConfig.mEnableEncryptionForInvitedMembers
|
||||
}
|
||||
|
||||
override fun getEncryptionAlgorithm(roomId: String): String? {
|
||||
return mCryptoStore.getRoomAlgorithm(roomId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether we should encrypt messages for invited users in this room.
|
||||
* <p>
|
||||
* Check here whether the invited members are allowed to read messages in the room history
|
||||
* from the point they were invited onwards.
|
||||
*
|
||||
* @return true if we should encrypt messages for invited users.
|
||||
*/
|
||||
override fun shouldEncryptForInvitedMembers(roomId: String): Boolean {
|
||||
return mCryptoStore.shouldEncryptForInvitedMembers(roomId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt an event content according to the configuration of the room.
|
||||
*
|
||||
|
@ -572,10 +596,10 @@ internal class CryptoManager(
|
|||
* @param room the room the event will be sent.
|
||||
* @param callback the asynchronous callback
|
||||
*/
|
||||
fun encryptEventContent(eventContent: Content,
|
||||
eventType: String,
|
||||
room: Room,
|
||||
callback: MatrixCallback<MXEncryptEventContentResult>) {
|
||||
override fun encryptEventContent(eventContent: Content,
|
||||
eventType: String,
|
||||
room: Room,
|
||||
callback: MatrixCallback<MXEncryptEventContentResult>) {
|
||||
// wait that the crypto is really started
|
||||
if (!isStarted()) {
|
||||
Timber.v("## encryptEventContent() : wait after e2e init")
|
||||
|
@ -596,13 +620,15 @@ internal class CryptoManager(
|
|||
}
|
||||
|
||||
// Check whether the event content must be encrypted for the invited members.
|
||||
val encryptForInvitedMembers = mCryptoConfig.mEnableEncryptionForInvitedMembers && room.shouldEncryptForInvitedMembers()
|
||||
val encryptForInvitedMembers = mCryptoConfig.mEnableEncryptionForInvitedMembers && shouldEncryptForInvitedMembers(room.roomId)
|
||||
|
||||
val userIds = if (encryptForInvitedMembers) {
|
||||
room.getActiveRoomMemberIds()
|
||||
} else {
|
||||
room.getJoinedRoomMemberIds()
|
||||
}
|
||||
// TODO
|
||||
//val userIds = if (encryptForInvitedMembers) {
|
||||
// room.getActiveRoomMemberIds()
|
||||
//} else {
|
||||
// room.getJoinedRoomMemberIds()
|
||||
//}
|
||||
val userIds = emptyList<String>()
|
||||
|
||||
// just as you are sending a secret message?
|
||||
|
||||
|
@ -749,22 +775,8 @@ internal class CryptoManager(
|
|||
*
|
||||
* @param event the encryption event.
|
||||
*/
|
||||
private fun onRoomEncryptionEvent(roomId: String, event: Event) {
|
||||
// TODO Parse the event
|
||||
val eventContent = event.content // wireEventContent
|
||||
|
||||
val room = mRoomService.getRoom(roomId)!!
|
||||
|
||||
// Check whether the event content must be encrypted for the invited members.
|
||||
val encryptForInvitedMembers = mCryptoConfig.mEnableEncryptionForInvitedMembers && room.shouldEncryptForInvitedMembers()
|
||||
|
||||
val userIds = if (encryptForInvitedMembers) {
|
||||
room.getActiveRoomMemberIds()
|
||||
} else {
|
||||
room.getJoinedRoomMemberIds()
|
||||
}
|
||||
|
||||
setEncryptionInRoom(roomId, eventContent!!["algorithm"] as String, true, userIds)
|
||||
fun onRoomEncryptionEvent(event: Event, userIds: List<String>) {
|
||||
setEncryptionInRoom(event.roomId!!, event.content!!["algorithm"] as String, true, userIds)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -785,6 +797,8 @@ internal class CryptoManager(
|
|||
}
|
||||
|
||||
val userId = event.stateKey!!
|
||||
|
||||
/* FIXME
|
||||
val room = mRoomService.getRoom(roomId)
|
||||
|
||||
val roomMember = room?.getRoomMember(userId)
|
||||
|
@ -796,7 +810,7 @@ internal class CryptoManager(
|
|||
// make sure we are tracking the deviceList for this user.
|
||||
deviceListManager.startTrackingDeviceList(Arrays.asList(userId))
|
||||
} else if (membership == Membership.INVITE
|
||||
&& room.shouldEncryptForInvitedMembers()
|
||||
&& shouldEncryptForInvitedMembers(roomId)
|
||||
&& mCryptoConfig.mEnableEncryptionForInvitedMembers) {
|
||||
// track the deviceList for this invited user.
|
||||
// Caution: there's a big edge case here in that federated servers do not
|
||||
|
@ -806,8 +820,18 @@ internal class CryptoManager(
|
|||
deviceListManager.startTrackingDeviceList(Arrays.asList(userId))
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private fun onRoomHistoryVisibilityEvent(roomId: String, event: Event) {
|
||||
val eventContent = event.content.toModel<RoomHistoryVisibilityContent>()
|
||||
|
||||
eventContent?.historyVisibility?.let {
|
||||
mCryptoStore.setShouldEncryptForInvitedMembers(roomId, it != RoomHistoryVisibility.JOINED)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Upload my user's device keys.
|
||||
* This method must called on getEncryptingThreadHandler() thread.
|
||||
|
@ -996,6 +1020,7 @@ internal class CryptoManager(
|
|||
* @param roomId the room id
|
||||
* @return true if the client should encrypt messages only for the verified devices.
|
||||
*/
|
||||
// TODO add this info in CryptoRoomEntity?
|
||||
override fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean {
|
||||
return if (null != roomId) {
|
||||
mCryptoStore.getRoomsListBlacklistUnverifiedDevices().contains(roomId)
|
||||
|
@ -1011,13 +1036,6 @@ internal class CryptoManager(
|
|||
* @param add true to add the room id to the list, false to remove it.
|
||||
*/
|
||||
private fun setRoomBlacklistUnverifiedDevices(roomId: String, add: Boolean) {
|
||||
val room = mRoomService.getRoom(roomId)
|
||||
|
||||
// sanity check
|
||||
if (null == room) {
|
||||
return
|
||||
}
|
||||
|
||||
val roomIds = mCryptoStore.getRoomsListBlacklistUnverifiedDevices().toMutableList()
|
||||
|
||||
if (add) {
|
||||
|
|
|
@ -80,7 +80,7 @@ internal class CryptoModule {
|
|||
|
||||
// CryptoService
|
||||
scope(DefaultSession.SCOPE) {
|
||||
DefaultCryptoService(get()) as CryptoService
|
||||
get<CryptoManager>() as CryptoService
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -187,7 +187,6 @@ internal class CryptoModule {
|
|||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
// Actions
|
||||
get(),
|
||||
get(),
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* 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 im.vector.matrix.android.internal.crypto
|
||||
|
||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||
|
||||
internal class DefaultCryptoService(val cryptoManager: CryptoManager)
|
||||
: CryptoService by cryptoManager
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* 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 im.vector.matrix.android.internal.crypto.live
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
||||
import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersTask
|
||||
import im.vector.matrix.android.internal.session.room.members.RoomMembers
|
||||
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.WorkerParamsFactory
|
||||
import org.koin.standalone.inject
|
||||
|
||||
internal class EnableEncryptionWorker(context: Context,
|
||||
workerParameters: WorkerParameters
|
||||
) : Worker(context, workerParameters), MatrixKoinComponent {
|
||||
|
||||
private val monarchy by inject<Monarchy>()
|
||||
private val cryptoManager by inject<CryptoManager>()
|
||||
private val loadRoomMembersTask by inject<LoadRoomMembersTask>()
|
||||
private val taskExecutor by inject<TaskExecutor>()
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal class Params(
|
||||
val eventIds: List<String>
|
||||
)
|
||||
|
||||
|
||||
override fun doWork(): Result {
|
||||
val params = WorkerParamsFactory.fromData<EnableEncryptionWorker.Params>(inputData)
|
||||
?: return Result.failure()
|
||||
|
||||
|
||||
val events = monarchy.fetchAllMappedSync(
|
||||
{ EventEntity.where(it, params.eventIds) },
|
||||
{ it.asDomain() }
|
||||
)
|
||||
|
||||
events.forEach {
|
||||
val roomId = it.roomId!!
|
||||
|
||||
loadRoomMembersTask
|
||||
.configureWith(LoadRoomMembersTask.Params(roomId))
|
||||
.executeOn(TaskThread.CALLER)
|
||||
.executeBy(taskExecutor)
|
||||
|
||||
var userIds: List<String> = emptyList()
|
||||
|
||||
monarchy.doWithRealm { realm ->
|
||||
// Check whether the event content must be encrypted for the invited members.
|
||||
val encryptForInvitedMembers = cryptoManager.isEncryptionEnabledForInvitedUser()
|
||||
&& cryptoManager.shouldEncryptForInvitedMembers(roomId)
|
||||
|
||||
|
||||
userIds = if (encryptForInvitedMembers) {
|
||||
RoomMembers(realm, roomId).getActiveRoomMemberIds()
|
||||
} else {
|
||||
RoomMembers(realm, roomId).getJoinedRoomMemberIds()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cryptoManager.onRoomEncryptionEvent(it, userIds)
|
||||
}
|
||||
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* 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 im.vector.matrix.android.internal.crypto.live
|
||||
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
||||
import timber.log.Timber
|
||||
|
||||
private const val ENABLE_ENCRYPTION_EVENT_WORKER = "ENABLE_ENCRYPTION_EVENT_WORKER"
|
||||
|
||||
internal class RoomEncryptionEnabler(monarchy: Monarchy) : RealmLiveEntityObserver<EventEntity>(monarchy) {
|
||||
|
||||
override val query: Monarchy.Query<EventEntity>
|
||||
get() = Monarchy.Query<EventEntity> { EventEntity.where(it, type = EventType.ENCRYPTION) }
|
||||
|
||||
|
||||
override fun processChanges(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) {
|
||||
Timber.v("RoomEncryption received")
|
||||
|
||||
val eventIds = inserted.mapNotNull { it.asDomain().eventId }
|
||||
|
||||
val workParam = EnableEncryptionWorker.Params(eventIds)
|
||||
val workData = WorkerParamsFactory.toData(workParam)
|
||||
|
||||
val work = OneTimeWorkRequestBuilder<EnableEncryptionWorker>()
|
||||
.setInputData(workData)
|
||||
.build()
|
||||
|
||||
WorkManager.getInstance()
|
||||
.beginUniqueWork(ENABLE_ENCRYPTION_EVENT_WORKER, ExistingWorkPolicy.APPEND, work)
|
||||
.enqueue()
|
||||
}
|
||||
}
|
|
@ -19,11 +19,11 @@ package im.vector.matrix.android.internal.crypto.store
|
|||
|
||||
import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequest
|
||||
import im.vector.matrix.android.internal.crypto.OutgoingRoomKeyRequest
|
||||
import im.vector.matrix.android.internal.crypto.store.db.model.KeysBackupDataEntity
|
||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.MXOlmInboundGroupSession2
|
||||
import im.vector.matrix.android.internal.crypto.model.MXOlmSession
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||
import im.vector.matrix.android.internal.crypto.store.db.model.KeysBackupDataEntity
|
||||
import org.matrix.olm.OlmAccount
|
||||
|
||||
/**
|
||||
|
@ -204,6 +204,10 @@ internal interface IMXCryptoStore {
|
|||
*/
|
||||
fun getRoomAlgorithm(roomId: String): String?
|
||||
|
||||
fun shouldEncryptForInvitedMembers(roomId: String): Boolean
|
||||
|
||||
fun setShouldEncryptForInvitedMembers(roomId: String, shouldEncryptForInvitedMembers: Boolean)
|
||||
|
||||
/**
|
||||
* Store a session between the logged-in user and another device.
|
||||
*
|
||||
|
|
|
@ -20,15 +20,15 @@ import android.text.TextUtils
|
|||
import im.vector.matrix.android.api.auth.data.Credentials
|
||||
import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequest
|
||||
import im.vector.matrix.android.internal.crypto.OutgoingRoomKeyRequest
|
||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.MXOlmInboundGroupSession2
|
||||
import im.vector.matrix.android.internal.crypto.model.MXOlmSession
|
||||
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.store.db.model.*
|
||||
import im.vector.matrix.android.internal.crypto.store.db.query.delete
|
||||
import im.vector.matrix.android.internal.crypto.store.db.query.getById
|
||||
import im.vector.matrix.android.internal.crypto.store.db.query.getOrCreate
|
||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.MXOlmInboundGroupSession2
|
||||
import im.vector.matrix.android.internal.crypto.model.MXOlmSession
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||
import io.realm.RealmConfiguration
|
||||
import io.realm.Sort
|
||||
import io.realm.kotlin.where
|
||||
|
@ -55,7 +55,7 @@ internal class RealmCryptoStore(private val enableFileEncryption: Boolean = fals
|
|||
// Cache for InboundGroupSession, to release them properly
|
||||
private val inboundGroupSessionToRelease = HashMap<String, MXOlmInboundGroupSession2>()
|
||||
|
||||
/* ==========================================================================================
|
||||
/* ==========================================================================================
|
||||
* Other data
|
||||
* ========================================================================================== */
|
||||
|
||||
|
@ -241,6 +241,19 @@ internal class RealmCryptoStore(private val enableFileEncryption: Boolean = fals
|
|||
?.algorithm
|
||||
}
|
||||
|
||||
override fun shouldEncryptForInvitedMembers(roomId: String): Boolean {
|
||||
return doRealmQueryAndCopy(realmConfiguration) {
|
||||
CryptoRoomEntity.getById(it, roomId)
|
||||
}
|
||||
?.shouldEncryptForInvitedMembers ?: false
|
||||
}
|
||||
|
||||
override fun setShouldEncryptForInvitedMembers(roomId: String, shouldEncryptForInvitedMembers: Boolean) {
|
||||
doRealmTransaction(realmConfiguration) {
|
||||
CryptoRoomEntity.getOrCreate(it, roomId).shouldEncryptForInvitedMembers = shouldEncryptForInvitedMembers
|
||||
}
|
||||
}
|
||||
|
||||
override fun storeSession(session: MXOlmSession, deviceKey: String) {
|
||||
var sessionIdentifier: String? = null
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import io.realm.annotations.PrimaryKey
|
|||
internal open class CryptoRoomEntity(
|
||||
@PrimaryKey var roomId: String? = null,
|
||||
var algorithm: String? = null,
|
||||
var shouldEncryptForInvitedMembers: Boolean? = null,
|
||||
var blacklistUnverifiedDevices: Boolean = false)
|
||||
: RealmObject() {
|
||||
|
||||
|
|
|
@ -70,6 +70,9 @@ internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val m
|
|||
processChanges(inserted, updated, deleted)
|
||||
}
|
||||
|
||||
/**
|
||||
* Do quick treatment or delegate on a task
|
||||
*/
|
||||
protected abstract fun processChanges(inserted: List<T>, updated: List<T>, deleted: List<T>)
|
||||
|
||||
}
|
|
@ -30,6 +30,10 @@ internal fun EventEntity.Companion.where(realm: Realm, eventId: String): RealmQu
|
|||
return realm.where<EventEntity>().equalTo(EventEntityFields.EVENT_ID, eventId)
|
||||
}
|
||||
|
||||
internal fun EventEntity.Companion.where(realm: Realm, eventIds: List<String>): RealmQuery<EventEntity> {
|
||||
return realm.where<EventEntity>().`in`(EventEntityFields.EVENT_ID, eventIds.toTypedArray())
|
||||
}
|
||||
|
||||
internal fun EventEntity.Companion.where(realm: Realm,
|
||||
roomId: String? = null,
|
||||
type: String? = null,
|
||||
|
|
|
@ -48,6 +48,7 @@ object MoshiProvider {
|
|||
return moshi
|
||||
}
|
||||
|
||||
// TODO Move
|
||||
fun <T> getCanonicalJson(type: Class<T>, o: T): String {
|
||||
val adapter = moshi.adapter<T>(type)
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
|||
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupService
|
||||
import im.vector.matrix.android.api.session.crypto.keyshare.RoomKeysRequestListener
|
||||
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationService
|
||||
import im.vector.matrix.android.api.session.events.model.Content
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.group.Group
|
||||
import im.vector.matrix.android.api.session.group.GroupService
|
||||
|
@ -44,13 +45,14 @@ import im.vector.matrix.android.api.session.sync.FilterService
|
|||
import im.vector.matrix.android.api.session.user.UserService
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
import im.vector.matrix.android.api.util.MatrixCallbackDelegate
|
||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
||||
import im.vector.matrix.android.internal.crypto.CryptoModule
|
||||
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
||||
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.CryptoManager
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
||||
import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
||||
import im.vector.matrix.android.internal.di.MatrixKoinHolder
|
||||
|
@ -321,6 +323,17 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
|
|||
cryptoService.setRoomBlacklistUnverifiedDevices(roomId)
|
||||
}
|
||||
|
||||
override fun isRoomEncrypted(roomId: String): Boolean {
|
||||
return cryptoService.isRoomEncrypted(roomId)
|
||||
}
|
||||
|
||||
override fun encryptEventContent(eventContent: Content,
|
||||
eventType: String,
|
||||
room: Room,
|
||||
callback: MatrixCallback<MXEncryptEventContentResult>) {
|
||||
cryptoService.encryptEventContent(eventContent, eventType, room, callback)
|
||||
}
|
||||
|
||||
override fun getDeviceInfo(userId: String, deviceId: String?): MXDeviceInfo? {
|
||||
return cryptoService.getDeviceInfo(userId, deviceId)
|
||||
}
|
||||
|
@ -341,6 +354,14 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
|
|||
return cryptoService.decryptEvent(event, timeline)
|
||||
}
|
||||
|
||||
override fun getEncryptionAlgorithm(roomId: String): String? {
|
||||
return cryptoService.getEncryptionAlgorithm(roomId)
|
||||
}
|
||||
|
||||
override fun shouldEncryptForInvitedMembers(roomId: String): Boolean {
|
||||
return cryptoService.shouldEncryptForInvitedMembers(roomId)
|
||||
}
|
||||
|
||||
// Private methods *****************************************************************************
|
||||
|
||||
private fun assertMainThread() {
|
||||
|
|
|
@ -25,6 +25,7 @@ import im.vector.matrix.android.api.session.room.RoomService
|
|||
import im.vector.matrix.android.api.session.signout.SignOutService
|
||||
import im.vector.matrix.android.api.session.sync.FilterService
|
||||
import im.vector.matrix.android.api.session.user.UserService
|
||||
import im.vector.matrix.android.internal.crypto.live.RoomEncryptionEnabler
|
||||
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
||||
import im.vector.matrix.android.internal.database.model.SessionRealmModule
|
||||
import im.vector.matrix.android.internal.session.cache.ClearCacheTask
|
||||
|
@ -151,7 +152,8 @@ internal class SessionModule(private val sessionParams: SessionParams) {
|
|||
val groupSummaryUpdater = GroupSummaryUpdater(get())
|
||||
val eventsPruner = EventsPruner(get())
|
||||
val userEntityUpdater = UserEntityUpdater(get(), get(), get())
|
||||
listOf<LiveEntityObserver>(groupSummaryUpdater, eventsPruner, userEntityUpdater)
|
||||
val roomEncryptionEnabler = RoomEncryptionEnabler(get())
|
||||
listOf<LiveEntityObserver>(groupSummaryUpdater, eventsPruner, userEntityUpdater, roomEncryptionEnabler)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.session.room
|
|||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||
import im.vector.matrix.android.api.session.room.Room
|
||||
import im.vector.matrix.android.api.session.room.members.RoomMembersService
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
|
@ -39,7 +40,8 @@ internal class DefaultRoom(
|
|||
private val sendService: SendService,
|
||||
private val stateService: StateService,
|
||||
private val readService: ReadService,
|
||||
private val roomMembersService: RoomMembersService
|
||||
private val roomMembersService: RoomMembersService,
|
||||
private val cryptoService: CryptoService
|
||||
) : Room,
|
||||
TimelineService by timelineService,
|
||||
SendService by sendService,
|
||||
|
@ -63,4 +65,16 @@ internal class DefaultRoom(
|
|||
}
|
||||
}
|
||||
|
||||
override fun isEncrypted(): Boolean {
|
||||
return cryptoService.isRoomEncrypted(roomId)
|
||||
}
|
||||
|
||||
override fun encryptionAlgorithm(): String? {
|
||||
return cryptoService.getEncryptionAlgorithm(roomId)
|
||||
}
|
||||
|
||||
override fun shouldEncryptForInvitedMembers(): Boolean {
|
||||
return cryptoService.shouldEncryptForInvitedMembers(roomId)
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
package im.vector.matrix.android.internal.session.room
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||
import im.vector.matrix.android.api.session.room.Room
|
||||
import im.vector.matrix.android.internal.session.room.invite.InviteTask
|
||||
import im.vector.matrix.android.internal.session.room.members.DefaultRoomMembersService
|
||||
|
@ -42,13 +43,14 @@ internal class RoomFactory(private val loadRoomMembersTask: LoadRoomMembersTask,
|
|||
private val contextOfEventTask: GetContextOfEventTask,
|
||||
private val setReadMarkersTask: SetReadMarkersTask,
|
||||
private val eventFactory: LocalEchoEventFactory,
|
||||
private val cryptoService: CryptoService,
|
||||
private val taskExecutor: TaskExecutor) {
|
||||
|
||||
fun instantiate(roomId: String): Room {
|
||||
val roomMemberExtractor = SenderRoomMemberExtractor(roomId)
|
||||
val timelineEventFactory = TimelineEventFactory(roomMemberExtractor)
|
||||
val timelineService = DefaultTimelineService(roomId, monarchy, taskExecutor, contextOfEventTask, timelineEventFactory, paginationTask)
|
||||
val sendService = DefaultSendService(roomId, eventFactory, monarchy)
|
||||
val sendService = DefaultSendService(roomId, eventFactory, cryptoService, monarchy)
|
||||
val stateService = DefaultStateService(roomId, sendStateTask, taskExecutor)
|
||||
val roomMembersService = DefaultRoomMembersService(roomId, monarchy, loadRoomMembersTask, inviteTask, taskExecutor)
|
||||
val readService = DefaultReadService(roomId, monarchy, setReadMarkersTask, taskExecutor)
|
||||
|
@ -60,7 +62,8 @@ internal class RoomFactory(private val loadRoomMembersTask: LoadRoomMembersTask,
|
|||
sendService,
|
||||
stateService,
|
||||
readService,
|
||||
roomMembersService
|
||||
roomMembersService,
|
||||
cryptoService
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ class RoomModule {
|
|||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
RoomFactory(get(), get(), get(), get(), get(), get(), get(), get(), get())
|
||||
RoomFactory(get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
|
|
|
@ -68,26 +68,4 @@ internal class DefaultRoomMembersService(private val roomId: String,
|
|||
.dispatchTo(callback)
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override fun getActiveRoomMemberIds(): List<String> {
|
||||
return getRoomMemberIdsFiltered { it.membership == Membership.JOIN || it.membership == Membership.INVITE }
|
||||
}
|
||||
|
||||
override fun getJoinedRoomMemberIds(): List<String> {
|
||||
return getRoomMemberIdsFiltered { it.membership == Membership.JOIN }
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* Private
|
||||
* ========================================================================================== */
|
||||
|
||||
private fun getRoomMemberIdsFiltered(predicate: (RoomMember) -> Boolean): List<String> {
|
||||
return monarchy.fetchAllCopiedSync { RoomMembers(it, roomId).queryRoomMembersEvent() }
|
||||
.map { it.asDomain() }
|
||||
.associateBy { it.stateKey!! }
|
||||
.mapValues { it.value.content.toModel<RoomMember>()!! }
|
||||
.filterValues { predicate(it) }
|
||||
.keys
|
||||
.toList()
|
||||
}
|
||||
}
|
|
@ -95,5 +95,38 @@ internal class RoomMembers(private val realm: Realm,
|
|||
return getNumberOfJoinedMembers() + getNumberOfInvitedMembers()
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the roomMembers ids which are joined or invited to the room
|
||||
*
|
||||
* @return a roomMember id list of joined or invited members.
|
||||
*/
|
||||
fun getActiveRoomMemberIds(): List<String> {
|
||||
return getRoomMemberIdsFiltered { it.membership == Membership.JOIN || it.membership == Membership.INVITE }
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the roomMembers ids which are joined to the room
|
||||
*
|
||||
* @return a roomMember id list of joined members.
|
||||
*/
|
||||
fun getJoinedRoomMemberIds(): List<String> {
|
||||
return getRoomMemberIdsFiltered { it.membership == Membership.JOIN }
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* Private
|
||||
* ========================================================================================== */
|
||||
|
||||
private fun getRoomMemberIdsFiltered(predicate: (RoomMember) -> Boolean): List<String> {
|
||||
return RoomMembers(realm, roomId)
|
||||
.queryRoomMembersEvent()
|
||||
.findAll()
|
||||
.map { it.asDomain() }
|
||||
.associateBy { it.stateKey!! }
|
||||
.mapValues { it.value.content.toModel<RoomMember>()!! }
|
||||
.filterValues { predicate(it) }
|
||||
.keys
|
||||
.toList()
|
||||
}
|
||||
|
||||
}
|
|
@ -16,15 +16,10 @@
|
|||
|
||||
package im.vector.matrix.android.internal.session.room.send
|
||||
|
||||
import androidx.work.BackoffPolicy
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.*
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.send.SendService
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
|
@ -39,6 +34,7 @@ import im.vector.matrix.android.internal.session.content.UploadContentWorker
|
|||
import im.vector.matrix.android.internal.util.CancelableWork
|
||||
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
||||
import im.vector.matrix.android.internal.util.tryTransactionAsync
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
private const val SEND_WORK = "SEND_WORK"
|
||||
|
@ -51,6 +47,7 @@ private val WORK_CONSTRAINTS = Constraints.Builder()
|
|||
|
||||
internal class DefaultSendService(private val roomId: String,
|
||||
private val eventFactory: LocalEchoEventFactory,
|
||||
private val cryptoService: CryptoService,
|
||||
private val monarchy: Monarchy)
|
||||
: SendService {
|
||||
|
||||
|
@ -59,6 +56,33 @@ internal class DefaultSendService(private val roomId: String,
|
|||
val event = eventFactory.createTextEvent(roomId, msgType, text).also {
|
||||
saveLocalEcho(it)
|
||||
}
|
||||
|
||||
// Encrypted room handling
|
||||
if (cryptoService.isRoomEncrypted(roomId)) {
|
||||
Timber.v("Send event in encrypted room")
|
||||
// Encrypt then send
|
||||
|
||||
val encryptWork = createEncryptEventWork(event)
|
||||
|
||||
val sendWork = OneTimeWorkRequestBuilder<SendEventWorker>()
|
||||
.setConstraints(WORK_CONSTRAINTS)
|
||||
.setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
|
||||
WorkManager.getInstance()
|
||||
// Encrypt
|
||||
.beginUniqueWork(buildWorkIdentifier(SEND_WORK), ExistingWorkPolicy.APPEND, encryptWork)
|
||||
// then send
|
||||
.then(sendWork)
|
||||
.enqueue()
|
||||
|
||||
return CancelableWork(encryptWork.id)
|
||||
} else {
|
||||
return sendEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendEvent(event: Event): Cancelable {
|
||||
val sendWork = createSendEventWork(event)
|
||||
WorkManager.getInstance()
|
||||
.beginUniqueWork(buildWorkIdentifier(SEND_WORK), ExistingWorkPolicy.APPEND, sendWork)
|
||||
|
@ -93,9 +117,9 @@ internal class DefaultSendService(private val roomId: String,
|
|||
private fun saveLocalEcho(event: Event) {
|
||||
monarchy.tryTransactionAsync { realm ->
|
||||
val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst()
|
||||
?: return@tryTransactionAsync
|
||||
?: return@tryTransactionAsync
|
||||
val liveChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId = roomId)
|
||||
?: return@tryTransactionAsync
|
||||
?: return@tryTransactionAsync
|
||||
|
||||
roomEntity.addSendingEvent(event, liveChunk.forwardsStateIndex ?: 0)
|
||||
}
|
||||
|
@ -105,6 +129,18 @@ internal class DefaultSendService(private val roomId: String,
|
|||
return "${roomId}_$identifier"
|
||||
}
|
||||
|
||||
private fun createEncryptEventWork(event: Event): OneTimeWorkRequest {
|
||||
// Same parameter
|
||||
val sendContentWorkerParams = SendEventWorker.Params(roomId, event)
|
||||
val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
|
||||
|
||||
return OneTimeWorkRequestBuilder<EncryptEventWorker>()
|
||||
.setConstraints(WORK_CONSTRAINTS)
|
||||
.setInputData(sendWorkData)
|
||||
.setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun createSendEventWork(event: Event): OneTimeWorkRequest {
|
||||
val sendContentWorkerParams = SendEventWorker.Params(roomId, event)
|
||||
val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* 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 im.vector.matrix.android.internal.session.room.send
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.RoomService
|
||||
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
||||
import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
||||
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
||||
import org.koin.standalone.inject
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
internal class EncryptEventWorker(context: Context, params: WorkerParameters)
|
||||
: Worker(context, params), MatrixKoinComponent {
|
||||
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class Params(
|
||||
val roomId: String,
|
||||
val event: Event
|
||||
)
|
||||
|
||||
private val crypto by inject<CryptoService>()
|
||||
private val roomService by inject<RoomService>()
|
||||
|
||||
override fun doWork(): Result {
|
||||
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.failure()
|
||||
|
||||
val localEvent = params.event
|
||||
if (localEvent.eventId == null) {
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
// TODO Better async handling
|
||||
val latch = CountDownLatch(1)
|
||||
|
||||
var result: MXEncryptEventContentResult? = null
|
||||
var error: Throwable? = null
|
||||
|
||||
crypto.encryptEventContent(localEvent.content!!, localEvent.type, roomService.getRoom(params.roomId)!!, object : MatrixCallback<MXEncryptEventContentResult> {
|
||||
override fun onSuccess(data: MXEncryptEventContentResult) {
|
||||
result = data
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
error = failure
|
||||
latch.countDown()
|
||||
}
|
||||
})
|
||||
|
||||
latch.await()
|
||||
|
||||
// TODO Update local echo
|
||||
|
||||
if (error != null) {
|
||||
return Result.failure() // TODO Pass error!!)
|
||||
} else if (result != null) {
|
||||
return Result.success(WorkerParamsFactory.toData(SendEventWorker.Params(params.roomId,
|
||||
Event(type = result!!.mEventType,
|
||||
content = result!!.mEventContent))))
|
||||
} else {
|
||||
return Result.failure()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -63,9 +63,9 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
|
|||
|
||||
private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy) {
|
||||
val rooms = when (handlingStrategy) {
|
||||
is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) }
|
||||
is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) }
|
||||
is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) }
|
||||
is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(it.key, it.value) }
|
||||
is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(it.key, it.value) }
|
||||
}
|
||||
realm.insertOrUpdate(rooms)
|
||||
}
|
||||
|
@ -91,9 +91,16 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
|
|||
val numberOfStateEvents = roomSync.state?.events?.size ?: 0
|
||||
val stateIndexOffset = lastStateIndex + numberOfStateEvents
|
||||
|
||||
// State event
|
||||
if (roomSync.state != null && roomSync.state.events.isNotEmpty()) {
|
||||
val untimelinedStateIndex = if (isInitialSync) Int.MIN_VALUE else stateIndexOffset
|
||||
roomEntity.addStateEvents(roomSync.state.events, filterDuplicates = true, stateIndex = untimelinedStateIndex)
|
||||
|
||||
// Give info to crypto module
|
||||
// TODO Remove
|
||||
roomSync.state.events.forEach {
|
||||
mCrypto.onStateEvent(roomId, it)
|
||||
}
|
||||
}
|
||||
|
||||
if (roomSync.timeline != null && roomSync.timeline.events.isNotEmpty()) {
|
||||
|
|
Loading…
Reference in New Issue