Merge pull request #2253 from vector-im/feature/bma/small_fixies

Feature/bma/small fixies
This commit is contained in:
Benoit Marty 2020-10-13 11:35:50 +02:00 committed by GitHub
commit 86b4e34031
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 226 additions and 106 deletions

View File

@ -17,6 +17,8 @@
package org.matrix.android.sdk.api
import android.content.Context
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.work.Configuration
import androidx.work.WorkManager
@ -48,14 +50,18 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
@Inject internal lateinit var olmManager: OlmManager
@Inject internal lateinit var sessionManager: SessionManager
private val uiHandler = Handler(Looper.getMainLooper())
init {
Monarchy.init(context)
DaggerTestMatrixComponent.factory().create(context, matrixConfiguration).inject(this)
if (context.applicationContext !is Configuration.Provider) {
WorkManager.initialize(context, Configuration.Builder().setExecutor(Executors.newCachedThreadPool()).build())
}
uiHandler.post {
ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)
}
}
fun getUserAgent() = userAgentHolder.userAgent

View File

@ -16,7 +16,6 @@
package org.matrix.android.sdk.internal.crypto
import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreModule
@ -34,14 +33,8 @@ internal class CryptoStoreHelper {
.modules(RealmCryptoStoreModule())
.build(),
crossSigningKeysMapper = CrossSigningKeysMapper(MoshiProvider.providesMoshi()),
credentials = createCredential())
}
fun createCredential() = Credentials(
userId = "userId_" + Random.nextInt(),
homeServer = "http://matrix.org",
accessToken = "access_token",
refreshToken = null,
deviceId = "deviceId_sample"
)
}
}

View File

@ -0,0 +1,111 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.crypto.encryption
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.amshove.kluent.shouldBe
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.NoOpMatrixCallback
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.crypto.model.event.EncryptionEventContent
import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class EncryptionTest : InstrumentedTest {
private val mTestHelper = CommonTestHelper(context())
private val mCryptoTestHelper = CryptoTestHelper(mTestHelper)
@Test
fun test_EncryptionEvent() {
performTest(roomShouldBeEncrypted = false) { room ->
// Send an encryption Event as an Event (and not as a state event)
room.sendEvent(
eventType = EventType.STATE_ROOM_ENCRYPTION,
content = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
)
}
}
@Test
fun test_EncryptionStateEvent() {
performTest(roomShouldBeEncrypted = true) { room ->
// Send an encryption Event as a State Event
room.sendStateEvent(
eventType = EventType.STATE_ROOM_ENCRYPTION,
stateKey = null,
body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent(),
callback = NoOpMatrixCallback()
)
}
}
private fun performTest(roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) {
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceInARoom(encryptedRoom = false)
val aliceSession = cryptoTestData.firstSession
val room = aliceSession.getRoom(cryptoTestData.roomId)!!
room.isEncrypted() shouldBe false
val timeline = room.createTimeline(null, TimelineSettings(10))
val latch = CountDownLatch(1)
val timelineListener = object : Timeline.Listener {
override fun onTimelineFailure(throwable: Throwable) {
}
override fun onNewTimelineEvents(eventIds: List<String>) {
// noop
}
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
val newMessages = snapshot
.filter { it.root.sendState == SendState.SYNCED }
.filter { it.root.getClearType() == EventType.STATE_ROOM_ENCRYPTION }
if (newMessages.isNotEmpty()) {
timeline.removeListener(this)
latch.countDown()
}
}
}
timeline.start()
timeline.addListener(timelineListener)
action.invoke(room)
mTestHelper.await(latch)
timeline.dispose()
room.isEncrypted() shouldBe roomShouldBeEncrypted
cryptoTestData.cleanUp(mTestHelper)
}
}

View File

@ -17,15 +17,14 @@
package org.matrix.android.sdk.internal.crypto.verification.qrcode
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.matrix.android.sdk.InstrumentedTest
import org.amshove.kluent.shouldBeEqualTo
import org.amshove.kluent.shouldBeNull
import org.amshove.kluent.shouldEqual
import org.amshove.kluent.shouldEqualTo
import org.amshove.kluent.shouldNotBeNull
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
@ -66,32 +65,32 @@ class QrCodeTest : InstrumentedTest {
@Test
fun testEncoding1() {
qrCode1.toEncodedString() shouldEqual value1
qrCode1.toEncodedString() shouldBeEqualTo value1
}
@Test
fun testEncoding2() {
qrCode2.toEncodedString() shouldEqual value2
qrCode2.toEncodedString() shouldBeEqualTo value2
}
@Test
fun testEncoding3() {
qrCode3.toEncodedString() shouldEqual value3
qrCode3.toEncodedString() shouldBeEqualTo value3
}
@Test
fun testSymmetry1() {
qrCode1.toEncodedString().toQrCodeData() shouldEqual qrCode1
qrCode1.toEncodedString().toQrCodeData() shouldBeEqualTo qrCode1
}
@Test
fun testSymmetry2() {
qrCode2.toEncodedString().toQrCodeData() shouldEqual qrCode2
qrCode2.toEncodedString().toQrCodeData() shouldBeEqualTo qrCode2
}
@Test
fun testSymmetry3() {
qrCode3.toEncodedString().toQrCodeData() shouldEqual qrCode3
qrCode3.toEncodedString().toQrCodeData() shouldBeEqualTo qrCode3
}
@Test
@ -102,7 +101,7 @@ class QrCodeTest : InstrumentedTest {
checkHeader(byteArray)
// Mode
byteArray[7] shouldEqualTo 0
byteArray[7] shouldBeEqualTo 0
checkSizeAndTransaction(byteArray)
@ -120,7 +119,7 @@ class QrCodeTest : InstrumentedTest {
checkHeader(byteArray)
// Mode
byteArray[7] shouldEqualTo 1
byteArray[7] shouldBeEqualTo 1
checkSizeAndTransaction(byteArray)
compareArray(byteArray.copyOfRange(23, 23 + 32), kte_byteArray)
@ -137,7 +136,7 @@ class QrCodeTest : InstrumentedTest {
checkHeader(byteArray)
// Mode
byteArray[7] shouldEqualTo 2
byteArray[7] shouldBeEqualTo 2
checkSizeAndTransaction(byteArray)
compareArray(byteArray.copyOfRange(23, 23 + 32), tlx_byteArray)
@ -156,10 +155,10 @@ class QrCodeTest : InstrumentedTest {
val result = qrCode.toEncodedString()
val expected = value1.replace("\u0000\u000DMaTransaction", "\u0007\u00D0$longTransactionId")
result shouldEqual expected
result shouldBeEqualTo expected
// Reverse operation
expected.toQrCodeData() shouldEqual qrCode
expected.toQrCodeData() shouldBeEqualTo qrCode
}
@Test
@ -170,7 +169,7 @@ class QrCodeTest : InstrumentedTest {
val qrCode = qrCode1.copy(transactionId = longTransactionId)
// Symmetric operation
qrCode.toEncodedString().toQrCodeData() shouldEqual qrCode
qrCode.toEncodedString().toQrCodeData() shouldBeEqualTo qrCode
}
}
@ -218,32 +217,32 @@ class QrCodeTest : InstrumentedTest {
}
private fun compareArray(actual: ByteArray, expected: ByteArray) {
actual.size shouldEqual expected.size
actual.size shouldBeEqualTo expected.size
for (i in actual.indices) {
actual[i] shouldEqualTo expected[i]
actual[i] shouldBeEqualTo expected[i]
}
}
private fun checkHeader(byteArray: ByteArray) {
// MATRIX
byteArray[0] shouldEqualTo 'M'.toByte()
byteArray[1] shouldEqualTo 'A'.toByte()
byteArray[2] shouldEqualTo 'T'.toByte()
byteArray[3] shouldEqualTo 'R'.toByte()
byteArray[4] shouldEqualTo 'I'.toByte()
byteArray[5] shouldEqualTo 'X'.toByte()
byteArray[0] shouldBeEqualTo 'M'.toByte()
byteArray[1] shouldBeEqualTo 'A'.toByte()
byteArray[2] shouldBeEqualTo 'T'.toByte()
byteArray[3] shouldBeEqualTo 'R'.toByte()
byteArray[4] shouldBeEqualTo 'I'.toByte()
byteArray[5] shouldBeEqualTo 'X'.toByte()
// Version
byteArray[6] shouldEqualTo 2
byteArray[6] shouldBeEqualTo 2
}
private fun checkSizeAndTransaction(byteArray: ByteArray) {
// Size
byteArray[8] shouldEqualTo 0
byteArray[9] shouldEqualTo 13
byteArray[8] shouldBeEqualTo 0
byteArray[9] shouldBeEqualTo 13
// Transaction
byteArray.copyOfRange(10, 10 + "MaTransaction".length).toString(Charsets.ISO_8859_1) shouldEqual "MaTransaction"
byteArray.copyOfRange(10, 10 + "MaTransaction".length).toString(Charsets.ISO_8859_1) shouldBeEqualTo "MaTransaction"
}
}

View File

@ -18,6 +18,14 @@ package org.matrix.android.sdk.session.room.timeline
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.zhuinden.monarchy.Monarchy
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.kotlin.createObject
import org.amshove.kluent.shouldBeEqualTo
import org.amshove.kluent.shouldBeTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.send.SendState
@ -29,14 +37,6 @@ import org.matrix.android.sdk.internal.database.model.SessionRealmModule
import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection
import org.matrix.android.sdk.session.room.timeline.RoomDataHelper.createFakeListOfEvents
import org.matrix.android.sdk.session.room.timeline.RoomDataHelper.createFakeMessageEvent
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.kotlin.createObject
import org.amshove.kluent.shouldBeTrue
import org.amshove.kluent.shouldEqual
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
internal class ChunkEntityTest : InstrumentedTest {
@ -60,10 +60,10 @@ internal class ChunkEntityTest : InstrumentedTest {
val chunk: ChunkEntity = realm.createObject()
val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED, System.currentTimeMillis()).let {
realm.copyToRealmOrUpdate(it)
realm.copyToRealm(it)
}
chunk.addTimelineEvent(ROOM_ID, fakeEvent, PaginationDirection.FORWARDS, emptyMap())
chunk.timelineEvents.size shouldEqual 1
chunk.timelineEvents.size shouldBeEqualTo 1
}
}
@ -72,11 +72,11 @@ internal class ChunkEntityTest : InstrumentedTest {
monarchy.runTransactionSync { realm ->
val chunk: ChunkEntity = realm.createObject()
val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED, System.currentTimeMillis()).let {
realm.copyToRealmOrUpdate(it)
realm.copyToRealm(it)
}
chunk.addTimelineEvent(ROOM_ID, fakeEvent, PaginationDirection.FORWARDS, emptyMap())
chunk.addTimelineEvent(ROOM_ID, fakeEvent, PaginationDirection.FORWARDS, emptyMap())
chunk.timelineEvents.size shouldEqual 1
chunk.timelineEvents.size shouldBeEqualTo 1
}
}
@ -88,7 +88,7 @@ internal class ChunkEntityTest : InstrumentedTest {
chunk1.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk2.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk1.merge(ROOM_ID, chunk2, PaginationDirection.BACKWARDS)
chunk1.timelineEvents.size shouldEqual 60
chunk1.timelineEvents.size shouldBeEqualTo 60
}
}
@ -104,7 +104,7 @@ internal class ChunkEntityTest : InstrumentedTest {
chunk1.addAll(ROOM_ID, eventsForChunk1, PaginationDirection.FORWARDS)
chunk2.addAll(ROOM_ID, eventsForChunk2, PaginationDirection.BACKWARDS)
chunk1.merge(ROOM_ID, chunk2, PaginationDirection.BACKWARDS)
chunk1.timelineEvents.size shouldEqual 40
chunk1.timelineEvents.size shouldBeEqualTo 40
chunk1.isLastForward.shouldBeTrue()
}
}
@ -119,7 +119,7 @@ internal class ChunkEntityTest : InstrumentedTest {
chunk1.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk2.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk1.merge(ROOM_ID, chunk2, PaginationDirection.FORWARDS)
chunk1.prevToken shouldEqual prevToken
chunk1.prevToken shouldBeEqualTo prevToken
}
}
@ -133,7 +133,7 @@ internal class ChunkEntityTest : InstrumentedTest {
chunk1.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk2.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk1.merge(ROOM_ID, chunk2, PaginationDirection.BACKWARDS)
chunk1.nextToken shouldEqual nextToken
chunk1.nextToken shouldBeEqualTo nextToken
}
}
@ -142,7 +142,7 @@ internal class ChunkEntityTest : InstrumentedTest {
direction: PaginationDirection) {
events.forEach { event ->
val fakeEvent = event.toEntity(roomId, SendState.SYNCED, System.currentTimeMillis()).let {
realm.copyToRealmOrUpdate(it)
realm.copyToRealm(it)
}
addTimelineEvent(roomId, fakeEvent, direction, emptyMap())
}

View File

@ -21,7 +21,7 @@ import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType
import kotlin.random.Random
@ -41,7 +41,7 @@ object RoomDataHelper {
}
}
fun createFakeEvent(type: String,
private fun createFakeEvent(type: String,
content: Content? = null,
prevContent: Content? = null,
sender: String = FAKE_TEST_SENDER,
@ -62,8 +62,8 @@ object RoomDataHelper {
return createFakeEvent(EventType.MESSAGE, message)
}
fun createFakeRoomMemberEvent(): Event {
val roomMember = RoomMemberSummary(Membership.JOIN, "Fake name #${Random.nextLong()}").toContent()
private fun createFakeRoomMemberEvent(): Event {
val roomMember = RoomMemberContent(Membership.JOIN, "Fake name #${Random.nextLong()}").toContent()
return createFakeEvent(EventType.STATE_ROOM_MEMBER, roomMember)
}
}

View File

@ -78,7 +78,7 @@ internal class TimelineTest : InstrumentedTest {
// }
// }
// latch.await()
// timelineEvents.size shouldEqual initialLoad + paginationCount
// timelineEvents.size shouldBeEqualTo initialLoad + paginationCount
// timeline.dispose()
// }
}

View File

@ -2,8 +2,10 @@
xmlns:tools="http://schemas.android.com/tools"
package="org.matrix.android.sdk">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<!-- TODO Is WRITE_EXTERNAL_STORAGE necessary? -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application android:networkSecurityConfig="@xml/network_security_config">

View File

@ -194,18 +194,18 @@ internal class DefaultCryptoService @Inject constructor(
private val lastNewSessionForcedDates = MXUsersDevicesMap<Long>()
fun onStateEvent(roomId: String, event: Event) {
when {
event.getClearType() == EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
event.getClearType() == EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event)
event.getClearType() == EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event)
when (event.getClearType()) {
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event)
EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event)
}
}
fun onLiveEvent(roomId: String, event: Event) {
when {
event.getClearType() == EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
event.getClearType() == EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event)
event.getClearType() == EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event)
when (event.getClearType()) {
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event)
EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event)
}
}
@ -615,6 +615,7 @@ internal class DefaultCryptoService @Inject constructor(
val encryptionEvent = monarchy.fetchCopied { realm ->
EventEntity.whereType(realm, roomId = roomId, type = EventType.STATE_ROOM_ENCRYPTION)
.contains(EventEntityFields.CONTENT, "\"algorithm\":\"$MXCRYPTO_ALGORITHM_MEGOLM\"")
.isNotNull(EventEntityFields.STATE_KEY)
.findFirst()
}
return encryptionEvent != null
@ -915,6 +916,11 @@ internal class DefaultCryptoService @Inject constructor(
* @param event the encryption event.
*/
private fun onRoomEncryptionEvent(roomId: String, event: Event) {
if (!event.isStateEvent()) {
// Ignore
Timber.w("Invalid encryption event")
return
}
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
val params = LoadRoomMembersTask.Params(roomId)
try {

View File

@ -23,7 +23,6 @@ import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.Sort
import io.realm.kotlin.where
import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.LocalEcho
@ -86,7 +85,9 @@ import org.matrix.android.sdk.internal.crypto.store.db.query.getById
import org.matrix.android.sdk.internal.crypto.store.db.query.getOrCreate
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
import org.matrix.android.sdk.internal.di.CryptoDatabase
import org.matrix.android.sdk.internal.di.DeviceId
import org.matrix.android.sdk.internal.di.MoshiProvider
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.olm.OlmAccount
import org.matrix.olm.OlmException
@ -98,7 +99,9 @@ import kotlin.collections.set
internal class RealmCryptoStore @Inject constructor(
@CryptoDatabase private val realmConfiguration: RealmConfiguration,
private val crossSigningKeysMapper: CrossSigningKeysMapper,
private val credentials: Credentials) : IMXCryptoStore {
@UserId private val userId: String,
@DeviceId private val deviceId: String?
) : IMXCryptoStore {
/* ==========================================================================================
* Memory cache, to correctly release JNI objects
@ -141,8 +144,8 @@ internal class RealmCryptoStore @Inject constructor(
// Check credentials
// The device id may not have been provided in credentials.
// Check it only if provided, else trust the stored one.
if (currentMetadata.userId != credentials.userId
|| (credentials.deviceId != null && credentials.deviceId != currentMetadata.deviceId)) {
if (currentMetadata.userId != userId
|| (deviceId != null && deviceId != currentMetadata.deviceId)) {
Timber.w("## open() : Credentials do not match, close this store and delete data")
deleteAll = true
currentMetadata = null
@ -155,8 +158,8 @@ internal class RealmCryptoStore @Inject constructor(
}
// Metadata not found, or database cleaned, create it
realm.createObject(CryptoMetadataEntity::class.java, credentials.userId).apply {
deviceId = credentials.deviceId
realm.createObject(CryptoMetadataEntity::class.java, userId).apply {
deviceId = this@RealmCryptoStore.deviceId
}
}
}
@ -312,7 +315,7 @@ internal class RealmCryptoStore @Inject constructor(
Timber.d("## CrossSigning MSK change for $userId")
val keyEntity = crossSigningKeysMapper.map(masterKey)
signingInfo.setMasterKey(keyEntity)
if (userId == credentials.userId) {
if (userId == this.userId) {
shouldResetMyDevicesLocalTrust = true
// my msk has changed! clear my private key
// Could we have some race here? e.g I am the one that did change the keys
@ -331,7 +334,7 @@ internal class RealmCryptoStore @Inject constructor(
Timber.d("## CrossSigning SSK change for $userId")
val keyEntity = crossSigningKeysMapper.map(selfSigningKey)
signingInfo.setSelfSignedKey(keyEntity)
if (userId == credentials.userId) {
if (userId == this.userId) {
shouldResetMyDevicesLocalTrust = true
// my ssk has changed! clear my private key
realm.where<CryptoMetadataEntity>().findFirst()?.apply {
@ -349,7 +352,7 @@ internal class RealmCryptoStore @Inject constructor(
Timber.d("## CrossSigning USK change for $userId")
val keyEntity = crossSigningKeysMapper.map(userSigningKey)
signingInfo.setUserSignedKey(keyEntity)
if (userId == credentials.userId) {
if (userId == this.userId) {
shouldResetMyDevicesLocalTrust = true
// my usk has changed! clear my private key
realm.where<CryptoMetadataEntity>().findFirst()?.apply {
@ -362,11 +365,11 @@ internal class RealmCryptoStore @Inject constructor(
// When my cross signing keys are reset, we consider clearing all existing device trust
if (shouldResetMyDevicesLocalTrust) {
realm.where<UserEntity>()
.equalTo(UserEntityFields.USER_ID, credentials.userId)
.equalTo(UserEntityFields.USER_ID, this.userId)
.findFirst()
?.devices?.forEach {
it?.trustLevelEntity?.crossSignedVerified = false
it?.trustLevelEntity?.locallyVerified = it.deviceId == credentials.deviceId
it?.trustLevelEntity?.locallyVerified = it.deviceId == deviceId
}
}
userEntity.crossSigningInfoEntity = signingInfo
@ -1355,7 +1358,7 @@ internal class RealmCryptoStore @Inject constructor(
.findAll()
xInfoEntities?.forEach { info ->
// Need to ignore mine
if (info.userId != credentials.userId) {
if (info.userId != userId) {
info.crossSigningKeys.forEach {
it.trustLevelEntity = null
}
@ -1370,7 +1373,7 @@ internal class RealmCryptoStore @Inject constructor(
.findAll()
xInfoEntities?.forEach { xInfoEntity ->
// Need to ignore mine
if (xInfoEntity.userId == credentials.userId) return@forEach
if (xInfoEntity.userId == userId) return@forEach
val mapped = mapCrossSigningInfoEntity(xInfoEntity)
val currentTrust = mapped.isTrusted()
val newTrust = check(mapped.userId)

View File

@ -94,6 +94,7 @@ internal class RoomSummaryUpdater @Inject constructor(
// Don't use current state for this one as we are only interested in having MXCRYPTO_ALGORITHM_MEGOLM event in the room
val encryptionEvent = EventEntity.whereType(realm, roomId = roomId, type = EventType.STATE_ROOM_ENCRYPTION)
.contains(EventEntityFields.CONTENT, "\"algorithm\":\"$MXCRYPTO_ALGORITHM_MEGOLM\"")
.isNotNull(EventEntityFields.STATE_KEY)
.findFirst()
val latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)

View File

@ -17,13 +17,13 @@
package org.matrix.android.sdk.internal.crypto.verification.qrcode
import org.matrix.android.sdk.MatrixTest
import org.amshove.kluent.shouldEqualTo
import org.amshove.kluent.shouldBeEqualTo
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
@FixMethodOrder(MethodSorters.JVM)
class BinaryStringTest: MatrixTest {
class BinaryStringTest : MatrixTest {
/**
* I want to put bytes to a String, and vice versa
@ -37,17 +37,17 @@ class BinaryStringTest: MatrixTest {
val str = byteArray.toString(Charsets.ISO_8859_1)
str.length shouldEqualTo 256
str.length shouldBeEqualTo 256
// Ok convert back to bytearray
val result = str.toByteArray(Charsets.ISO_8859_1)
result.size shouldEqualTo 256
result.size shouldBeEqualTo 256
for (i in 0..255) {
result[i] shouldEqualTo i.toByte()
result[i] shouldEqualTo byteArray[i]
result[i] shouldBeEqualTo i.toByte()
result[i] shouldBeEqualTo byteArray[i]
}
}
}

View File

@ -79,9 +79,5 @@ layout_constraintLeft_
### Use im.vector.app.core.preference.VectorPreference to support multiline of the title
<Preference\n
### Will crash on API < 21. Use ?colorAccent instead
\?android:colorAccent
\?android:attr/colorAccent
### Use androidx.recyclerview.widget.RecyclerView because EpoxyRecyclerViews add behavior we do not want to
<com\.airbnb\.epoxy\.EpoxyRecyclerView

View File

@ -44,6 +44,9 @@ class EncryptionItemFactory @Inject constructor(
fun create(event: TimelineEvent,
highlight: Boolean,
callback: TimelineEventController.Callback?): StatusTileTimelineItem? {
if (!event.root.isStateEvent()) {
return null
}
val algorithm = event.root.getClearContent().toModel<EncryptionEventContent>()?.algorithm
val informationData = informationDataFactory.create(event, null)
val attributes = messageItemAttributesFactory.create(null, informationData, callback)

View File

@ -148,7 +148,7 @@ class MergedHeaderItemFactory @Inject constructor(private val activeSessionHolde
var hasEncryption = false
var encryptionAlgorithm: String? = null
while (prevEvent != null && prevEvent.isRoomConfiguration(null)) {
if (prevEvent.root.getClearType() == EventType.STATE_ROOM_ENCRYPTION) {
if (prevEvent.root.isStateEvent() && prevEvent.root.getClearType() == EventType.STATE_ROOM_ENCRYPTION) {
hasEncryption = true
encryptionAlgorithm = prevEvent.root.getClearContent()?.toModel<EncryptionEventContent>()?.algorithm
}

View File

@ -428,6 +428,9 @@ class NoticeEventFormatter @Inject constructor(private val activeSessionDataSour
}
private fun formatRoomEncryptionEvent(event: Event, senderName: String?): CharSequence? {
if (!event.isStateEvent()) {
return null
}
val content = event.content.toModel<EncryptionEventContent>() ?: return null
return when (content.algorithm) {
MXCRYPTO_ALGORITHM_MEGOLM ->

View File

@ -55,7 +55,7 @@ fun TimelineEvent.canBeMerged(): Boolean {
}
fun TimelineEvent.isRoomConfiguration(roomCreatorUserId: String?): Boolean {
return when (root.getClearType()) {
return root.isStateEvent() && when (root.getClearType()) {
EventType.STATE_ROOM_GUEST_ACCESS,
EventType.STATE_ROOM_HISTORY_VISIBILITY,
EventType.STATE_ROOM_JOIN_RULES,

View File

@ -58,9 +58,6 @@ class RoomMemberListFragment @Inject constructor(
setupSearchView()
setupInviteUsersButton()
recyclerView.configureWith(roomMemberListController, hasFixedSize = true)
viewModel.selectSubscribe(this, RoomMemberListViewState::actionsPermissions) {
invalidateOptionsMenu()
}
}
private fun setupInviteUsersButton() {
@ -88,7 +85,6 @@ class RoomMemberListFragment @Inject constructor(
}
private fun setupSearchView() {
searchViewAppBarLayout.isVisible = true
searchView.queryHint = getString(R.string.search_members_hint)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
@ -111,6 +107,8 @@ class RoomMemberListFragment @Inject constructor(
roomMemberListController.setData(viewState)
renderRoomSummary(viewState)
inviteUsersButton.isVisible = viewState.actionsPermissions.canInvite
// Display filter only if there are more than 2 members in this room
searchViewAppBarLayout.isVisible = viewState.roomSummary()?.otherMemberIds.orEmpty().size > 1
}
override fun onRoomMemberClicked(roomMember: RoomMemberSummary) {

View File

@ -10,7 +10,11 @@
android:id="@+id/expandableContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:ellipsize="end"
android:fontFamily="sans-serif"
android:textSize="14sp"
android:textStyle="normal"
app:layout_constraintBottom_toTopOf="@+id/expandableArrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -23,12 +27,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:autoLink="web"
android:fontFamily="sans-serif"
android:gravity="center"
android:src="@drawable/ic_expand_more"
android:textSize="14sp"
android:textStyle="normal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/expandableContent"