diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index db1a9beb84433853e479227c98b27bbb8e5e0fa1..e0012e9c65b406634d5f02f89100584b1fe860fa 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -13,7 +13,10 @@ jobs: uses: actions/checkout@v2 - name: Build docs - run: ./gradlew dokkaHtml + run: | + sed -i.bak "s/.*nightly documentation.*//" ./matrix-sdk-android/docs/modules.md + rm ./matrix-sdk-android/docs/modules.md.bak + ./gradlew dokkaHtml - name: Deploy docs uses: peaceiris/actions-gh-pages@v3 diff --git a/CHANGES.md b/CHANGES.md index 292e34de5a789dd3ddeba696170a0b719610af50..5e0467aa9398530c5f658beb434cb0833b65da67 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,20 @@ Please also refer to the Changelog of Element Android: https://github.com/vector-im/element-android/blob/main/CHANGES.md +Changes in Matrix-SDK 1.4.16 (2022-05-23) +=================================================== + +Imported from Element 1.4.16. (https://github.com/vector-im/element-android/releases/tag/v1.4.16) + +SDK API changes âš ï¸ +------------------ +- New API to enable/disable key forwarding CryptoService#enableKeyGossiping() +- New API to limit room key request only to own devices MXCryptoConfig#limitRoomKeyRequestsToMyDevices +- Event Trail API has changed, now using AuditTrail events +- New API to manually accept an incoming key request CryptoService#manuallyAcceptRoomKeyRequest() ([#5559](https://github.com/vector-im/element-android/issues/5559)) +- Small change in the Matrix class: deprecated methods have been removed and the constructor is now public. Also the fun `workerFactory()` has been renamed to `getWorkerFactory()` ([#5887](https://github.com/vector-im/element-android/issues/5887)) +- Including SSL/TLS error handing when doing WellKnown lookups without a custom HomeServerConnectionConfig ([#5965](https://github.com/vector-im/element-android/issues/5965)) + + Changes in Matrix-SDK 1.4.14 (2022-05-10) =================================================== diff --git a/build.gradle b/build.gradle index 56e7e1de82cc529b9541ec215cf6955554b987b8..757d08ddcc2264b4e4a3fd53ea90aa793c4e621d 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ buildscript { classpath libs.gradle.gradlePlugin classpath libs.gradle.kotlinPlugin classpath 'com.vanniktech:gradle-maven-publish-plugin:0.18.0' - classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.20" + classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.21" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/dependencies.gradle b/dependencies.gradle index 7666a3bf9f8b4cc9929a65f2b0822eaae753cb33..10f9539e5ac16392be44fd7774c8c397411f9216 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,26 +7,26 @@ ext.versions = [ 'targetCompat' : JavaVersion.VERSION_11, ] -def gradle = "7.0.4" +def gradle = "7.2.0" // Ref: https://kotlinlang.org/releases.html -def kotlin = "1.6.0" -def kotlinCoroutines = "1.6.0" -def dagger = "2.40.5" +def kotlin = "1.6.21" +def kotlinCoroutines = "1.6.1" +def dagger = "2.42" def retrofit = "2.9.0" def arrow = "0.8.2" def markwon = "4.6.2" def moshi = "1.13.0" -def lifecycle = "2.4.0" +def lifecycle = "2.4.1" def flowBinding = "1.2.0" def epoxy = "4.6.2" -def mavericks = "2.5.0" -def glide = "4.12.0" +def mavericks = "2.6.1" +def glide = "4.13.2" def bigImageViewer = "1.8.1" -def jjwt = "0.11.2" -def vanniktechEmoji = "0.8.0" +def jjwt = "0.11.5" +def vanniktechEmoji = "0.9.0" // Testing -def mockk = "1.12.1" +def mockk = "1.12.4" def espresso = "3.4.0" def androidxTest = "1.4.0" def androidxOrchestrator = "1.4.1" @@ -45,15 +45,15 @@ ext.libs = [ 'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines" ], androidx : [ - 'appCompat' : "androidx.appcompat:appcompat:1.4.0", + 'appCompat' : "androidx.appcompat:appcompat:1.4.1", 'core' : "androidx.core:core-ktx:1.7.0", 'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1", 'exifinterface' : "androidx.exifinterface:exifinterface:1.3.3", - 'fragmentKtx' : "androidx.fragment:fragment-ktx:1.4.0", - 'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.2", + 'fragmentKtx' : "androidx.fragment:fragment-ktx:1.4.1", + 'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.3", 'work' : "androidx.work:work-runtime-ktx:2.7.1", 'autoFill' : "androidx.autofill:autofill:1.1.0", - 'preferenceKtx' : "androidx.preference:preference-ktx:1.1.1", + 'preferenceKtx' : "androidx.preference:preference-ktx:1.2.0", 'junit' : "androidx.test.ext:junit:1.1.3", 'lifecycleCommon' : "androidx.lifecycle:lifecycle-common:$lifecycle", 'lifecycleLivedata' : "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle", @@ -72,7 +72,7 @@ ext.libs = [ 'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso" ], google : [ - 'material' : "com.google.android.material:material:1.5.0" + 'material' : "com.google.android.material:material:1.6.0" ], dagger : [ 'dagger' : "com.google.dagger:dagger:$dagger", diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 8422e05930f845e53890a281bcda60c766766add..76869fccf1c70d38dcafb076c1b239498b3a8fea 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -123,6 +123,7 @@ ext.groups = [ 'io.github.detekt.sarif4k', 'io.github.microutils', 'io.github.reactivecircus.flowbinding', + 'io.gitlab.arturbosch.detekt', 'io.grpc', 'io.jsonwebtoken', 'io.kindedj', @@ -195,6 +196,7 @@ ext.groups = [ 'org.testng', 'org.threeten', 'org.webjars', + 'org.yaml', 'ru.noties', 'xerces', 'xml-apis', diff --git a/gradle.properties b/gradle.properties index 6402e3ad3a9b07b41f5e6aa166f272d93357f297..97384e645c0a6dbdf353943d4d298f288515ce73 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,7 +26,7 @@ vector.httpLogLevel=NONE # Ref: https://github.com/vanniktech/gradle-maven-publish-plugin GROUP=org.matrix.android POM_ARTIFACT_ID=matrix-android-sdk2 -VERSION_NAME=1.4.14 +VERSION_NAME=1.4.16 POM_PACKAGING=aar diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 8362d35960f8a43d103a6599481dfe6d90c2fba3..d04a675cbaa67e173db8b91b14a0622e057d27c3 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -9,7 +9,10 @@ apply plugin: "com.vanniktech.maven.publish" buildscript { repositories { - mavenCentral() + // Do not use `mavenCentral()`, it prevents Dependabot from working properly + maven { + url 'https://repo1.maven.org/maven2' + } } dependencies { classpath "io.realm:realm-gradle-plugin:10.9.0" @@ -20,7 +23,7 @@ dokkaHtml { dokkaSourceSets { configureEach { // Emit warnings about not documented members. - reportUndocumented.set(true) + // reportUndocumented.set(true) // Suppress legacy Riot's packages. perPackageOption { matchingRegex.set("org.matrix.android.sdk.internal.legacy.riot") @@ -101,6 +104,9 @@ android { freeCompilerArgs += [ // Disabled for now, there are too many errors. Could be handled in another dedicated PR // '-Xexplicit-api=strict', // or warning + "-opt-in=kotlin.RequiresOptIn", + // Opt in for kotlinx.coroutines.FlowPreview + "-opt-in=kotlinx.coroutines.FlowPreview", ] } @@ -178,7 +184,7 @@ dependencies { implementation libs.arrow.instances // olm lib is now hosted in MavenCentral - implementation 'org.matrix.android:olm-sdk:3.2.10' + implementation 'org.matrix.android:olm-sdk:3.2.11' // DI implementation libs.dagger.dagger @@ -195,7 +201,7 @@ dependencies { implementation libs.apache.commonsImaging // Phone number https://github.com/google/libphonenumber - implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.47' + implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.48' testImplementation libs.tests.junit testImplementation 'org.robolectric:robolectric:4.7.3' diff --git a/matrix-sdk-android/docs/modules.md b/matrix-sdk-android/docs/modules.md index edf5af64d024d6a214e3657bc73701ec4182b214..fb082c1bc216f67f578b63d51c747e288293f329 100644 --- a/matrix-sdk-android/docs/modules.md +++ b/matrix-sdk-android/docs/modules.md @@ -1,5 +1,8 @@ # Module matrix-sdk-android +<!-- Note: the line below will appear only when the documentation is generated from Element-Android project, and not when it's generated from the SDK project --> +**Note**: You are viewing the nightly documentation of the Android Matrix SDK library. The documentation of the released library can be found here: [https://matrix-org.github.io/matrix-android-sdk2/](https://matrix-org.github.io/matrix-android-sdk2/) + ## Welcome to the matrix-sdk-android documentation! This pages list the complete API that this SDK is exposing to a client application. @@ -8,11 +11,11 @@ This pages list the complete API that this SDK is exposing to a client applicati A few entry points: -- **Matrix**: The app will have to create and manage a Matrix object. -- From this **Matrix** object, you will be able to get various services, including the **AuthenticationService**. -- With this **AuthenticationService** you will be able to get an existing **Session**, or create one using a **LoginWizard** or a **RegistrationWizard**, which will finally give you a **Session**. -- From the **Session**, you will be able to retrieve many Services, including the **RoomService**. -- From the **RoomService**, you will be able to list the rooms, create a **Room**, and get a specific **Room**. -- And from a **Room**, you will be able to do many things, including get a **Timeline**, send messages, etc. +- **[Matrix](org.matrix.android.sdk.api.Matrix)**: The app will have to create and manage a **[Matrix](org.matrix.android.sdk.api.Matrix)** object. +- From this **[Matrix](org.matrix.android.sdk.api.Matrix)** object, you will be able to get various services, including the **[AuthenticationService](org.matrix.android.sdk.api.auth.AuthenticationService)**. +- With this **[AuthenticationService](org.matrix.android.sdk.api.auth.AuthenticationService)** you will be able to get an existing **[Session](org.matrix.android.sdk.api.session.Session)**, or create one using a **[LoginWizard](org.matrix.android.sdk.api.auth.login.LoginWizard)** or a **[RegistrationWizard](org.matrix.android.sdk.api.auth.registration.RegistrationWizard)**, which will finally give you a **[Session](org.matrix.android.sdk.api.session.Session)**. +- From the **[Session](org.matrix.android.sdk.api.session.Session)**, you will be able to retrieve many Services, including the **[RoomService](org.matrix.android.sdk.api.session.room.RoomService)**. +- From the **[RoomService](org.matrix.android.sdk.api.session.room.RoomService)**, you will be able to list the rooms, create a **[Room](org.matrix.android.sdk.api.session.room.Room)**, and get a specific **[Room](org.matrix.android.sdk.api.session.room.Room)**. +- And from a **[Room](org.matrix.android.sdk.api.session.room.Room)**, you will be able to do many things, including get a **[Timeline](org.matrix.android.sdk.api.session.room.timeline.Timeline)**, send messages, etc. Please read the whole documentation to learn more! diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/PermalinkParserTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/PermalinkParserTest.kt index b11a538949a151f702bbce3f9da12ae4ece48357..8717b3f7a856e37318373aeb3cd1844dc2a11d99 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/PermalinkParserTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/PermalinkParserTest.kt @@ -37,7 +37,10 @@ class PermalinkParserTest { Assert.assertTrue("Should be parsed as email invite but was ${parsedLink::class.java}", parsedLink is PermalinkData.RoomEmailInviteLink) parsedLink as PermalinkData.RoomEmailInviteLink Assert.assertEquals("!MRBNLPtFnMAazZVPMO:matrix.org", parsedLink.roomId) - Assert.assertEquals("XmOwRZnSFabCRhTywFbJWKXWVNPysOpXIbroMGaUymqkJSvHeVKRsjHajwjCYdBsvGSvHauxbKfJmOxtXldtyLnyBMLKpBQCMzyYggrdapbVIceWZBtmslOQrXLABRoe", parsedLink.token) + Assert.assertEquals( + "XmOwRZnSFabCRhTywFbJWKXWVNPysOpXIbroMGaUymqkJSvHeVKRsjHajwjCYdBsvGSvHauxbKfJmOxtXldtyLnyBMLKpBQCMzyYggrdapbVIceWZBtmslOQrXLABRoe", + parsedLink.token + ) Assert.assertEquals("vector.im", parsedLink.identityServer) Assert.assertEquals("Team2", parsedLink.roomName) Assert.assertEquals("hiphop5", parsedLink.inviterName) @@ -45,7 +48,8 @@ class PermalinkParserTest { @Test fun testParseLinkWIthEvent() { - val rawInvite = "https://matrix.to/#/!OGEhHVWSdvArJzumhm:matrix.org/\$xuvJUVDJnwEeVjPx029rAOZ50difpmU_5gZk_T0jGfc?via=matrix.org&via=libera.chat&via=matrix.example.io" + val rawInvite = + "https://matrix.to/#/!OGEhHVWSdvArJzumhm:matrix.org/\$xuvJUVDJnwEeVjPx029rAOZ50difpmU_5gZk_T0jGfc?via=matrix.org&via=libera.chat&via=matrix.example.io" val parsedLink = PermalinkParser.parse(rawInvite) Assert.assertTrue("Should be parsed as room link", parsedLink is PermalinkData.RoomLink) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/SingleThreadCoroutineDispatcher.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/SingleThreadCoroutineDispatcher.kt index 3e3af10799a4d07daa6395ad1c96af33fcf9032b..a44cd6c80f9485d5b3773b31803eae9bf6c6b913 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/SingleThreadCoroutineDispatcher.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/SingleThreadCoroutineDispatcher.kt @@ -21,5 +21,7 @@ import kotlinx.coroutines.asCoroutineDispatcher import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import java.util.concurrent.Executors -internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main, - Executors.newSingleThreadExecutor().asCoroutineDispatcher()) +internal val testCoroutineDispatchers = MatrixCoroutineDispatchers( + Main, Main, Main, Main, + Executors.newSingleThreadExecutor().asCoroutineDispatcher() +) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt index 52dbfc7155b53f10b188dd845a02ee486efc2b26..d2dfe4d9454b2f02d44602a39b185398deb29054 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt @@ -67,9 +67,11 @@ class DeactivateAccountTest : InstrumentedTest { val throwable = commonTestHelper.logAccountWithError(session.myUserId, TestConstants.PASSWORD) // Test the error - assertTrue(throwable is Failure.ServerError && - throwable.error.code == MatrixError.M_USER_DEACTIVATED && - throwable.error.message == "This account has been deactivated") + assertTrue( + throwable is Failure.ServerError && + throwable.error.code == MatrixError.M_USER_DEACTIVATED && + throwable.error.message == "This account has been deactivated" + ) // Try to create an account with the deactivate account user id, it will fail (M_USER_IN_USE) val hs = commonTestHelper.createHomeServerConfig() @@ -95,8 +97,10 @@ class DeactivateAccountTest : InstrumentedTest { // Test the error accountCreationError.let { - assertTrue(it is Failure.ServerError && - it.error.code == MatrixError.M_USER_IN_USE) + assertTrue( + it is Failure.ServerError && + it.error.code == MatrixError.M_USER_IN_USE + ) } // No need to close the session, it has been deactivated diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index 4b9e605cd0a54e068b1c6cdb5bad94e6f228bb18..e33e4faea2920db2b6e75956254bcb42dac6eff5 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -63,8 +63,9 @@ class CommonTestHelper(context: Context) { fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor init { + var _matrix: TestMatrix? = null UiThreadStatement.runOnUiThread { - TestMatrix.initialize( + _matrix = TestMatrix( context, MatrixConfiguration( applicationFlavor = "TestFlavor", @@ -72,7 +73,7 @@ class CommonTestHelper(context: Context) { ) ) } - matrix = TestMatrix.getInstance() + matrix = _matrix!! } fun createAccount(userNamePrefix: String, testParams: SessionTestParams): Session { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt index 058b1f79338237569877e21ee8c255e0a0987e90..348841313b5f9f5fd6f73d9f551a0c1edfc80f79 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt @@ -19,6 +19,7 @@ package org.matrix.android.sdk.common import android.os.SystemClock import android.util.Log import androidx.lifecycle.Observer +import org.amshove.kluent.fail import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull @@ -31,8 +32,16 @@ import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupAuthData import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo +import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey +import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.OutgoingSasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod @@ -40,13 +49,19 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxStat 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.events.model.toModel import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams +import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams +import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner +import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService import org.matrix.android.sdk.api.util.Optional +import org.matrix.android.sdk.api.util.awaitCallback +import org.matrix.android.sdk.api.util.toBase64NoPadding import java.util.UUID import kotlin.coroutines.Continuation import kotlin.coroutines.resume @@ -188,17 +203,49 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!! // Alice sends a message - testHelper.sendTextMessage(roomFromAlicePOV, messagesFromAlice[0], 1) + testHelper.sendTextMessage(roomFromAlicePOV, messagesFromAlice[0], 1).first().eventId.let { sentEventId -> + // ensure bob got it + ensureEventReceived(aliceRoomId, sentEventId, bobSession, true) + } // Bob send 3 messages - testHelper.sendTextMessage(roomFromBobPOV, messagesFromBob[0], 1) - testHelper.sendTextMessage(roomFromBobPOV, messagesFromBob[1], 1) - testHelper.sendTextMessage(roomFromBobPOV, messagesFromBob[2], 1) + testHelper.sendTextMessage(roomFromBobPOV, messagesFromBob[0], 1).first().eventId.let { sentEventId -> + // ensure alice got it + ensureEventReceived(aliceRoomId, sentEventId, aliceSession, true) + } + + testHelper.sendTextMessage(roomFromBobPOV, messagesFromBob[1], 1).first().eventId.let { sentEventId -> + // ensure alice got it + ensureEventReceived(aliceRoomId, sentEventId, aliceSession, true) + } + testHelper.sendTextMessage(roomFromBobPOV, messagesFromBob[2], 1).first().eventId.let { sentEventId -> + // ensure alice got it + ensureEventReceived(aliceRoomId, sentEventId, aliceSession, true) + } + // Alice sends a message - testHelper.sendTextMessage(roomFromAlicePOV, messagesFromAlice[1], 1) + testHelper.sendTextMessage(roomFromAlicePOV, messagesFromAlice[1], 1).first().eventId.let { sentEventId -> + // ensure bob got it + ensureEventReceived(aliceRoomId, sentEventId, bobSession, true) + } return cryptoTestData } + private fun ensureEventReceived(roomId: String, eventId: String, session: Session, andCanDecrypt: Boolean) { + testHelper.waitWithLatch { latch -> + testHelper.retryPeriodicallyWithLatch(latch) { + val timeLineEvent = session.getRoom(roomId)?.timelineService()?.getTimelineEvent(eventId) + if (andCanDecrypt) { + timeLineEvent != null && + timeLineEvent.isEncrypted() && + timeLineEvent.root.getClearType() == EventType.MESSAGE + } else { + timeLineEvent != null + } + } + } + } + fun checkEncryptedEvent(event: Event, roomId: String, clearMessage: String, senderSession: Session) { assertEquals(EventType.ENCRYPTED, event.type) assertNotNull(event.content) @@ -291,7 +338,61 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { ) ) } - }, it) + }, it + ) + } + } + + /** + * Initialize cross-signing, set up megolm backup and save all in 4S + */ + fun bootstrapSecurity(session: Session) { + initializeCrossSigning(session) + val ssssService = session.sharedSecretStorageService() + testHelper.runBlockingTest { + val keyInfo = ssssService.generateKey( + UUID.randomUUID().toString(), + null, + "ssss_key", + EmptyKeySigner() + ) + ssssService.setDefaultKey(keyInfo.keyId) + + ssssService.storeSecret( + MASTER_KEY_SSSS_NAME, + session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.master!!, + listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + ) + + ssssService.storeSecret( + SELF_SIGNING_KEY_SSSS_NAME, + session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.selfSigned!!, + listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + ) + + ssssService.storeSecret( + USER_SIGNING_KEY_SSSS_NAME, + session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.user!!, + listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + ) + + // set up megolm backup + val creationInfo = awaitCallback<MegolmBackupCreationInfo> { + session.cryptoService().keysBackupService().prepareKeysBackupVersion(null, null, it) + } + val version = awaitCallback<KeysVersion> { + session.cryptoService().keysBackupService().createKeysBackupVersion(creationInfo, it) + } + // Save it for gossiping + session.cryptoService().keysBackupService().saveBackupRecoveryKey(creationInfo.recoveryKey, version = version.version) + + extractCurveKeyFromRecoveryKey(creationInfo.recoveryKey)?.toBase64NoPadding()?.let { secret -> + ssssService.storeSecret( + KEYBACKUP_SECRET_SSSS_NAME, + secret, + listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec)) + ) + } } } @@ -299,28 +400,37 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { assertTrue(alice.cryptoService().crossSigningService().canCrossSign()) assertTrue(bob.cryptoService().crossSigningService().canCrossSign()) - val requestID = UUID.randomUUID().toString() val aliceVerificationService = alice.cryptoService().verificationService() val bobVerificationService = bob.cryptoService().verificationService() - aliceVerificationService.beginKeyVerificationInDMs( - VerificationMethod.SAS, - requestID, - roomId, - bob.myUserId, - bob.sessionParams.credentials.deviceId!!) + val localId = UUID.randomUUID().toString() + aliceVerificationService.requestKeyVerificationInDMs( + localId = localId, + methods = listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW), + otherUserId = bob.myUserId, + roomId = roomId + ).transactionId - // we should reach SHOW SAS on both - var alicePovTx: OutgoingSasVerificationTransaction? = null - var bobPovTx: IncomingSasVerificationTransaction? = null + testHelper.waitWithLatch { + testHelper.retryPeriodicallyWithLatch(it) { + bobVerificationService.getExistingVerificationRequests(alice.myUserId).firstOrNull { + it.requestInfo?.fromDevice == alice.sessionParams.deviceId + } != null + } + } + val incomingRequest = bobVerificationService.getExistingVerificationRequests(alice.myUserId).first { + it.requestInfo?.fromDevice == alice.sessionParams.deviceId + } + bobVerificationService.readyPendingVerification(listOf(VerificationMethod.SAS), alice.myUserId, incomingRequest.transactionId!!) - // wait for alice to get the ready + var requestID: String? = null + // wait for it to be readied testHelper.waitWithLatch { testHelper.retryPeriodicallyWithLatch(it) { - bobPovTx = bobVerificationService.getExistingTransaction(alice.myUserId, requestID) as? IncomingSasVerificationTransaction - Log.v("TEST", "== bobPovTx is ${alicePovTx?.uxState}") - if (bobPovTx?.state == VerificationTxState.OnStarted) { - bobPovTx?.performAccept() + val outgoingRequest = aliceVerificationService.getExistingVerificationRequests(bob.myUserId) + .firstOrNull { it.localId == localId } + if (outgoingRequest?.isReady == true) { + requestID = outgoingRequest.transactionId!! true } else { false @@ -328,9 +438,21 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { } } + aliceVerificationService.beginKeyVerificationInDMs( + VerificationMethod.SAS, + requestID!!, + roomId, + bob.myUserId, + bob.sessionParams.credentials.deviceId!! + ) + + // we should reach SHOW SAS on both + var alicePovTx: OutgoingSasVerificationTransaction? = null + var bobPovTx: IncomingSasVerificationTransaction? = null + testHelper.waitWithLatch { testHelper.retryPeriodicallyWithLatch(it) { - alicePovTx = aliceVerificationService.getExistingTransaction(bob.myUserId, requestID) as? OutgoingSasVerificationTransaction + alicePovTx = aliceVerificationService.getExistingTransaction(bob.myUserId, requestID!!) as? OutgoingSasVerificationTransaction Log.v("TEST", "== alicePovTx is ${alicePovTx?.uxState}") alicePovTx?.state == VerificationTxState.ShortCodeReady } @@ -338,7 +460,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { // wait for alice to get the ready testHelper.waitWithLatch { testHelper.retryPeriodicallyWithLatch(it) { - bobPovTx = bobVerificationService.getExistingTransaction(alice.myUserId, requestID) as? IncomingSasVerificationTransaction + bobPovTx = bobVerificationService.getExistingTransaction(alice.myUserId, requestID!!) as? IncomingSasVerificationTransaction Log.v("TEST", "== bobPovTx is ${alicePovTx?.uxState}") if (bobPovTx?.state == VerificationTxState.OnStarted) { bobPovTx?.performAccept() @@ -390,4 +512,50 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { return CryptoTestData(roomId, sessions) } + + fun ensureCanDecrypt(sentEventIds: List<String>, session: Session, e2eRoomID: String, messagesText: List<String>) { + sentEventIds.forEachIndexed { index, sentEventId -> + testHelper.waitWithLatch { latch -> + testHelper.retryPeriodicallyWithLatch(latch) { + val event = session.getRoom(e2eRoomID)!!.timelineService().getTimelineEvent(sentEventId)!!.root + testHelper.runBlockingTest { + try { + session.cryptoService().decryptEvent(event, "").let { result -> + event.mxDecryptionResult = OlmDecryptionResult( + payload = result.clearEvent, + senderKey = result.senderCurve25519Key, + keysClaimed = result.claimedEd25519Key?.let { mapOf("ed25519" to it) }, + forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain + ) + } + } catch (error: MXCryptoError) { + // nop + } + } + Log.v("TEST", "ensureCanDecrypt ${event.getClearType()} is ${event.getClearContent()}") + event.getClearType() == EventType.MESSAGE && + messagesText[index] == event.getClearContent()?.toModel<MessageContent>()?.body + } + } + } + } + + fun ensureCannotDecrypt(sentEventIds: List<String>, session: Session, e2eRoomID: String, expectedError: MXCryptoError.ErrorType? = null) { + sentEventIds.forEach { sentEventId -> + val event = session.getRoom(e2eRoomID)!!.timelineService().getTimelineEvent(sentEventId)!!.root + testHelper.runBlockingTest { + try { + session.cryptoService().decryptEvent(event, "") + fail("Should not be able to decrypt event") + } catch (error: MXCryptoError) { + val errorType = (error as? MXCryptoError.Base)?.errorType + if (expectedError == null) { + assertNotNull(errorType) + } else { + assertEquals("Unexpected reason", expectedError, errorType) + } + } + } + } + } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrix.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrix.kt index fa44167a8f37f1403a321a03ebdb669a6a11d7d0..e663cc186571b539fbde872f1c10331c1aec5f37 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrix.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrix.kt @@ -38,13 +38,12 @@ import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory import org.matrix.olm.OlmManager import java.util.concurrent.Executors -import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject /** * This mimics the Matrix class but using TestMatrixComponent internally instead of regular MatrixComponent. */ -internal class TestMatrix constructor(context: Context, matrixConfiguration: MatrixConfiguration) { +internal class TestMatrix(context: Context, matrixConfiguration: MatrixConfiguration) { @Inject internal lateinit var legacySessionImporter: LegacySessionImporter @Inject internal lateinit var authenticationService: AuthenticationService @@ -60,13 +59,14 @@ internal class TestMatrix constructor(context: Context, matrixConfiguration: Mat private val uiHandler = Handler(Looper.getMainLooper()) init { - Monarchy.init(context) - DaggerTestMatrixComponent.factory().create(context, matrixConfiguration).inject(this) + val appContext = context.applicationContext + Monarchy.init(appContext) + DaggerTestMatrixComponent.factory().create(appContext, matrixConfiguration).inject(this) val configuration = Configuration.Builder() .setExecutor(Executors.newCachedThreadPool()) .setWorkerFactory(matrixWorkerFactory) .build() - WorkManager.initialize(context, configuration) + WorkManager.initialize(appContext, configuration) uiHandler.post { ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver) } @@ -95,23 +95,6 @@ internal class TestMatrix constructor(context: Context, matrixConfiguration: Mat } companion object { - - private lateinit var instance: TestMatrix - private val isInit = AtomicBoolean(false) - - fun initialize(context: Context, matrixConfiguration: MatrixConfiguration) { - if (isInit.compareAndSet(false, true)) { - instance = TestMatrix(context.applicationContext, matrixConfiguration) - } - } - - fun getInstance(): TestMatrix { - if (isInit.compareAndSet(false, false)) { - throw IllegalStateException("Matrix is not initialized properly. You should call TestMatrix.initialize first") - } - return instance - } - fun getSdkVersion(): String { return BuildConfig.SDK_VERSION + " (" + BuildConfig.GIT_SDK_REVISION + ")" } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt index dc58339498c720c4d211b5e112d1517eb610d5be..525e168cf1f2a19170d74ba0547a4551e70ff23e 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt @@ -29,15 +29,17 @@ import org.matrix.android.sdk.internal.raw.RawModule import org.matrix.android.sdk.internal.settings.SettingsModule import org.matrix.android.sdk.internal.util.system.SystemModule -@Component(modules = [ - TestModule::class, - MatrixModule::class, - NetworkModule::class, - AuthModule::class, - RawModule::class, - SettingsModule::class, - SystemModule::class -]) +@Component( + modules = [ + TestModule::class, + MatrixModule::class, + NetworkModule::class, + AuthModule::class, + RawModule::class, + SettingsModule::class, + SystemModule::class + ] +) @MatrixScope internal interface TestMatrixComponent : MatrixComponent { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt index 3f75aa09798a476184cf35bd170a73b318e17b47..e823aa39a1115124acc2daf9d9918e4a834a3bd6 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt @@ -76,9 +76,11 @@ class CryptoStoreTest : InstrumentedTest { } val olmSession1 = OlmSession().apply { - initOutboundSession(olmAccount1, + initOutboundSession( + olmAccount1, olmAccount1.identityKeys()[OlmAccount.JSON_KEY_IDENTITY_KEY], - olmAccount1.oneTimeKeys()[OlmAccount.JSON_KEY_ONE_TIME_KEY]?.values?.first()) + olmAccount1.oneTimeKeys()[OlmAccount.JSON_KEY_ONE_TIME_KEY]?.values?.first() + ) } val sessionId1 = olmSession1.sessionIdentifier() @@ -93,9 +95,11 @@ class CryptoStoreTest : InstrumentedTest { } val olmSession2 = OlmSession().apply { - initOutboundSession(olmAccount2, + initOutboundSession( + olmAccount2, olmAccount2.identityKeys()[OlmAccount.JSON_KEY_IDENTITY_KEY], - olmAccount2.oneTimeKeys()[OlmAccount.JSON_KEY_ONE_TIME_KEY]?.values?.first()) + olmAccount2.oneTimeKeys()[OlmAccount.JSON_KEY_ONE_TIME_KEY]?.values?.first() + ) } val sessionId2 = olmSession2.sessionIdentifier() diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt index 88d99f12e062237540b28fed1cff3ae2e952a176..ebe4c5ff6fb52e2408650ed722173309a4236712 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt @@ -30,13 +30,21 @@ import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.RequestResult import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult -import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult +import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction +import org.matrix.android.sdk.api.session.crypto.verification.OutgoingSasVerificationTransaction +import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest +import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod +import org.matrix.android.sdk.api.session.crypto.verification.VerificationService +import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent +import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.getRoomSummary @@ -52,15 +60,13 @@ import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.common.TestMatrixCallback +import java.util.concurrent.CountDownLatch @RunWith(JUnit4::class) @FixMethodOrder(MethodSorters.JVM) @LargeTest class E2eeSanityTests : InstrumentedTest { - private val testHelper = CommonTestHelper(context()) - private val cryptoTestHelper = CryptoTestHelper(testHelper) - /** * Simple test that create an e2ee room. * Some new members are added, and a message is sent. @@ -72,16 +78,24 @@ class E2eeSanityTests : InstrumentedTest { */ @Test fun testSendingE2EEMessages() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession val e2eRoomID = cryptoTestData.roomId val aliceRoomPOV = aliceSession.getRoom(e2eRoomID)!! + // we want to disable key gossiping to just check initial sending of keys + aliceSession.cryptoService().enableKeyGossiping(false) + cryptoTestData.secondSession?.cryptoService()?.enableKeyGossiping(false) // add some more users and invite them val otherAccounts = listOf("benoit", "valere", "ganfra") // , "adam", "manu") .map { - testHelper.createAccount(it, SessionTestParams(true)) + testHelper.createAccount(it, SessionTestParams(true)).also { + it.cryptoService().enableKeyGossiping(false) + } } Log.v("#E2E TEST", "All accounts created") @@ -95,18 +109,18 @@ class E2eeSanityTests : InstrumentedTest { // All user should accept invite otherAccounts.forEach { otherSession -> - waitForAndAcceptInviteInRoom(otherSession, e2eRoomID) + waitForAndAcceptInviteInRoom(testHelper, otherSession, e2eRoomID) Log.v("#E2E TEST", "${otherSession.myUserId} joined room $e2eRoomID") } // check that alice see them as joined (not really necessary?) - ensureMembersHaveJoined(aliceSession, otherAccounts, e2eRoomID) + ensureMembersHaveJoined(testHelper, aliceSession, otherAccounts, e2eRoomID) Log.v("#E2E TEST", "All users have joined the room") Log.v("#E2E TEST", "Alice is sending the message") val text = "This is my message" - val sentEventId: String? = sendMessageInRoom(aliceRoomPOV, text) + val sentEventId: String? = sendMessageInRoom(testHelper, aliceRoomPOV, text) // val sentEvent = testHelper.sendTextMessage(aliceRoomPOV, "Hello all", 1).first() Assert.assertTrue("Message should be sent", sentEventId != null) @@ -114,10 +128,10 @@ class E2eeSanityTests : InstrumentedTest { otherAccounts.forEach { otherSession -> testHelper.waitWithLatch { latch -> testHelper.retryPeriodicallyWithLatch(latch) { - val timelineEvent = otherSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEventId!!) - timelineEvent != null && - timelineEvent.isEncrypted() && - timelineEvent.root.getClearType() == EventType.MESSAGE + val timeLineEvent = otherSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEventId!!) + timeLineEvent != null && + timeLineEvent.isEncrypted() && + timeLineEvent.root.getClearType() == EventType.MESSAGE } } } @@ -136,10 +150,10 @@ class E2eeSanityTests : InstrumentedTest { } newAccount.forEach { - waitForAndAcceptInviteInRoom(it, e2eRoomID) + waitForAndAcceptInviteInRoom(testHelper, it, e2eRoomID) } - ensureMembersHaveJoined(aliceSession, newAccount, e2eRoomID) + ensureMembersHaveJoined(testHelper, aliceSession, newAccount, e2eRoomID) // wait a bit testHelper.runBlockingTest { @@ -164,7 +178,7 @@ class E2eeSanityTests : InstrumentedTest { Log.v("#E2E TEST", "Alice sends a new message") val secondMessage = "2 This is my message" - val secondSentEventId: String? = sendMessageInRoom(aliceRoomPOV, secondMessage) + val secondSentEventId: String? = sendMessageInRoom(testHelper, aliceRoomPOV, secondMessage) // new members should be able to decrypt it newAccount.forEach { otherSession -> @@ -188,6 +202,14 @@ class E2eeSanityTests : InstrumentedTest { cryptoTestData.cleanUp(testHelper) } + @Test + fun testKeyGossipingIsEnabledByDefault() { + val testHelper = CommonTestHelper(context()) + val session = testHelper.createAccount("alice", SessionTestParams(true)) + Assert.assertTrue("Key gossiping should be enabled by default", session.cryptoService().isKeyGossipingEnabled()) + testHelper.signOutAndClose(session) + } + /** * Quick test for basic key backup * 1. Create e2e between Alice and Bob @@ -204,6 +226,9 @@ class E2eeSanityTests : InstrumentedTest { */ @Test fun testBasicBackupImport() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession val bobSession = cryptoTestData.secondSession!! @@ -227,16 +252,16 @@ class E2eeSanityTests : InstrumentedTest { val sentEventIds = mutableListOf<String>() val messagesText = listOf("1. Hello", "2. Bob", "3. Good morning") messagesText.forEach { text -> - val sentEventId = sendMessageInRoom(aliceRoomPOV, text)!!.also { + val sentEventId = sendMessageInRoom(testHelper, aliceRoomPOV, text)!!.also { sentEventIds.add(it) } testHelper.waitWithLatch { latch -> testHelper.retryPeriodicallyWithLatch(latch) { - val timelineEvent = bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEventId) - timelineEvent != null && - timelineEvent.isEncrypted() && - timelineEvent.root.getClearType() == EventType.MESSAGE + val timeLineEvent = bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEventId) + timeLineEvent != null && + timeLineEvent.isEncrypted() && + timeLineEvent.root.getClearType() == EventType.MESSAGE } } // we want more so let's discard the session @@ -289,28 +314,31 @@ class E2eeSanityTests : InstrumentedTest { } } // after initial sync events are not decrypted, so we have to try manually - ensureCannotDecrypt(sentEventIds, newBobSession, e2eRoomID, MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID) + cryptoTestHelper.ensureCannotDecrypt(sentEventIds, newBobSession, e2eRoomID, MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID) // Let's now import keys from backup - newBobSession.cryptoService().keysBackupService().let { keysBackupService -> + newBobSession.cryptoService().keysBackupService().let { kbs -> val keyVersionResult = testHelper.doSync<KeysVersionResult?> { - keysBackupService.getVersion(version.version, it) + kbs.getVersion(version.version, it) } val importedResult = testHelper.doSync<ImportRoomKeysResult> { - keysBackupService.restoreKeyBackupWithPassword(keyVersionResult!!, + kbs.restoreKeyBackupWithPassword( + keyVersionResult!!, keyBackupPassword, null, null, - null, it) + null, + it + ) } assertEquals(3, importedResult.totalNumberOfKeys) } // ensure bob can now decrypt - ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText) + cryptoTestHelper.ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText) testHelper.signOutAndClose(newBobSession) } @@ -321,6 +349,9 @@ class E2eeSanityTests : InstrumentedTest { */ @Test fun testSimpleGossip() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession val bobSession = cryptoTestData.secondSession!! @@ -328,30 +359,28 @@ class E2eeSanityTests : InstrumentedTest { val aliceRoomPOV = aliceSession.getRoom(e2eRoomID)!! - cryptoTestHelper.initializeCrossSigning(bobSession) - // let's send a few message to bob val sentEventIds = mutableListOf<String>() val messagesText = listOf("1. Hello", "2. Bob") Log.v("#E2E TEST", "Alice sends some messages") messagesText.forEach { text -> - val sentEventId = sendMessageInRoom(aliceRoomPOV, text)!!.also { + val sentEventId = sendMessageInRoom(testHelper, aliceRoomPOV, text)!!.also { sentEventIds.add(it) } testHelper.waitWithLatch { latch -> testHelper.retryPeriodicallyWithLatch(latch) { - val timelineEvent = bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEventId) - timelineEvent != null && - timelineEvent.isEncrypted() && - timelineEvent.root.getClearType() == EventType.MESSAGE + val timeLineEvent = bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEventId) + timeLineEvent != null && + timeLineEvent.isEncrypted() && + timeLineEvent.root.getClearType() == EventType.MESSAGE } } } // Ensure bob can decrypt - ensureIsDecrypted(sentEventIds, bobSession, e2eRoomID) + ensureIsDecrypted(testHelper, sentEventIds, bobSession, e2eRoomID) // Let's now add a new bob session // Create a new session for bob @@ -361,7 +390,11 @@ class E2eeSanityTests : InstrumentedTest { // check that new bob can't currently decrypt Log.v("#E2E TEST", "check that new bob can't currently decrypt") - ensureCannotDecrypt(sentEventIds, newBobSession, e2eRoomID, MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID) + cryptoTestHelper.ensureCannotDecrypt(sentEventIds, newBobSession, e2eRoomID, null) +// newBobSession.cryptoService().getOutgoingRoomKeyRequests() +// .firstOrNull { +// it.sessionId == +// } // Try to request sentEventIds.forEach { sentEventId -> @@ -370,12 +403,34 @@ class E2eeSanityTests : InstrumentedTest { } // wait a bit - testHelper.runBlockingTest { - delay(10_000) - } + // we need to wait a couple of syncs to let sharing occurs +// testHelper.waitFewSyncs(newBobSession, 6) // Ensure that new bob still can't decrypt (keys must have been withheld) - ensureCannotDecrypt(sentEventIds, newBobSession, e2eRoomID, MXCryptoError.ErrorType.KEYS_WITHHELD) + sentEventIds.forEach { sentEventId -> + val megolmSessionId = newBobSession.getRoom(e2eRoomID)!! + .getTimelineEvent(sentEventId)!! + .root.content.toModel<EncryptedEventContent>()!!.sessionId + testHelper.waitWithLatch { latch -> + testHelper.retryPeriodicallyWithLatch(latch) { + val aliceReply = newBobSession.cryptoService().getOutgoingRoomKeyRequests() + .first { + it.sessionId == megolmSessionId && + it.roomId == e2eRoomID + } + .results.also { + Log.w("##TEST", "result list is $it") + } + .firstOrNull { it.userId == aliceSession.myUserId } + ?.result + aliceReply != null && + aliceReply is RequestResult.Failure && + WithHeldCode.UNAUTHORISED == aliceReply.code + } + } + } + + cryptoTestHelper.ensureCannotDecrypt(sentEventIds, newBobSession, e2eRoomID, null) // Now mark new bob session as verified @@ -388,12 +443,7 @@ class E2eeSanityTests : InstrumentedTest { newBobSession.cryptoService().reRequestRoomKeyForEvent(event) } - // wait a bit - testHelper.runBlockingTest { - delay(10_000) - } - - ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText) + cryptoTestHelper.ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText) cryptoTestData.cleanUp(testHelper) testHelper.signOutAndClose(newBobSession) @@ -404,6 +454,9 @@ class E2eeSanityTests : InstrumentedTest { */ @Test fun testForwardBetterKey() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val aliceSession = cryptoTestData.firstSession val bobSessionWithBetterKey = cryptoTestData.secondSession!! @@ -411,35 +464,33 @@ class E2eeSanityTests : InstrumentedTest { val aliceRoomPOV = aliceSession.getRoom(e2eRoomID)!! - cryptoTestHelper.initializeCrossSigning(bobSessionWithBetterKey) - // let's send a few message to bob var firstEventId: String val firstMessage = "1. Hello" Log.v("#E2E TEST", "Alice sends some messages") firstMessage.let { text -> - firstEventId = sendMessageInRoom(aliceRoomPOV, text)!! + firstEventId = sendMessageInRoom(testHelper, aliceRoomPOV, text)!! testHelper.waitWithLatch { latch -> testHelper.retryPeriodicallyWithLatch(latch) { - val timelineEvent = bobSessionWithBetterKey.getRoom(e2eRoomID)?.getTimelineEvent(firstEventId) - timelineEvent != null && - timelineEvent.isEncrypted() && - timelineEvent.root.getClearType() == EventType.MESSAGE + val timeLineEvent = bobSessionWithBetterKey.getRoom(e2eRoomID)?.getTimelineEvent(firstEventId) + timeLineEvent != null && + timeLineEvent.isEncrypted() && + timeLineEvent.root.getClearType() == EventType.MESSAGE } } } // Ensure bob can decrypt - ensureIsDecrypted(listOf(firstEventId), bobSessionWithBetterKey, e2eRoomID) + ensureIsDecrypted(testHelper, listOf(firstEventId), bobSessionWithBetterKey, e2eRoomID) // Let's add a new unverified session from bob val newBobSession = testHelper.logIntoAccount(bobSessionWithBetterKey.myUserId, SessionTestParams(true)) // check that new bob can't currently decrypt Log.v("#E2E TEST", "check that new bob can't currently decrypt") - ensureCannotDecrypt(listOf(firstEventId), newBobSession, e2eRoomID, MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID) + cryptoTestHelper.ensureCannotDecrypt(listOf(firstEventId), newBobSession, e2eRoomID, null) // Now let alice send a new message. this time the new bob session will be able to decrypt var secondEventId: String @@ -447,14 +498,14 @@ class E2eeSanityTests : InstrumentedTest { Log.v("#E2E TEST", "Alice sends some messages") secondMessage.let { text -> - secondEventId = sendMessageInRoom(aliceRoomPOV, text)!! + secondEventId = sendMessageInRoom(testHelper, aliceRoomPOV, text)!! testHelper.waitWithLatch { latch -> testHelper.retryPeriodicallyWithLatch(latch) { - val timelineEvent = newBobSession.getRoom(e2eRoomID)?.getTimelineEvent(secondEventId) - timelineEvent != null && - timelineEvent.isEncrypted() && - timelineEvent.root.getClearType() == EventType.MESSAGE + val timeLineEvent = newBobSession.getRoom(e2eRoomID)?.getTimelineEvent(secondEventId) + timeLineEvent != null && + timeLineEvent.isEncrypted() && + timeLineEvent.root.getClearType() == EventType.MESSAGE } } } @@ -473,9 +524,7 @@ class E2eeSanityTests : InstrumentedTest { try { newBobSession.cryptoService().decryptEvent(firstEventNewBobPov.root, "") fail("Should not be able to decrypt event") - } catch (error: MXCryptoError) { - val errorType = (error as? MXCryptoError.Base)?.errorType - assertEquals(MXCryptoError.ErrorType.UNKNOWN_MESSAGE_INDEX, errorType) + } catch (_: MXCryptoError) { } } @@ -497,41 +546,45 @@ class E2eeSanityTests : InstrumentedTest { .markedLocallyAsManuallyVerified(bobSessionWithBetterKey.myUserId, bobSessionWithBetterKey.sessionParams.deviceId!!) // now let new session request - newBobSession.cryptoService().requestRoomKeyForEvent(firstEventNewBobPov.root) + newBobSession.cryptoService().reRequestRoomKeyForEvent(firstEventNewBobPov.root) - // wait a bit - testHelper.runBlockingTest { - delay(10_000) - } + // We need to wait for the key request to be sent out and then a reply to be received // old session should have shared the key at earliest known index now // we should be able to decrypt both - testHelper.runBlockingTest { - try { - newBobSession.cryptoService().decryptEvent(firstEventNewBobPov.root, "") - } catch (error: MXCryptoError) { - fail("Should be able to decrypt first event now $error") - } - } - testHelper.runBlockingTest { - try { - newBobSession.cryptoService().decryptEvent(secondEventNewBobPov.root, "") - } catch (error: MXCryptoError) { - fail("Should be able to decrypt event $error") + testHelper.waitWithLatch { + testHelper.retryPeriodicallyWithLatch(it) { + val canDecryptFirst = try { + testHelper.runBlockingTest { + newBobSession.cryptoService().decryptEvent(firstEventNewBobPov.root, "") + } + true + } catch (error: MXCryptoError) { + false + } + val canDecryptSecond = try { + testHelper.runBlockingTest { + newBobSession.cryptoService().decryptEvent(secondEventNewBobPov.root, "") + } + true + } catch (error: MXCryptoError) { + false + } + canDecryptFirst && canDecryptSecond } } - cryptoTestData.cleanUp(testHelper) + testHelper.signOutAndClose(aliceSession) + testHelper.signOutAndClose(bobSessionWithBetterKey) testHelper.signOutAndClose(newBobSession) } - private fun sendMessageInRoom(aliceRoomPOV: Room, text: String): String? { + private fun sendMessageInRoom(testHelper: CommonTestHelper, aliceRoomPOV: Room, text: String): String? { aliceRoomPOV.sendService().sendTextMessage(text) var sentEventId: String? = null testHelper.waitWithLatch(4 * TestConstants.timeOutMillis) { latch -> val timeline = aliceRoomPOV.timelineService().createTimeline(null, TimelineSettings(60)) timeline.start() - testHelper.retryPeriodicallyWithLatch(latch) { val decryptedMsg = timeline.getSnapshot() .filter { it.root.getClearType() == EventType.MESSAGE } @@ -550,7 +603,157 @@ class E2eeSanityTests : InstrumentedTest { return sentEventId } - private fun ensureMembersHaveJoined(aliceSession: Session, otherAccounts: List<Session>, e2eRoomID: String) { + /** + * Test that if a better key is forwared (lower index, it is then used) + */ + @Test + fun testSelfInteractiveVerificationAndGossip() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + + val aliceSession = testHelper.createAccount("alice", SessionTestParams(true)) + cryptoTestHelper.bootstrapSecurity(aliceSession) + + // now let's create a new login from alice + + val aliceNewSession = testHelper.logIntoAccount(aliceSession.myUserId, SessionTestParams(true)) + + val oldCompleteLatch = CountDownLatch(1) + lateinit var oldCode: String + aliceSession.cryptoService().verificationService().addListener(object : VerificationService.Listener { + + override fun verificationRequestUpdated(pr: PendingVerificationRequest) { + val readyInfo = pr.readyInfo + if (readyInfo != null) { + aliceSession.cryptoService().verificationService().beginKeyVerification( + VerificationMethod.SAS, + aliceSession.myUserId, + readyInfo.fromDevice, + readyInfo.transactionId + + ) + } + } + + override fun transactionUpdated(tx: VerificationTransaction) { + Log.d("##TEST", "exitsingPov: $tx") + val sasTx = tx as OutgoingSasVerificationTransaction + when (sasTx.uxState) { + OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> { + // for the test we just accept? + oldCode = sasTx.getDecimalCodeRepresentation() + sasTx.userHasVerifiedShortCode() + } + OutgoingSasVerificationTransaction.UxState.VERIFIED -> { + // we can release this latch? + oldCompleteLatch.countDown() + } + else -> Unit + } + } + }) + + val newCompleteLatch = CountDownLatch(1) + lateinit var newCode: String + aliceNewSession.cryptoService().verificationService().addListener(object : VerificationService.Listener { + + override fun verificationRequestCreated(pr: PendingVerificationRequest) { + // let's ready + aliceNewSession.cryptoService().verificationService().readyPendingVerification( + listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW), + aliceSession.myUserId, + pr.transactionId!! + ) + } + + var matchOnce = true + override fun transactionUpdated(tx: VerificationTransaction) { + Log.d("##TEST", "newPov: $tx") + + val sasTx = tx as IncomingSasVerificationTransaction + when (sasTx.uxState) { + IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> { + // no need to accept as there was a request first it will auto accept + } + IncomingSasVerificationTransaction.UxState.SHOW_SAS -> { + if (matchOnce) { + sasTx.userHasVerifiedShortCode() + newCode = sasTx.getDecimalCodeRepresentation() + matchOnce = false + } + } + IncomingSasVerificationTransaction.UxState.VERIFIED -> { + newCompleteLatch.countDown() + } + else -> Unit + } + } + }) + + // initiate self verification + aliceSession.cryptoService().verificationService().requestKeyVerification( + listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW), + aliceNewSession.myUserId, + listOf(aliceNewSession.sessionParams.deviceId!!) + ) + testHelper.await(oldCompleteLatch) + testHelper.await(newCompleteLatch) + assertEquals("Decimal code should have matched", oldCode, newCode) + + // Assert that devices are verified + val newDeviceFromOldPov: CryptoDeviceInfo? = aliceSession.cryptoService().getDeviceInfo(aliceSession.myUserId, aliceNewSession.sessionParams.deviceId) + val oldDeviceFromNewPov: CryptoDeviceInfo? = aliceSession.cryptoService().getDeviceInfo(aliceSession.myUserId, aliceSession.sessionParams.deviceId) + + Assert.assertTrue("new device should be verified from old point of view", newDeviceFromOldPov!!.isVerified) + Assert.assertTrue("old device should be verified from new point of view", oldDeviceFromNewPov!!.isVerified) + + // wait for secret gossiping to happen + testHelper.waitWithLatch { latch -> + testHelper.retryPeriodicallyWithLatch(latch) { + aliceNewSession.cryptoService().crossSigningService().allPrivateKeysKnown() + } + } + + testHelper.waitWithLatch { latch -> + testHelper.retryPeriodicallyWithLatch(latch) { + aliceNewSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo() != null + } + } + + assertEquals( + "MSK Private parts should be the same", + aliceSession.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.master, + aliceNewSession.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.master + ) + assertEquals( + "USK Private parts should be the same", + aliceSession.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.user, + aliceNewSession.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.user + ) + + assertEquals( + "SSK Private parts should be the same", + aliceSession.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.selfSigned, + aliceNewSession.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.selfSigned + ) + + // Let's check that we have the megolm backup key + assertEquals( + "Megolm key should be the same", + aliceSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.recoveryKey, + aliceNewSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.recoveryKey + ) + assertEquals( + "Megolm version should be the same", + aliceSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.version, + aliceNewSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.version + ) + + testHelper.signOutAndClose(aliceSession) + testHelper.signOutAndClose(aliceNewSession) + } + + private fun ensureMembersHaveJoined(testHelper: CommonTestHelper, aliceSession: Session, otherAccounts: List<Session>, e2eRoomID: String) { testHelper.waitWithLatch { latch -> testHelper.retryPeriodicallyWithLatch(latch) { otherAccounts.map { @@ -562,7 +765,7 @@ class E2eeSanityTests : InstrumentedTest { } } - private fun waitForAndAcceptInviteInRoom(otherSession: Session, e2eRoomID: String) { + private fun waitForAndAcceptInviteInRoom(testHelper: CommonTestHelper, otherSession: Session, e2eRoomID: String) { testHelper.waitWithLatch { latch -> testHelper.retryPeriodicallyWithLatch(latch) { val roomSummary = otherSession.getRoomSummary(e2eRoomID) @@ -574,7 +777,8 @@ class E2eeSanityTests : InstrumentedTest { } } - testHelper.runBlockingTest(60_000) { + // not sure why it's taking so long :/ + testHelper.runBlockingTest(90_000) { Log.v("#E2E TEST", "${otherSession.myUserId} tries to join room $e2eRoomID") try { otherSession.roomService().joinRoom(e2eRoomID) @@ -592,59 +796,14 @@ class E2eeSanityTests : InstrumentedTest { } } - private fun ensureCanDecrypt(sentEventIds: MutableList<String>, session: Session, e2eRoomID: String, messagesText: List<String>) { - sentEventIds.forEachIndexed { index, sentEventId -> - testHelper.waitWithLatch { latch -> - testHelper.retryPeriodicallyWithLatch(latch) { - val event = session.getRoom(e2eRoomID)!!.getTimelineEvent(sentEventId)!!.root - testHelper.runBlockingTest { - try { - session.cryptoService().decryptEvent(event, "").let { result -> - event.mxDecryptionResult = OlmDecryptionResult( - payload = result.clearEvent, - senderKey = result.senderCurve25519Key, - keysClaimed = result.claimedEd25519Key?.let { mapOf("ed25519" to it) }, - forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain - ) - } - } catch (error: MXCryptoError) { - // nop - } - } - event.getClearType() == EventType.MESSAGE && - messagesText[index] == event.getClearContent()?.toModel<MessageContent>()?.body - } - } - } - } - - private fun ensureIsDecrypted(sentEventIds: List<String>, session: Session, e2eRoomID: String) { + private fun ensureIsDecrypted(testHelper: CommonTestHelper, sentEventIds: List<String>, session: Session, e2eRoomID: String) { testHelper.waitWithLatch { latch -> sentEventIds.forEach { sentEventId -> testHelper.retryPeriodicallyWithLatch(latch) { - val timelineEvent = session.getRoom(e2eRoomID)?.getTimelineEvent(sentEventId) - timelineEvent != null && - timelineEvent.isEncrypted() && - timelineEvent.root.getClearType() == EventType.MESSAGE - } - } - } - } - - private fun ensureCannotDecrypt(sentEventIds: List<String>, newBobSession: Session, e2eRoomID: String, expectedError: MXCryptoError.ErrorType?) { - sentEventIds.forEach { sentEventId -> - val event = newBobSession.getRoom(e2eRoomID)!!.getTimelineEvent(sentEventId)!!.root - testHelper.runBlockingTest { - try { - newBobSession.cryptoService().decryptEvent(event, "") - fail("Should not be able to decrypt event") - } catch (error: MXCryptoError) { - val errorType = (error as? MXCryptoError.Base)?.errorType - if (expectedError == null) { - Assert.assertNotNull(errorType) - } else { - assertEquals(expectedError, errorType, "Message expected to be UISI") - } + val timeLineEvent = session.getRoom(e2eRoomID)?.getTimelineEvent(sentEventId) + timeLineEvent != null && + timeLineEvent.isEncrypted() && + timeLineEvent.root.getClearType() == EventType.MESSAGE } } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ExportEncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ExportEncryptionTest.kt index 17664c78aa51afb6df278341d33006c4eb0bf218..c2d8f4fb35f30c99457c8b81c2298d1a29b90763 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ExportEncryptionTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ExportEncryptionTest.kt @@ -93,9 +93,11 @@ class ExportEncryptionTest { fail("## checkExportDecrypt1() failed : " + e.message) } - assertEquals("## checkExportDecrypt1() : expectedString $expectedString -- decodedString $decodedString", + assertEquals( + "## checkExportDecrypt1() : expectedString $expectedString -- decodedString $decodedString", expectedString, - decodedString) + decodedString + ) } @Test @@ -111,9 +113,11 @@ class ExportEncryptionTest { fail("## checkExportDecrypt2() failed : " + e.message) } - assertEquals("## checkExportDecrypt2() : expectedString $expectedString -- decodedString $decodedString", + assertEquals( + "## checkExportDecrypt2() : expectedString $expectedString -- decodedString $decodedString", expectedString, - decodedString) + decodedString + ) } @Test @@ -129,9 +133,11 @@ class ExportEncryptionTest { fail("## checkExportDecrypt3() failed : " + e.message) } - assertEquals("## checkExportDecrypt3() : expectedString $expectedString -- decodedString $decodedString", + assertEquals( + "## checkExportDecrypt3() : expectedString $expectedString -- decodedString $decodedString", expectedString, - decodedString) + decodedString + ) } @Test @@ -147,9 +153,11 @@ class ExportEncryptionTest { fail("## checkExportEncrypt1() failed : " + e.message) } - assertEquals("## checkExportEncrypt1() : expectedString $expectedString -- decodedString $decodedString", + assertEquals( + "## checkExportEncrypt1() : expectedString $expectedString -- decodedString $decodedString", expectedString, - decodedString) + decodedString + ) } @Test @@ -165,9 +173,11 @@ class ExportEncryptionTest { fail("## checkExportEncrypt2() failed : " + e.message) } - assertEquals("## checkExportEncrypt2() : expectedString $expectedString -- decodedString $decodedString", + assertEquals( + "## checkExportEncrypt2() : expectedString $expectedString -- decodedString $decodedString", expectedString, - decodedString) + decodedString + ) } @Test @@ -183,9 +193,11 @@ class ExportEncryptionTest { fail("## checkExportEncrypt3() failed : " + e.message) } - assertEquals("## checkExportEncrypt3() : expectedString $expectedString -- decodedString $decodedString", + assertEquals( + "## checkExportEncrypt3() : expectedString $expectedString -- decodedString $decodedString", expectedString, - decodedString) + decodedString + ) } @Test @@ -201,8 +213,10 @@ class ExportEncryptionTest { fail("## checkExportEncrypt4() failed : " + e.message) } - assertEquals("## checkExportEncrypt4() : expectedString $expectedString -- decodedString $decodedString", + assertEquals( + "## checkExportEncrypt4() : expectedString $expectedString -- decodedString $decodedString", expectedString, - decodedString) + decodedString + ) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt index 8a1edec5e3dcd9448998992fa801b3f952accac2..93aa78a3050a8cb6e48f5ca288d2d60626fade8c 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt @@ -27,7 +27,6 @@ import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent -import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.getTimelineEvent @@ -51,10 +50,7 @@ class PreShareKeysTest : InstrumentedTest { // clear any outbound session aliceSession.cryptoService().discardOutboundSession(e2eRoomID) - val preShareCount = bobSession.cryptoService().getGossipingEvents().count { - it.senderId == aliceSession.myUserId && - it.getClearType() == EventType.ROOM_KEY - } + val preShareCount = bobSession.cryptoService().keysBackupService().getTotalNumbersOfKeys() assertEquals("Bob should not have receive any key from alice at this point", 0, preShareCount) Log.d("#Test", "Room Key Received from alice $preShareCount") @@ -66,23 +62,23 @@ class PreShareKeysTest : InstrumentedTest { testHelper.waitWithLatch { latch -> testHelper.retryPeriodicallyWithLatch(latch) { - val newGossipCount = bobSession.cryptoService().getGossipingEvents().count { - it.senderId == aliceSession.myUserId && - it.getClearType() == EventType.ROOM_KEY - } - newGossipCount > preShareCount + val newKeysCount = bobSession.cryptoService().keysBackupService().getTotalNumbersOfKeys() + newKeysCount > preShareCount } } - val latest = bobSession.cryptoService().getGossipingEvents().lastOrNull { - it.senderId == aliceSession.myUserId && - it.getClearType() == EventType.ROOM_KEY - } + val aliceCryptoStore = (aliceSession.cryptoService() as DefaultCryptoService).cryptoStoreForTesting + val aliceOutboundSessionInRoom = aliceCryptoStore.getCurrentOutboundGroupSessionForRoom(e2eRoomID)!!.outboundGroupSession.sessionIdentifier() + + val bobCryptoStore = (bobSession.cryptoService() as DefaultCryptoService).cryptoStoreForTesting + val aliceDeviceBobPov = bobCryptoStore.getUserDevice(aliceSession.myUserId, aliceSession.sessionParams.deviceId!!)!! + val bobInboundForAlice = bobCryptoStore.getInboundGroupSession(aliceOutboundSessionInRoom, aliceDeviceBobPov.identityKey()!!) + assertNotNull("Bob should have received and decrypted a room key event from alice", bobInboundForAlice) + assertEquals("Wrong room", e2eRoomID, bobInboundForAlice!!.roomId) + + val megolmSessionId = bobInboundForAlice.olmInboundGroupSession!!.sessionIdentifier() - val content = latest?.getClearContent().toModel<RoomKeyContent>() - assertNotNull("Bob should have received and decrypted a room key event from alice", content) - assertEquals("Wrong room", e2eRoomID, content!!.roomId) - val megolmSessionId = content.sessionId!! + assertEquals("Wrong session", aliceOutboundSessionInRoom, megolmSessionId) val sharedIndex = aliceSession.cryptoService().getSharedWithInfo(e2eRoomID, megolmSessionId) .getObject(bobSession.myUserId, bobSession.sessionParams.deviceId) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt index de4a928dc36f4bedfb079b8cf6c99a05666b1669..0f3a4b4181923e7c032ef4dc96b076f2933e1bd2 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt @@ -171,7 +171,10 @@ class UnwedgingTest : InstrumentedTest { // Let us wedge the session now. Set crypto state like after the first message Timber.i("## CRYPTO | testUnwedging: wedge the session now. Set crypto state like after the first message") - aliceCryptoStore.storeSession(OlmSessionWrapper(deserializeFromRealm<OlmSession>(oldSession)!!), bobSession.cryptoService().getMyDevice().identityKey()!!) + aliceCryptoStore.storeSession( + OlmSessionWrapper(deserializeFromRealm<OlmSession>(oldSession)!!), + bobSession.cryptoService().getMyDevice().identityKey()!! + ) olmDevice.clearOlmSessionCache() Thread.sleep(6_000) @@ -218,7 +221,8 @@ class UnwedgingTest : InstrumentedTest { ) ) } - }, it) + }, it + ) } // Wait until we received back the key diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt index 0f3ff7898fd357c3ceada6d94f14cb873274fe7f..a37626dc20b9bd7bc825def322e6e1287625fbb3 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt @@ -126,8 +126,16 @@ class XSigningTest : InstrumentedTest { assertNull("Alice should not see bob User key", bobKeysFromAlicePOV.userKey()) assertNotNull("Alice can see bob SelfSigned key", bobKeysFromAlicePOV.selfSigningKey()) - assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV.masterKey()?.unpaddedBase64PublicKey, bobSession.cryptoService().crossSigningService().getMyCrossSigningKeys()?.masterKey()?.unpaddedBase64PublicKey) - assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV.selfSigningKey()?.unpaddedBase64PublicKey, bobSession.cryptoService().crossSigningService().getMyCrossSigningKeys()?.selfSigningKey()?.unpaddedBase64PublicKey) + assertEquals( + "Bob keys from alice pov should match", + bobKeysFromAlicePOV.masterKey()?.unpaddedBase64PublicKey, + bobSession.cryptoService().crossSigningService().getMyCrossSigningKeys()?.masterKey()?.unpaddedBase64PublicKey + ) + assertEquals( + "Bob keys from alice pov should match", + bobKeysFromAlicePOV.selfSigningKey()?.unpaddedBase64PublicKey, + bobSession.cryptoService().crossSigningService().getMyCrossSigningKeys()?.selfSigningKey()?.unpaddedBase64PublicKey + ) assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted()) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt index 592d24fb690650338a44e8e166cb93aee72a29e0..2e4fd62822ba37ca2c43ba3cc9c17497e2f18817 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt @@ -19,59 +19,45 @@ package org.matrix.android.sdk.internal.crypto.gossiping import android.util.Log import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertNotNull import junit.framework.TestCase.assertTrue import junit.framework.TestCase.fail +import org.amshove.kluent.internal.assertEquals import org.junit.Assert +import org.junit.Assert.assertNull import org.junit.FixMethodOrder -import org.junit.Ignore 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.auth.UIABaseAuth -import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor -import org.matrix.android.sdk.api.auth.UserPasswordAuth -import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse -import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.crypto.OutgoingRoomKeyRequestState +import org.matrix.android.sdk.api.session.crypto.RequestResult import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion -import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo -import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState -import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction -import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction -import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod -import org.matrix.android.sdk.api.session.crypto.verification.VerificationService -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent +import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams -import org.matrix.android.sdk.api.session.room.model.message.MessageContent +import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants -import kotlin.coroutines.Continuation -import kotlin.coroutines.resume @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.JVM) @LargeTest class KeyShareTests : InstrumentedTest { - private val commonTestHelper = CommonTestHelper(context()) - @Test - @Ignore("This test will be ignored until it is fixed") fun test_DoNotSelfShareIfNotTrusted() { + val commonTestHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + val aliceSession = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) + Log.v("TEST", "=======> AliceSession 1 is ${aliceSession.sessionParams.deviceId}") // Create an encrypted room and add a message val roomId = commonTestHelper.runBlockingTest { @@ -86,11 +72,18 @@ class KeyShareTests : InstrumentedTest { assertNotNull(room) Thread.sleep(4_000) assertTrue(room?.roomCryptoService()?.isEncrypted() == true) - val sentEventId = commonTestHelper.sendTextMessage(room!!, "My Message", 1).first().eventId - // Open a new sessionx + val sentEvent = commonTestHelper.sendTextMessage(room!!, "My Message", 1).first() + val sentEventId = sentEvent.eventId + val sentEventText = sentEvent.getLastMessageContent()?.body - val aliceSession2 = commonTestHelper.logIntoAccount(aliceSession.myUserId, SessionTestParams(true)) + // Open a new session + val aliceSession2 = commonTestHelper.logIntoAccount(aliceSession.myUserId, SessionTestParams(false)) + // block key requesting for now as decrypt will send requests (room summary is trying to decrypt) + aliceSession2.cryptoService().enableKeyGossiping(false) + commonTestHelper.syncSession(aliceSession2) + + Log.v("TEST", "=======> AliceSession 2 is ${aliceSession2.sessionParams.deviceId}") val roomSecondSessionPOV = aliceSession2.getRoom(roomId) @@ -107,7 +100,10 @@ class KeyShareTests : InstrumentedTest { } val outgoingRequestsBefore = aliceSession2.cryptoService().getOutgoingRoomKeyRequests() + assertEquals("There should be no request as it's disabled", 0, outgoingRequestsBefore.size) + // Try to request + aliceSession2.cryptoService().enableKeyGossiping(true) aliceSession2.cryptoService().requestRoomKeyForEvent(receivedEvent.root) val eventMegolmSessionId = receivedEvent.root.content.toModel<EncryptedEventContent>()?.sessionId @@ -117,10 +113,6 @@ class KeyShareTests : InstrumentedTest { commonTestHelper.waitWithLatch { latch -> commonTestHelper.retryPeriodicallyWithLatch(latch) { aliceSession2.cryptoService().getOutgoingRoomKeyRequests() - .filter { req -> - // filter out request that was known before - !outgoingRequestsBefore.any { req.requestId == it.requestId } - } .let { val outgoing = it.firstOrNull { it.sessionId == eventMegolmSessionId } outGoingRequestId = outgoing?.requestId @@ -141,17 +133,34 @@ class KeyShareTests : InstrumentedTest { commonTestHelper.waitWithLatch { latch -> commonTestHelper.retryPeriodicallyWithLatch(latch) { // DEBUG LOGS - aliceSession.cryptoService().getIncomingRoomKeyRequests().let { - Log.v("TEST", "Incoming request Session 1 (looking for $outGoingRequestId)") +// aliceSession.cryptoService().getIncomingRoomKeyRequests().let { +// Log.v("TEST", "Incoming request Session 1 (looking for $outGoingRequestId)") +// Log.v("TEST", "=========================") +// it.forEach { keyRequest -> +// Log.v("TEST", "[ts${keyRequest.localCreationTimestamp}] requestId ${keyRequest.requestId}, for sessionId ${keyRequest.requestBody?.sessionId}") +// } +// Log.v("TEST", "=========================") +// } + + val incoming = aliceSession.cryptoService().getIncomingRoomKeyRequests().firstOrNull { it.requestId == outGoingRequestId } + incoming != null + } + } + + commonTestHelper.waitWithLatch { latch -> + commonTestHelper.retryPeriodicallyWithLatch(latch) { + // DEBUG LOGS + aliceSession2.cryptoService().getOutgoingRoomKeyRequests().forEach { keyRequest -> Log.v("TEST", "=========================") - it.forEach { keyRequest -> - Log.v("TEST", "[ts${keyRequest.localCreationTimestamp}] requestId ${keyRequest.requestId}, for sessionId ${keyRequest.requestBody?.sessionId} is ${keyRequest.state}") - } + Log.v("TEST", "requestId ${keyRequest.requestId}, for sessionId ${keyRequest.requestBody?.sessionId}") + Log.v("TEST", "replies -> ${keyRequest.results.joinToString { it.toString() }}") Log.v("TEST", "=========================") } - val incoming = aliceSession.cryptoService().getIncomingRoomKeyRequests().firstOrNull { it.requestId == outGoingRequestId } - incoming?.state == GossipingRequestState.REJECTED + val outgoing = aliceSession2.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.requestId == outGoingRequestId } + val reply = outgoing?.results?.firstOrNull { it.userId == aliceSession.myUserId && it.fromDevice == aliceSession.sessionParams.deviceId } + val resultCode = (reply?.result as? RequestResult.Failure)?.code + resultCode == WithHeldCode.UNVERIFIED } } @@ -164,255 +173,309 @@ class KeyShareTests : InstrumentedTest { } // Mark the device as trusted - aliceSession.cryptoService().setDeviceVerification(DeviceTrustLevel(crossSigningVerified = false, locallyVerified = true), aliceSession.myUserId, - aliceSession2.sessionParams.deviceId ?: "") + aliceSession.cryptoService().setDeviceVerification( + DeviceTrustLevel(crossSigningVerified = false, locallyVerified = true), aliceSession.myUserId, + aliceSession2.sessionParams.deviceId ?: "" + ) // Re request aliceSession2.cryptoService().reRequestRoomKeyForEvent(receivedEvent.root) + cryptoTestHelper.ensureCanDecrypt(listOf(receivedEvent.eventId), aliceSession2, roomId, listOf(sentEventText ?: "")) + + commonTestHelper.signOutAndClose(aliceSession) + commonTestHelper.signOutAndClose(aliceSession2) + } + + // See E2ESanityTest for a test regarding secret sharing + + /** + * Test that the sender of a message accepts to re-share to another user + * if the key was originally shared with him + */ + @Test + fun test_reShareIfWasIntendedToBeShared() { + val commonTestHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + + val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) + val aliceSession = testData.firstSession + val roomFromAlice = aliceSession.getRoom(testData.roomId)!! + val bobSession = testData.secondSession!! + + val sentEvent = commonTestHelper.sendTextMessage(roomFromAlice, "Hello", 1).first() + val sentEventMegolmSession = sentEvent.root.content.toModel<EncryptedEventContent>()!!.sessionId!! + + // bob should be able to decrypt + cryptoTestHelper.ensureCanDecrypt(listOf(sentEvent.eventId), bobSession, testData.roomId, listOf(sentEvent.getLastMessageContent()?.body ?: "")) + + // Let's try to request any how. + // As it was share previously alice should accept to reshare + bobSession.cryptoService().reRequestRoomKeyForEvent(sentEvent.root) + commonTestHelper.waitWithLatch { latch -> commonTestHelper.retryPeriodicallyWithLatch(latch) { - aliceSession.cryptoService().getIncomingRoomKeyRequests().let { - Log.v("TEST", "Incoming request Session 1") - Log.v("TEST", "=========================") - it.forEach { - Log.v("TEST", "requestId ${it.requestId}, for sessionId ${it.requestBody?.sessionId} is ${it.state}") - } - Log.v("TEST", "=========================") - - it.any { it.requestBody?.sessionId == eventMegolmSessionId && it.state == GossipingRequestState.ACCEPTED } - } + val outgoing = bobSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } + val aliceReply = outgoing?.results?.firstOrNull { it.userId == aliceSession.myUserId && it.fromDevice == aliceSession.sessionParams.deviceId } + aliceReply != null && aliceReply.result is RequestResult.Success } } + } - Thread.sleep(6_000) + /** + * Test that our own devices accept to reshare to unverified device if it was shared initialy + * if the key was originally shared with him + */ + @Test + fun test_reShareToUnverifiedIfWasIntendedToBeShared() { + val commonTestHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(commonTestHelper) + + val testData = cryptoTestHelper.doE2ETestWithAliceInARoom(true) + val aliceSession = testData.firstSession + val roomFromAlice = aliceSession.getRoom(testData.roomId)!! + + val aliceNewSession = commonTestHelper.logIntoAccount(aliceSession.myUserId, SessionTestParams(true)) + + // we wait for alice first session to be aware of that session? commonTestHelper.waitWithLatch { latch -> commonTestHelper.retryPeriodicallyWithLatch(latch) { - aliceSession2.cryptoService().getOutgoingRoomKeyRequests().let { - it.any { it.requestBody?.sessionId == eventMegolmSessionId && it.state == OutgoingGossipingRequestState.CANCELLED } - } + val newSession = aliceSession.cryptoService().getUserDevices(aliceSession.myUserId) + .firstOrNull { it.deviceId == aliceNewSession.sessionParams.deviceId } + newSession != null } } + val sentEvent = commonTestHelper.sendTextMessage(roomFromAlice, "Hello", 1).first() + val sentEventMegolmSession = sentEvent.root.content.toModel<EncryptedEventContent>()!!.sessionId!! - try { - commonTestHelper.runBlockingTest { - aliceSession2.cryptoService().decryptEvent(receivedEvent.root, "foo") + // Let's try to request any how. + // As it was share previously alice should accept to reshare + aliceNewSession.cryptoService().reRequestRoomKeyForEvent(sentEvent.root) + + commonTestHelper.waitWithLatch { latch -> + commonTestHelper.retryPeriodicallyWithLatch(latch) { + val outgoing = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } + val ownDeviceReply = + outgoing?.results?.firstOrNull { it.userId == aliceSession.myUserId && it.fromDevice == aliceSession.sessionParams.deviceId } + ownDeviceReply != null && ownDeviceReply.result is RequestResult.Success } - } catch (failure: Throwable) { - fail("should have been able to decrypt") } - - commonTestHelper.signOutAndClose(aliceSession) - commonTestHelper.signOutAndClose(aliceSession2) } + /** + * Tests that keys reshared with own verified session are done from the earliest known index + */ @Test - @Ignore("This test will be ignored until it is fixed") - fun test_ShareSSSSSecret() { - val aliceSession1 = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) - - commonTestHelper.doSync<Unit> { - aliceSession1.cryptoService().crossSigningService() - .initializeCrossSigning( - object : UserInteractiveAuthInterceptor { - override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { - promise.resume( - UserPasswordAuth( - user = aliceSession1.myUserId, - password = TestConstants.PASSWORD - ) - ) - } - }, it) - } + fun test_reShareFromTheEarliestKnownIndexWithOwnVerifiedSession() { + val commonTestHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(commonTestHelper) - // Also bootstrap keybackup on first session - val creationInfo = commonTestHelper.doSync<MegolmBackupCreationInfo> { - aliceSession1.cryptoService().keysBackupService().prepareKeysBackupVersion(null, null, it) - } - val version = commonTestHelper.doSync<KeysVersion> { - aliceSession1.cryptoService().keysBackupService().createKeysBackupVersion(creationInfo, it) - } - // Save it for gossiping - aliceSession1.cryptoService().keysBackupService().saveBackupRecoveryKey(creationInfo.recoveryKey, version = version.version) + val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) + val aliceSession = testData.firstSession + val bobSession = testData.secondSession!! + val roomFromBob = bobSession.getRoom(testData.roomId)!! - val aliceSession2 = commonTestHelper.logIntoAccount(aliceSession1.myUserId, SessionTestParams(true)) + val sentEvents = commonTestHelper.sendTextMessage(roomFromBob, "Hello", 3) + val sentEventMegolmSession = sentEvents.first().root.content.toModel<EncryptedEventContent>()!!.sessionId!! - val aliceVerificationService1 = aliceSession1.cryptoService().verificationService() - val aliceVerificationService2 = aliceSession2.cryptoService().verificationService() + // Let alice now add a new session + val aliceNewSession = commonTestHelper.logIntoAccount(aliceSession.myUserId, SessionTestParams(false)) + aliceNewSession.cryptoService().enableKeyGossiping(false) + commonTestHelper.syncSession(aliceNewSession) - // force keys download - commonTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> { - aliceSession1.cryptoService().downloadKeys(listOf(aliceSession1.myUserId), true, it) + // we wait bob first session to be aware of that session? + commonTestHelper.waitWithLatch { latch -> + commonTestHelper.retryPeriodicallyWithLatch(latch) { + val newSession = bobSession.cryptoService().getUserDevices(aliceSession.myUserId) + .firstOrNull { it.deviceId == aliceNewSession.sessionParams.deviceId } + newSession != null + } } - commonTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> { - aliceSession2.cryptoService().downloadKeys(listOf(aliceSession2.myUserId), true, it) + + val newEvent = commonTestHelper.sendTextMessage(roomFromBob, "The New", 1).first() + val newEventId = newEvent.eventId + val newEventText = newEvent.getLastMessageContent()!!.body + + // alice should be able to decrypt the new one + cryptoTestHelper.ensureCanDecrypt(listOf(newEventId), aliceNewSession, testData.roomId, listOf(newEventText)) + // but not the first one! + cryptoTestHelper.ensureCannotDecrypt(sentEvents.map { it.eventId }, aliceNewSession, testData.roomId) + + // All should be using the same session id + sentEvents.forEach { + assertEquals(sentEventMegolmSession, it.root.content.toModel<EncryptedEventContent>()!!.sessionId) } + assertEquals(sentEventMegolmSession, newEvent.root.content.toModel<EncryptedEventContent>()!!.sessionId) - var session1ShortCode: String? = null - var session2ShortCode: String? = null + // Request a first time, bob should reply with unauthorized and alice should reply with unverified + aliceNewSession.cryptoService().enableKeyGossiping(true) + aliceNewSession.cryptoService().reRequestRoomKeyForEvent(newEvent.root) - aliceVerificationService1.addListener(object : VerificationService.Listener { - override fun transactionUpdated(tx: VerificationTransaction) { - Log.d("#TEST", "AA: tx incoming?:${tx.isIncoming} state ${tx.state}") - if (tx is SasVerificationTransaction) { - if (tx.state == VerificationTxState.OnStarted) { - (tx as IncomingSasVerificationTransaction).performAccept() - } - if (tx.state == VerificationTxState.ShortCodeReady) { - session1ShortCode = tx.getDecimalCodeRepresentation() - Thread.sleep(500) - tx.userHasVerifiedShortCode() - } - } - } - }) - - aliceVerificationService2.addListener(object : VerificationService.Listener { - override fun transactionUpdated(tx: VerificationTransaction) { - Log.d("#TEST", "BB: tx incoming?:${tx.isIncoming} state ${tx.state}") - if (tx is SasVerificationTransaction) { - if (tx.state == VerificationTxState.ShortCodeReady) { - session2ShortCode = tx.getDecimalCodeRepresentation() - Thread.sleep(500) - tx.userHasVerifiedShortCode() - } - } + commonTestHelper.waitWithLatch { latch -> + commonTestHelper.retryPeriodicallyWithLatch(latch) { + val outgoing = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } + val ownDeviceReply = outgoing?.results + ?.firstOrNull { it.userId == aliceSession.myUserId && it.fromDevice == aliceSession.sessionParams.deviceId } + val result = ownDeviceReply?.result + Log.v("TEST", "own device result is $result") + result != null && result is RequestResult.Failure && result.code == WithHeldCode.UNVERIFIED } - }) - - val txId = "m.testVerif12" - aliceVerificationService2.beginKeyVerification(VerificationMethod.SAS, aliceSession1.myUserId, aliceSession1.sessionParams.deviceId - ?: "", txId) + } commonTestHelper.waitWithLatch { latch -> commonTestHelper.retryPeriodicallyWithLatch(latch) { - aliceSession1.cryptoService().getDeviceInfo(aliceSession1.myUserId, aliceSession2.sessionParams.deviceId ?: "")?.isVerified == true + val outgoing = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } + val bobDeviceReply = outgoing?.results + ?.firstOrNull { it.userId == bobSession.myUserId && it.fromDevice == bobSession.sessionParams.deviceId } + val result = bobDeviceReply?.result + Log.v("TEST", "bob device result is $result") + result != null && result is RequestResult.Success && result.chainIndex > 0 } } - assertNotNull(session1ShortCode) - Log.d("#TEST", "session1ShortCode: $session1ShortCode") - assertNotNull(session2ShortCode) - Log.d("#TEST", "session2ShortCode: $session2ShortCode") - assertEquals(session1ShortCode, session2ShortCode) + // it's a success but still can't decrypt first message + cryptoTestHelper.ensureCannotDecrypt(sentEvents.map { it.eventId }, aliceNewSession, testData.roomId) - // SSK and USK private keys should have been shared + // Mark the new session as verified + aliceSession.cryptoService() + .verificationService() + .markedLocallyAsManuallyVerified(aliceNewSession.myUserId, aliceNewSession.sessionParams.deviceId!!) - commonTestHelper.waitWithLatch(60_000) { latch -> + // Let's now try to request + aliceNewSession.cryptoService().reRequestRoomKeyForEvent(sentEvents.first().root) + + commonTestHelper.waitWithLatch { latch -> commonTestHelper.retryPeriodicallyWithLatch(latch) { - Log.d("#TEST", "CAN XS :${aliceSession2.cryptoService().crossSigningService().getMyCrossSigningKeys()}") - aliceSession2.cryptoService().crossSigningService().canCrossSign() + // DEBUG LOGS + aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().forEach { keyRequest -> + Log.v("TEST", "=========================") + Log.v("TEST", "requestId ${keyRequest.requestId}, for sessionId ${keyRequest.requestBody?.sessionId}") + Log.v("TEST", "replies -> ${keyRequest.results.joinToString { it.toString() }}") + Log.v("TEST", "=========================") + } + val outgoing = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } + val ownDeviceReply = + outgoing?.results?.firstOrNull { it.userId == aliceSession.myUserId && it.fromDevice == aliceSession.sessionParams.deviceId } + val result = ownDeviceReply?.result + result != null && result is RequestResult.Success && result.chainIndex == 0 } } - // Test that key backup key has been shared to - commonTestHelper.waitWithLatch(60_000) { latch -> - val keysBackupService = aliceSession2.cryptoService().keysBackupService() + // now the new session should be able to decrypt all! + cryptoTestHelper.ensureCanDecrypt( + sentEvents.map { it.eventId }, + aliceNewSession, + testData.roomId, + sentEvents.map { it.getLastMessageContent()!!.body } + ) + + // Additional test, can we check that bob replied successfully but with a ratcheted key + commonTestHelper.waitWithLatch { latch -> commonTestHelper.retryPeriodicallyWithLatch(latch) { - Log.d("#TEST", "Recovery :${keysBackupService.getKeyBackupRecoveryKeyInfo()?.recoveryKey}") - keysBackupService.getKeyBackupRecoveryKeyInfo()?.recoveryKey == creationInfo.recoveryKey + val outgoing = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } + val bobReply = outgoing?.results?.firstOrNull { it.userId == bobSession.myUserId } + val result = bobReply?.result + result != null && result is RequestResult.Success && result.chainIndex == 3 } } - commonTestHelper.signOutAndClose(aliceSession1) - commonTestHelper.signOutAndClose(aliceSession2) + commonTestHelper.signOutAndClose(aliceNewSession) + commonTestHelper.signOutAndClose(aliceSession) + commonTestHelper.signOutAndClose(bobSession) } + /** + * Tests that we don't cancel a request to early on first forward if the index is not good enough + */ @Test - @Ignore("This test will be ignored until it is fixed") - fun test_ImproperKeyShareBug() { - val aliceSession = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) + fun test_dontCancelToEarly() { + val commonTestHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(commonTestHelper) - commonTestHelper.doSync<Unit> { - aliceSession.cryptoService().crossSigningService() - .initializeCrossSigning( - object : UserInteractiveAuthInterceptor { - override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { - promise.resume( - UserPasswordAuth( - user = aliceSession.myUserId, - password = TestConstants.PASSWORD, - session = flowResponse.session - ) - ) - } - }, it) - } + val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) + val aliceSession = testData.firstSession + val bobSession = testData.secondSession!! + val roomFromBob = bobSession.getRoom(testData.roomId)!! - // Create an encrypted room and send a couple of messages - val roomId = commonTestHelper.runBlockingTest { - aliceSession.roomService().createRoom( - CreateRoomParams().apply { - visibility = RoomDirectoryVisibility.PRIVATE - enableEncryption() - } - ) - } - val roomAlicePov = aliceSession.getRoom(roomId) - assertNotNull(roomAlicePov) - Thread.sleep(1_000) - assertTrue(roomAlicePov?.roomCryptoService()?.isEncrypted() == true) - val secondEventId = commonTestHelper.sendTextMessage(roomAlicePov!!, "Message", 3)[1].eventId - - // Create bob session - - val bobSession = commonTestHelper.createAccount(TestConstants.USER_BOB, SessionTestParams(true)) - commonTestHelper.doSync<Unit> { - bobSession.cryptoService().crossSigningService() - .initializeCrossSigning( - object : UserInteractiveAuthInterceptor { - override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { - promise.resume( - UserPasswordAuth( - user = bobSession.myUserId, - password = TestConstants.PASSWORD, - session = flowResponse.session - ) - ) - } - }, it) - } + val sentEvents = commonTestHelper.sendTextMessage(roomFromBob, "Hello", 3) + val sentEventMegolmSession = sentEvents.first().root.content.toModel<EncryptedEventContent>()!!.sessionId!! - // Let alice invite bob - commonTestHelper.runBlockingTest { - roomAlicePov.membershipService().invite(bobSession.myUserId, null) + // Let alice now add a new session + val aliceNewSession = commonTestHelper.logIntoAccount(aliceSession.myUserId, SessionTestParams(true)) + + // we wait bob first session to be aware of that session? + commonTestHelper.waitWithLatch { latch -> + commonTestHelper.retryPeriodicallyWithLatch(latch) { + val newSession = bobSession.cryptoService().getUserDevices(aliceSession.myUserId) + .firstOrNull { it.deviceId == aliceNewSession.sessionParams.deviceId } + newSession != null + } } - commonTestHelper.runBlockingTest { - bobSession.roomService().joinRoom(roomAlicePov.roomId, null, emptyList()) + val newEvent = commonTestHelper.sendTextMessage(roomFromBob, "The New", 1).first() + val newEventId = newEvent.eventId + val newEventText = newEvent.getLastMessageContent()!!.body + + // alice should be able to decrypt the new one + cryptoTestHelper.ensureCanDecrypt(listOf(newEventId), aliceNewSession, testData.roomId, listOf(newEventText)) + // but not the first one! + cryptoTestHelper.ensureCannotDecrypt(sentEvents.map { it.eventId }, aliceNewSession, testData.roomId) + + // All should be using the same session id + sentEvents.forEach { + assertEquals(sentEventMegolmSession, it.root.content.toModel<EncryptedEventContent>()!!.sessionId) } + assertEquals(sentEventMegolmSession, newEvent.root.content.toModel<EncryptedEventContent>()!!.sessionId) - // we want to discard alice outbound session - aliceSession.cryptoService().discardOutboundSession(roomAlicePov.roomId) + // Mark the new session as verified + aliceSession.cryptoService() + .verificationService() + .markedLocallyAsManuallyVerified(aliceNewSession.myUserId, aliceNewSession.sessionParams.deviceId!!) - // and now resend a new message to reset index to 0 - commonTestHelper.sendTextMessage(roomAlicePov, "After", 1) + // /!\ Stop initial alice session syncing so that it can't reply + aliceSession.cryptoService().enableKeyGossiping(false) + aliceSession.stopSync() - val roomRoomBobPov = aliceSession.getRoom(roomId) - val beforeJoin = roomRoomBobPov!!.getTimelineEvent(secondEventId) + // Let's now try to request + aliceNewSession.cryptoService().reRequestRoomKeyForEvent(sentEvents.first().root) - var dRes = tryOrNull { - commonTestHelper.runBlockingTest { - bobSession.cryptoService().decryptEvent(beforeJoin!!.root, "") + // Should get a reply from bob and not from alice + commonTestHelper.waitWithLatch { latch -> + commonTestHelper.retryPeriodicallyWithLatch(latch) { + // Log.d("#TEST", "outgoing key requests :${aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().joinToString { it.sessionId ?: "?" }}") + val outgoing = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } + val bobReply = outgoing?.results?.firstOrNull { it.userId == bobSession.myUserId } + val result = bobReply?.result + result != null && result is RequestResult.Success && result.chainIndex == 3 } } - assert(dRes == null) - - // Try to re-ask the keys + val outgoingReq = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } - bobSession.cryptoService().reRequestRoomKeyForEvent(beforeJoin!!.root) + assertNull("We should not have a reply from first session", outgoingReq!!.results.firstOrNull { it.fromDevice == aliceSession.sessionParams.deviceId }) + assertEquals("The request should not be canceled", OutgoingRoomKeyRequestState.SENT, outgoingReq.state) - Thread.sleep(3_000) + // let's wake up alice + aliceSession.cryptoService().enableKeyGossiping(true) + aliceSession.startSync(true) - // With the bug the first session would have improperly reshare that key :/ - dRes = tryOrNull { - commonTestHelper.runBlockingTest { - bobSession.cryptoService().decryptEvent(beforeJoin.root, "") + // We should now get a reply from first session + commonTestHelper.waitWithLatch { latch -> + commonTestHelper.retryPeriodicallyWithLatch(latch) { + val outgoing = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } + val ownDeviceReply = + outgoing?.results?.firstOrNull { it.userId == aliceSession.myUserId && it.fromDevice == aliceSession.sessionParams.deviceId } + val result = ownDeviceReply?.result + result != null && result is RequestResult.Success && result.chainIndex == 0 } } - Log.d("#TEST", "KS: sgould not decrypt that ${beforeJoin.root.getClearContent().toModel<MessageContent>()?.body}") - assert(dRes?.clearEvent == null) + + // It should be in sent then cancel + val outgoing = aliceNewSession.cryptoService().getOutgoingRoomKeyRequests().firstOrNull { it.sessionId == sentEventMegolmSession } + assertEquals("The request should be canceled", OutgoingRoomKeyRequestState.SENT_THEN_CANCELED, outgoing!!.state) + + commonTestHelper.signOutAndClose(aliceNewSession) + commonTestHelper.signOutAndClose(aliceSession) + commonTestHelper.signOutAndClose(bobSession) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt index bad9fd0f68775a6618767cff21546cf059e96f73..cb31a2232fb672c7e54fecbfff1a5c5c91e90d9e 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt @@ -21,7 +21,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import org.junit.Assert import org.junit.FixMethodOrder -import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters @@ -29,6 +28,7 @@ import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.NoOpMatrixCallback import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.RequestResult import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode @@ -46,12 +46,11 @@ import org.matrix.android.sdk.common.TestConstants @LargeTest class WithHeldTests : InstrumentedTest { - private val testHelper = CommonTestHelper(context()) - private val cryptoTestHelper = CryptoTestHelper(testHelper) - @Test - @Ignore("This test will be ignored until it is fixed") fun test_WithHeldUnverifiedReason() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + // ============================= // ARRANGE // ============================= @@ -69,7 +68,6 @@ class WithHeldTests : InstrumentedTest { val roomAlicePOV = aliceSession.getRoom(roomId)!! val bobUnverifiedSession = testHelper.logIntoAccount(bobSession.myUserId, SessionTestParams(true)) - // ============================= // ACT // ============================= @@ -88,6 +86,7 @@ class WithHeldTests : InstrumentedTest { val eventBobPOV = bobUnverifiedSession.getRoom(roomId)?.getTimelineEvent(timelineEvent.eventId)!! + val megolmSessionId = eventBobPOV.root.content.toModel<EncryptedEventContent>()!!.sessionId!! // ============================= // ASSERT // ============================= @@ -103,9 +102,23 @@ class WithHeldTests : InstrumentedTest { val type = (failure as MXCryptoError.Base).errorType val technicalMessage = failure.technicalMessage Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type) - Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage) + Assert.assertEquals("Cause should be unverified", WithHeldCode.UNAUTHORISED.value, technicalMessage) } + // Let's see if the reply we got from bob first session is unverified + testHelper.waitWithLatch { latch -> + testHelper.retryPeriodicallyWithLatch(latch) { + bobUnverifiedSession.cryptoService().getOutgoingRoomKeyRequests() + .firstOrNull { it.sessionId == megolmSessionId } + ?.results + ?.firstOrNull { it.fromDevice == bobSession.sessionParams.deviceId } + ?.result + ?.let { + it as? RequestResult.Failure + } + ?.code == WithHeldCode.UNVERIFIED + } + } // enable back sending to unverified aliceSession.cryptoService().setGlobalBlacklistUnverifiedDevices(false) @@ -130,7 +143,7 @@ class WithHeldTests : InstrumentedTest { val type = (failure as MXCryptoError.Base).errorType val technicalMessage = failure.technicalMessage Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type) - Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage) + Assert.assertEquals("Cause should be unverified", WithHeldCode.UNAUTHORISED.value, technicalMessage) } testHelper.signOutAndClose(aliceSession) @@ -139,21 +152,25 @@ class WithHeldTests : InstrumentedTest { } @Test - @Ignore("This test will be ignored until it is fixed") fun test_WithHeldNoOlm() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = testData.firstSession val bobSession = testData.secondSession!! val aliceInterceptor = testHelper.getTestInterceptor(aliceSession) // Simulate no OTK - aliceInterceptor!!.addRule(MockOkHttpInterceptor.SimpleRule( - "/keys/claim", - 200, - """ + aliceInterceptor!!.addRule( + MockOkHttpInterceptor.SimpleRule( + "/keys/claim", + 200, + """ { "one_time_keys" : {} } """ - )) + ) + ) Log.d("#TEST", "Recovery :${aliceSession.sessionParams.credentials.accessToken}") val roomAlicePov = aliceSession.getRoom(testData.roomId)!! @@ -184,7 +201,10 @@ class WithHeldTests : InstrumentedTest { // Ensure that alice has marked the session to be shared with bob val sessionId = eventBobPOV!!.root.content.toModel<EncryptedEventContent>()!!.sessionId!! - val chainIndex = aliceSession.cryptoService().getSharedWithInfo(testData.roomId, sessionId).getObject(bobSession.myUserId, bobSession.sessionParams.credentials.deviceId) + val chainIndex = aliceSession.cryptoService().getSharedWithInfo(testData.roomId, sessionId).getObject( + bobSession.myUserId, + bobSession.sessionParams.credentials.deviceId + ) Assert.assertEquals("Alice should have marked bob's device for this session", 0, chainIndex) // Add a new device for bob @@ -202,7 +222,10 @@ class WithHeldTests : InstrumentedTest { } } - val chainIndex2 = aliceSession.cryptoService().getSharedWithInfo(testData.roomId, sessionId).getObject(bobSecondSession.myUserId, bobSecondSession.sessionParams.credentials.deviceId) + val chainIndex2 = aliceSession.cryptoService().getSharedWithInfo(testData.roomId, sessionId).getObject( + bobSecondSession.myUserId, + bobSecondSession.sessionParams.credentials.deviceId + ) Assert.assertEquals("Alice should have marked bob's device for this session", 1, chainIndex2) @@ -212,8 +235,10 @@ class WithHeldTests : InstrumentedTest { } @Test - @Ignore("This test will be ignored until it is fixed") fun test_WithHeldKeyRequest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = testData.firstSession val bobSession = testData.secondSession!! @@ -259,5 +284,8 @@ class WithHeldTests : InstrumentedTest { wc?.code == WithHeldCode.UNAUTHORISED } } + + testHelper.signOutAndClose(aliceSession) + testHelper.signOutAndClose(bobSecondSession) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPasswordTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPasswordTest.kt index d035fe5fdea677c056ffcae700542ef97a5b1b8a..9bf08f6fc043d3760847d967cd5450b04924246d 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPasswordTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPasswordTest.kt @@ -54,9 +54,11 @@ class KeysBackupPasswordTest : InstrumentedTest { assertEquals(OlmPkDecryption.privateKeyLength(), generatePrivateKeyResult.privateKey.size) // Reverse operation - val retrievedPrivateKey = retrievePrivateKeyWithPassword(PASSWORD, + val retrievedPrivateKey = retrievePrivateKeyWithPassword( + PASSWORD, generatePrivateKeyResult.salt, - generatePrivateKeyResult.iterations) + generatePrivateKeyResult.iterations + ) assertEquals(OlmPkDecryption.privateKeyLength(), retrievedPrivateKey.size) assertArrayEquals(generatePrivateKeyResult.privateKey, retrievedPrivateKey) @@ -102,9 +104,11 @@ class KeysBackupPasswordTest : InstrumentedTest { assertEquals(OlmPkDecryption.privateKeyLength(), generatePrivateKeyResult.privateKey.size) // Reverse operation, with bad password - val retrievedPrivateKey = retrievePrivateKeyWithPassword(BAD_PASSWORD, + val retrievedPrivateKey = retrievePrivateKeyWithPassword( + BAD_PASSWORD, generatePrivateKeyResult.salt, - generatePrivateKeyResult.iterations) + generatePrivateKeyResult.iterations + ) assertEquals(OlmPkDecryption.privateKeyLength(), retrievedPrivateKey.size) assertByteArrayNotEqual(generatePrivateKeyResult.privateKey, retrievedPrivateKey) @@ -122,9 +126,11 @@ class KeysBackupPasswordTest : InstrumentedTest { assertEquals(OlmPkDecryption.privateKeyLength(), generatePrivateKeyResult.privateKey.size) // Reverse operation, with bad iteration - val retrievedPrivateKey = retrievePrivateKeyWithPassword(PASSWORD, + val retrievedPrivateKey = retrievePrivateKeyWithPassword( + PASSWORD, generatePrivateKeyResult.salt, - 500_001) + 500_001 + ) assertEquals(OlmPkDecryption.privateKeyLength(), retrievedPrivateKey.size) assertByteArrayNotEqual(generatePrivateKeyResult.privateKey, retrievedPrivateKey) @@ -142,9 +148,11 @@ class KeysBackupPasswordTest : InstrumentedTest { assertEquals(OlmPkDecryption.privateKeyLength(), generatePrivateKeyResult.privateKey.size) // Reverse operation, with bad iteration - val retrievedPrivateKey = retrievePrivateKeyWithPassword(PASSWORD, + val retrievedPrivateKey = retrievePrivateKeyWithPassword( + PASSWORD, BAD_SALT, - generatePrivateKeyResult.iterations) + generatePrivateKeyResult.iterations + ) assertEquals(OlmPkDecryption.privateKeyLength(), retrievedPrivateKey.size) assertByteArrayNotEqual(generatePrivateKeyResult.privateKey, retrievedPrivateKey) @@ -168,7 +176,8 @@ class KeysBackupPasswordTest : InstrumentedTest { 116.toByte(), 224.toByte(), 229.toByte(), 224.toByte(), 9.toByte(), 3.toByte(), 178.toByte(), 162.toByte(), 120.toByte(), 23.toByte(), 108.toByte(), 218.toByte(), 22.toByte(), 61.toByte(), 241.toByte(), 200.toByte(), 235.toByte(), 173.toByte(), 236.toByte(), 100.toByte(), 115.toByte(), 247.toByte(), 33.toByte(), 132.toByte(), - 195.toByte(), 154.toByte(), 64.toByte(), 158.toByte(), 184.toByte(), 148.toByte(), 20.toByte(), 85.toByte()) + 195.toByte(), 154.toByte(), 64.toByte(), 158.toByte(), 184.toByte(), 148.toByte(), 20.toByte(), 85.toByte() + ) assertArrayEquals(privateKeyBytes, retrievedPrivateKey) } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt index 3220f161fa499a131b968baff01631372cdf11c0..9136272b1ee7fc396c7a162e797efe1c75a5d72d 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt @@ -24,7 +24,6 @@ import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.FixMethodOrder -import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters @@ -37,7 +36,9 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersio import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrust +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrustSignature import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult @@ -54,18 +55,16 @@ import java.util.concurrent.CountDownLatch @LargeTest class KeysBackupTest : InstrumentedTest { - private val testHelper = CommonTestHelper(context()) - private val cryptoTestHelper = CryptoTestHelper(testHelper) - private val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) - /** * - From doE2ETestWithAliceAndBobInARoomWithEncryptedMessages, we should have no backed up keys * - Check backup keys after having marked one as backed up * - Reset keys backup markers */ @Test - @Ignore("This test will be ignored until it is fixed") fun roomKeysTest_testBackupStore_ok() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() // From doE2ETestWithAliceAndBobInARoomWithEncryptedMessages, we should have no backed up keys @@ -104,6 +103,8 @@ class KeysBackupTest : InstrumentedTest { */ @Test fun prepareKeysBackupVersionTest() { + val testHelper = CommonTestHelper(context()) + val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams) assertNotNull(bobSession.cryptoService().keysBackupService()) @@ -132,7 +133,11 @@ class KeysBackupTest : InstrumentedTest { */ @Test fun createKeysBackupVersionTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams) + cryptoTestHelper.initializeCrossSigning(bobSession) val keysBackup = bobSession.cryptoService().keysBackupService() @@ -147,13 +152,46 @@ class KeysBackupTest : InstrumentedTest { assertFalse(keysBackup.isEnabled) // Create the version - testHelper.doSync<KeysVersion> { + val version = testHelper.doSync<KeysVersion> { keysBackup.createKeysBackupVersion(megolmBackupCreationInfo, it) } // Backup must be enable now assertTrue(keysBackup.isEnabled) + // Check that it's signed with MSK + val versionResult = testHelper.doSync<KeysVersionResult?> { + keysBackup.getVersion(version.version, it) + } + val trust = testHelper.doSync<KeysBackupVersionTrust> { + keysBackup.getKeysBackupTrust(versionResult!!, it) + } + + assertEquals("Should have 2 signatures", 2, trust.signatures.size) + + trust.signatures + .firstOrNull { it is KeysBackupVersionTrustSignature.DeviceSignature } + .let { + assertNotNull("Should be signed by a device", it) + it as KeysBackupVersionTrustSignature.DeviceSignature + }.let { + assertEquals("Should be signed by current device", bobSession.sessionParams.deviceId, it.deviceId) + assertTrue("Signature should be valid", it.valid) + } + + trust.signatures + .firstOrNull { it is KeysBackupVersionTrustSignature.UserSignature } + .let { + assertNotNull("Should be signed by a user", it) + it as KeysBackupVersionTrustSignature.UserSignature + }.let { + val msk = bobSession.cryptoService().crossSigningService() + .getMyCrossSigningKeys()?.masterKey()?.unpaddedBase64PublicKey + assertEquals("Should be signed by my msk 1", msk, it.keyId) + assertEquals("Should be signed by my msk 2", msk, it.cryptoCrossSigningKey?.unpaddedBase64PublicKey) + assertTrue("Signature should be valid", it.valid) + } + stateObserver.stopAndCheckStates(null) testHelper.signOutAndClose(bobSession) } @@ -163,8 +201,11 @@ class KeysBackupTest : InstrumentedTest { * - Check the backup completes */ @Test - @Ignore("This test will be ignored until it is fixed") fun backupAfterCreateKeysBackupVersionTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() keysBackupTestHelper.waitForKeybackUpBatching() @@ -204,8 +245,11 @@ class KeysBackupTest : InstrumentedTest { * Check that backupAllGroupSessions() returns valid data */ @Test - @Ignore("This test will be ignored until it is fixed") fun backupAllGroupSessionsTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() val keysBackup = cryptoTestData.firstSession.cryptoService().keysBackupService() @@ -249,8 +293,11 @@ class KeysBackupTest : InstrumentedTest { * - Compare the decrypted megolm key with the original one */ @Test - @Ignore("This test will be ignored until it is fixed") fun testEncryptAndDecryptKeysBackupData() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() val keysBackup = cryptoTestData.firstSession.cryptoService().keysBackupService() as DefaultKeysBackupService @@ -272,10 +319,12 @@ class KeysBackupTest : InstrumentedTest { assertNotNull(decryption) // - Check decryptKeyBackupData() returns stg val sessionData = keysBackup - .decryptKeyBackupData(keyBackupData, + .decryptKeyBackupData( + keyBackupData, session.olmInboundGroupSession!!.sessionIdentifier(), cryptoTestData.roomId, - decryption!!) + decryption!! + ) assertNotNull(sessionData) // - Compare the decrypted megolm key with the original one keysBackupTestHelper.assertKeysEquals(session.exportKeys(), sessionData) @@ -291,13 +340,17 @@ class KeysBackupTest : InstrumentedTest { * - Restore must be successful */ @Test - @Ignore("This test will be ignored until it is fixed") fun restoreKeysBackupTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null) // - Restore the e2e backup from the homeserver val importRoomKeysResult = testHelper.doSync<ImportRoomKeysResult> { - testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!, + testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey( + testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!, testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey, null, null, @@ -375,8 +428,11 @@ class KeysBackupTest : InstrumentedTest { * - It must be trusted and must have with 2 signatures now */ @Test - @Ignore("This test will be ignored until it is fixed") fun trustKeyBackupVersionTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + // - Do an e2e backup to the homeserver with a recovery key // - And log Alice on a new device val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null) @@ -435,8 +491,11 @@ class KeysBackupTest : InstrumentedTest { * - It must be trusted and must have with 2 signatures now */ @Test - @Ignore("This test will be ignored until it is fixed") fun trustKeyBackupVersionWithRecoveryKeyTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + // - Do an e2e backup to the homeserver with a recovery key // - And log Alice on a new device val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null) @@ -493,8 +552,11 @@ class KeysBackupTest : InstrumentedTest { * - The backup must still be untrusted and disabled */ @Test - @Ignore("This test will be ignored until it is fixed") fun trustKeyBackupVersionWithWrongRecoveryKeyTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + // - Do an e2e backup to the homeserver with a recovery key // - And log Alice on a new device val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null) @@ -535,8 +597,11 @@ class KeysBackupTest : InstrumentedTest { * - It must be trusted and must have with 2 signatures now */ @Test - @Ignore("This test will be ignored until it is fixed") fun trustKeyBackupVersionWithPasswordTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val password = "Password" // - Do an e2e backup to the homeserver with a password @@ -595,8 +660,11 @@ class KeysBackupTest : InstrumentedTest { * - The backup must still be untrusted and disabled */ @Test - @Ignore("This test will be ignored until it is fixed") fun trustKeyBackupVersionWithWrongPasswordTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val password = "Password" val badPassword = "Bad Password" @@ -636,8 +704,11 @@ class KeysBackupTest : InstrumentedTest { * - It must fail */ @Test - @Ignore("This test will be ignored until it is fixed") fun restoreKeysBackupWithAWrongRecoveryKeyTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null) // - Try to restore the e2e backup with a wrong recovery key @@ -670,8 +741,11 @@ class KeysBackupTest : InstrumentedTest { * - Restore must be successful */ @Test - @Ignore("This test will be ignored until it is fixed") fun testBackupWithPassword() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val password = "password" val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(password) @@ -680,7 +754,8 @@ class KeysBackupTest : InstrumentedTest { val steps = ArrayList<StepProgressListener.Step>() val importRoomKeysResult = testHelper.doSync<ImportRoomKeysResult> { - testData.aliceSession2.cryptoService().keysBackupService().restoreKeyBackupWithPassword(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!, + testData.aliceSession2.cryptoService().keysBackupService().restoreKeyBackupWithPassword( + testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!, password, null, null, @@ -726,8 +801,11 @@ class KeysBackupTest : InstrumentedTest { * - It must fail */ @Test - @Ignore("This test will be ignored until it is fixed") fun restoreKeysBackupWithAWrongPasswordTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val password = "password" val wrongPassword = "passw0rd" @@ -763,15 +841,19 @@ class KeysBackupTest : InstrumentedTest { * - Restore must be successful */ @Test - @Ignore("This test will be ignored until it is fixed") fun testUseRecoveryKeyToRestoreAPasswordBasedKeysBackup() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val password = "password" val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(password) // - Restore the e2e backup with the recovery key. val importRoomKeysResult = testHelper.doSync<ImportRoomKeysResult> { - testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!, + testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey( + testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!, testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey, null, null, @@ -792,8 +874,11 @@ class KeysBackupTest : InstrumentedTest { * - It must fail */ @Test - @Ignore("This test will be ignored until it is fixed") fun testUsePasswordToRestoreARecoveryKeyBasedKeysBackup() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null) // - Try to restore the e2e backup with a password @@ -824,8 +909,11 @@ class KeysBackupTest : InstrumentedTest { * - Check the returned KeysVersionResult is trusted */ @Test - @Ignore("This test will be ignored until it is fixed") fun testIsKeysBackupTrusted() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + // - Create a backup version val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() @@ -850,7 +938,7 @@ class KeysBackupTest : InstrumentedTest { assertTrue(keysBackupVersionTrust.usable) assertEquals(1, keysBackupVersionTrust.signatures.size) - val signature = keysBackupVersionTrust.signatures[0] + val signature = keysBackupVersionTrust.signatures[0] as KeysBackupVersionTrustSignature.DeviceSignature assertTrue(signature.valid) assertNotNull(signature.device) assertEquals(cryptoTestData.firstSession.cryptoService().getMyDevice().deviceId, signature.deviceId) @@ -860,66 +948,6 @@ class KeysBackupTest : InstrumentedTest { cryptoTestData.cleanUp(testHelper) } - /** - * Check backup starts automatically if there is an existing and compatible backup - * version on the homeserver. - * - Create a backup version - * - Restart alice session - * -> The new alice session must back up to the same version - */ - @Test - @Ignore("This test will be ignored until it is fixed") - fun testCheckAndStartKeysBackupWhenRestartingAMatrixSession() { - // - Create a backup version - val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() - - val keysBackup = cryptoTestData.firstSession.cryptoService().keysBackupService() - - val stateObserver = StateObserver(keysBackup) - - assertFalse(keysBackup.isEnabled) - - val keyBackupCreationInfo = keysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup) - - assertTrue(keysBackup.isEnabled) - - // - Restart alice session - // - Log Alice on a new device - val aliceSession2 = testHelper.logIntoAccount(cryptoTestData.firstSession.myUserId, KeysBackupTestConstants.defaultSessionParamsWithInitialSync) - - cryptoTestData.cleanUp(testHelper) - - val keysBackup2 = aliceSession2.cryptoService().keysBackupService() - - val stateObserver2 = StateObserver(keysBackup2) - - // -> The new alice session must back up to the same version - val latch = CountDownLatch(1) - var count = 0 - keysBackup2.addListener(object : KeysBackupStateListener { - override fun onStateChange(newState: KeysBackupState) { - // Check the backup completes - if (newState == KeysBackupState.ReadyToBackUp) { - count++ - - if (count == 2) { - // Remove itself from the list of listeners - keysBackup2.removeListener(this) - - latch.countDown() - } - } - } - }) - testHelper.await(latch) - - assertEquals(keyBackupCreationInfo.version, keysBackup2.currentBackupVersion) - - stateObserver.stopAndCheckStates(null) - stateObserver2.stopAndCheckStates(null) - testHelper.signOutAndClose(aliceSession2) - } - /** * Check WrongBackUpVersion state * @@ -930,6 +958,10 @@ class KeysBackupTest : InstrumentedTest { */ @Test fun testBackupWhenAnotherBackupWasCreated() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + // - Create a backup version val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() @@ -1000,8 +1032,11 @@ class KeysBackupTest : InstrumentedTest { * -> It must success */ @Test - @Ignore("This test will be ignored until it is fixed") fun testBackupAfterVerifyingADevice() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + // - Create a backup version val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() @@ -1034,6 +1069,8 @@ class KeysBackupTest : InstrumentedTest { // - Try to backup all in aliceSession2, it must fail val keysBackup2 = aliceSession2.cryptoService().keysBackupService() + assertFalse("Backup should not be enabled", keysBackup2.isEnabled) + val stateObserver2 = StateObserver(keysBackup2) var isSuccessful = false @@ -1051,11 +1088,15 @@ class KeysBackupTest : InstrumentedTest { assertFalse(isSuccessful) // Backup state must be NotTrusted - assertEquals(KeysBackupState.NotTrusted, keysBackup2.state) - assertFalse(keysBackup2.isEnabled) + assertEquals("Backup state must be NotTrusted", KeysBackupState.NotTrusted, keysBackup2.state) + assertFalse("Backup should not be enabled", keysBackup2.isEnabled) // - Validate the old device from the new one - aliceSession2.cryptoService().setDeviceVerification(DeviceTrustLevel(crossSigningVerified = false, locallyVerified = true), aliceSession2.myUserId, oldDeviceId) + aliceSession2.cryptoService().setDeviceVerification( + DeviceTrustLevel(crossSigningVerified = false, locallyVerified = true), + aliceSession2.myUserId, + oldDeviceId + ) // -> Backup should automatically enable on the new device val latch4 = CountDownLatch(1) @@ -1094,6 +1135,10 @@ class KeysBackupTest : InstrumentedTest { */ @Test fun deleteKeysBackupTest() { + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) + val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper) + // - Create a backup version val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages() diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt index ac83cb88821dbab69503276b023d547468d41079..2220536e28c7579d8cf5af4367b425e2deb494a4 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt @@ -88,10 +88,12 @@ internal class KeysBackupTestHelper( stateObserver.stopAndCheckStates(null) - return KeysBackupScenarioData(cryptoTestData, + return KeysBackupScenarioData( + cryptoTestData, aliceKeys, prepareKeysBackupDataResult, - aliceSession2) + aliceSession2 + ) } fun prepareAndCreateKeysBackupData(keysBackup: KeysBackupService, @@ -104,14 +106,14 @@ internal class KeysBackupTestHelper( Assert.assertNotNull(megolmBackupCreationInfo) - Assert.assertFalse(keysBackup.isEnabled) + Assert.assertFalse("Key backup should not be enabled before creation", keysBackup.isEnabled) // Create the version val keysVersion = testHelper.doSync<KeysVersion> { keysBackup.createKeysBackupVersion(megolmBackupCreationInfo, it) } - Assert.assertNotNull(keysVersion.version) + Assert.assertNotNull("Key backup version should not be null", keysVersion.version) // Backup must be enable now Assert.assertTrue(keysBackup.isEnabled) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt index a882f690132c3da214982a50d10f8150e7f79675..c758050fc9548f4a1fb926462e7ffb2e6c211279 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt @@ -207,14 +207,16 @@ class QuadSTests : InstrumentedTest { // Assert that can decrypt with both keys testHelper.runBlockingTest { - aliceSession.sharedSecretStorageService().getSecret("my.secret", + aliceSession.sharedSecretStorageService().getSecret( + "my.secret", keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)!! ) } testHelper.runBlockingTest { - aliceSession.sharedSecretStorageService().getSecret("my.secret", + aliceSession.sharedSecretStorageService().getSecret( + "my.secret", keyId2, RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)!! ) @@ -245,13 +247,15 @@ class QuadSTests : InstrumentedTest { testHelper.runBlockingTest { try { - aliceSession.sharedSecretStorageService().getSecret("my.secret", + aliceSession.sharedSecretStorageService().getSecret( + "my.secret", keyId1, RawBytesKeySpec.fromPassphrase( "A bad passphrase", key1Info.content?.passphrase?.salt ?: "", key1Info.content?.passphrase?.iterations ?: 0, - null) + null + ) ) } catch (throwable: Throwable) { assert(throwable is SharedSecretStorageError.BadMac) @@ -260,13 +264,15 @@ class QuadSTests : InstrumentedTest { // Now try with correct key testHelper.runBlockingTest { - aliceSession.sharedSecretStorageService().getSecret("my.secret", + aliceSession.sharedSecretStorageService().getSecret( + "my.secret", keyId1, RawBytesKeySpec.fromPassphrase( passphrase, key1Info.content?.passphrase?.salt ?: "", key1Info.content?.passphrase?.iterations ?: 0, - null) + null + ) ) } @@ -321,7 +327,8 @@ class QuadSTests : InstrumentedTest { keyId, passphrase, emptyKeySigner, - null) + null + ) } assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId") diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt index 14e659e2b606bfa8b434b078206ff95db59d2347..2892cf846411d3dcaf273713d1184de254b02c57 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt @@ -75,10 +75,12 @@ class SASTest : InstrumentedTest { } bobVerificationService.addListener(bobListener) - val txID = aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, + val txID = aliceVerificationService.beginKeyVerification( + VerificationMethod.SAS, bobSession.myUserId, bobSession.cryptoService().getMyDevice().deviceId, - null) + null + ) assertNotNull("Alice should have a started transaction", txID) val aliceKeyTx = aliceVerificationService.getExistingTransaction(bobSession.myUserId, txID!!) @@ -467,8 +469,10 @@ class SASTest : InstrumentedTest { val aliceTx = aliceVerificationService.getExistingTransaction(bobUserId, verificationSAS!!) as SASDefaultVerificationTransaction val bobTx = bobVerificationService.getExistingTransaction(aliceSession.myUserId, verificationSAS) as SASDefaultVerificationTransaction - assertEquals("Should have same SAS", aliceTx.getShortCodeRepresentation(SasMode.DECIMAL), - bobTx.getShortCodeRepresentation(SasMode.DECIMAL)) + assertEquals( + "Should have same SAS", aliceTx.getShortCodeRepresentation(SasMode.DECIMAL), + bobTx.getShortCodeRepresentation(SasMode.DECIMAL) + ) cryptoTestData.cleanUp(testHelper) } @@ -544,7 +548,8 @@ class SASTest : InstrumentedTest { // Assert that devices are verified val bobDeviceInfoFromAlicePOV: CryptoDeviceInfo? = aliceSession.cryptoService().getDeviceInfo(bobUserId, bobDeviceId) - val aliceDeviceInfoFromBobPOV: CryptoDeviceInfo? = bobSession.cryptoService().getDeviceInfo(aliceSession.myUserId, aliceSession.cryptoService().getMyDevice().deviceId) + val aliceDeviceInfoFromBobPOV: CryptoDeviceInfo? = + bobSession.cryptoService().getDeviceInfo(aliceSession.myUserId, aliceSession.cryptoService().getMyDevice().deviceId) assertTrue("alice device should be verified from bob point of view", aliceDeviceInfoFromBobPOV!!.isVerified) assertTrue("bob device should be verified from alice point of view", bobDeviceInfoFromAlicePOV!!.isVerified) @@ -611,14 +616,16 @@ class SASTest : InstrumentedTest { requestID!!, cryptoTestData.roomId, bobSession.myUserId, - bobSession.sessionParams.deviceId!!) + bobSession.sessionParams.deviceId!! + ) bobVerificationService.beginKeyVerificationInDMs( VerificationMethod.SAS, requestID!!, cryptoTestData.roomId, aliceSession.myUserId, - aliceSession.sessionParams.deviceId!!) + aliceSession.sessionParams.deviceId!! + ) // we should reach SHOW SAS on both var alicePovTx: SasVerificationTransaction? diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/QrCodeTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/QrCodeTest.kt index 76bf6dc0408aa82365e5c840cb195eb46e118536..d7b4d636fc9be340fb7cb52c6e4da69dcbff5aa9 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/QrCodeTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/QrCodeTest.kt @@ -37,7 +37,8 @@ class QrCodeTest : InstrumentedTest { sharedSecret = "MTIzNDU2Nzg" ) - private val value1 = "MATRIX\u0002\u0000\u0000\u000DMaTransaction\u0092Ñ0qCú²Ãq\u0087á®\u0013à \u0098\u0091\u000DÇéoÃ\"_²lq]hC«¢UMynd¤Ù.ô\u0091XäÃ\u0094ê\u008B«\u009Døl\u000F¿+\u008CË\u0014¤®õÃ\u008BAÂ¥12345678" + private val value1 = + "MATRIX\u0002\u0000\u0000\u000DMaTransaction\u0092Ñ0qCú²Ãq\u0087á®\u0013à \u0098\u0091\u000DÇéoÃ\"_²lq]hC«¢UMynd¤Ù.ô\u0091XäÃ\u0094ê\u008B«\u009Døl\u000F¿+\u008CË\u0014¤®õÃ\u008BAÂ¥12345678" private val qrCode2 = QrCodeData.SelfVerifyingMasterKeyTrusted( transactionId = "MaTransaction", @@ -46,7 +47,8 @@ class QrCodeTest : InstrumentedTest { sharedSecret = "MTIzNDU2Nzg" ) - private val value2 = "MATRIX\u0002\u0001\u0000\u000DMaTransaction\u0092Ñ0qCú²Ãq\u0087á®\u0013à \u0098\u0091\u000DÇéoÃ\"_²lq]hC«¢UMynd¤Ù.ô\u0091XäÃ\u0094ê\u008B«\u009Døl\u000F¿+\u008CË\u0014¤®õÃ\u008BAÂ¥12345678" + private val value2 = + "MATRIX\u0002\u0001\u0000\u000DMaTransaction\u0092Ñ0qCú²Ãq\u0087á®\u0013à \u0098\u0091\u000DÇéoÃ\"_²lq]hC«¢UMynd¤Ù.ô\u0091XäÃ\u0094ê\u008B«\u009Døl\u000F¿+\u008CË\u0014¤®õÃ\u008BAÂ¥12345678" private val qrCode3 = QrCodeData.SelfVerifyingMasterKeyNotTrusted( transactionId = "MaTransaction", @@ -55,7 +57,8 @@ class QrCodeTest : InstrumentedTest { sharedSecret = "MTIzNDU2Nzg" ) - private val value3 = "MATRIX\u0002\u0002\u0000\u000DMaTransactionMynd¤Ù.ô\u0091XäÃ\u0094ê\u008B«\u009Døl\u000F¿+\u008CË\u0014¤®õÃ\u008BAÂ¥\u0092Ñ0qCú²Ãq\u0087á®\u0013à \u0098\u0091\u000DÇéoÃ\"_²lq]hC«¢U12345678" + private val value3 = + "MATRIX\u0002\u0002\u0000\u000DMaTransactionMynd¤Ù.ô\u0091XäÃ\u0094ê\u008B«\u009Døl\u000F¿+\u008CË\u0014¤®õÃ\u008BAÂ¥\u0092Ñ0qCú²Ãq\u0087á®\u0013à \u0098\u0091\u000DÇéoÃ\"_²lq]hC«¢U12345678" private val sharedSecretByteArray = "12345678".toByteArray(Charsets.ISO_8859_1) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt index 374d709505311572790f0019f01d2b8dddadde79..df3b2ffe276d2e982eb79963add0dcec97ad1d40 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt @@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.crypto.verification.qrcode import androidx.test.ext.junit.runners.AndroidJUnit4 import org.amshove.kluent.shouldBe import org.junit.FixMethodOrder -import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters @@ -40,7 +39,6 @@ import kotlin.coroutines.resume @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.JVM) -@Ignore("This test is flaky ; see issue #5449") class VerificationTest : InstrumentedTest { data class ExpectedResult( @@ -175,7 +173,8 @@ class VerificationTest : InstrumentedTest { ) ) } - }, callback) + }, callback + ) } testHelper.doSync<Unit> { callback -> @@ -191,7 +190,8 @@ class VerificationTest : InstrumentedTest { ) ) } - }, callback) + }, callback + ) } val aliceVerificationService = aliceSession.cryptoService().verificationService() diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt index ef98ed22c7112328b79ca1512ef0f93170dfc4eb..acb23bf72382776d55b9f2f68eb352220417eaeb 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt @@ -71,10 +71,12 @@ class MarkdownParserTest : InstrumentedTest { testIdentity("") testIdentity("a") testIdentity("1") - testIdentity("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et " + - "dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea com" + - "modo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pari" + - "atur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") + testIdentity( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et " + + "dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea com" + + "modo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pari" + + "atur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." + ) } @Test @@ -294,16 +296,20 @@ class MarkdownParserTest : InstrumentedTest { "$markdownPattern$name$markdownPattern" .let { markdownParser.parse(it) - .expect(expectedText = it, - expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag>") + .expect( + expectedText = it, + expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag>" + ) } // Test twice the same tag "$markdownPattern$name$markdownPattern and $markdownPattern$name bis$markdownPattern" .let { markdownParser.parse(it) - .expect(expectedText = it, - expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag> and <$htmlExpectedTag>$name bis</$htmlExpectedTag>") + .expect( + expectedText = it, + expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag> and <$htmlExpectedTag>$name bis</$htmlExpectedTag>" + ) } val textBefore = "a" @@ -313,48 +319,60 @@ class MarkdownParserTest : InstrumentedTest { "$textBefore$markdownPattern$name$markdownPattern" .let { markdownParser.parse(it) - .expect(expectedText = it, - expectedFormattedText = "$textBefore<$htmlExpectedTag>$name</$htmlExpectedTag>") + .expect( + expectedText = it, + expectedFormattedText = "$textBefore<$htmlExpectedTag>$name</$htmlExpectedTag>" + ) } // With text before and space "$textBefore $markdownPattern$name$markdownPattern" .let { markdownParser.parse(it) - .expect(expectedText = it, - expectedFormattedText = "$textBefore <$htmlExpectedTag>$name</$htmlExpectedTag>") + .expect( + expectedText = it, + expectedFormattedText = "$textBefore <$htmlExpectedTag>$name</$htmlExpectedTag>" + ) } // With sticked text after "$markdownPattern$name$markdownPattern$textAfter" .let { markdownParser.parse(it) - .expect(expectedText = it, - expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag>$textAfter") + .expect( + expectedText = it, + expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag>$textAfter" + ) } // With space and text after "$markdownPattern$name$markdownPattern $textAfter" .let { markdownParser.parse(it) - .expect(expectedText = it, - expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag> $textAfter") + .expect( + expectedText = it, + expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag> $textAfter" + ) } // With sticked text before and text after "$textBefore$markdownPattern$name$markdownPattern$textAfter" .let { markdownParser.parse(it) - .expect(expectedText = it, - expectedFormattedText = "a<$htmlExpectedTag>$name</$htmlExpectedTag>$textAfter") + .expect( + expectedText = it, + expectedFormattedText = "a<$htmlExpectedTag>$name</$htmlExpectedTag>$textAfter" + ) } // With text before and after, with spaces "$textBefore $markdownPattern$name$markdownPattern $textAfter" .let { markdownParser.parse(it) - .expect(expectedText = it, - expectedFormattedText = "$textBefore <$htmlExpectedTag>$name</$htmlExpectedTag> $textAfter") + .expect( + expectedText = it, + expectedFormattedText = "$textBefore <$htmlExpectedTag>$name</$htmlExpectedTag> $textAfter" + ) } } @@ -366,16 +384,20 @@ class MarkdownParserTest : InstrumentedTest { "$markdownPattern$name\n$name$markdownPattern" .let { markdownParser.parse(it) - .expect(expectedText = it, - expectedFormattedText = "<$htmlExpectedTag>$name$softBreak$name</$htmlExpectedTag>") + .expect( + expectedText = it, + expectedFormattedText = "<$htmlExpectedTag>$name$softBreak$name</$htmlExpectedTag>" + ) } // With new line between two blocks "$markdownPattern$name$markdownPattern\n$markdownPattern$name$markdownPattern" .let { markdownParser.parse(it) - .expect(expectedText = it, - expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag><br /><$htmlExpectedTag>$name</$htmlExpectedTag>") + .expect( + expectedText = it, + expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag><br /><$htmlExpectedTag>$name</$htmlExpectedTag>" + ) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/util/JsonCanonicalizerTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/util/JsonCanonicalizerTest.kt index d38afc6b62f53a7092d00fb4cb1b4a02db58f3f4..67eafea55d998b1eccd7f11e2840b6eb02fe3024 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/util/JsonCanonicalizerTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/util/JsonCanonicalizerTest.kt @@ -39,27 +39,35 @@ internal class JsonCanonicalizerTest : InstrumentedTest { """{"a":["c":"b","d":"e"]}""", """{"a":["d":"b","c":"e"]}""" ).forEach { - assertEquals(it, - JsonCanonicalizer.canonicalize(it)) + assertEquals( + it, + JsonCanonicalizer.canonicalize(it) + ) } } @Test fun reorderTest() { - assertEquals("""{"a":true,"b":false}""", - JsonCanonicalizer.canonicalize("""{"b":false,"a":true}""")) + assertEquals( + """{"a":true,"b":false}""", + JsonCanonicalizer.canonicalize("""{"b":false,"a":true}""") + ) } @Test fun realSampleTest() { - assertEquals("""{"algorithms":["m.megolm.v1.aes-sha2","m.olm.v1.curve25519-aes-sha2"],"device_id":"VSCUNFSOUI","keys":{"curve25519:VSCUNFSOUI":"utyOjnhiQ73qNhi9HlN0OgWIowe5gthTS8r0r9TcJ3o","ed25519:VSCUNFSOUI":"qNhEt+Yggaajet0hX\/FjTRLfySgs65ldYyomm7PIx6U"},"user_id":"@benoitx:matrix.org"}""", - JsonCanonicalizer.canonicalize("""{"algorithms":["m.megolm.v1.aes-sha2","m.olm.v1.curve25519-aes-sha2"],"device_id":"VSCUNFSOUI","user_id":"@benoitx:matrix.org","keys":{"curve25519:VSCUNFSOUI":"utyOjnhiQ73qNhi9HlN0OgWIowe5gthTS8r0r9TcJ3o","ed25519:VSCUNFSOUI":"qNhEt+Yggaajet0hX/FjTRLfySgs65ldYyomm7PIx6U"}}""")) + assertEquals( + """{"algorithms":["m.megolm.v1.aes-sha2","m.olm.v1.curve25519-aes-sha2"],"device_id":"VSCUNFSOUI","keys":{"curve25519:VSCUNFSOUI":"utyOjnhiQ73qNhi9HlN0OgWIowe5gthTS8r0r9TcJ3o","ed25519:VSCUNFSOUI":"qNhEt+Yggaajet0hX\/FjTRLfySgs65ldYyomm7PIx6U"},"user_id":"@benoitx:matrix.org"}""", + JsonCanonicalizer.canonicalize("""{"algorithms":["m.megolm.v1.aes-sha2","m.olm.v1.curve25519-aes-sha2"],"device_id":"VSCUNFSOUI","user_id":"@benoitx:matrix.org","keys":{"curve25519:VSCUNFSOUI":"utyOjnhiQ73qNhi9HlN0OgWIowe5gthTS8r0r9TcJ3o","ed25519:VSCUNFSOUI":"qNhEt+Yggaajet0hX/FjTRLfySgs65ldYyomm7PIx6U"}}""") + ) } @Test fun doubleQuoteTest() { - assertEquals("{\"a\":\"\\\"\"}", - JsonCanonicalizer.canonicalize("{\"a\":\"\\\"\"}")) + assertEquals( + "{\"a\":\"\\\"\"}", + JsonCanonicalizer.canonicalize("{\"a\":\"\\\"\"}") + ) } /* ========================================================================================== @@ -68,38 +76,52 @@ internal class JsonCanonicalizerTest : InstrumentedTest { @Test fun matrixOrg001Test() { - assertEquals("""{}""", - JsonCanonicalizer.canonicalize("""{}""")) + assertEquals( + """{}""", + JsonCanonicalizer.canonicalize("""{}""") + ) } @Test fun matrixOrg002Test() { - assertEquals("""{"one":1,"two":"Two"}""", - JsonCanonicalizer.canonicalize("""{ + assertEquals( + """{"one":1,"two":"Two"}""", + JsonCanonicalizer.canonicalize( + """{ "one": 1, "two": "Two" -}""")) +}""" + ) + ) } @Test fun matrixOrg003Test() { - assertEquals("""{"a":"1","b":"2"}""", - JsonCanonicalizer.canonicalize("""{ + assertEquals( + """{"a":"1","b":"2"}""", + JsonCanonicalizer.canonicalize( + """{ "b": "2", "a": "1" -}""")) +}""" + ) + ) } @Test fun matrixOrg004Test() { - assertEquals("""{"a":"1","b":"2"}""", - JsonCanonicalizer.canonicalize("""{"b":"2","a":"1"}""")) + assertEquals( + """{"a":"1","b":"2"}""", + JsonCanonicalizer.canonicalize("""{"b":"2","a":"1"}""") + ) } @Test fun matrixOrg005Test() { - assertEquals("""{"auth":{"mxid":"@john.doe:example.com","profile":{"display_name":"John Doe","three_pids":[{"address":"john.doe@example.org","medium":"email"},{"address":"123456789","medium":"msisdn"}]},"success":true}}""", - JsonCanonicalizer.canonicalize("""{ + assertEquals( + """{"auth":{"mxid":"@john.doe:example.com","profile":{"display_name":"John Doe","three_pids":[{"address":"john.doe@example.org","medium":"email"},{"address":"123456789","medium":"msisdn"}]},"success":true}}""", + JsonCanonicalizer.canonicalize( + """{ "auth": { "success": true, "mxid": "@john.doe:example.com", @@ -117,37 +139,53 @@ internal class JsonCanonicalizerTest : InstrumentedTest { ] } } -}""")) +}""" + ) + ) } @Test fun matrixOrg006Test() { - assertEquals("""{"a":"日本語"}""", - JsonCanonicalizer.canonicalize("""{ + assertEquals( + """{"a":"日本語"}""", + JsonCanonicalizer.canonicalize( + """{ "a": "日本語" -}""")) +}""" + ) + ) } @Test fun matrixOrg007Test() { - assertEquals("""{"æ—¥":1,"本":2}""", - JsonCanonicalizer.canonicalize("""{ + assertEquals( + """{"æ—¥":1,"本":2}""", + JsonCanonicalizer.canonicalize( + """{ "本": 2, "æ—¥": 1 -}""")) +}""" + ) + ) } @Test fun matrixOrg008Test() { - assertEquals("""{"a":"æ—¥"}""", - JsonCanonicalizer.canonicalize("{\"a\": \"\u65E5\"}")) + assertEquals( + """{"a":"æ—¥"}""", + JsonCanonicalizer.canonicalize("{\"a\": \"\u65E5\"}") + ) } @Test fun matrixOrg009Test() { - assertEquals("""{"a":null}""", - JsonCanonicalizer.canonicalize("""{ + assertEquals( + """{"a":null}""", + JsonCanonicalizer.canonicalize( + """{ "a": null -}""")) +}""" + ) + ) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/ordering/StringOrderTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/ordering/StringOrderTest.kt index 728986441a0589e8f5dbd0af0f716b510bf79049..b5870ebf69798c6274ee89a939f849bbedd0ebaf 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/ordering/StringOrderTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/ordering/StringOrderTest.kt @@ -26,9 +26,18 @@ class StringOrderTest { @Test fun testbasing() { - assertEquals("a", StringOrderUtils.baseToString(StringOrderUtils.stringToBase("a", StringOrderUtils.DEFAULT_ALPHABET), StringOrderUtils.DEFAULT_ALPHABET)) - assertEquals("element", StringOrderUtils.baseToString(StringOrderUtils.stringToBase("element", StringOrderUtils.DEFAULT_ALPHABET), StringOrderUtils.DEFAULT_ALPHABET)) - assertEquals("matrix", StringOrderUtils.baseToString(StringOrderUtils.stringToBase("matrix", StringOrderUtils.DEFAULT_ALPHABET), StringOrderUtils.DEFAULT_ALPHABET)) + assertEquals( + "a", + StringOrderUtils.baseToString(StringOrderUtils.stringToBase("a", StringOrderUtils.DEFAULT_ALPHABET), StringOrderUtils.DEFAULT_ALPHABET) + ) + assertEquals( + "element", + StringOrderUtils.baseToString(StringOrderUtils.stringToBase("element", StringOrderUtils.DEFAULT_ALPHABET), StringOrderUtils.DEFAULT_ALPHABET) + ) + assertEquals( + "matrix", + StringOrderUtils.baseToString(StringOrderUtils.stringToBase("matrix", StringOrderUtils.DEFAULT_ALPHABET), StringOrderUtils.DEFAULT_ALPHABET) + ) } @Test diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt index f6e08a576e20b3fcf29a88f2689ec05d6bd635cc..a2984dd27e2de8d27d082e5df6579049a8f3e456 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt @@ -59,7 +59,8 @@ class ThreadMessagingTest : InstrumentedTest { val sentMessages = commonTestHelper.sendTextMessage( room = aliceRoom, message = textMessage, - nbOfMessages = 1) + nbOfMessages = 1 + ) val initMessage = sentMessages.first() @@ -73,7 +74,8 @@ class ThreadMessagingTest : InstrumentedTest { room = aliceRoom, message = "Reply In the above thread", numberOfMessages = 1, - rootThreadEventId = initMessage.root.eventId.orEmpty()) + rootThreadEventId = initMessage.root.eventId.orEmpty() + ) val replyInThread = repliesInThread.first() replyInThread.root.isThread().shouldBeTrue() @@ -116,7 +118,8 @@ class ThreadMessagingTest : InstrumentedTest { val sentMessages = commonTestHelper.sendTextMessage( room = aliceRoom, message = textMessage, - nbOfMessages = 1) + nbOfMessages = 1 + ) val initMessage = sentMessages.first() @@ -134,7 +137,8 @@ class ThreadMessagingTest : InstrumentedTest { room = bobRoom, message = "Reply In the above thread", numberOfMessages = 1, - rootThreadEventId = initMessage.root.eventId.orEmpty()) + rootThreadEventId = initMessage.root.eventId.orEmpty() + ) val replyInThread = repliesInThread.first() replyInThread.root.isThread().shouldBeTrue() @@ -190,7 +194,8 @@ class ThreadMessagingTest : InstrumentedTest { val sentMessages = commonTestHelper.sendTextMessage( room = aliceRoom, message = textMessage, - nbOfMessages = 5) + nbOfMessages = 5 + ) sentMessages.forEach { it.root.isThread().shouldBeFalse() @@ -206,7 +211,8 @@ class ThreadMessagingTest : InstrumentedTest { room = aliceRoom, message = "Reply In the above thread", numberOfMessages = 40, - rootThreadEventId = selectedInitMessage.root.eventId.orEmpty()) + rootThreadEventId = selectedInitMessage.root.eventId.orEmpty() + ) repliesInThread.forEach { it.root.isThread().shouldBeTrue() @@ -253,7 +259,8 @@ class ThreadMessagingTest : InstrumentedTest { val sentMessages = commonTestHelper.sendTextMessage( room = aliceRoom, message = textMessage, - nbOfMessages = 5) + nbOfMessages = 5 + ) sentMessages.forEach { it.root.isThread().shouldBeFalse() @@ -270,7 +277,8 @@ class ThreadMessagingTest : InstrumentedTest { room = aliceRoom, message = "Alice reply In the above second thread message", numberOfMessages = 35, - rootThreadEventId = secondMessage.root.eventId.orEmpty()) + rootThreadEventId = secondMessage.root.eventId.orEmpty() + ) // Let's reply in timeline to that message from another user val bobSession = cryptoTestData.secondSession!! @@ -282,14 +290,16 @@ class ThreadMessagingTest : InstrumentedTest { room = bobRoom, message = "Bob reply In the above first thread message", numberOfMessages = 42, - rootThreadEventId = firstMessage.root.eventId.orEmpty()) + rootThreadEventId = firstMessage.root.eventId.orEmpty() + ) // Bob will also reply in second thread 5 times val bobThreadRepliesInSecondMessage = commonTestHelper.replyInThreadMessage( room = bobRoom, message = "Another Bob reply In the above second thread message", numberOfMessages = 20, - rootThreadEventId = secondMessage.root.eventId.orEmpty()) + rootThreadEventId = secondMessage.root.eventId.orEmpty() + ) aliceThreadRepliesInSecondMessage.forEach { it.root.isThread().shouldBeTrue() diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt index 27d3fdc85615fe8e106ac69868560b04322ab088..94b2ba55a3456bdbacd1e47958b96a55b6a0bd0f 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt @@ -68,7 +68,8 @@ internal class ChunkEntityTest : InstrumentedTest { roomId = ROOM_ID, eventEntity = fakeEvent, direction = PaginationDirection.FORWARDS, - roomMemberContentsByUser = emptyMap()) + roomMemberContentsByUser = emptyMap() + ) chunk.timelineEvents.size shouldBeEqualTo 1 } } @@ -84,12 +85,14 @@ internal class ChunkEntityTest : InstrumentedTest { roomId = ROOM_ID, eventEntity = fakeEvent, direction = PaginationDirection.FORWARDS, - roomMemberContentsByUser = emptyMap()) + roomMemberContentsByUser = emptyMap() + ) chunk.addTimelineEvent( roomId = ROOM_ID, eventEntity = fakeEvent, direction = PaginationDirection.FORWARDS, - roomMemberContentsByUser = emptyMap()) + roomMemberContentsByUser = emptyMap() + ) chunk.timelineEvents.size shouldBeEqualTo 1 } } @@ -162,7 +165,8 @@ internal class ChunkEntityTest : InstrumentedTest { roomId = roomId, eventEntity = fakeEvent, direction = direction, - roomMemberContentsByUser = emptyMap()) + roomMemberContentsByUser = emptyMap() + ) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt index 3864ea1cd1b28941f485677c719e2deff006a6af..d5b4a07fc0fd19a43c625acbfeb15c14a8c0d12a 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt @@ -71,7 +71,8 @@ class TimelineForwardPaginationTest : InstrumentedTest { val sentMessages = commonTestHelper.sendTextMessage( roomFromAlicePOV, message, - numberOfMessagesToSend) + numberOfMessagesToSend + ) // Alice clear the cache and restart the sync commonTestHelper.clearCacheAndSync(aliceSession) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt index 5d09b74e6c3f8773ef10ffea907996418dfd8524..6e5fed8df9f2f2c11125f525f80fc0e07ca6db14 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt @@ -94,7 +94,8 @@ class TimelinePreviousLastForwardTest : InstrumentedTest { val firstMessageFromAliceId = commonTestHelper.sendTextMessage( roomFromAlicePOV, firstMessage, - 30) + 30 + ) .last() .eventId @@ -130,7 +131,8 @@ class TimelinePreviousLastForwardTest : InstrumentedTest { commonTestHelper.sendTextMessage( roomFromAlicePOV, secondMessage, - 30) + 30 + ) // Bob start to sync bobSession.startSync(true) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt index 251b2c614cd7302c1738fb7ba7ee86f0506b5df8..42f710d7cf431f2a90f14fb56e8b61b05cea4674 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt @@ -64,7 +64,8 @@ class TimelineSimpleBackPaginationTest : InstrumentedTest { commonTestHelper.sendTextMessage( roomFromAlicePOV, message, - numberOfMessagesToSent) + numberOfMessagesToSent + ) val bobTimeline = roomFromBobPOV.timelineService().createTimeline(null, TimelineSettings(30)) bobTimeline.start() diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt index ab0bbe7f73f9450fc913577e3f3c1c417bbb93de..e17b7efbd6d9d348c39ebb02ba9c99fc625b1bdc 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt @@ -85,7 +85,8 @@ class SearchMessagesTest : InstrumentedTest { commonTestHelper.sendTextMessage( roomFromAlicePOV, MESSAGE, - 2) + 2 + ) val data = commonTestHelper.runBlockingTest { block.invoke(cryptoTestData) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt index d2c8b52fc7693ac08e1eab3c4c7e9b953a2395ab..6a17cb74add602e49100d148a961a6615fe2c450 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt @@ -177,21 +177,27 @@ class SpaceHierarchyTest : InstrumentedTest { val commonTestHelper = CommonTestHelper(context()) val session = commonTestHelper.createAccount("John", SessionTestParams(true)) - val spaceAInfo = createPublicSpace(session, "SpaceA", listOf( + val spaceAInfo = createPublicSpace( + session, "SpaceA", listOf( Triple("A1", true /*auto-join*/, true/*canonical*/), Triple("A2", true, true) - )) + ) + ) - /* val spaceBInfo = */ createPublicSpace(session, "SpaceB", listOf( + /* val spaceBInfo = */ createPublicSpace( + session, "SpaceB", listOf( Triple("B1", true /*auto-join*/, true/*canonical*/), Triple("B2", true, true), Triple("B3", true, true) - )) + ) + ) - val spaceCInfo = createPublicSpace(session, "SpaceC", listOf( + val spaceCInfo = createPublicSpace( + session, "SpaceC", listOf( Triple("C1", true /*auto-join*/, true/*canonical*/), Triple("C2", true, true) - )) + ) + ) // add C as a subspace of A val spaceA = session.spaceService().getSpace(spaceAInfo.spaceId) @@ -254,15 +260,19 @@ class SpaceHierarchyTest : InstrumentedTest { val commonTestHelper = CommonTestHelper(context()) val session = commonTestHelper.createAccount("John", SessionTestParams(true)) - val spaceAInfo = createPublicSpace(session, "SpaceA", listOf( + val spaceAInfo = createPublicSpace( + session, "SpaceA", listOf( Triple("A1", true /*auto-join*/, true/*canonical*/), Triple("A2", true, true) - )) + ) + ) - val spaceCInfo = createPublicSpace(session, "SpaceC", listOf( + val spaceCInfo = createPublicSpace( + session, "SpaceC", listOf( Triple("C1", true /*auto-join*/, true/*canonical*/), Triple("C2", true, true) - )) + ) + ) // add C as a subspace of A val spaceA = session.spaceService().getSpace(spaceAInfo.spaceId) @@ -296,16 +306,20 @@ class SpaceHierarchyTest : InstrumentedTest { val commonTestHelper = CommonTestHelper(context()) val session = commonTestHelper.createAccount("John", SessionTestParams(true)) - val spaceAInfo = createPublicSpace(session, "SpaceA", listOf( + val spaceAInfo = createPublicSpace( + session, "SpaceA", listOf( Triple("A1", true /*auto-join*/, true/*canonical*/), Triple("A2", true, true) - )) + ) + ) - val spaceBInfo = createPublicSpace(session, "SpaceB", listOf( + val spaceBInfo = createPublicSpace( + session, "SpaceB", listOf( Triple("B1", true /*auto-join*/, true/*canonical*/), Triple("B2", true, true), Triple("B3", true, true) - )) + ) + ) // add B as a subspace of A val spaceA = session.spaceService().getSpace(spaceAInfo.spaceId) @@ -315,10 +329,12 @@ class SpaceHierarchyTest : InstrumentedTest { session.spaceService().setSpaceParent(spaceBInfo.spaceId, spaceAInfo.spaceId, true, viaServers) } - val spaceCInfo = createPublicSpace(session, "SpaceC", listOf( + val spaceCInfo = createPublicSpace( + session, "SpaceC", listOf( Triple("C1", true /*auto-join*/, true/*canonical*/), Triple("C2", true, true) - )) + ) + ) commonTestHelper.waitWithLatch { latch -> @@ -446,21 +462,27 @@ class SpaceHierarchyTest : InstrumentedTest { val commonTestHelper = CommonTestHelper(context()) val session = commonTestHelper.createAccount("John", SessionTestParams(true)) - /* val spaceAInfo = */ createPublicSpace(session, "SpaceA", listOf( + /* val spaceAInfo = */ createPublicSpace( + session, "SpaceA", listOf( Triple("A1", true /*auto-join*/, true/*canonical*/), Triple("A2", true, true) - )) + ) + ) - val spaceBInfo = createPublicSpace(session, "SpaceB", listOf( + val spaceBInfo = createPublicSpace( + session, "SpaceB", listOf( Triple("B1", true /*auto-join*/, true/*canonical*/), Triple("B2", true, true), Triple("B3", true, true) - )) + ) + ) - val spaceCInfo = createPublicSpace(session, "SpaceC", listOf( + val spaceCInfo = createPublicSpace( + session, "SpaceC", listOf( Triple("C1", true /*auto-join*/, true/*canonical*/), Triple("C2", true, true) - )) + ) + ) val viaServers = listOf(session.sessionParams.homeServerHost ?: "") @@ -494,10 +516,12 @@ class SpaceHierarchyTest : InstrumentedTest { val aliceSession = commonTestHelper.createAccount("Alice", SessionTestParams(true)) val bobSession = commonTestHelper.createAccount("Bib", SessionTestParams(true)) - val spaceAInfo = createPrivateSpace(aliceSession, "Private Space A", listOf( + val spaceAInfo = createPrivateSpace( + aliceSession, "Private Space A", listOf( Triple("General", true /*suggested*/, true/*canonical*/), Triple("Random", true, true) - )) + ) + ) commonTestHelper.runBlockingTest { aliceSession.getRoom(spaceAInfo.spaceId)!!.membershipService().invite(bobSession.myUserId, null) diff --git a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsHtmlNodeRenderer.kt b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsHtmlNodeRenderer.kt index 0efecbbe8a9946a0b46a31c00337e33cf5cd1ebd..83fcae7190b35c978596d7a745eb60abaddcaff5 100644 --- a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsHtmlNodeRenderer.kt +++ b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsHtmlNodeRenderer.kt @@ -28,8 +28,12 @@ internal class MathsHtmlNodeRenderer(private val context: HtmlNodeRendererContex val display = node.javaClass == DisplayMaths::class.java val contents = node.firstChild // should be the only child val latex = (contents as Text).literal - val attributes = context.extendAttributes(node, if (display) "div" else "span", Collections.singletonMap("data-mx-maths", - latex)) + val attributes = context.extendAttributes( + node, if (display) "div" else "span", Collections.singletonMap( + "data-mx-maths", + latex + ) + ) html.tag(if (display) "div" else "span", attributes) html.tag("code") context.render(contents) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt index 217f7e3da81361100540b2baa43f25eb16b2b13f..979201706b20cb838744b7764c8db745589239f7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt @@ -38,15 +38,18 @@ import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory import org.matrix.olm.OlmManager import java.util.concurrent.Executors -import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject /** * This is the main entry point to the matrix sdk. * <br/> - * See [Companion.createInstance] to create an instance. The app should create and manage the instance itself. + * + * The constructor creates a new instance of Matrix, it's recommended to manage this instance as a singleton. + * + * @param context the application context + * @param matrixConfiguration global configuration that will be used for every [org.matrix.android.sdk.api.session.Session] */ -class Matrix private constructor(context: Context, matrixConfiguration: MatrixConfiguration) { +class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) { @Inject internal lateinit var legacySessionImporter: LegacySessionImporter @Inject internal lateinit var authenticationService: AuthenticationService @@ -61,87 +64,72 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo @Inject internal lateinit var lightweightSettingsStorage: LightweightSettingsStorage init { - Monarchy.init(context) - DaggerMatrixComponent.factory().create(context, matrixConfiguration).inject(this) - if (context.applicationContext !is Configuration.Provider) { + val appContext = context.applicationContext + Monarchy.init(appContext) + DaggerMatrixComponent.factory().create(appContext, matrixConfiguration).inject(this) + if (appContext !is Configuration.Provider) { val configuration = Configuration.Builder() .setExecutor(Executors.newCachedThreadPool()) .setWorkerFactory(matrixWorkerFactory) .build() - WorkManager.initialize(context, configuration) + WorkManager.initialize(appContext, configuration) } ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver) } + /** + * Return the User Agent used for any request that the SDK is making to the homeserver. + * There is no way to change the user agent at the moment. + */ fun getUserAgent() = userAgentHolder.userAgent + /** + * Return the AuthenticationService. + */ fun authenticationService() = authenticationService + /** + * Return the RawService. + */ fun rawService() = rawService + /** + * Return the LightweightSettingsStorage. + */ fun lightweightSettingsStorage() = lightweightSettingsStorage + /** + * Return the HomeServerHistoryService. + */ fun homeServerHistoryService() = homeServerHistoryService + /** + * Return the legacy session importer, useful if you want to migrate an app, which was using the legacy Matrix Android Sdk. + */ fun legacySessionImporter() = legacySessionImporter - fun workerFactory(): WorkerFactory = matrixWorkerFactory + /** + * Get the worker factory. The returned value has to be provided to `WorkConfiguration.Builder()`. + */ + fun getWorkerFactory(): WorkerFactory = matrixWorkerFactory + /** + * Register an API interceptor, to be able to be notified when the specified API got a response. + */ fun registerApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) { apiInterceptor.addListener(path, listener) } + /** + * Un-register an API interceptor. + */ fun unregisterApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) { apiInterceptor.removeListener(path, listener) } companion object { - - private lateinit var instance: Matrix - private val isInit = AtomicBoolean(false) - - /** - * Creates a new instance of Matrix, it's recommended to manage this instance as a singleton. - * To make use of the built in singleton use Matrix.initialize() and/or Matrix.getInstance(context) instead - **/ - fun createInstance(context: Context, matrixConfiguration: MatrixConfiguration): Matrix { - return Matrix(context.applicationContext, matrixConfiguration) - } - - /** - * Initializes a singleton instance of Matrix for the given MatrixConfiguration - * This instance will be returned by Matrix.getInstance(context) - */ - @Deprecated("Use Matrix.createInstance and manage the instance manually") - fun initialize(context: Context, matrixConfiguration: MatrixConfiguration) { - if (isInit.compareAndSet(false, true)) { - instance = Matrix(context.applicationContext, matrixConfiguration) - } - } - - /** - * Either provides an already initialized singleton Matrix instance or queries the application context for a MatrixConfiguration.Provider - * to lazily create and store the instance. - */ - @Suppress("deprecation") // suppressing warning as this method is unused but is still provided for SDK clients - @Deprecated("Use Matrix.createInstance and manage the instance manually") - fun getInstance(context: Context): Matrix { - if (isInit.compareAndSet(false, true)) { - val appContext = context.applicationContext - if (appContext is MatrixConfiguration.Provider) { - val matrixConfiguration = (appContext as MatrixConfiguration.Provider).providesMatrixConfiguration() - instance = Matrix(appContext, matrixConfiguration) - } else { - throw IllegalStateException("Matrix is not initialized properly." + - " If you want to manage your own Matrix instance use Matrix.createInstance" + - " otherwise you should call Matrix.initialize or let your application implement MatrixConfiguration.Provider.") - } - } - return instance - } - /** - * @return a String with details about the Matrix SDK version + * @return a String with details about the Matrix SDK version. */ fun getSdkVersion(): String { return BuildConfig.SDK_VERSION + " (" + BuildConfig.GIT_SDK_REVISION + ")" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixCallback.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixCallback.kt index 166ba8eab9942f87565329a65a0805efe012eb9d..7cd450b5ad4dc512233ce652c6e46bcaf43de869 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixCallback.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixCallback.kt @@ -23,7 +23,7 @@ package org.matrix.android.sdk.api interface MatrixCallback<in T> { /** - * On success method, default to no-op + * On success method, default to no-op. * @param data the data successfully returned from the async function */ fun onSuccess(data: T) { @@ -31,7 +31,7 @@ interface MatrixCallback<in T> { } /** - * On failure method, default to no-op + * On failure method, default to no-op. * @param failure the failure data returned from the async function */ fun onFailure(failure: Throwable) { @@ -40,6 +40,6 @@ interface MatrixCallback<in T> { } /** - * Basic no op implementation + * Basic no op implementation. */ class NoOpMatrixCallback<T> : MatrixCallback<T> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt index f8472319fdc30456a9316c1a9d094cb9a32b0126..21106fba6c3d6d7f724310c1cf051961082200f5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt @@ -46,7 +46,7 @@ data class MatrixConfiguration( */ val proxy: Proxy? = null, /** - * TLS versions and cipher suites limitation for unauthenticated requests + * TLS versions and cipher suites limitation for unauthenticated requests. */ val connectionSpec: ConnectionSpec = ConnectionSpec.RESTRICTED_TLS, /** @@ -62,16 +62,7 @@ data class MatrixConfiguration( */ val roomDisplayNameFallbackProvider: RoomDisplayNameFallbackProvider, /** - * Thread messages default enable/disabled value + * Thread messages default enable/disabled value. */ val threadMessagesEnabledDefault: Boolean = false, -) { - - /** - * Can be implemented by your Application class. - */ - @Deprecated("Use Matrix.createInstance and manage the instance manually instead of Matrix.getInstance") - interface Provider { - fun providesMatrixConfiguration(): MatrixConfiguration - } -} +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConstants.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConstants.kt index 49520f36785e3d86bc2511f1bf30bfe6e351bea1..33a820ddde26808df92b24b216fe16e7cc314ee2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConstants.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConstants.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api /** - * This object define some global constants regarding the Matrix specification + * This object define some global constants regarding the Matrix specification. */ object MatrixConstants { /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixPatterns.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixPatterns.kt index 2a26b612fb082e45a3e73716c28d2fd4eb3057d2..867e066e604f83195213c57cd781882a3e570432 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixPatterns.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixPatterns.kt @@ -147,7 +147,7 @@ object MatrixPatterns { } /** - * Extract server name from a matrix id + * Extract server name from a matrix id. * * @param matrixId * @return null if not found or if matrixId is null @@ -172,7 +172,7 @@ object MatrixPatterns { } /** - * Return the domain form a userId + * Return the domain form a userId. * Examples: * - "@alice:domain.org".getDomain() will return "domain.org" * - "@bob:domain.org:3455".getDomain() will return "domain.org:3455" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixUrls.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixUrls.kt index 4a41eaec4a18b37cdd7cd43a829de18953dcf180..7958186f167f55564b2a989b077febb0cf21f8bd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixUrls.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixUrls.kt @@ -17,21 +17,21 @@ package org.matrix.android.sdk.api /** - * This class contains pattern to match Matrix Url, aka mxc urls + * This class contains pattern to match Matrix Url, aka mxc urls. */ object MatrixUrls { /** - * "mxc" scheme, including "://". So "mxc://" + * "mxc" scheme, including "://". So "mxc://". */ const val MATRIX_CONTENT_URI_SCHEME = "mxc://" /** - * Return true if the String starts with "mxc://" + * Return true if the String starts with "mxc://". */ fun String.isMxcUrl() = startsWith(MATRIX_CONTENT_URI_SCHEME) /** - * Remove the "mxc://" prefix. No op if the String is not a Mxc URL + * Remove the "mxc://" prefix. No op if the String is not a Mxc URL. */ fun String.removeMxcPrefix() = removePrefix(MATRIX_CONTENT_URI_SCHEME) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt index 9cb784c9c02321c8f0ba93e7e22d6b6b6500160a..5a19df90c4f99eb105f630241bc411ad541cdf1e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/AuthenticationService.kt @@ -40,12 +40,12 @@ interface AuthenticationService { suspend fun getLoginFlowOfSession(sessionId: String): LoginFlowResult /** - * Get a SSO url + * Get a SSO url. */ fun getSsoUrl(redirectUrl: String, deviceId: String?, providerId: String?): String? /** - * Get the sign in or sign up fallback URL + * Get the sign in or sign up fallback URL. */ fun getFallbackUrl(forSignIn: Boolean, deviceId: String?): String? @@ -64,17 +64,17 @@ interface AuthenticationService { fun getRegistrationWizard(): RegistrationWizard /** - * True when login and password has been sent with success to the homeserver + * True when login and password has been sent with success to the homeserver. */ val isRegistrationStarted: Boolean /** - * Cancel pending login or pending registration + * Cancel pending login or pending registration. */ suspend fun cancelPendingLoginOrRegistration() /** - * Reset all pending settings, including current HomeServerConnectionConfig + * Reset all pending settings, including current HomeServerConnectionConfig. */ suspend fun reset() @@ -91,20 +91,20 @@ interface AuthenticationService { fun getLastAuthenticatedSession(): Session? /** - * Create a session after a SSO successful login + * Create a session after a SSO successful login. */ suspend fun createSessionFromSso(homeServerConnectionConfig: HomeServerConnectionConfig, credentials: Credentials): Session /** - * Perform a wellknown request, using the domain from the matrixId + * Perform a wellknown request, using the domain from the matrixId. */ suspend fun getWellKnownData(matrixId: String, homeServerConnectionConfig: HomeServerConnectionConfig?): WellknownResult /** - * Authenticate with a matrixId and a password - * Usually call this after a successful call to getWellKnownData() + * Authenticate with a matrixId and a password. + * Usually call this after a successful call to getWellKnownData(). * @param homeServerConnectionConfig the information about the homeserver and other configuration * @param matrixId the matrixId of the user * @param password the password of the account diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/TokenBasedAuth.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/TokenBasedAuth.kt index e522352c3870735644f295556c5815651664c765..2c99ced995c2b73c8df73cd5910bd445855a8669 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/TokenBasedAuth.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/TokenBasedAuth.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.auth.data.LoginFlowTypes /** - * This class provides the authentication data by using user and password + * This class provides the authentication data by using user and password. */ @JsonClass(generateAdapter = true) data class TokenBasedAuth( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/UserPasswordAuth.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/UserPasswordAuth.kt index e985c5f08abfdeee95c5dcc214f4af169024f9a2..8cd5b5e6eb890aff6bf47700dbf2a803c9a5a280 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/UserPasswordAuth.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/UserPasswordAuth.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.auth.data.LoginFlowTypes /** - * This class provides the authentication data by using user and password + * This class provides the authentication data by using user and password. */ @JsonClass(generateAdapter = true) data class UserPasswordAuth( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt index 1a4c1ee51ce4fc0cb8a721c0752cc165eba2c2c5..80630bc4e7fbf7eafa3015b21bae6b07a6e8a955 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt @@ -1,127 +1,129 @@ -/* - * 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.api.auth - -import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms -import org.matrix.android.sdk.api.auth.registration.TermPolicies - -/** - * This method extract the policies from the login terms parameter, regarding the user language. - * For each policy, if user language is not found, the default language is used and if not found, the first url and name are used (not predictable) - * - * Example of Data: - * <pre> - * "m.login.terms": { - * "policies": { - * "privacy_policy": { - * "version": "1.0", - * "en": { - * "url": "http:\/\/matrix.org\/_matrix\/consent?v=1.0", - * "name": "Terms and Conditions" - * } - * } - * } - * } - *</pre> - * - * @param userLanguage the user language - * @param defaultLanguage the default language to use if the user language is not found for a policy in registrationFlowResponse - */ -fun TermPolicies.toLocalizedLoginTerms(userLanguage: String, - defaultLanguage: String = "en"): List<LocalizedFlowDataLoginTerms> { - val result = ArrayList<LocalizedFlowDataLoginTerms>() - - val policies = get("policies") - if (policies is Map<*, *>) { - policies.keys.forEach { policyName -> - val localizedFlowDataLoginTermsPolicyName = policyName as String - var localizedFlowDataLoginTermsVersion: String? = null - var localizedFlowDataLoginTermsLocalizedUrl: String? = null - var localizedFlowDataLoginTermsLocalizedName: String? = null - - val policy = policies[policyName] - - // Enter this policy - if (policy is Map<*, *>) { - // Version - localizedFlowDataLoginTermsVersion = policy["version"] as String? - - var userLanguageUrlAndName: UrlAndName? = null - var defaultLanguageUrlAndName: UrlAndName? = null - var firstUrlAndName: UrlAndName? = null - - // Search for language - policy.keys.forEach { policyKey -> - when (policyKey) { - "version" -> Unit // Ignore - userLanguage -> { - // We found the data for the user language - userLanguageUrlAndName = extractUrlAndName(policy[policyKey]) - } - defaultLanguage -> { - // We found default language - defaultLanguageUrlAndName = extractUrlAndName(policy[policyKey]) - } - else -> { - if (firstUrlAndName == null) { - // Get at least some data - firstUrlAndName = extractUrlAndName(policy[policyKey]) - } - } - } - } - - // Copy found language data by priority - when { - userLanguageUrlAndName != null -> { - localizedFlowDataLoginTermsLocalizedUrl = userLanguageUrlAndName!!.url - localizedFlowDataLoginTermsLocalizedName = userLanguageUrlAndName!!.name - } - defaultLanguageUrlAndName != null -> { - localizedFlowDataLoginTermsLocalizedUrl = defaultLanguageUrlAndName!!.url - localizedFlowDataLoginTermsLocalizedName = defaultLanguageUrlAndName!!.name - } - firstUrlAndName != null -> { - localizedFlowDataLoginTermsLocalizedUrl = firstUrlAndName!!.url - localizedFlowDataLoginTermsLocalizedName = firstUrlAndName!!.name - } - } - } - - result.add(LocalizedFlowDataLoginTerms( - policyName = localizedFlowDataLoginTermsPolicyName, - version = localizedFlowDataLoginTermsVersion, - localizedUrl = localizedFlowDataLoginTermsLocalizedUrl, - localizedName = localizedFlowDataLoginTermsLocalizedName - )) - } - } - - return result -} - -private fun extractUrlAndName(policyData: Any?): UrlAndName? { - if (policyData is Map<*, *>) { - val url = policyData["url"] as String? - val name = policyData["name"] as String? - - if (url != null && name != null) { - return UrlAndName(url, name) - } - } - return null -} +/* + * 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.api.auth + +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms +import org.matrix.android.sdk.api.auth.registration.TermPolicies + +/** + * This method extract the policies from the login terms parameter, regarding the user language. + * For each policy, if user language is not found, the default language is used and if not found, the first url and name are used (not predictable) + * + * Example of Data: + * <pre> + * "m.login.terms": { + * "policies": { + * "privacy_policy": { + * "version": "1.0", + * "en": { + * "url": "http:\/\/matrix.org\/_matrix\/consent?v=1.0", + * "name": "Terms and Conditions" + * } + * } + * } + * } + *</pre> + * + * @param userLanguage the user language + * @param defaultLanguage the default language to use if the user language is not found for a policy in registrationFlowResponse + */ +fun TermPolicies.toLocalizedLoginTerms(userLanguage: String, + defaultLanguage: String = "en"): List<LocalizedFlowDataLoginTerms> { + val result = ArrayList<LocalizedFlowDataLoginTerms>() + + val policies = get("policies") + if (policies is Map<*, *>) { + policies.keys.forEach { policyName -> + val localizedFlowDataLoginTermsPolicyName = policyName as String + var localizedFlowDataLoginTermsVersion: String? = null + var localizedFlowDataLoginTermsLocalizedUrl: String? = null + var localizedFlowDataLoginTermsLocalizedName: String? = null + + val policy = policies[policyName] + + // Enter this policy + if (policy is Map<*, *>) { + // Version + localizedFlowDataLoginTermsVersion = policy["version"] as String? + + var userLanguageUrlAndName: UrlAndName? = null + var defaultLanguageUrlAndName: UrlAndName? = null + var firstUrlAndName: UrlAndName? = null + + // Search for language + policy.keys.forEach { policyKey -> + when (policyKey) { + "version" -> Unit // Ignore + userLanguage -> { + // We found the data for the user language + userLanguageUrlAndName = extractUrlAndName(policy[policyKey]) + } + defaultLanguage -> { + // We found default language + defaultLanguageUrlAndName = extractUrlAndName(policy[policyKey]) + } + else -> { + if (firstUrlAndName == null) { + // Get at least some data + firstUrlAndName = extractUrlAndName(policy[policyKey]) + } + } + } + } + + // Copy found language data by priority + when { + userLanguageUrlAndName != null -> { + localizedFlowDataLoginTermsLocalizedUrl = userLanguageUrlAndName!!.url + localizedFlowDataLoginTermsLocalizedName = userLanguageUrlAndName!!.name + } + defaultLanguageUrlAndName != null -> { + localizedFlowDataLoginTermsLocalizedUrl = defaultLanguageUrlAndName!!.url + localizedFlowDataLoginTermsLocalizedName = defaultLanguageUrlAndName!!.name + } + firstUrlAndName != null -> { + localizedFlowDataLoginTermsLocalizedUrl = firstUrlAndName!!.url + localizedFlowDataLoginTermsLocalizedName = firstUrlAndName!!.name + } + } + } + + result.add( + LocalizedFlowDataLoginTerms( + policyName = localizedFlowDataLoginTermsPolicyName, + version = localizedFlowDataLoginTermsVersion, + localizedUrl = localizedFlowDataLoginTermsLocalizedUrl, + localizedName = localizedFlowDataLoginTermsLocalizedName + ) + ) + } + } + + return result +} + +private fun extractUrlAndName(policyData: Any?): UrlAndName? { + if (policyData is Map<*, *>) { + val url = policyData["url"] as String? + val name = policyData["name"] as String? + + if (url != null && name != null) { + return UrlAndName(url, name) + } + } + return null +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/Credentials.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/Credentials.kt index 317acccfb513cbfa77e04b8e87731e8c2c9f8ad4..e3728753adc6d9cea7003861ff88d6068bed0d7b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/Credentials.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/Credentials.kt @@ -37,7 +37,7 @@ data class Credentials( */ @Json(name = "access_token") val accessToken: String, /** - * Not documented + * Not documented. */ @Json(name = "refresh_token") val refreshToken: String?, /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SessionParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SessionParams.kt index b490ac877ee4e455532d5566631f7753b169fa51..e3815231d93dd04d2ac4f8422d90976fc07d54c7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SessionParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SessionParams.kt @@ -22,12 +22,12 @@ package org.matrix.android.sdk.api.auth.data */ data class SessionParams( /** - * Please consider using shortcuts instead + * Please consider using shortcuts instead. */ val credentials: Credentials, /** - * Please consider using shortcuts instead + * Please consider using shortcuts instead. */ val homeServerConnectionConfig: HomeServerConnectionConfig, @@ -41,12 +41,12 @@ data class SessionParams( */ /** - * The userId of the session (Ex: "@user:domain.org") + * The userId of the session (Ex: "@user:domain.org"). */ val userId = credentials.userId /** - * The deviceId of the session (Ex: "ABCDEFGH") + * The deviceId of the session (Ex: "ABCDEFGH"). */ val deviceId = credentials.deviceId @@ -62,12 +62,12 @@ data class SessionParams( val homeServerUrlBase = homeServerConnectionConfig.homeServerUriBase.toString() /** - * The current homeserver host, using what has been entered by the user during login phase + * The current homeserver host, using what has been entered by the user during login phase. */ val homeServerHost = homeServerConnectionConfig.homeServerUri.host /** - * The default identity server url if any, returned by the homeserver during login phase + * The default identity server url if any, returned by the homeserver during login phase. */ val defaultIdentityServerUrl = homeServerConnectionConfig.identityServerUri?.toString() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnown.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnown.kt index 4bcef606051672ec7e377a1b925153ff042951f1..10c7d513923b53c37ed47397957b8d288aaa3089 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnown.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnown.kt @@ -43,6 +43,7 @@ import org.matrix.android.sdk.api.util.JsonDict * } * } * </pre> + * . */ @JsonClass(generateAdapter = true) data class WellKnown( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnownBaseConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnownBaseConfig.kt index ad6b9970de4c3de4bc79d9fa6c2f3b001ab1f475..df0009923219c57ee51d9f3cbacbb6487f6c79ff 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnownBaseConfig.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnownBaseConfig.kt @@ -26,6 +26,7 @@ import com.squareup.moshi.JsonClass * "base_url": "https://vector.im" * } * </pre> + * . */ @JsonClass(generateAdapter = true) data class WellKnownBaseConfig( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt index 247d58ce7972bcd2157478726d2747cdcfbd8420..3232025de39a0c3c2271a7dbc34ed66e8466309a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt @@ -26,7 +26,7 @@ import org.matrix.android.sdk.api.util.JsonDict */ interface LoginWizard { /** - * Get some information about a matrixId: displayName and avatar url + * Get some information about a matrixId: displayName and avatar url. */ suspend fun getProfileInfo(matrixId: String): LoginProfileInfo diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt index 0da9eb4b7e157dc984fc5ad159b23ed08662d2c2..1252e93b84848d72b678977b269e37a73b603b9e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt @@ -73,7 +73,7 @@ data class RegistrationFlowResponse( ) /** - * Convert to something easier to handle on client side + * Convert to something easier to handle on client side. */ fun RegistrationFlowResponse.toFlowResult(): FlowResult { // Get all the returned stages @@ -88,8 +88,10 @@ fun RegistrationFlowResponse.toFlowResult(): FlowResult { val isMandatory = flows?.all { type in it.stages.orEmpty() } == true val stage = when (type) { - LoginFlowTypes.RECAPTCHA -> Stage.ReCaptcha(isMandatory, ((params?.get(type) as? Map<*, *>)?.get("public_key") as? String) - ?: "") + LoginFlowTypes.RECAPTCHA -> Stage.ReCaptcha( + isMandatory, ((params?.get(type) as? Map<*, *>)?.get("public_key") as? String) + ?: "" + ) LoginFlowTypes.DUMMY -> Stage.Dummy(isMandatory) LoginFlowTypes.TERMS -> Stage.Terms(isMandatory, params?.get(type) as? TermPolicies ?: emptyMap<String, String>()) LoginFlowTypes.EMAIL_IDENTITY -> Stage.Email(isMandatory) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt index 172cfa8360752d6a150a4e96be8d781ec047f837..37b9ac379e285f9814f675d72b8525f40c92cd78 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt @@ -32,7 +32,7 @@ const val MXCRYPTO_ALGORITHM_MEGOLM = "m.megolm.v1.aes-sha2" const val MXCRYPTO_ALGORITHM_MEGOLM_BACKUP = "m.megolm_backup.v1.curve25519-aes-sha2" /** - * Secured Shared Storage algorithm constant + * Secured Shared Storage algorithm constant. */ const val SSSS_ALGORITHM_CURVE25519_AES_SHA2 = "m.secret_storage.v1.curve25519-aes-sha2" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/Emojis.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/Emojis.kt index 9c0eb10970a2e4109d7a22c59bf11bad1a2eaccc..85d6961384fcf0378580f4fadbd3588e7beb9904 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/Emojis.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/Emojis.kt @@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentatio import org.matrix.android.sdk.internal.crypto.verification.getEmojiForCode /** - * Provide all the emojis used for SAS verification (for debug purpose) + * Provide all the emojis used for SAS verification (for debug purpose). */ fun getAllVerificationEmojis(): List<EmojiRepresentation> { return (0..63).map { getEmojiForCode(it) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/MXCryptoConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/MXCryptoConfig.kt index 9a686de2e123ac35617d782627968c41400dcf8a..9507ddda65726c55a513db0bbd707b224389e242 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/MXCryptoConfig.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/MXCryptoConfig.kt @@ -31,5 +31,11 @@ data class MXCryptoConfig constructor( * If set to false, the request will be forwarded to the application layer; in this * case the application can decide to prompt the user. */ - val discardRoomKeyRequestsFromUntrustedDevices: Boolean = true + val discardRoomKeyRequestsFromUntrustedDevices: Boolean = true, + + /** + * Currently megolm keys are requested to the sender device and to all of our devices. + * You can limit request only to your sessions by turning this setting to `true` + */ + val limitRoomKeyRequestsToMyDevices: Boolean = false, ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/Strings.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/Strings.kt index e264843ea49654ce151cb29b5529a12e69db8113..5e1350e32791ac60019659e3356511fc3b353708 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/Strings.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/Strings.kt @@ -24,6 +24,6 @@ fun CharSequence.ensurePrefix(prefix: CharSequence): CharSequence { } /** - * Append a new line and then the provided string + * Append a new line and then the provided string. */ fun StringBuilder.appendNl(str: String) = append("\n").append(str) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt index 362ebcec26db18b2f0829fd215685ba90f9c66e2..d3cc8fc8e48a94a394bebac28f15598a830edd5e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt @@ -47,7 +47,7 @@ fun Throwable.shouldBeRetried() = this is Failure.NetworkConnection || isLimitExceededError() /** - * Get the retry delay in case of rate limit exceeded error, adding 100 ms, of defaultValue otherwise + * Get the retry delay in case of rate limit exceeded error, adding 100 ms, of defaultValue otherwise. */ fun Throwable.getRetryDelay(defaultValue: Long): Long { return (this as? Failure.ServerError) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt index ebe07823f470f3fbdca55586dcb49e2787742b06..8bebbcc3a5d3bb51ba36de59aaba0b51dc464f82 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt @@ -17,11 +17,11 @@ package org.matrix.android.sdk.api.failure /** - * This enum provide the reason why the SDK request an initial sync to the application + * This enum provide the reason why the SDK request an initial sync to the application. */ enum class InitialSyncRequestReason { /** - * The list of ignored users has changed, and at least one user who was ignored is not ignored anymore + * The list of ignored users has changed, and at least one user who was ignored is not ignored anymore. */ IGNORED_USERS_LIST_CHANGE, } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/MatrixError.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/MatrixError.kt index 32e1aca17d83efdc7bea4d21c84204d0e16c6e6e..3dbbc3956436af4a38985783f682fe7115558c2f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/MatrixError.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/MatrixError.kt @@ -28,9 +28,9 @@ import org.matrix.android.sdk.api.util.JsonDict */ @JsonClass(generateAdapter = true) data class MatrixError( - /** unique string which can be used to handle an error message */ + /** unique string which can be used to handle an error message. */ @Json(name = "errcode") val code: String, - /** human-readable error message */ + /** human-readable error message. */ @Json(name = "error") val message: String, // For M_CONSENT_NOT_GIVEN @@ -92,19 +92,19 @@ data class MatrixError( /** Sent when the room alias given to the createRoom API is already in use. */ const val M_ROOM_IN_USE = "M_ROOM_IN_USE" - /** (Not documented yet) */ + /** (Not documented yet). */ const val M_BAD_PAGINATION = "M_BAD_PAGINATION" /** The request was not correctly authorized. Usually due to login failures. */ const val M_UNAUTHORIZED = "M_UNAUTHORIZED" - /** (Not documented yet) */ + /** (Not documented yet). */ const val M_OLD_VERSION = "M_OLD_VERSION" /** The server did not understand the request. */ const val M_UNRECOGNIZED = "M_UNRECOGNIZED" - /** (Not documented yet) */ + /** (Not documented yet). */ const val M_LOGIN_EMAIL_URL_NOT_YET = "M_LOGIN_EMAIL_URL_NOT_YET" /** Authentication could not be performed on the third party identifier. */ @@ -122,7 +122,7 @@ data class MatrixError( /** The request or entity was too large. */ const val M_TOO_LARGE = "M_TOO_LARGE" - /** (Not documented yet) */ + /** (Not documented yet). */ const val M_CONSENT_NOT_GIVEN = "M_CONSENT_NOT_GIVEN" /** The request cannot be completed because the homeserver has reached a resource limit imposed on it. For example, @@ -176,10 +176,10 @@ data class MatrixError( /** The user is unable to reject an invite to join the server notices room. See the Server Notices module for more information. */ const val M_CANNOT_LEAVE_SERVER_NOTICE_ROOM = "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM" - /** (Not documented yet) */ + /** (Not documented yet). */ const val M_WRONG_ROOM_KEYS_VERSION = "M_WRONG_ROOM_KEYS_VERSION" - /** (Not documented yet) */ + /** (Not documented yet). */ const val M_WEAK_PASSWORD = "M_WEAK_PASSWORD" /** The provided password's length is shorter than the minimum length required by the server. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/federation/FederationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/federation/FederationService.kt index 0761ef8d21a6fb731ceb2d1fe1acf0b72078429e..8fe646075346bf645e7ebf3e595a052f94a8aa14 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/federation/FederationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/federation/FederationService.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.federation interface FederationService { /** - * Get information about the homeserver + * Get information about the homeserver. */ suspend fun getFederationVersion(): FederationVersion } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/listeners/ProgressListener.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/listeners/ProgressListener.kt index 02ebd7f784ae17c51b1609f7d73ebdef9506d706..ec55348dc5abbc4bb0d87cd9be33413ff9f2fb99 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/listeners/ProgressListener.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/listeners/ProgressListener.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.listeners /** - * Interface to send a progress info + * Interface to send a progress info. */ interface ProgressListener { /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/listeners/StepProgressListener.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/listeners/StepProgressListener.kt index 0fabfed2ff393ab50f2e8adf33feb6e29957f0a7..4b87507c02e5084387fd37119d160f7d73a60a27 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/listeners/StepProgressListener.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/listeners/StepProgressListener.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.listeners /** - * Interface to send a progress info + * Interface to send a progress info. */ interface StepProgressListener { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/logger/LoggerTag.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/logger/LoggerTag.kt index 44ac439d7b04fc95ba3ec168ad4c210c737b75c7..ae65963f37b26c3ccf654d3bf1ca8ea29998b792 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/logger/LoggerTag.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/logger/LoggerTag.kt @@ -22,15 +22,15 @@ package org.matrix.android.sdk.api.logger * val loggerTag = LoggerTag("MyTag", LoggerTag.VOIP) * Timber.tag(loggerTag.value).v("My log message") */ -open class LoggerTag(_value: String, parentTag: LoggerTag? = null) { +open class LoggerTag(name: String, parentTag: LoggerTag? = null) { object SYNC : LoggerTag("SYNC") object VOIP : LoggerTag("VOIP") object CRYPTO : LoggerTag("CRYPTO") val value: String = if (parentTag == null) { - _value + name } else { - "${parentTag.value}/$_value" + "${parentTag.value}/$name" } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt index 31ec131c5ca9558710acf93335b196404776425e..368ff986613783037cd0b44771d9d8ebdfb9fdcd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt @@ -36,19 +36,19 @@ sealed interface QueryStringValue { enum class Case { /** - * Match query sensitive to case + * Match query sensitive to case. */ SENSITIVE, /** - * Match query insensitive to case, this only works for Latin-1 character sets + * Match query insensitive to case, this only works for Latin-1 character sets. */ INSENSITIVE, /** - * Match query with input normalized (case insensitive) - * Works around Realms inability to sort or filter by case for non Latin-1 character sets - * Expects the target field to contain normalized data + * Match query with input normalized (case insensitive). + * Works around Realms inability to sort or filter by case for non Latin-1 character sets. + * Expects the target field to contain normalized data. * * @see org.matrix.android.sdk.internal.util.Normalizer.normalize */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/raw/RawService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/raw/RawService.kt index 3366d040f7fa1227a6b72cc9668fa411681fea88..71a4f84a8da05a4f27ee17b43ff0bda4b9ed5018 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/raw/RawService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/raw/RawService.kt @@ -23,19 +23,19 @@ import org.matrix.android.sdk.api.cache.CacheStrategy */ interface RawService { /** - * Get a URL, either from cache or from the remote server, depending on the cache strategy + * Get a URL, either from cache or from the remote server, depending on the cache strategy. */ suspend fun getUrl(url: String, cacheStrategy: CacheStrategy): String /** - * Specific case for the well-known file. Cache validity is 8 hours + * Specific case for the well-known file. Cache validity is 8 hours. * @param domain the domain to get the .well-known file, for instance "matrix.org". * The URL will be "https://{domain}/.well-known/matrix/client" */ suspend fun getWellknown(domain: String): String /** - * Clear all the cache data + * Clear all the cache data. */ suspend fun clearCache() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt index 19502f0b46b873a1d658aad6986bbb53f9cce91c..2f1ae8cd87626fe744434bdecd911d40c5118312 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt @@ -72,23 +72,23 @@ interface Session { val coroutineDispatchers: MatrixCoroutineDispatchers /** - * The params associated to the session + * The params associated to the session. */ val sessionParams: SessionParams /** - * The session is valid, i.e. it has a valid token so far + * The session is valid, i.e. it has a valid token so far. */ val isOpenable: Boolean /** - * Useful shortcut to get access to the userId + * Useful shortcut to get access to the userId. */ val myUserId: String get() = sessionParams.userId /** - * The sessionId + * The sessionId. */ val sessionId: String @@ -99,16 +99,16 @@ interface Session { fun open() /** - * Requires a one time background sync + * Requires a one time background sync. */ fun requireBackgroundSync() /** - * Launches infinite self rescheduling background syncs via the WorkManager + * Launches infinite self rescheduling background syncs via the WorkManager. * - * While dozing, syncs will only occur during maintenance windows + * While dozing, syncs will only occur during maintenance windows. * For reliability it's recommended to also start a long running foreground service - * along with disabling battery optimizations + * along with disabling battery optimizations. */ fun startAutomaticBackgroundSync(timeOutInSeconds: Long, repeatDelayInSeconds: Long) @@ -125,7 +125,7 @@ interface Session { fun stopSync() /** - * Clear cache of the session + * Clear cache of the session. */ suspend fun clearCache() @@ -147,7 +147,7 @@ interface Session { fun syncFlow(): SharedFlow<SyncResponse> /** - * This methods return true if an initial sync has been processed + * This methods return true if an initial sync has been processed. */ fun hasAlreadySynced(): Boolean @@ -162,187 +162,187 @@ interface Session { fun contentUrlResolver(): ContentUrlResolver /** - * Returns the ContentUploadProgressTracker associated with the session + * Returns the ContentUploadProgressTracker associated with the session. */ fun contentUploadProgressTracker(): ContentUploadStateTracker /** - * Returns the TypingUsersTracker associated with the session + * Returns the TypingUsersTracker associated with the session. */ fun typingUsersTracker(): TypingUsersTracker /** - * Returns the ContentDownloadStateTracker associated with the session + * Returns the ContentDownloadStateTracker associated with the session. */ fun contentDownloadProgressTracker(): ContentDownloadStateTracker /** - * Returns the cryptoService associated with the session + * Returns the cryptoService associated with the session. */ fun cryptoService(): CryptoService /** - * Returns the ContentScannerService associated with the session + * Returns the ContentScannerService associated with the session. */ fun contentScannerService(): ContentScannerService /** - * Returns the identity service associated with the session + * Returns the identity service associated with the session. */ fun identityService(): IdentityService /** - * Returns the HomeServerCapabilities service associated with the session + * Returns the HomeServerCapabilities service associated with the session. */ fun homeServerCapabilitiesService(): HomeServerCapabilitiesService /** - * Returns the RoomService associated with the session + * Returns the RoomService associated with the session. */ fun roomService(): RoomService /** - * Returns the RoomDirectoryService associated with the session + * Returns the RoomDirectoryService associated with the session. */ fun roomDirectoryService(): RoomDirectoryService /** - * Returns the GroupService associated with the session + * Returns the GroupService associated with the session. */ fun groupService(): GroupService /** - * Returns the UserService associated with the session + * Returns the UserService associated with the session. */ fun userService(): UserService /** - * Returns the SignOutService associated with the session + * Returns the SignOutService associated with the session. */ fun signOutService(): SignOutService /** - * Returns the FilterService associated with the session + * Returns the FilterService associated with the session. */ fun filterService(): FilterService /** - * Returns the PushRuleService associated with the session + * Returns the PushRuleService associated with the session. */ fun pushRuleService(): PushRuleService /** - * Returns the PushersService associated with the session + * Returns the PushersService associated with the session. */ fun pushersService(): PushersService /** - * Returns the EventService associated with the session + * Returns the EventService associated with the session. */ fun eventService(): EventService /** - * Returns the TermsService associated with the session + * Returns the TermsService associated with the session. */ fun termsService(): TermsService /** - * Returns the SyncStatusService associated with the session + * Returns the SyncStatusService associated with the session. */ fun syncStatusService(): SyncStatusService /** - * Returns the SecureStorageService associated with the session + * Returns the SecureStorageService associated with the session. */ fun secureStorageService(): SecureStorageService /** - * Returns the ProfileService associated with the session + * Returns the ProfileService associated with the session. */ fun profileService(): ProfileService /** - * Returns the PresenceService associated with the session + * Returns the PresenceService associated with the session. */ fun presenceService(): PresenceService /** - * Returns the AccountService associated with the session + * Returns the AccountService associated with the session. */ fun accountService(): AccountService /** - * Returns the ToDeviceService associated with the session + * Returns the ToDeviceService associated with the session. */ fun toDeviceService(): ToDeviceService /** - * Returns the EventStreamService associated with the session + * Returns the EventStreamService associated with the session. */ fun eventStreamService(): EventStreamService /** - * Returns the widget service associated with the session + * Returns the widget service associated with the session. */ fun widgetService(): WidgetService /** - * Returns the media service associated with the session + * Returns the media service associated with the session. */ fun mediaService(): MediaService /** - * Returns the integration manager service associated with the session + * Returns the integration manager service associated with the session. */ fun integrationManagerService(): IntegrationManagerService /** - * Returns the call signaling service associated with the session + * Returns the call signaling service associated with the session. */ fun callSignalingService(): CallSignalingService /** - * Returns the file download service associated with the session + * Returns the file download service associated with the session. */ fun fileService(): FileService /** - * Returns the permalink service associated with the session + * Returns the permalink service associated with the session. */ fun permalinkService(): PermalinkService /** - * Returns the search service associated with the session + * Returns the search service associated with the session. */ fun searchService(): SearchService /** - * Returns the federation service associated with the session + * Returns the federation service associated with the session. */ fun federationService(): FederationService /** - * Returns the third party service associated with the session + * Returns the third party service associated with the session. */ fun thirdPartyService(): ThirdPartyService /** - * Returns the space service associated with the session + * Returns the space service associated with the session. */ fun spaceService(): SpaceService /** - * Returns the open id service associated with the session + * Returns the open id service associated with the session. */ fun openIdService(): OpenIdService /** - * Returns the account data service associated with the session + * Returns the account data service associated with the session. */ fun accountDataService(): SessionAccountDataService /** - * Returns the SharedSecretStorageService associated with the session + * Returns the SharedSecretStorageService associated with the session. */ fun sharedSecretStorageService(): SharedSecretStorageService @@ -377,8 +377,8 @@ interface Session { /** * Possible cases: * - The access token is not valid anymore, - * - a M_CONSENT_NOT_GIVEN error has been received from the homeserver - * See [GlobalError] for all the possible cases + * - a M_CONSENT_NOT_GIVEN error has been received from the homeserver; + * See [GlobalError] for all the possible cases. */ fun onGlobalError(session: Session, globalError: GlobalError) = Unit } @@ -386,7 +386,7 @@ interface Session { fun getUiaSsoFallbackUrl(authenticationSessionId: String): String /** - * Maintenance API, allows to print outs info on DB size to logcat + * Maintenance API, allows to print outs info on DB size to logcat. */ fun logDbUsageInfo() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt index aeb0e7e4ee73f5dee19e8e7cccb1ad16b1b4aa9a..a15e73eb88f007dd917797478d1c6c9896641f6c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt @@ -21,16 +21,16 @@ import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.user.model.User /** - * Get a room using the RoomService of a Session + * Get a room using the RoomService of a Session. */ fun Session.getRoom(roomId: String): Room? = roomService().getRoom(roomId) /** - * Get a room summary using the RoomService of a Session + * Get a room summary using the RoomService of a Session. */ fun Session.getRoomSummary(roomIdOrAlias: String): RoomSummary? = roomService().getRoomSummary(roomIdOrAlias) /** - * Get a user using the UserService of a Session + * Get a user using the UserService of a Session. */ fun Session.getUser(userId: String): User? = userService().getUser(userId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/ToDeviceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/ToDeviceService.kt index d7afad5b6c4ecd33f49201bc44e9973cabb725cc..56e5ebdbe7e3f5faa756d5bc3506712c7732bf3e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/ToDeviceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/ToDeviceService.kt @@ -21,9 +21,8 @@ import org.matrix.android.sdk.api.session.events.model.Content import java.util.UUID interface ToDeviceService { - /** - * Send an event to a specific list of devices + * Send an event to a specific list of devices. */ suspend fun sendToDevice(eventType: String, contentMap: MXUsersDevicesMap<Any>, txnId: String? = UUID.randomUUID().toString()) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt index 2ffb9112d1e8ee56bfaab92a491643bf8c15b96e..a22dd3377454036d620289e84f8e8cca52126b53 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt @@ -26,12 +26,12 @@ import org.matrix.android.sdk.api.util.Optional */ interface SessionAccountDataService { /** - * Retrieve the account data with the provided type or null if not found + * Retrieve the account data with the provided type or null if not found. */ fun getUserAccountDataEvent(type: String): UserAccountDataEvent? /** - * Observe the account data with the provided type + * Observe the account data with the provided type. */ fun getLiveUserAccountDataEvent(type: String): LiveData<Optional<UserAccountDataEvent>> @@ -60,7 +60,7 @@ interface SessionAccountDataService { fun getLiveRoomAccountDataEvents(types: Set<String>): LiveData<List<RoomAccountDataEvent>> /** - * Update the account data with the provided type and the provided account data content + * Update the account data with the provided type and the provided account data content. */ suspend fun updateUserAccountData(type: String, content: Content) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallListener.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallListener.kt index d17be59cd4d4cd5556b59b94dd7718dc1771b530..7f932e881532f1b1e0ab68dbfed9b5bd0c568278 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallListener.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallListener.kt @@ -39,32 +39,32 @@ interface CallListener { fun onCallAnswerReceived(callAnswerContent: CallAnswerContent) /** - * Called when a called has been hung up + * Called when a called has been hung up. */ fun onCallHangupReceived(callHangupContent: CallHangupContent) /** - * Called when a called has been rejected + * Called when a called has been rejected. */ fun onCallRejectReceived(callRejectContent: CallRejectContent) /** - * Called when an answer has been selected + * Called when an answer has been selected. */ fun onCallSelectAnswerReceived(callSelectAnswerContent: CallSelectAnswerContent) /** - * Called when a negotiation is sent + * Called when a negotiation is sent. */ fun onCallNegotiateReceived(callNegotiateContent: CallNegotiateContent) /** - * Called when the call has been managed by an other session + * Called when the call has been managed by an other session. */ fun onCallManagedByOtherSession(callId: String) /** - * Called when an asserted identity event is received + * Called when an asserted identity event is received. */ fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallSignalingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallSignalingService.kt index c34744e75f5f7ef13a6fa8edb68349897a36c309..e17c02c40aed9032c969132ff6ceca835fdf912d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallSignalingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallSignalingService.kt @@ -21,7 +21,7 @@ interface CallSignalingService { suspend fun getTurnServer(): TurnServerResponse /** - * Create an outgoing call + * Create an outgoing call. */ fun createOutgoingCall(roomId: String, otherUserId: String, isVideoCall: Boolean): MxCall diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallState.kt index ff1df63300c36f775b5731c6eaa74ae4183ef2c8..4bf78c9d6aa65cd3ecbd42d1e3b4206ebc64c66b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallState.kt @@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.session.room.model.call.EndCallReason sealed class CallState { - /** Idle, setting up objects */ + /** Idle, setting up objects. */ object Idle : CallState() /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/MxCall.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/MxCall.kt index dd23e81cc6a062697aa29bf1322727b6e6ed2697..e13f7310e05696cecfa81c396f8357a5266d67ec 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/MxCall.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/MxCall.kt @@ -35,7 +35,7 @@ interface MxCallDetail { } /** - * Define both an incoming call and on outgoing call + * Define both an incoming call and on outgoing call. */ interface MxCall : MxCallDetail { @@ -46,13 +46,13 @@ interface MxCall : MxCallDetail { var state: CallState /** - * Pick Up the incoming call - * It has no effect on outgoing call + * Pick Up the incoming call. + * It has no effect on outgoing call. */ fun accept(sdpString: String) /** - * SDP negotiation for media pause, hold/resume, ICE restarts and voice/video call up/downgrading + * SDP negotiation for media pause, hold/resume, ICE restarts and voice/video call up/downgrading. */ fun negotiate(sdpString: String, type: SdpType) @@ -62,17 +62,17 @@ interface MxCall : MxCallDetail { fun selectAnswer() /** - * Reject an incoming call + * Reject an incoming call. */ fun reject() /** - * End the call + * End the call. */ fun hangUp(reason: EndCallReason? = null) /** - * Start a call + * Start a call. * Send offer SDP to the other participant. */ fun offerSdp(sdpString: String) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt index 523d60359b00309392c01c65fab5185049aa4185..e59e676ed9587f2670bbce0db540e7e5011a34ad 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt @@ -29,7 +29,7 @@ interface ContentUrlResolver { } /** - * URL to use to upload content + * URL to use to upload content. */ val uploadUrl: String @@ -42,7 +42,7 @@ interface ContentUrlResolver { fun resolveFullSize(contentUrl: String?): String? /** - * Get the ResolvedMethod to download a URL + * Get the ResolvedMethod to download a URL. * * @param contentUrl the Matrix media content URI (in the form of "mxc://..."). * @param elementToDecrypt Encryption data may be required if you use a content scanner diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt index d6d1248de78f01711a14f2599caccf968752115e..35f3ab3162466745fb6c09ec19e33368d392cbf6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt @@ -26,6 +26,7 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningServic import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService import org.matrix.android.sdk.api.session.crypto.keyshare.GossipingRequestListener +import org.matrix.android.sdk.api.session.crypto.model.AuditTrail import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import org.matrix.android.sdk.api.session.crypto.model.DevicesListResponse @@ -35,8 +36,6 @@ import org.matrix.android.sdk.api.session.crypto.model.MXDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.MXEncryptEventContentResult import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest -import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event @@ -76,6 +75,15 @@ interface CryptoService { fun setGlobalBlacklistUnverifiedDevices(block: Boolean) + /** + * Enable or disable key gossiping. + * Default is true. + * If set to false this device won't send key_request nor will accept key forwarded + */ + fun enableKeyGossiping(enable: Boolean) + + fun isKeyGossipingEnabled(): Boolean + fun setRoomUnBlacklistUnverifiedDevices(roomId: String) fun getDeviceTrackingStatus(userId: String): Int @@ -94,8 +102,6 @@ interface CryptoService { fun reRequestRoomKeyForEvent(event: Event) - fun cancelRoomKeyRequest(requestBody: RoomKeyRequestBody) - fun addRoomKeysRequestListener(listener: GossipingRequestListener) fun removeRoomKeysRequestListener(listener: GossipingRequestListener) @@ -142,14 +148,20 @@ interface CryptoService { fun addNewSessionListener(newSessionListener: NewSessionListener) fun removeSessionListener(listener: NewSessionListener) - fun getOutgoingRoomKeyRequests(): List<OutgoingRoomKeyRequest> - fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingRoomKeyRequest>> + fun getOutgoingRoomKeyRequests(): List<OutgoingKeyRequest> + fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingKeyRequest>> fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> fun getIncomingRoomKeyRequestsPaged(): LiveData<PagedList<IncomingRoomKeyRequest>> - fun getGossipingEventsTrail(): LiveData<PagedList<Event>> - fun getGossipingEvents(): List<Event> + /** + * Can be called by the app layer to accept a request manually. + * Use carefully as it is prone to social attacks. + */ + suspend fun manuallyAcceptRoomKeyRequest(request: IncomingRoomKeyRequest) + + fun getGossipingEventsTrail(): LiveData<PagedList<AuditTrail>> + fun getGossipingEvents(): List<AuditTrail> // For testing shared session fun getSharedWithInfo(roomId: String?, sessionId: String): MXUsersDevicesMap<Int> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt index 5ff4b54b110907fe8e4eb1860ff7aaa2568b7524..0b5bbe3bbdb5f38e6fd818b5490e6b8850825b6d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt @@ -28,7 +28,7 @@ sealed class MXCryptoError : Throwable() { data class Base(val errorType: ErrorType, val technicalMessage: String, /** - * Describe the error with more details + * Describe the error with more details. */ val detailedErrorDescription: String? = null) : MXCryptoError() @@ -63,7 +63,7 @@ sealed class MXCryptoError : Throwable() { companion object { /** - * Resource for technicalMessage + * Resource for technicalMessage. */ const val UNABLE_TO_ENCRYPT_REASON = "Unable to encrypt %s" const val UNABLE_TO_DECRYPT_REASON = "Unable to decrypt %1\$s. Algorithm: %2\$s" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/NewSessionListener.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/NewSessionListener.kt index 73cbf5fb78a382d1c687985063e8850bbca951d2..d9e841a50ffe01461a2bef0f0fc4e400537540b0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/NewSessionListener.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/NewSessionListener.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.session.crypto /** - * This listener notifies on new Megolm sessions being created + * This listener notifies on new Megolm sessions being created. */ interface NewSessionListener { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/OutgoingKeyRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/OutgoingKeyRequest.kt new file mode 100644 index 0000000000000000000000000000000000000000..855f17a34fff1d165893a2e92db43555a1d2f52f --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/OutgoingKeyRequest.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022 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.api.session.crypto + +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody +import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode + +data class RequestReply( + val userId: String, + val fromDevice: String?, + val result: RequestResult +) + +sealed class RequestResult { + data class Success(val chainIndex: Int) : RequestResult() + data class Failure(val code: WithHeldCode) : RequestResult() +} + +data class OutgoingKeyRequest( + var requestBody: RoomKeyRequestBody?, + // recipients for the request map of users to list of deviceId + val recipients: Map<String, List<String>>, + val fromIndex: Int, + // Unique id for this request. Used for both + // an id within the request for later pairing with a cancellation, and for + // the transaction id when sending the to_device messages to our local + val requestId: String, // current state of this request + val state: OutgoingRoomKeyRequestState, + val results: List<RequestReply> +) { + /** + * Used only for log. + * + * @return the room id. + */ + val roomId = requestBody?.roomId + + /** + * Used only for log. + * + * @return the session id + */ + val sessionId = requestBody?.sessionId +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingGossipingRequestState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/OutgoingRoomKeyRequestState.kt similarity index 57% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingGossipingRequestState.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/OutgoingRoomKeyRequestState.kt index 8c1bdf6768b5397f4457e113a09e91d20de5666f..6e80bdc1334c3df169e2594241d4c2fabcbd7f66 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingGossipingRequestState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/OutgoingRoomKeyRequestState.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 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. @@ -14,14 +14,20 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.session.crypto.model +package org.matrix.android.sdk.api.session.crypto -enum class OutgoingGossipingRequestState { +enum class OutgoingRoomKeyRequestState { UNSENT, - SENDING, SENT, - CANCELLING, - CANCELLED, - FAILED_TO_SEND, - FAILED_TO_CANCEL + SENT_THEN_CANCELED, + CANCELLATION_PENDING, + CANCELLATION_PENDING_AND_WILL_RESEND; + + companion object { + fun pendingStates() = setOf( + UNSENT, + CANCELLATION_PENDING_AND_WILL_RESEND, + CANCELLATION_PENDING + ) + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/attachments/ElementToDecrypt.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/attachments/ElementToDecrypt.kt index de168ac6e524b2501fc55bbdba6cfc50da073ccb..2591703e0c99f46211f0c01299cdc85c374e7c8c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/attachments/ElementToDecrypt.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/attachments/ElementToDecrypt.kt @@ -35,7 +35,7 @@ fun EncryptedFileInfo.toElementToDecrypt(): ElementToDecrypt? { } /** - * Represent data to decode an attachment + * Represent data to decode an attachment. */ @Parcelize data class ElementToDecrypt( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt index 46b131f613f009d19f8eb8ba370e9bd2cde103cc..5439389096bbd3cb6210f2c89d0509cd83562c05 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt @@ -66,7 +66,7 @@ interface CrossSigningService { fun markMyMasterKeyAsTrusted() /** - * Sign one of your devices and upload the signature + * Sign one of your devices and upload the signature. */ fun trustDevice(deviceId: String, callback: MatrixCallback<Unit>) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CryptoCrossSigningKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CryptoCrossSigningKey.kt index 11996e673e348b59e38b89eae91cd146447473e4..70ff76a4ef82a130dd58453181f5f74488fac4f9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CryptoCrossSigningKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CryptoCrossSigningKey.kt @@ -93,7 +93,8 @@ data class CryptoCrossSigningKey( userId = userId, usages = listOf(usage.value), keys = mapOf("ed25519:$b64key" to b64key), - signatures = signMap) + signatures = signMap + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt index 9ff99f8dce144f8f5b83a8bb3327742e9ceba868..0d40490c3e6858a290d21c0937d828cb687ce1b1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt @@ -23,7 +23,7 @@ import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult interface KeysBackupService { /** - * Retrieve the current version of the backup from the homeserver + * Retrieve the current version of the backup from the homeserver. * * It can be different than keysBackupVersion. * @param callback Asynchronous callback @@ -40,12 +40,12 @@ interface KeysBackupService { callback: MatrixCallback<KeysVersion>) /** - * Facility method to get the total number of locally stored keys + * Facility method to get the total number of locally stored keys. */ fun getTotalNumbersOfKeys(): Int /** - * Facility method to get the number of backed up keys + * Facility method to get the number of backed up keys. */ fun getTotalNumbersOfBackedUpKeys(): Int @@ -68,7 +68,7 @@ interface KeysBackupService { callback: MatrixCallback<KeysBackupVersionTrust>) /** - * Return the current progress of the backup + * Return the current progress of the backup. */ fun getBackupProgress(progressListener: ProgressListener) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupStateListener.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupStateListener.kt index a6f4bd0ec756619e0ec5dbb496c8568f8a4e9dc0..32216fe3f52baa6f515486881c78b0e1993d9e81 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupStateListener.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupStateListener.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.api.session.crypto.keysbackup interface KeysBackupStateListener { /** - * The keys backup state has changed + * The keys backup state has changed. * @param newState the new state */ fun onStateChange(newState: KeysBackupState) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt index 219a328cfdd0411e406ab7685fdbab1ca7df7375..7127c8d3f45063112dbedd822a5e9809b81e45ac 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt @@ -16,25 +16,35 @@ package org.matrix.android.sdk.api.session.crypto.keysbackup +import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo /** * A signature in a `KeysBackupVersionTrust` object. */ -data class KeysBackupVersionTrustSignature( - /** - * The id of the device that signed the backup version. - */ - val deviceId: String?, - - /** - * The device that signed the backup version. - * Can be null if the device is not known. - */ - val device: CryptoDeviceInfo?, - - /** - * Flag to indicate the signature from this device is valid. - */ - val valid: Boolean, -) + +sealed class KeysBackupVersionTrustSignature { + + data class DeviceSignature( + /** + * The id of the device that signed the backup version. + */ + val deviceId: String?, + + /** + * The device that signed the backup version. + * Can be null if the device is not known. + */ + val device: CryptoDeviceInfo?, + + /** + * Flag to indicate the signature from this device is valid. + */ + val valid: Boolean) : KeysBackupVersionTrustSignature() + + data class UserSignature( + val keyId: String?, + val cryptoCrossSigningKey: CryptoCrossSigningKey?, + val valid: Boolean + ) : KeysBackupVersionTrustSignature() +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysVersionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysVersionResult.kt index f283a34e98f665ded75c3cc32beb21c57a3d13a6..3d89bf9e2fec99e225acdc7e7093ae6ce9914b04 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysVersionResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysVersionResult.kt @@ -30,8 +30,8 @@ data class KeysVersionResult( override val algorithm: String, /** - * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" - * see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData] + * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2". + * @see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData] */ @Json(name = "auth_data") override val authData: JsonDict, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/RecoveryKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/RecoveryKey.kt index 85d6ef43653a8481134c19aa57bb87fc76c7d66c..9ad0bfc8b688585063dd10eedb9899bd17d9a43c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/RecoveryKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/RecoveryKey.kt @@ -30,7 +30,7 @@ private const val CHAR_1 = 0x01.toByte() private const val RECOVERY_KEY_LENGTH = 2 + 32 + 1 /** - * Tell if the format of the recovery key is correct + * Tell if the format of the recovery key is correct. * * @param recoveryKey * @return true if the format of the recovery key is correct @@ -40,7 +40,7 @@ fun isValidRecoveryKey(recoveryKey: String?): Boolean { } /** - * Compute recovery key from curve25519 key + * Compute recovery key from curve25519 key. * * @param curve25519Key * @return the recovery key @@ -69,7 +69,7 @@ fun computeRecoveryKey(curve25519Key: ByteArray): String { } /** - * Please call [.isValidRecoveryKey] and ensure it returns true before calling this method + * Please call [.isValidRecoveryKey] and ensure it returns true before calling this method. * * @param recoveryKey the recovery key * @return curveKey, or null in case of error diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keyshare/GossipingRequestListener.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keyshare/GossipingRequestListener.kt index 3cd36c2ce8cdd6a6bd9b18d70b6e9da1fe059171..cc160f8d859530950c3286829b7f9f9d5f98d782 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keyshare/GossipingRequestListener.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keyshare/GossipingRequestListener.kt @@ -16,12 +16,11 @@ package org.matrix.android.sdk.api.session.crypto.keyshare -import org.matrix.android.sdk.api.session.crypto.model.IncomingRequestCancellation import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest -import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest +import org.matrix.android.sdk.api.session.crypto.model.SecretShareRequest /** - * Room keys events listener + * Room keys events listener. */ interface GossipingRequestListener { /** @@ -32,15 +31,15 @@ interface GossipingRequestListener { fun onRoomKeyRequest(request: IncomingRoomKeyRequest) /** - * Returns the secret value to be shared + * Returns the secret value to be shared. * @return true if is handled */ - fun onSecretShareRequest(request: IncomingSecretShareRequest): Boolean + fun onSecretShareRequest(request: SecretShareRequest): Boolean /** * A room key request cancellation has been received. * * @param request the cancellation request */ - fun onRoomKeyRequestCancellation(request: IncomingRequestCancellation) + fun onRequestCancelled(request: IncomingRoomKeyRequest) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/AuditTrail.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/AuditTrail.kt new file mode 100644 index 0000000000000000000000000000000000000000..861f3bd30b0b6693fdb3b84c8f72a929ad3a756d --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/AuditTrail.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2022 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.api.session.crypto.model + +import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode + +enum class TrailType { + OutgoingKeyForward, + IncomingKeyForward, + OutgoingKeyWithheld, + IncomingKeyRequest, + Unknown +} + +interface AuditInfo { + val roomId: String + val sessionId: String + val senderKey: String + val alg: String + val userId: String + val deviceId: String +} + +@JsonClass(generateAdapter = true) +data class ForwardInfo( + override val roomId: String, + override val sessionId: String, + override val senderKey: String, + override val alg: String, + override val userId: String, + override val deviceId: String, + val chainIndex: Long? +) : AuditInfo + +object UnknownInfo : AuditInfo { + override val roomId: String = "" + override val sessionId: String = "" + override val senderKey: String = "" + override val alg: String = "" + override val userId: String = "" + override val deviceId: String = "" +} + +@JsonClass(generateAdapter = true) +data class WithheldInfo( + override val roomId: String, + override val sessionId: String, + override val senderKey: String, + override val alg: String, + val code: WithHeldCode, + override val userId: String, + override val deviceId: String +) : AuditInfo + +@JsonClass(generateAdapter = true) +data class IncomingKeyRequestInfo( + override val roomId: String, + override val sessionId: String, + override val senderKey: String, + override val alg: String, + override val userId: String, + override val deviceId: String, + val requestId: String +) : AuditInfo + +data class AuditTrail( + val ageLocalTs: Long, + val type: TrailType, + val info: AuditInfo +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/DeviceInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/DeviceInfo.kt index 221d0793d94e88a92d82115a5a8772d61a91cb85..b144069b9947b49f5eeeb10959eab881c53f763d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/DeviceInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/DeviceInfo.kt @@ -20,24 +20,24 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.interfaces.DatedObject /** - * This class describes the device information + * This class describes the device information. */ @JsonClass(generateAdapter = true) data class DeviceInfo( /** - * The owner user id (not documented and useless but the homeserver sent it. You should not need it) + * The owner user id (not documented and useless but the homeserver sent it. You should not need it). */ @Json(name = "user_id") val userId: String? = null, /** - * The device id + * The device id. */ @Json(name = "device_id") val deviceId: String? = null, /** - * The device display name + * The device display name. */ @Json(name = "display_name") val displayName: String? = null, @@ -49,7 +49,7 @@ data class DeviceInfo( val lastSeenTs: Long? = null, /** - * The last ip address + * The last ip address. */ @Json(name = "last_seen_ip") val lastSeenIp: String? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileInfo.kt index 13ad1df47655389e5d2623508dc1b3bdce58054b..fb64c6f3384ccf679d5ee1cd0132b6caca5c4b28 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileInfo.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * In Matrix specs: EncryptedFile + * In Matrix specs: EncryptedFile. */ @JsonClass(generateAdapter = true) data class EncryptedFileInfo( @@ -56,7 +56,7 @@ data class EncryptedFileInfo( val v: String? = null ) { /** - * Check what the spec tells us + * Check what the spec tells us. */ fun isValid(): Boolean { if (url.isNullOrBlank()) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileKey.kt index 859c6ac43f0dc374a8c5fd6c32bc09abef705e0c..6308e3d615e6282340fcdc5cbfc5807e5df7da2a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileKey.kt @@ -52,7 +52,7 @@ data class EncryptedFileKey( val k: String? = null ) { /** - * Check what the spec tells us + * Check what the spec tells us. */ fun isValid(): Boolean { if (alg != "A256CTR") { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingToDeviceObject.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingToDeviceObject.kt index 1922b2bceef7eaec21ded77307eddcb423d2b764..ac575332da12ec254537939f63118b76d97328a7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingToDeviceObject.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingToDeviceObject.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.session.crypto.model /** - * Interface representing an room key action request + * Interface representing an room key action request. * Note: this class cannot be abstract because of [org.matrix.androidsdk.core.JsonUtils.toRoomKeyShare] */ interface GossipingToDeviceObject : SendToDeviceObject { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRequestCancellation.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRequestCancellation.kt deleted file mode 100755 index ad11ef9a5e465b2cfc04a92af2ecd43511404dbf..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRequestCancellation.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.api.session.crypto.model - -import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.api.session.events.model.toModel -import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon -import org.matrix.android.sdk.internal.crypto.model.rest.ShareRequestCancellation - -/** - * IncomingRequestCancellation describes the incoming room key cancellation. - */ -data class IncomingRequestCancellation( - /** - * The user id - */ - override val userId: String? = null, - - /** - * The device id - */ - override val deviceId: String? = null, - - /** - * The request id - */ - override val requestId: String? = null, - override val localCreationTimestamp: Long? -) : IncomingShareRequestCommon { - companion object { - /** - * Factory - * - * @param event the event - * @param currentTimeMillis the current time in milliseconds - */ - fun fromEvent(event: Event, currentTimeMillis: Long): IncomingRequestCancellation? { - return event.getClearContent() - .toModel<ShareRequestCancellation>() - ?.let { - IncomingRequestCancellation( - userId = event.senderId, - deviceId = it.requestingDeviceId, - requestId = it.requestId, - localCreationTimestamp = event.ageLocalTs ?: currentTimeMillis - ) - } - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt index 0b2c32284b05edd79316b5de883b5b5bb8e4d232..0c19d275cc375a4f47206fdaf0dc9966ce858d61 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt @@ -16,68 +16,71 @@ package org.matrix.android.sdk.api.session.crypto.model -import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.api.session.events.model.toModel -import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon +import org.matrix.android.sdk.internal.util.time.Clock /** * IncomingRoomKeyRequest class defines the incoming room keys request. */ data class IncomingRoomKeyRequest( /** - * The user id + * The user id. */ - override val userId: String? = null, + val userId: String? = null, /** - * The device id + * The device id. */ - override val deviceId: String? = null, + val deviceId: String? = null, /** - * The request id + * The request id. */ - override val requestId: String? = null, + val requestId: String? = null, /** - * The request body + * The request body. */ val requestBody: RoomKeyRequestBody? = null, - val state: GossipingRequestState = GossipingRequestState.NONE, - - /** - * The runnable to call to accept to share the keys - */ - @Transient - var share: Runnable? = null, - - /** - * The runnable to call to ignore the key share request. - */ - @Transient - var ignore: Runnable? = null, - override val localCreationTimestamp: Long? -) : IncomingShareRequestCommon { + val localCreationTimestamp: Long? +) { companion object { /** - * Factory + * Factory. * * @param event the event * @param currentTimeMillis the current time in milliseconds */ - fun fromEvent(event: Event, currentTimeMillis: Long): IncomingRoomKeyRequest? { - return event.getClearContent() - .toModel<RoomKeyShareRequest>() + fun fromEvent(trail: AuditTrail): IncomingRoomKeyRequest? { + return trail + .takeIf { it.type == TrailType.IncomingKeyRequest } + ?.let { + it.info as? IncomingKeyRequestInfo + } ?.let { IncomingRoomKeyRequest( - userId = event.senderId, - deviceId = it.requestingDeviceId, + userId = it.userId, + deviceId = it.deviceId, requestId = it.requestId, - requestBody = it.body ?: RoomKeyRequestBody(), - localCreationTimestamp = event.ageLocalTs ?: currentTimeMillis + requestBody = RoomKeyRequestBody( + algorithm = it.alg, + roomId = it.roomId, + senderKey = it.senderKey, + sessionId = it.sessionId + ), + localCreationTimestamp = trail.ageLocalTs ) } } + + internal fun fromRestRequest(senderId: String, request: RoomKeyShareRequest, clock: Clock): IncomingRoomKeyRequest? { + return IncomingRoomKeyRequest( + userId = senderId, + deviceId = request.requestingDeviceId, + requestId = request.requestId, + requestBody = request.body, + localCreationTimestamp = clock.epochMillis() + ) + } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingSecretShareRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingSecretShareRequest.kt deleted file mode 100755 index 80f70c83f3a6e7671bc53cc463b95b448ebe7d4e..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingSecretShareRequest.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.api.session.crypto.model - -import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.api.session.events.model.toModel -import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon - -/** - * IncomingSecretShareRequest class defines the incoming secret keys request. - */ -data class IncomingSecretShareRequest( - /** - * The user id - */ - override val userId: String? = null, - - /** - * The device id - */ - override val deviceId: String? = null, - - /** - * The request id - */ - override val requestId: String? = null, - - /** - * The request body - */ - val secretName: String? = null, - - /** - * The runnable to call to accept to share the keys - */ - @Transient - var share: ((String) -> Unit)? = null, - - /** - * The runnable to call to ignore the key share request. - */ - @Transient - var ignore: Runnable? = null, - - override val localCreationTimestamp: Long? - -) : IncomingShareRequestCommon { - companion object { - /** - * Factory - * - * @param event the event - * @param currentTimeMillis the current time in milliseconds - */ - fun fromEvent(event: Event, currentTimeMillis: Long): IncomingSecretShareRequest? { - return event.getClearContent() - .toModel<SecretShareRequest>() - ?.let { - IncomingSecretShareRequest( - userId = event.senderId, - deviceId = it.requestingDeviceId, - requestId = it.requestId, - secretName = it.secretName, - localCreationTimestamp = event.ageLocalTs ?: currentTimeMillis - ) - } - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXDeviceInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXDeviceInfo.kt index 286ab2b7d518ef0f55dd33b5bc569dbcc1ea5241..a5a581d240279ed6e1137d0d19af94b4a42261c6 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXDeviceInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXDeviceInfo.kt @@ -30,7 +30,7 @@ data class MXDeviceInfo( val deviceId: String, /** - * the user id + * the user id. */ @Json(name = "user_id") val userId: String, @@ -66,7 +66,7 @@ data class MXDeviceInfo( val verified: Int = DEVICE_VERIFICATION_UNKNOWN ) : Serializable { /** - * Tells if the device is unknown + * Tells if the device is unknown. * * @return true if the device is unknown */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXEncryptEventContentResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXEncryptEventContentResult.kt index 706e40a769e485b298edb2911ac828b30e9bab0b..4cfcc01a26f1e2b87f0fbe379453942464fa557f 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXEncryptEventContentResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXEncryptEventContentResult.kt @@ -20,11 +20,11 @@ import org.matrix.android.sdk.api.session.events.model.Content data class MXEncryptEventContentResult( /** - * The encrypted event content + * The encrypted event content. */ val eventContent: Content, /** - * the event type + * The event type. */ val eventType: String ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXUsersDevicesMap.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXUsersDevicesMap.kt index dc5567e908d760354ff95efd1dc35b137e41de8b..744fe74d0da947bf5b0b2d141cf340f4a8b6e6e9 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXUsersDevicesMap.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXUsersDevicesMap.kt @@ -31,7 +31,7 @@ class MXUsersDevicesMap<E> { get() = map.isEmpty() /** - * Provides the device ids list for a user id + * Provides the device ids list for a user id. * FIXME Should maybe return emptyList and not null, to avoid many !! in the code * * @param userId the user id @@ -44,7 +44,7 @@ class MXUsersDevicesMap<E> { } /** - * Provides the object for a device id and a user Id + * Provides the object for a device id and a user Id. * * @param deviceId the device id * @param userId the object id @@ -57,7 +57,7 @@ class MXUsersDevicesMap<E> { } /** - * Set an object for a dedicated user Id and device Id + * Set an object for a dedicated user Id and device Id. * * @param userId the user Id * @param deviceId the device id @@ -71,7 +71,7 @@ class MXUsersDevicesMap<E> { } /** - * Defines the objects map for a user Id + * Defines the objects map for a user Id. * * @param objectsPerDevices the objects maps * @param userId the user id @@ -87,7 +87,7 @@ class MXUsersDevicesMap<E> { } /** - * Removes objects for a dedicated user + * Removes objects for a dedicated user. * * @param userId the user id. */ @@ -98,14 +98,14 @@ class MXUsersDevicesMap<E> { } /** - * Clear the internal dictionary + * Clear the internal dictionary. */ fun removeAllObjects() { map.clear() } /** - * Add entries from another MXUsersDevicesMap + * Add entries from another MXUsersDevicesMap. * * @param other the other one */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OlmDecryptionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OlmDecryptionResult.kt index 9cf2bf75fbd27206d91b683ebd0e46b75edd14b9..a26f6606edd1a8f7fea8108520ad9a277619b516 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OlmDecryptionResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OlmDecryptionResult.kt @@ -26,7 +26,7 @@ import org.matrix.android.sdk.api.util.JsonDict @JsonClass(generateAdapter = true) data class OlmDecryptionResult( /** - * The decrypted payload (with properties 'type', 'content') + * The decrypted payload (with properties 'type', 'content'). */ @Json(name = "payload") val payload: JsonDict? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingRoomKeyRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingRoomKeyRequest.kt deleted file mode 100755 index 5f35cc908f9bd63d736cdc16082848972d18069d..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingRoomKeyRequest.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.api.session.crypto.model - -import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequest - -/** - * Represents an outgoing room key request - */ -@JsonClass(generateAdapter = true) -data class OutgoingRoomKeyRequest( - // RequestBody - val requestBody: RoomKeyRequestBody?, - // list of recipients for the request - override val recipients: Map<String, List<String>>, - // Unique id for this request. Used for both - // an id within the request for later pairing with a cancellation, and for - // the transaction id when sending the to_device messages to our local - override val requestId: String, // current state of this request - override val state: OutgoingGossipingRequestState - // transaction id for the cancellation, if any - // override var cancellationTxnId: String? = null -) : OutgoingGossipingRequest { - - /** - * Used only for log. - * - * @return the room id. - */ - val roomId: String? - get() = requestBody?.roomId - - /** - * Used only for log. - * - * @return the session id - */ - val sessionId: String? - get() = requestBody?.sessionId -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyRequestBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyRequestBody.kt index 15163248dc94365e5faf0569dafacbe3ac7d551e..8352949263d3379de0bc4a5228f2fff34fcd11f0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyRequestBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyRequestBody.kt @@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.internal.di.MoshiProvider /** - * Class representing an room key request body content + * Class representing an room key request body content. */ @JsonClass(generateAdapter = true) data class RoomKeyRequestBody( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyShareRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyShareRequest.kt index b6bb4c55af9f1f5acf217265968b92d429555d93..adbe831a07ffbbdf3be42e69049e934d7cd428f1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyShareRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyShareRequest.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing a room key request content + * Class representing a room key request content. */ @JsonClass(generateAdapter = true) data class RoomKeyShareRequest( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/SecretShareRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/SecretShareRequest.kt index 6009077806146c541581a6a99618de17dd5e3d20..263a7b16e4d2b22fca448d548f6fd4e43ef8d410 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/SecretShareRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/SecretShareRequest.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing a room key request content + * Class representing a room key request content. */ @JsonClass(generateAdapter = true) data class SecretShareRequest( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/PendingVerificationRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/PendingVerificationRequest.kt index be450b9d03c2a9e43050353841bdc3697d4fd002..7db450e8613b250686a21497dd77e90f1ca684d8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/PendingVerificationRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/PendingVerificationRequest.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_SAS import java.util.UUID /** - * Stores current pending verification requests + * Stores current pending verification requests. */ data class PendingVerificationRequest( val ageLocalTs: Long, @@ -45,7 +45,7 @@ data class PendingVerificationRequest( val isFinished: Boolean = isSuccessful || cancelConclusion != null /** - * SAS is supported if I support it and the other party support it + * SAS is supported if I support it and the other party support it. */ fun isSasSupported(): Boolean { return requestInfo?.methods?.contains(VERIFICATION_METHOD_SAS).orFalse() && @@ -53,7 +53,7 @@ data class PendingVerificationRequest( } /** - * Other can show QR code if I can scan QR code and other can show QR code + * Other can show QR code if I can scan QR code and other can show QR code. */ fun otherCanShowQrCode(): Boolean { return if (isIncoming) { @@ -66,7 +66,7 @@ data class PendingVerificationRequest( } /** - * Other can scan QR code if I can show QR code and other can scan QR code + * Other can scan QR code if I can show QR code and other can scan QR code. */ fun otherCanScanQrCode(): Boolean { return if (isIncoming) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/QrCodeVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/QrCodeVerificationTransaction.kt index 37855099be34d516bc61dea321c0c9528ce12e26..06bac4109b4783e777f70a289401de893cae8d04 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/QrCodeVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/QrCodeVerificationTransaction.kt @@ -19,22 +19,22 @@ package org.matrix.android.sdk.api.session.crypto.verification interface QrCodeVerificationTransaction : VerificationTransaction { /** - * To use to display a qr code, for the other user to scan it + * To use to display a qr code, for the other user to scan it. */ val qrCodeText: String? /** - * Call when you have scan the other user QR code + * Call when you have scan the other user QR code. */ fun userHasScannedOtherQrCode(otherQrCodeText: String) /** - * Call when you confirm that other user has scanned your QR code + * Call when you confirm that other user has scanned your QR code. */ fun otherUserScannedMyQrCode() /** - * Call when you do not confirm that other user has scanned your QR code + * Call when you do not confirm that other user has scanned your QR code. */ fun otherUserDidNotScannedMyQrCode() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/SasVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/SasVerificationTransaction.kt index da546be68f39a984119811175a896e02adcf5cca..095b4208f8654e458d0aa1b4332594f100bd8e17 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/SasVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/SasVerificationTransaction.kt @@ -28,7 +28,7 @@ interface SasVerificationTransaction : VerificationTransaction { /** * To be called by the client when the user has verified that - * both short codes do match + * both short codes do match. */ fun userHasVerifiedShortCode() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt index 4efec93a34cf3b995167eaa3e2fe316480430e4e..f2de2c4b47ed2fedd920021d9dcd21e5d9a6a9ee 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationMethod.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.session.crypto.verification /** - * Verification methods + * Verification methods. */ enum class VerificationMethod { // Use it when your application supports the SAS verification method diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt index ec67e4b31d143adfdc048d6eea232d8be0376546..321ec7309403b5a961b96a7f26ae85e214b32fb2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt @@ -34,7 +34,7 @@ interface VerificationService { fun removeListener(listener: Listener) /** - * Mark this device as verified manually + * Mark this device as verified manually. */ fun markedLocallyAsManuallyVerified(userId: String, deviceID: String) @@ -52,7 +52,7 @@ interface VerificationService { transactionId: String?): String? /** - * Request key verification with another user via room events (instead of the to-device API) + * Request key verification with another user via room events (instead of the to-device API). */ fun requestKeyVerificationInDMs(methods: List<VerificationMethod>, otherUserId: String, @@ -81,7 +81,7 @@ interface VerificationService { otherDeviceId: String): String /** - * Returns false if the request is unknown + * Returns false if the request is unknown. */ fun readyPendingVerificationInDMs(methods: List<VerificationMethod>, otherUserId: String, @@ -89,7 +89,7 @@ interface VerificationService { transactionId: String): Boolean /** - * Returns false if the request is unknown + * Returns false if the request is unknown. */ fun readyPendingVerification(methods: List<VerificationMethod>, otherUserId: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTransaction.kt index 4d35bc44ace9e74092e61b52283bfa0b18b655d2..b68a82c604013a5a82d6398567c7a0a19d8af513 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTransaction.kt @@ -28,7 +28,7 @@ interface VerificationTransaction { val isIncoming: Boolean /** - * User wants to cancel the transaction + * User wants to cancel the transaction. */ fun cancel() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt index 1ce51a2bded08c7c43c1e83ccd690bc8da7a6779..16bdbd3432bd5bfb1d67a999af754803ff361c0a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt @@ -62,7 +62,7 @@ inline fun <reified T> Content?.toModel(catchError: Boolean = true): T? { } /** - * This methods is a facility method to map a model to a json Content + * This methods is a facility method to map a model to a json Content. */ @Suppress("UNCHECKED_CAST") inline fun <reified T> T.toContent(): Content { @@ -123,7 +123,7 @@ data class Event( var ageLocalTs: Long? = null /** - * Copy all fields, including transient fields + * Copy all fields, including transient fields. */ fun copyAll(): Event { return copy().also { @@ -227,14 +227,14 @@ data class Event( } /** - * Determines whether or not current event has mentioned the user + * Determines whether or not current event has mentioned the user. */ fun isUserMentioned(userId: String): Boolean { return getDecryptedValue("formatted_body")?.contains(userId) ?: false } /** - * Decrypt the message, or return the pure payload value if there is no encryption + * Decrypt the message, or return the pure payload value if there is no encryption. */ private fun getDecryptedValue(key: String = "body"): String? { return if (isEncrypted()) { @@ -247,7 +247,7 @@ data class Event( } /** - * Tells if the event is redacted + * Tells if the event is redacted. */ fun isRedacted() = unsignedData?.redactedEvent != null @@ -305,7 +305,7 @@ data class Event( /** * Return the value of "content.msgtype", if the Event type is "m.room.message" - * and if the content has it, and if it is a String + * and if the content has it, and if it is a String. */ fun Event.getMsgType(): String? { if (getClearType() != EventType.MESSAGE) return null @@ -386,13 +386,13 @@ fun Event.getRelationContent(): RelationDefaultContent? { } /** - * Returns the poll question or null otherwise + * Returns the poll question or null otherwise. */ fun Event.getPollQuestion(): String? = getPollContent()?.getBestPollCreationInfo()?.question?.getBestQuestion() /** - * Returns the relation content for a specific type or null otherwise + * Returns the relation content for a specific type or null otherwise. */ fun Event.getRelationContentForType(type: String): RelationDefaultContent? = getRelationContent()?.takeIf { it.type == type } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/RelationType.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/RelationType.kt index 74dc74b294964e2669c558405f2bec33c59eb386..3db9262c5b102fc2da4399f65d4398a4c0106c17 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/RelationType.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/RelationType.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.api.session.events.model /** - * Constants defining known event relation types from Matrix specifications + * Constants defining known event relation types from Matrix specifications. */ object RelationType { /** Lets you define an event which annotates an existing event.*/ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptedEventContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptedEventContent.kt index 4f39bb61e14871cc5d79b44e94fa57b994fc6026..b8388ea00246b57e0c41c26725ec5879d8f8eb49 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptedEventContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptedEventContent.kt @@ -20,37 +20,37 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent /** - * Class representing an encrypted event content + * Class representing an encrypted event content. */ @JsonClass(generateAdapter = true) data class EncryptedEventContent( /** - * the used algorithm + * The used algorithm. */ @Json(name = "algorithm") val algorithm: String? = null, /** - * The encrypted event + * The encrypted event. */ @Json(name = "ciphertext") val ciphertext: String? = null, /** - * The device id + * The device id. */ @Json(name = "device_id") val deviceId: String? = null, /** - * the sender key + * The sender key. */ @Json(name = "sender_key") val senderKey: String? = null, /** - * The session id + * The session id. */ @Json(name = "session_id") val sessionId: String? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptionEventContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptionEventContent.kt index 103293ba8316fc88949389b51fcb9f92a1996f92..321afd186d381ebdca70472470d00fac066a06a3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptionEventContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptionEventContent.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing an encrypted event content + * Class representing an encrypted event content. */ @JsonClass(generateAdapter = true) data class EncryptionEventContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmEventContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmEventContent.kt index b972dd20bbf622a32b86e3b2ae2559dd52452d9a..65e81281821165786de143cfea58b6290f2ed602 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmEventContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmEventContent.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing an encrypted event content + * Class representing an encrypted event content. */ @JsonClass(generateAdapter = true) data class OlmEventContent( @@ -30,7 +30,7 @@ data class OlmEventContent( val ciphertext: Map<String, Any>? = null, /** - * the sender key + * the sender key. */ @Json(name = "sender_key") val senderKey: String? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmPayloadContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmPayloadContent.kt index 6060ab5c4b258f6a023818e04014114db47ebec2..c3d8a5a800cec01a9aa17a07ba9c756de8ef120e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmPayloadContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmPayloadContent.kt @@ -20,36 +20,36 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.internal.di.MoshiProvider /** - * Class representing the OLM payload content + * Class representing the OLM payload content. */ @JsonClass(generateAdapter = true) data class OlmPayloadContent( /** - * The room id + * The room id. */ @Json(name = "room_id") val roomId: String? = null, /** - * The sender + * The sender. */ @Json(name = "sender") val sender: String? = null, /** - * The recipient + * The recipient. */ @Json(name = "recipient") val recipient: String? = null, /** - * the recipient keys + * The recipient keys. */ @Json(name = "recipient_keys") val recipientKeys: Map<String, String>? = null, /** - * The keys + * The keys. */ @Json(name = "keys") val keys: Map<String, String>? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyContent.kt index 43a47b818f6bf856adf286a7a366ff72e2990456..0830a566ab86d6bc301a5f94004f93b3bf369819 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyContent.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing an sharekey content + * Class representing an sharekey content. */ @JsonClass(generateAdapter = true) data class RoomKeyContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt index a577daf9e42cf0cb2729b384eed455feea447da9..d58c3614a70af1f0ef522243c0595dcacc1b79d6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing an sharekey content + * Class representing an sharekey content. */ @JsonClass(generateAdapter = true) data class RoomKeyWithHeldContent( @@ -52,7 +52,13 @@ data class RoomKeyWithHeldContent( /** * A human-readable reason for why the key was not sent. The receiving client should only use this string if it does not understand the code. */ - @Json(name = "reason") val reason: String? = null + @Json(name = "reason") val reason: String? = null, + + /** + * the device ID of the device sending the m.room_key.withheld message + * MSC3735. + */ + @Json(name = "from_device") val fromDevice: String? = null ) { val code: WithHeldCode? @@ -63,23 +69,23 @@ data class RoomKeyWithHeldContent( enum class WithHeldCode(val value: String) { /** - * the user/device was blacklisted + * the user/device was blacklisted. */ BLACKLISTED("m.blacklisted"), /** - * the user/devices is unverified + * the user/devices is unverified. */ UNVERIFIED("m.unverified"), /** * the user/device is not allowed have the key. For example, this would usually be sent in response - * to a key request if the user was not in the room when the message was sent + * to a key request if the user was not in the room when the message was sent. */ UNAUTHORISED("m.unauthorised"), /** - * Sent in reply to a key request if the device that the key is requested from does not have the requested key + * Sent in reply to a key request if the device that the key is requested from does not have the requested key. */ UNAVAILABLE("m.unavailable"), diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/SecretSendEventContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/SecretSendEventContent.kt index 5099aba403066b7747271e23451b61a63f17c1c7..be9d9d638c9e1858c319d39303cbe9a333ecf344 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/SecretSendEventContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/SecretSendEventContent.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing an encrypted event content + * Class representing an encrypted event content. */ @JsonClass(generateAdapter = true) data class SecretSendEventContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt index e3ccbad2490b712587f7e15779c3524ad8ea30f3..84a99908268ecccf607f51473b7e9cb90ddea35b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt @@ -68,11 +68,12 @@ interface FileService { mxcUrl = messageContent.getFileUrl(), fileName = messageContent.getFileName(), mimeType = messageContent.mimeType, - elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt()) + elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt() + ) /** * Use this URI and pass it to intent using flag Intent.FLAG_GRANT_READ_URI_PERMISSION - * (if not other app won't be able to access it) + * (if not other app won't be able to access it). */ fun getTemporarySharableURI(mxcUrl: String?, fileName: String, @@ -105,17 +106,17 @@ interface FileService { ) /** - * Clears all the files downloaded by the service, including decrypted files + * Clears all the files downloaded by the service, including decrypted files. */ fun clearCache() /** - * Clears all the decrypted files by the service + * Clears all the decrypted files by the service. */ fun clearDecryptedCache() /** - * Get size of cached files + * Get size of cached files. */ fun getCacheSize(): Long } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/MatrixSDKFileProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/MatrixSDKFileProvider.kt index ee1550d1db905029eb9a82767f2033af92a916e2..113bf9333f5a58fd4bd302024f87198ec51ad1b3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/MatrixSDKFileProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/MatrixSDKFileProvider.kt @@ -21,7 +21,7 @@ import androidx.core.content.FileProvider /** * We have to declare our own file provider to avoid collision with apps using the sdk - * and having their own + * and having their own. */ class MatrixSDKFileProvider : FileProvider() { override fun getType(uri: Uri): String? { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupService.kt index a96466603c5eadbe248f25f871e00835685a513b..1968af222aa1c6c44912302ad0561f8f3433b94a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupService.kt @@ -23,16 +23,15 @@ import org.matrix.android.sdk.api.session.group.model.GroupSummary * This interface defines methods to get groups. It's implemented at the session level. */ interface GroupService { - /** - * Get a group from a groupId + * Get a group from a groupId. * @param groupId the groupId to look for. * @return the group with groupId or null */ fun getGroup(groupId: String): Group? /** - * Get a groupSummary from a groupId + * Get a groupSummary from a groupId. * @param groupId the groupId to look for. * @return the groupSummary with groupId or null */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupSummaryQueryParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupSummaryQueryParams.kt index 0761a22c777ba153396c9e52c18466bd7cbe11d9..5104b3ee5371a5b0e53c2a892f82e408e27dcaed 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupSummaryQueryParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/group/GroupSummaryQueryParams.kt @@ -24,7 +24,7 @@ fun groupSummaryQueryParams(init: (GroupSummaryQueryParams.Builder.() -> Unit) = } /** - * This class can be used to filter group summaries + * This class can be used to filter group summaries. */ data class GroupSummaryQueryParams( val displayName: QueryStringValue, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt index 597c1a0ca8df0087f0b6d44a0f5eceefadb4eec6..5b06fdacae2c938fa9126c3a398ac94d488d309e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt @@ -34,25 +34,25 @@ data class HomeServerCapabilities( */ val canChange3pid: Boolean = true, /** - * Max size of file which can be uploaded to the homeserver in bytes. [MAX_UPLOAD_FILE_SIZE_UNKNOWN] if unknown or not retrieved yet + * Max size of file which can be uploaded to the homeserver in bytes. [MAX_UPLOAD_FILE_SIZE_UNKNOWN] if unknown or not retrieved yet. */ val maxUploadFileSize: Long = MAX_UPLOAD_FILE_SIZE_UNKNOWN, /** - * Last version identity server and binding supported + * Last version identity server and binding supported. */ val lastVersionIdentityServerSupported: Boolean = false, /** - * Default identity server url, provided in Wellknown + * Default identity server url, provided in Wellknown. */ val defaultIdentityServerUrl: String? = null, /** - * Room versions supported by the server + * Room versions supported by the server. * This capability describes the default and available room versions a server supports, and at what level of stability. * Clients should make use of this capability to determine if users need to be encouraged to upgrade their rooms. */ val roomVersions: RoomVersionCapabilities? = null, /** - * True if the home server support threading + * True if the home server support threading. */ val canUseThreading: Boolean = false ) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesService.kt index f12cbcd6db12b79a7a8dabf6436447bc5317869e..9d2c48e194f930a7f47e0f5642a7f602b9e59f76 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesService.kt @@ -22,12 +22,12 @@ package org.matrix.android.sdk.api.session.homeserver interface HomeServerCapabilitiesService { /** - * Force a refresh of the stored data + * Force a refresh of the stored data. */ suspend fun refreshHomeServerCapabilities() /** - * Get the HomeServer capabilities + * Get the HomeServer capabilities. */ fun getHomeServerCapabilities(): HomeServerCapabilities } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt index fdcb30a5c826390f8a0e1b68053d6586992f1e44..c03b42e6c894037487126dc7e7b133be156ace9b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt @@ -19,13 +19,13 @@ package org.matrix.android.sdk.api.session.identity import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult /** - * Provides access to the identity server configuration and services identity server can provide + * Provides access to the identity server configuration and services identity server can provide. */ interface IdentityService { /** * Return the default identity server of the user, which may have been provided at login time by the homeserver, - * or by the Well-known setup of the homeserver - * It may be different from the current configured identity server + * or by the Well-known setup of the homeserver. + * It may be different from the current configured identity server. */ fun getDefaultIdentityServer(): String? @@ -35,9 +35,9 @@ interface IdentityService { fun getCurrentIdentityServerUrl(): String? /** - * Check if the identity server is valid - * See https://matrix.org/docs/spec/identity_service/latest#status-check - * Matrix Android SDK2 only supports identity server API v2 + * Check if the identity server is valid. + * See https://matrix.org/docs/spec/identity_service/latest#status-check. + * Matrix Android SDK2 only supports identity server API v2. */ suspend fun isValidIdentityServer(url: String) @@ -52,12 +52,12 @@ interface IdentityService { suspend fun setNewIdentityServer(url: String): String /** - * Disconnect (logout) from the current identity server + * Disconnect (logout) from the current identity server. */ suspend fun disconnect() /** - * This will ask the identity server to send an email or an SMS to let the user confirm he owns the ThreePid + * This will ask the identity server to send an email or an SMS to let the user confirm he owns the ThreePid. */ suspend fun startBindThreePid(threePid: ThreePid) @@ -67,32 +67,32 @@ interface IdentityService { suspend fun cancelBindThreePid(threePid: ThreePid) /** - * This will ask the identity server to send an new email or a new SMS to let the user confirm he owns the ThreePid + * This will ask the identity server to send an new email or a new SMS to let the user confirm he owns the ThreePid. */ suspend fun sendAgainValidationCode(threePid: ThreePid) /** - * Submit the code that the identity server has sent to the user (in email or SMS) + * Submit the code that the identity server has sent to the user (in email or SMS). * Once successful, you will have to call [finalizeBindThreePid] * @param code the code sent to the user */ suspend fun submitValidationToken(threePid: ThreePid, code: String) /** - * This will perform the actual association of ThreePid and Matrix account + * This will perform the actual association of ThreePid and Matrix account. */ suspend fun finalizeBindThreePid(threePid: ThreePid) /** - * Unbind a threePid - * The request will actually be done on the homeserver + * Unbind a threePid. + * The request will actually be done on the homeserver. */ suspend fun unbindThreePid(threePid: ThreePid) /** - * Search MatrixId of users providing email and phone numbers - * Note the the user consent has to be set to true, or it will throw a UserConsentNotProvided failure - * Application has to explicitly ask for the user consent, and the answer can be stored using [setUserConsent] + * Search MatrixId of users providing email and phone numbers. + * Note the the user consent has to be set to true, or it will throw a UserConsentNotProvided failure. + * Application has to explicitly ask for the user consent, and the answer can be stored using [setUserConsent]. * Please see https://support.google.com/googleplay/android-developer/answer/9888076?hl=en for more details. */ suspend fun lookUp(threePids: List<ThreePid>): List<FoundThreePid> @@ -115,8 +115,8 @@ interface IdentityService { fun setUserConsent(newValue: Boolean) /** - * Get the status of the current user's threePid - * A lookup will be performed, but also pending binding state will be restored + * Get the status of the current user's threePid. + * A lookup will be performed, but also pending binding state will be restored. * * @param threePids the list of threePid the user owns (retrieved form the homeserver) * @return a map of ThreePid -> SharedState @@ -126,7 +126,7 @@ interface IdentityService { /** * When one performs a 3pid invite and the third party identifier is unknown, the home server * will store the invitation in the Identity server and store some information in the room state membership event. - * The email invite will contains the token and secret that can be used to claim the stored invitation + * The email invite will contains the token and secret that can be used to claim the stored invitation. * * To aid clients who may not be able to perform crypto themselves, * the identity server offers some crypto functionality to help in accepting invitations. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/model/SignInvitationResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/model/SignInvitationResult.kt index b1662b9cf821349678afb5b0214fa9f8336773d6..28d9d154f3a4c74e446c29294b6fcf622aade855 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/model/SignInvitationResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/model/SignInvitationResult.kt @@ -33,7 +33,7 @@ data class SignInvitationResult( */ val signatures: Map<String, *>, /** - * The token for the invitation + * The token for the invitation. */ val token: String ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt index 759813939f432691cc4e9e389d362bf831759704..7006e117512bf4405c7f17e52f2334f2c52f57a3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt @@ -23,7 +23,7 @@ interface SyncStatusService { sealed class Status { /** - * For initial sync + * For initial sync. */ abstract class InitialSyncStatus : Status() @@ -34,7 +34,7 @@ interface SyncStatusService { ) : InitialSyncStatus() /** - * For incremental sync + * For incremental sync. */ abstract class IncrementalSyncStatus : Status() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/integrationmanager/IntegrationManagerConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/integrationmanager/IntegrationManagerConfig.kt index 069ed7427c534dffef46d226d31fb960772f852e..b04b31af3b23c795d5120a9fd5a7da54073722ee 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/integrationmanager/IntegrationManagerConfig.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/integrationmanager/IntegrationManagerConfig.kt @@ -30,17 +30,17 @@ data class IntegrationManagerConfig( */ enum class Kind { /** - * Defined in UserAccountData + * Defined in UserAccountData. */ ACCOUNT, /** - * Defined in Wellknown + * Defined in Wellknown. */ HOMESERVER, /** - * Fallback value, hardcoded by the SDK + * Fallback value, hardcoded by the SDK. */ DEFAULT } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/MediaService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/MediaService.kt index 3b3ef57d738da17fe793709884f74e825181886a..2e53e67b0c2cec9a7cbb3cdd34c369472f7ce009 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/MediaService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/MediaService.kt @@ -36,7 +36,7 @@ interface MediaService { suspend fun getRawPreviewUrl(url: String, timestamp: Long?): JsonDict /** - * Get Url Preview data from the homeserver, or from cache, depending on the cache strategy + * Get Url Preview data from the homeserver, or from cache, depending on the cache strategy. * @param url The url to get the preview data from * @param timestamp The optional timestamp. Note that this parameter is not taken into account * if the data is already in cache and the cache strategy allow to use it @@ -45,7 +45,7 @@ interface MediaService { suspend fun getPreviewUrl(url: String, timestamp: Long?, cacheStrategy: CacheStrategy): PreviewUrlData /** - * Clear the cache of all retrieved UrlPreview data + * Clear the cache of all retrieved UrlPreview data. */ suspend fun clearCache() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/PreviewUrlData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/PreviewUrlData.kt index bfba43a82d2cb8d2e4cb8c1c44b20040d9081f70..b142ad9754a639e9861fca3b6a7c100997203fe3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/PreviewUrlData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/PreviewUrlData.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.session.media /** - * Facility data class to get the common field of a PreviewUrl response form the server + * Facility data class to get the common field of a PreviewUrl response form the server. * * Example of return data for the url `https://matrix.org`: * <pre> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt index 57aacc98b81a64509699d5707a393c04ca4c3e5a..e8d9c89b547539423f7c8ea9bf48d7726d7b24ea 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt @@ -33,10 +33,10 @@ sealed class PermalinkData { val viaParameters: List<String> ) : PermalinkData() - /** + /* * &room_name=Team2 - &room_avatar_url=mxc: - &inviter_name=bob + * &room_avatar_url=mxc: + * &inviter_name=bob */ @Parcelize data class RoomEmailInviteLink( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt index edb748c76ebe9ad8763bce7995a074d07bcd08ac..9d078dc4b243e1f9ff0b5407a22c6f29364e8198 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt @@ -23,7 +23,7 @@ import timber.log.Timber import java.net.URLDecoder /** - * This class turns a uri to a [PermalinkData] + * This class turns a uri to a [PermalinkData]. * element-based domains (e.g. https://app.element.io/#/user/@chagai95:matrix.org) permalinks * or matrix.to permalinks (e.g. https://matrix.to/#/@chagai95:matrix.org) * or client permalinks (e.g. <clientPermalinkBaseUrl>user/@chagai95:matrix.org) @@ -31,7 +31,7 @@ import java.net.URLDecoder object PermalinkParser { /** - * Turns a uri string to a [PermalinkData] + * Turns a uri string to a [PermalinkData]. */ fun parse(uriString: String): PermalinkData { val uri = Uri.parse(uriString) @@ -39,7 +39,7 @@ object PermalinkParser { } /** - * Turns a uri to a [PermalinkData] + * Turns a uri to a [PermalinkData]. * https://github.com/matrix-org/matrix-doc/blob/master/proposals/1704-matrix.to-permalinks.md */ fun parse(uri: Uri): PermalinkData { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt index c139da813ab75484865f9540314de811e48b718a..b49b80df099c87206773cf54898bc717f97b7c98 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkService.kt @@ -57,7 +57,7 @@ interface PermalinkService { fun createPermalink(id: String, forceMatrixTo: Boolean = false): String? /** - * Creates a permalink for a roomId, including the via parameters + * Creates a permalink for a roomId, including the via parameters. * * @param roomId the room id * @param forceMatrixTo whether we should force using matrix.to base URL @@ -79,7 +79,7 @@ interface PermalinkService { fun createPermalink(roomId: String, eventId: String, forceMatrixTo: Boolean = false): String /** - * Extract the linked id from the universal link + * Extract the linked id from the universal link. * * @param url the universal link, Ex: "https://matrix.to/#/@benoit:matrix.org" * @return the id from the url, ex: "@benoit:matrix.org", or null if the url is not a permalink diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/presence/PresenceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/presence/PresenceService.kt index 82a81f4b64e064fb61cd0d3536ebc63259349172..901e7ec3dd9ceb577f4322ca91d9a2b3e517a749 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/presence/PresenceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/presence/PresenceService.kt @@ -25,7 +25,7 @@ import org.matrix.android.sdk.api.session.presence.model.UserPresence */ interface PresenceService { /** - * Update the presence status for the current user + * Update the presence status for the current user. * @param presence the new presence state * @param statusMsg the status message to attach to this state */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/presence/model/PresenceEnum.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/presence/model/PresenceEnum.kt index 6d9994ef1ca9e75b0bde56257e4ba7603f260fbd..c678e2a706b329769e7c4ec69f2ba738c24e92cf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/presence/model/PresenceEnum.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/presence/model/PresenceEnum.kt @@ -28,7 +28,10 @@ enum class PresenceEnum(val value: String) { OFFLINE("offline"), @Json(name = "unavailable") - UNAVAILABLE("unavailable"); + UNAVAILABLE("unavailable"), + + @Json(name = "org.matrix.msc3026.busy") + BUSY("busy"); companion object { fun from(s: String): PresenceEnum? = values().find { it.value == s } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt index d2c677bb31425be809668548914608b3334a425a..095f2ef7c2c9058f463c4b361a73eb05e76fb9fa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt @@ -36,21 +36,21 @@ interface ProfileService { } /** - * Return the current display name for this user + * Return the current display name for this user. * @param userId the userId param to look for * */ suspend fun getDisplayName(userId: String): Optional<String> /** - * Update the display name for this user + * Update the display name for this user. * @param userId the userId to update the display name of * @param newDisplayName the new display name of the user */ suspend fun setDisplayName(userId: String, newDisplayName: String) /** - * Update the avatar for this user + * Update the avatar for this user. * @param userId the userId to update the avatar of * @param newAvatarUri the new avatar uri of the user * @param fileName the fileName of selected image @@ -74,12 +74,12 @@ interface ProfileService { suspend fun getProfile(userId: String): JsonDict /** - * Get the current user 3Pids + * Get the current user 3Pids. */ fun getThreePids(): List<ThreePid> /** - * Get the current user 3Pids Live + * Get the current user 3Pids Live. * @param refreshData set to true to fetch data from the homeserver */ fun getThreePidsLive(refreshData: Boolean): LiveData<List<ThreePid>> @@ -90,7 +90,7 @@ interface ProfileService { fun getPendingThreePids(): List<ThreePid> /** - * Get the pending 3Pids Live + * Get the pending 3Pids Live. */ fun getPendingThreePidsLive(): LiveData<List<ThreePid>> @@ -100,18 +100,18 @@ interface ProfileService { suspend fun addThreePid(threePid: ThreePid) /** - * Validate a code received by text message + * Validate a code received by text message. */ suspend fun submitSmsCode(threePid: ThreePid.Msisdn, code: String) /** - * Finalize adding a 3Pids. Call this method once the user has validated that he owns the ThreePid + * Finalize adding a 3Pids. Call this method once the user has validated that he owns the ThreePid. */ suspend fun finalizeAddingThreePid(threePid: ThreePid, userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor) /** - * Cancel adding a threepid. It will remove locally stored data about this ThreePid + * Cancel adding a threepid. It will remove locally stored data about this ThreePid. */ suspend fun cancelAddingThreePid(threePid: ThreePid) @@ -121,7 +121,7 @@ interface ProfileService { suspend fun deleteThreePid(threePid: ThreePid) /** - * Return a User object from a userId + * Return a User object from a userId. */ suspend fun getProfileAsUser(userId: String): User { return getProfile(userId).let { dict -> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt index f884d3e8906b8c298d55191254729d41ef363069..5f9857eb2fbb60a19848ead18578bb8ae454675f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt @@ -21,7 +21,7 @@ import java.util.UUID interface PushersService { /** - * Refresh pushers from server state + * Refresh pushers from server state. */ fun refreshPushers() @@ -66,7 +66,7 @@ interface PushersService { append: Boolean = true) /** - * Directly ask the push gateway to send a push to this device + * Directly ask the push gateway to send a push to this device. * If successful, the push gateway has accepted the request. In this case, the app should receive a Push with the provided eventId. * In case of error, PusherRejected will be thrown. In this case it means that the pushkey is not valid. * @@ -81,30 +81,30 @@ interface PushersService { eventId: String) /** - * Remove a registered pusher + * Remove a registered pusher. * @param pusher the pusher to remove, can be http or email */ suspend fun removePusher(pusher: Pusher) /** - * Remove a Http pusher by its pushkey and appId + * Remove a Http pusher by its pushkey and appId. * @see addHttpPusher */ suspend fun removeHttpPusher(pushkey: String, appId: String) /** - * Remove an Email pusher + * Remove an Email pusher. * @see addEmailPusher */ suspend fun removeEmailPusher(email: String) /** - * Get the current pushers, as a LiveData + * Get the current pushers, as a LiveData. */ fun getPushersLive(): LiveData<List<Pusher>> /** - * Get the current pushers + * Get the current pushers. */ fun getPushers(): List<Pusher> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt index 7790942d8453bf4655f1dbad1521f36c9c0414a6..2b2930c1ba01022e4352c076647a3563ef1d532e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt @@ -42,7 +42,7 @@ sealed class Action { } /** - * Ref: https://matrix.org/docs/spec/client_server/latest#actions + * Ref: https://matrix.org/docs/spec/client_server/latest#actions. * * Convert * <pre> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt index abbdbf81049660d2edd0411a0d1b2c5be7329983..bc4860be1153d3aebb783d9d66b2c6aa1650643f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.session.pushrules.rest.RuleSet interface PushRuleService { /** - * Fetch the push rules from the server + * Fetch the push rules from the server. */ fun fetchPushRules(scope: String = RuleScope.GLOBAL) @@ -33,7 +33,7 @@ interface PushRuleService { suspend fun addPushRule(kind: RuleKind, pushRule: PushRule) /** - * Enables/Disables a push rule and updates the actions if necessary + * Enables/Disables a push rule and updates the actions if necessary. * @param enable Enables/Disables the rule * @param actions Actions to update if not null */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt index 270ffb29408ec9a2699fdb8dc2963b1cf443de0d..a11ffc0a989d1ccaeb06ad1dc57b070c63b60910 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt @@ -49,7 +49,7 @@ data class PushRule( @Json(name = "rule_id") val ruleId: String, /** - * The conditions that must hold true for an event in order for a rule to be applied to an event + * The conditions that must hold true for an event in order for a rule to be applied to an event. */ @Json(name = "conditions") val conditions: List<PushCondition>? = null, @@ -71,7 +71,7 @@ data class PushRule( } /** - * Set the notification sound + * Set the notification sound. * * @param sound notification sound */ @@ -82,7 +82,7 @@ data class PushRule( } /** - * Remove the notification sound + * Remove the notification sound. */ fun removeNotificationSound(): PushRule { return copy( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt index 1f990f4c0a51cdf083a214e3b72329f9f6e0794e..3a18cf1497ac49f79b228475b0e8ac92c3929cdb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt @@ -49,18 +49,18 @@ interface Room { val coroutineDispatchers: MatrixCoroutineDispatchers /** - * The roomId of this room + * The roomId of this room. */ val roomId: String /** - * A live [RoomSummary] associated with the room + * A live [RoomSummary] associated with the room. * You can observe this summary to get dynamic data from this room. */ fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>> /** - * A current snapshot of [RoomSummary] associated with the room + * A current snapshot of [RoomSummary] associated with the room. */ fun roomSummary(): RoomSummary? @@ -70,97 +70,97 @@ interface Room { fun asSpace(): Space? /** - * Get the TimelineService associated to this Room + * Get the TimelineService associated to this Room. */ fun timelineService(): TimelineService /** - * Get the ThreadsService associated to this Room + * Get the ThreadsService associated to this Room. */ fun threadsService(): ThreadsService /** - * Get the ThreadsLocalService associated to this Room + * Get the ThreadsLocalService associated to this Room. */ fun threadsLocalService(): ThreadsLocalService /** - * Get the SendService associated to this Room + * Get the SendService associated to this Room. */ fun sendService(): SendService /** - * Get the DraftService associated to this Room + * Get the DraftService associated to this Room. */ fun draftService(): DraftService /** - * Get the ReadService associated to this Room + * Get the ReadService associated to this Room. */ fun readService(): ReadService /** - * Get the TypingService associated to this Room + * Get the TypingService associated to this Room. */ fun typingService(): TypingService /** - * Get the AliasService associated to this Room + * Get the AliasService associated to this Room. */ fun aliasService(): AliasService /** - * Get the TagsService associated to this Room + * Get the TagsService associated to this Room. */ fun tagsService(): TagsService /** - * Get the MembershipService associated to this Room + * Get the MembershipService associated to this Room. */ fun membershipService(): MembershipService /** - * Get the StateService associated to this Room + * Get the StateService associated to this Room. */ fun stateService(): StateService /** - * Get the UploadsService associated to this Room + * Get the UploadsService associated to this Room. */ fun uploadsService(): UploadsService /** - * Get the ReportingService associated to this Room + * Get the ReportingService associated to this Room. */ fun reportingService(): ReportingService /** - * Get the RoomCallService associated to this Room + * Get the RoomCallService associated to this Room. */ fun roomCallService(): RoomCallService /** - * Get the RelationService associated to this Room + * Get the RelationService associated to this Room. */ fun relationService(): RelationService /** - * Get the RoomCryptoService associated to this Room + * Get the RoomCryptoService associated to this Room. */ fun roomCryptoService(): RoomCryptoService /** - * Get the RoomPushRuleService associated to this Room + * Get the RoomPushRuleService associated to this Room. */ fun roomPushRuleService(): RoomPushRuleService /** - * Get the RoomAccountDataService associated to this Room + * Get the RoomAccountDataService associated to this Room. */ fun roomAccountDataService(): RoomAccountDataService /** - * Get the RoomVersionService associated to this Room + * Get the RoomVersionService associated to this Room. */ fun roomVersionService(): RoomVersionService } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomDirectoryService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomDirectoryService.kt index 9446f0fdffd3033c3fb00e17509c030c67fc673c..cb70603e66cf4c9810b30995b92c055b4bdfc581 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomDirectoryService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomDirectoryService.kt @@ -26,18 +26,18 @@ import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsRe interface RoomDirectoryService { /** - * Get rooms from directory + * Get rooms from directory. */ suspend fun getPublicRooms(server: String?, publicRoomsParams: PublicRoomsParams): PublicRoomsResponse /** - * Get the visibility of a room in the directory + * Get the visibility of a room in the directory. */ suspend fun getRoomDirectoryVisibility(roomId: String): RoomDirectoryVisibility /** - * Set the visibility of a room in the directory + * Set the visibility of a room in the directory. */ suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt index ece9cfbfacf59a77f9f9a7cfc57fb48041f5a6bf..0e631427bd320aefbf516ca120f16b278a31071d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt @@ -21,13 +21,13 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent /** - * Get a TimelineEvent using the TimelineService of a Room + * Get a TimelineEvent using the TimelineService of a Room. */ fun Room.getTimelineEvent(eventId: String): TimelineEvent? = timelineService().getTimelineEvent(eventId) /** - * Get a StateEvent using the StateService of a Room + * Get a StateEvent using the StateService of a Room. */ fun Room.getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event? = stateService().getStateEvent(eventType, stateKey) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt index 700e292b0c16fc7b26e93c899c73b5f4f270e7aa..6d5551ddf02d43bfe53e872d4eed8201432626b1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt @@ -36,12 +36,12 @@ import org.matrix.android.sdk.api.util.Optional interface RoomService { /** - * Create a room asynchronously + * Create a room asynchronously. */ suspend fun createRoom(createRoomParams: CreateRoomParams): String /** - * Create a direct room asynchronously. This is a facility method to create a direct room with the necessary parameters + * Create a direct room asynchronously. This is a facility method to create a direct room with the necessary parameters. */ suspend fun createDirectRoom(otherUserId: String): String { return createRoom( @@ -55,7 +55,7 @@ interface RoomService { } /** - * Join a room by id + * Join a room by id. * @param roomIdOrAlias the roomId or the room alias of the room to join * @param reason optional reason for joining the room * @param viaServers the servers to attempt to join the room through. One of the servers must be participating in the room. @@ -84,14 +84,14 @@ interface RoomService { suspend fun leaveRoom(roomId: String, reason: String? = null) /** - * Get a room from a roomId + * Get a room from a roomId. * @param roomId the roomId to look for. * @return a room with roomId or null */ fun getRoom(roomId: String): Room? /** - * Get a roomSummary from a roomId or a room alias + * Get a roomSummary from a roomId or a room alias. * @param roomIdOrAlias the roomId or the alias of a room to look for. * @return a matching room summary or null */ @@ -112,14 +112,14 @@ interface RoomService { sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): LiveData<List<RoomSummary>> /** - * Get a snapshot list of Breadcrumbs + * Get a snapshot list of Breadcrumbs. * @param queryParams parameters to query the room summaries. It can be use to keep only joined rooms, for instance. * @return the immutable list of [RoomSummary] */ fun getBreadcrumbs(queryParams: RoomSummaryQueryParams): List<RoomSummary> /** - * Get a live list of Breadcrumbs + * Get a live list of Breadcrumbs. * @param queryParams parameters to query the room summaries. It can be use to keep only joined rooms, for instance. * @return the [LiveData] of [RoomSummary] */ @@ -132,7 +132,7 @@ interface RoomService { suspend fun onRoomDisplayed(roomId: String) /** - * Mark all rooms as read + * Mark all rooms as read. */ suspend fun markAllAsRead(roomIds: List<String>) @@ -143,7 +143,7 @@ interface RoomService { searchOnServer: Boolean): Optional<RoomAliasDescription> /** - * Delete a room alias + * Delete a room alias. */ suspend fun deleteRoomAlias(roomAlias: String) @@ -162,7 +162,7 @@ interface RoomService { fun getChangeMembershipsLive(): LiveData<Map<String, ChangeMembershipState>> /** - * Return the roomId of an existing DM with the other user, or null if such room does not exist + * Return the roomId of an existing DM with the other user, or null if such room does not exist. * A room is a DM if: * - it is listed in the `m.direct` account data * - the current user has joined the room @@ -175,7 +175,7 @@ interface RoomService { fun getExistingDirectRoomWithUser(otherUserId: String): String? /** - * Get a room member for the tuple {userId,roomId} + * Get a room member for the tuple {userId,roomId}. * @param userId the userId to look for. * @param roomId the roomId to look for. * @return the room member or null @@ -183,7 +183,7 @@ interface RoomService { fun getRoomMember(userId: String, roomId: String): RoomMemberSummary? /** - * Observe a live room member for the tuple {userId,roomId} + * Observe a live room member for the tuple {userId,roomId}. * @param userId the userId to look for. * @param roomId the roomId to look for. * @return a LiveData of the optional found room member @@ -191,39 +191,39 @@ interface RoomService { fun getRoomMemberLive(userId: String, roomId: String): LiveData<Optional<RoomMemberSummary>> /** - * Get some state events about a room + * Get some state events about a room. */ suspend fun getRoomState(roomId: String): List<Event> /** - * Use this if you want to get information from a room that you are not yet in (or invited) - * It might be possible to get some information on this room if it is public or if guest access is allowed - * This call will try to gather some information on this room, but it could fail and get nothing more + * Use this if you want to get information from a room that you are not yet in (or invited). + * It might be possible to get some information on this room if it is public or if guest access is allowed. + * This call will try to gather some information on this room, but it could fail and get nothing more. */ suspend fun peekRoom(roomIdOrAlias: String): PeekResult /** - * TODO Doc + * TODO Doc. */ fun getPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams, pagedListConfig: PagedList.Config = defaultPagedListConfig, sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): LiveData<PagedList<RoomSummary>> /** - * TODO Doc + * TODO Doc. */ fun getFilteredPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams, pagedListConfig: PagedList.Config = defaultPagedListConfig, sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): UpdatableLivePageResult /** - * Return a LiveData on the number of rooms + * Return a LiveData on the number of rooms. * @param queryParams parameters to query the room summaries. It can be use to keep only joined rooms, for instance. */ fun getRoomCountLive(queryParams: RoomSummaryQueryParams): LiveData<Int> /** - * TODO Doc + * TODO Doc. */ fun getNotificationCountForRooms(queryParams: RoomSummaryQueryParams): RoomAggregateNotificationCount @@ -238,16 +238,16 @@ interface RoomService { fun getFlattenRoomSummaryChildrenOf(spaceId: String?, memberships: List<Membership> = Membership.activeMemberships()): List<RoomSummary> /** - * Returns all the children of this space, as LiveData + * Returns all the children of this space, as LiveData. */ fun getFlattenRoomSummaryChildrenOfLive(spaceId: String?, memberships: List<Membership> = Membership.activeMemberships()): LiveData<List<RoomSummary>> /** - * Refreshes the RoomSummary LatestPreviewContent for the given @param roomId - * If the roomId is null, all rooms are updated + * Refreshes the RoomSummary LatestPreviewContent for the given @param roomId. + * If the roomId is null, all rooms are updated. * - * This is useful for refreshing summary content with encrypted messages after receiving new room keys + * This is useful for refreshing summary content with encrypted messages after receiving new room keys. */ fun refreshJoinedRoomSummaryPreviews(roomId: String?) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt index b4408575187b8ec5d362980ada7d9e0aa135cef4..5c74dcced1be6fe65fdb8024615de874e54cb36a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSummaryQueryParams.kt @@ -41,7 +41,7 @@ fun spaceSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = /** * This class can be used to filter room summaries to use with: - * [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService] + * [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService]. */ data class RoomSummaryQueryParams( val roomId: QueryStringValue, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt index 190749c85cee92957fe16e1729a898d51b0da7f2..b6925dd4a3f47662c2c381c8ae5f7528dad9afff 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt @@ -25,29 +25,29 @@ import org.matrix.android.sdk.api.util.Optional */ interface RoomAccountDataService { /** - * Retrieve the account data with the provided type or null if not found + * Retrieve the account data with the provided type or null if not found. */ fun getAccountDataEvent(type: String): RoomAccountDataEvent? /** - * Observe the account data with the provided type + * Observe the account data with the provided type. */ fun getLiveAccountDataEvent(type: String): LiveData<Optional<RoomAccountDataEvent>> /** * Retrieve the account data with the provided types. The return list can have a different size that * the size of the types set, because some AccountData may not exist. - * If an empty set is provided, all the AccountData are retrieved + * If an empty set is provided, all the AccountData are retrieved. */ fun getAccountDataEvents(types: Set<String>): List<RoomAccountDataEvent> /** - * Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed + * Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed. */ fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<RoomAccountDataEvent>> /** - * Update the account data with the provided type and the provided account data content + * Update the account data with the provided type and the provided account data content. */ suspend fun updateAccountData(type: String, content: Content) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/alias/AliasService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/alias/AliasService.kt index 5fe7e99425e27b4c6ee1afe3165103bbc6ce83e5..2073db15b30641c34cd7a97b53e7a6135c1a5bc7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/alias/AliasService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/alias/AliasService.kt @@ -18,13 +18,13 @@ package org.matrix.android.sdk.api.session.room.alias interface AliasService { /** - * Get list of local alias of the room + * Get list of local alias of the room. * @return the list of the aliases (full aliases, not only the local part) */ suspend fun getRoomAliases(): List<String> /** - * Add local alias to the room + * Add local alias to the room. * @param aliasLocalPart the local part of the alias. * Ex: for the alias "#my_alias:example.org", the local part is "my_alias" */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/call/RoomCallService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/call/RoomCallService.kt index cac5217dd6bd9702ede12dc242cdfc96214c9768..4439253a57a517be17ff58cb4d25562eedf53c8b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/call/RoomCallService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/call/RoomCallService.kt @@ -21,7 +21,7 @@ package org.matrix.android.sdk.api.session.room.call */ interface RoomCallService { /** - * Return true if calls (audio or video) can be performed on this Room + * Return true if calls (audio or video) can be performed on this Room. */ fun canStartCall(): Boolean } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/MembershipService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/MembershipService.kt index 6c8e2d310c0777591f056d223652223635e7941d..e7ac69be74a5f284721b230ae5580d3234465c9c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/MembershipService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/MembershipService.kt @@ -39,14 +39,14 @@ interface MembershipService { fun getRoomMember(userId: String): RoomMemberSummary? /** - * Return all the roomMembers of the room with params + * Return all the roomMembers of the room with params. * @param queryParams the params to query for * @return a roomMember list. */ fun getRoomMembers(queryParams: RoomMemberQueryParams): List<RoomMemberSummary> /** - * Return all the roomMembers of the room filtered by memberships + * Return all the roomMembers of the room filtered by memberships. * @param queryParams the params to query for * @return a [LiveData] of roomMember list. */ @@ -55,27 +55,27 @@ interface MembershipService { fun getNumberOfJoinedMembers(): Int /** - * Invite a user in the room + * Invite a user in the room. */ suspend fun invite(userId: String, reason: String? = null) /** - * Invite a user with email or phone number in the room + * Invite a user with email or phone number in the room. */ suspend fun invite3pid(threePid: ThreePid) /** - * Ban a user from the room + * Ban a user from the room. */ suspend fun ban(userId: String, reason: String? = null) /** - * Unban a user from the room + * Unban a user from the room. */ suspend fun unban(userId: String, reason: String? = null) /** - * Remove a user from the room + * Remove a user from the room. */ suspend fun remove(userId: String, reason: String? = null) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/RoomMemberQueryParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/RoomMemberQueryParams.kt index c2c5a7f8045b1e7c2e96a77db0741c0af7a1b5e4..dd83066dbbc7934cac2a423d1851a0ce1d736a15 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/RoomMemberQueryParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/RoomMemberQueryParams.kt @@ -24,7 +24,7 @@ fun roomMemberQueryParams(init: (RoomMemberQueryParams.Builder.() -> Unit) = {}) } /** - * This class can be used to filter room members + * This class can be used to filter room members. */ data class RoomMemberQueryParams( val displayName: QueryStringValue, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Invite.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Invite.kt index 2841da35d12461d5bd3764d1d45dac40c94e2b3c..f3c83c223a522f68ee840dd2067afbe2b5d04ebf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Invite.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Invite.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Subclass representing a search API response + * Subclass representing a search API response. */ @JsonClass(generateAdapter = true) data class Invite( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Membership.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Membership.kt index a5d0f63722c43dc1f110f4de549f76fc0f838dce..c0325d87ec2202a26d11f1a8171d219c68ad0c13 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Membership.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Membership.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Represents the membership of a user on a room + * Represents the membership of a user on a room. */ @JsonClass(generateAdapter = false) enum class Membership { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt index 5c46db7166efbaadd24479c70e3fee3cd3626e40..8ef94b28968ee2bdf165883166c21702d1b27653 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PowerLevelsContent.kt @@ -67,7 +67,7 @@ data class PowerLevelsContent( @Json(name = "notifications") val notifications: Map<String, Any>? = null ) { /** - * Return a copy of this content with a new power level for the specified user + * Return a copy of this content with a new power level for the specified user. * * @param userId the userId to alter the power level of * @param powerLevel the new power level, or null to set the default value. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedSummary.kt index 49ba2d5ab6a1015d85eef6cc5bd3775bc5a6ed21..0bc87c9bf1927c01c70b5c312ec987e135a3a2f3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedSummary.kt @@ -19,7 +19,7 @@ import org.matrix.android.sdk.api.session.events.model.Content /** * Events can relates to other events, this object keeps a summary - * of all events that are referencing the 'eventId' event via the RelationType.REFERENCE + * of all events that are referencing the 'eventId' event via the RelationType.REFERENCE. */ data class ReferencesAggregatedSummary( val content: Content?, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomAvatarContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomAvatarContent.kt index 8c1c9e6b1213ebae256cd8f623016353e9cb828e..b6567fcf2117905a2a1e822705c3a3a3a6fcfecc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomAvatarContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomAvatarContent.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing the EventType.STATE_ROOM_AVATAR state event content + * Class representing the EventType.STATE_ROOM_AVATAR state event content. */ @JsonClass(generateAdapter = true) data class RoomAvatarContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomCanonicalAliasContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomCanonicalAliasContent.kt index 4e8bd2e71b4335371a931ae609a98292950883f6..1e76bef6f3e60adc41f2519dbb6915d54b7e3011 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomCanonicalAliasContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomCanonicalAliasContent.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing the EventType.STATE_ROOM_CANONICAL_ALIAS state event content + * Class representing the EventType.STATE_ROOM_CANONICAL_ALIAS state event content. */ @JsonClass(generateAdapter = true) data class RoomCanonicalAliasContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt index 020e7ed39e50c6c40400bb2025ccdffc19e63de4..ba274325bc5b4ff67789a4245c7766886bb5e0cb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt @@ -27,13 +27,13 @@ import timber.log.Timber @JsonClass(generateAdapter = true) data class RoomGuestAccessContent( // Required. Whether guests can join the room. One of: ["can_join", "forbidden"] - @Json(name = "guest_access") val _guestAccess: String? = null + @Json(name = "guest_access") val guestAccessStr: String? = null ) { - val guestAccess: GuestAccess? = when (_guestAccess) { + val guestAccess: GuestAccess? = when (guestAccessStr) { "can_join" -> GuestAccess.CanJoin "forbidden" -> GuestAccess.Forbidden else -> { - Timber.w("Invalid value for GuestAccess: `$_guestAccess`") + Timber.w("Invalid value for GuestAccess: `$guestAccessStr`") null } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt index 3ac14e48de77e592e05fcb75ed80b6ce371e4423..da5c90ff0534f955b4b30e1fa37c3dfee9b21d32 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt @@ -22,15 +22,15 @@ import timber.log.Timber @JsonClass(generateAdapter = true) data class RoomHistoryVisibilityContent( - @Json(name = "history_visibility") val _historyVisibility: String? = null + @Json(name = "history_visibility") val historyVisibilityStr: String? = null ) { - val historyVisibility: RoomHistoryVisibility? = when (_historyVisibility) { + val historyVisibility: RoomHistoryVisibility? = when (historyVisibilityStr) { "world_readable" -> RoomHistoryVisibility.WORLD_READABLE "shared" -> RoomHistoryVisibility.SHARED "invited" -> RoomHistoryVisibility.INVITED "joined" -> RoomHistoryVisibility.JOINED else -> { - Timber.w("Invalid value for RoomHistoryVisibility: `$_historyVisibility`") + Timber.w("Invalid value for RoomHistoryVisibility: `$historyVisibilityStr`") null } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt index 5237b10d52b3cbd8d9edcdb85309029ad7caa8e9..3b338a36cd0056ee4ad5628c9c8342cf8df59da9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt @@ -23,11 +23,11 @@ import com.squareup.moshi.JsonClass import timber.log.Timber /** - * Class representing the EventType.STATE_ROOM_JOIN_RULES state event content + * Class representing the EventType.STATE_ROOM_JOIN_RULES state event content. */ @JsonClass(generateAdapter = true) data class RoomJoinRulesContent( - @Json(name = "join_rule") val _joinRules: String? = null, + @Json(name = "join_rule") val joinRulesStr: String? = null, /** * If the allow key is an empty list (or not a list at all), * then no users are allowed to join without an invite. @@ -35,14 +35,14 @@ data class RoomJoinRulesContent( */ @Json(name = "allow") val allowList: List<RoomJoinRulesAllowEntry>? = null ) { - val joinRules: RoomJoinRules? = when (_joinRules) { + val joinRules: RoomJoinRules? = when (joinRulesStr) { "public" -> RoomJoinRules.PUBLIC "invite" -> RoomJoinRules.INVITE "knock" -> RoomJoinRules.KNOCK "private" -> RoomJoinRules.PRIVATE "restricted" -> RoomJoinRules.RESTRICTED else -> { - Timber.w("Invalid value for RoomJoinRules: `$_joinRules`") + Timber.w("Invalid value for RoomJoinRules: `$joinRulesStr`") null } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomMemberContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomMemberContent.kt index f29dd6a3e55c02087a8f72014bb4ae360bfb03e8..2529edbfdd9c80481a302c423f18f77caf7df92c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomMemberContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomMemberContent.kt @@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.session.events.model.UnsignedData /** - * Class representing the EventType.STATE_ROOM_MEMBER state event content + * Class representing the EventType.STATE_ROOM_MEMBER state event content. */ @JsonClass(generateAdapter = true) data class RoomMemberContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomMemberSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomMemberSummary.kt index 39177a4296b8983dcb5b8e66e5e1c7531e05b9ac..8e7382190a3f7ce692a3399c4448afe9480168f1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomMemberSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomMemberSummary.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.api.session.room.model import org.matrix.android.sdk.api.session.presence.model.UserPresence /** - * Class representing a simplified version of EventType.STATE_ROOM_MEMBER state event content + * Class representing a simplified version of EventType.STATE_ROOM_MEMBER state event content. */ data class RoomMemberSummary constructor( val membership: Membership, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomNameContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomNameContent.kt index a0b45e881b5ae33065857086b0c0327bab1180f0..2dbb5f9e5736414b8a60fc79be625ada02b6f078 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomNameContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomNameContent.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing the EventType.STATE_ROOM_NAME state event content + * Class representing the EventType.STATE_ROOM_NAME state event content. */ @JsonClass(generateAdapter = true) data class RoomNameContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomStrippedState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomStrippedState.kt index dc0c00b282c93efc6958c12fff0f7abecca88d89..b4f663f8010cde6d3309ac3ef2fd54c5c3c51555 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomStrippedState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomStrippedState.kt @@ -79,7 +79,7 @@ data class RoomStrippedState( val avatarUrl: String? = null, /** - * Undocumented item + * Undocumented item. */ @Json(name = "m.federate") val isFederated: Boolean = false, @@ -103,7 +103,7 @@ data class RoomStrippedState( val membership: String? ) { /** - * Return the canonical alias, or the first alias from the list of aliases, or null + * Return the canonical alias, or the first alias from the list of aliases, or null. */ fun getPrimaryAlias(): String? { return canonicalAlias ?: aliases?.firstOrNull() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomTopicContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomTopicContent.kt index b97ee44dee8b5cfa01b2ed538c797d4185c6517c..18092f12ac4283218835f4e7ffa4bebf7d91e38a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomTopicContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomTopicContent.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing the EventType.STATE_ROOM_TOPIC state event content + * Class representing the EventType.STATE_ROOM_TOPIC state event content. */ @JsonClass(generateAdapter = true) data class RoomTopicContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallCapabilities.kt index d911ca3b88927bd8b5f6608019d83d1af0cedff7..6937b2c2e4275c156fe9e1630828f42913248dd9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallCapabilities.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.api.extensions.orFalse data class CallCapabilities( /** * If set to true, states that the sender of the event supports the m.call.replaces event and therefore supports - * being transferred to another destination + * being transferred to another destination. */ @Json(name = "m.call.transferee") val transferee: Boolean? = null ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallInviteContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallInviteContent.kt index 24c8152f3cca195faa00c3ada52b74688ea5665f..40038ab8ec55cb4b910ecb924c982a1a3d7600e6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallInviteContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallInviteContent.kt @@ -47,7 +47,7 @@ data class CallInviteContent( */ @Json(name = "lifetime") val lifetime: Int?, /** - * The field should be added for all invites where the target is a specific user + * The field should be added for all invites where the target is a specific user. */ @Json(name = "invitee") val invitee: String? = null, /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallReplacesContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallReplacesContent.kt index e480e013ea9ced4c49dffe7029a3a6a0dddbc719..849fa50537e6eb75d244002b93641d3442d13dfc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallReplacesContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallReplacesContent.kt @@ -44,7 +44,7 @@ data class CallReplacesContent( */ @Json(name = "target_room") val targetRoomId: String? = null, /** - * An object giving information about the transfer target + * An object giving information about the transfer target. */ @Json(name = "target_user") val targetUser: TargetUser? = null, /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt index ce1e0e0d144493ab328ee054673f05ff6bac54f2..b7b0cc890b382f2f33598250623d26b5f49820ae 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt @@ -69,13 +69,13 @@ open class CreateRoomParams { val invite3pids = mutableListOf<ThreePid>() /** - * Initial Guest Access + * Initial Guest Access. */ var guestAccess: GuestAccess? = null /** * If set to true, when the room will be created, if cross-signing is enabled and we can get keys for every invited users, - * the encryption will be enabled on the created room + * the encryption will be enabled on the created room. */ var enableEncryptionIfInvitedUsersSupportIt: Boolean = false @@ -135,7 +135,7 @@ open class CreateRoomParams { } /** - * The power level content to override in the default power level event + * The power level content to override in the default power level event. */ var powerLevelContentOverride: PowerLevelsContent? = null @@ -148,7 +148,7 @@ open class CreateRoomParams { } /** - * Supported value: MXCRYPTO_ALGORITHM_MEGOLM + * Supported value: MXCRYPTO_ALGORITHM_MEGOLM. */ var algorithm: String? = null private set diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/Predecessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/Predecessor.kt index f48beb299aeb7cc2a53a20b77c57f9e0c4555091..99c829b0e24c8ee67b7e07f27c6e0520684a5fc8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/Predecessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/Predecessor.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * A link to an old room in case of room versioning + * A link to an old room in case of room versioning. */ @JsonClass(generateAdapter = true) data class Predecessor( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomCreateContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomCreateContent.kt index 52e5c0e9c7f67081934570e0aa22b1fd6b523f3a..d73c941a863cf9b318444eb71f5d2b9d3ce95428 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomCreateContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomCreateContent.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Content of a m.room.create type event + * Content of a m.room.create type event. */ @JsonClass(generateAdapter = true) data class RoomCreateContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt index f5f722d7833059eaa3d2d81d00f287249df0641b..6487ad947fa18356c5c6b9d3893ec080a4468170 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt @@ -47,7 +47,7 @@ class RestrictedRoomPreset(val homeServerCapabilities: HomeServerCapabilities, v type = EventType.STATE_ROOM_JOIN_RULES, stateKey = "", content = RoomJoinRulesContent( - _joinRules = RoomJoinRules.RESTRICTED.value, + joinRulesStr = RoomJoinRules.RESTRICTED.value, allowList = restrictedList ).toContent() ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt index 132b72902f5e9de2c397fc6ded5c29ce468ad25f..ae786ff7062915f86a95f40df071966540be80f2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt @@ -49,7 +49,7 @@ data class FileInfo( ) /** - * Get the url of the encrypted thumbnail or of the thumbnail + * Get the url of the encrypted thumbnail or of the thumbnail. */ fun FileInfo.getThumbnailUrl(): String? { return thumbnailFile?.url ?: thumbnailUrl diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt index bd99ea690019b9ba428f5bf0d96376226e553eaa..ec6669d4ec36dbf3843620d71ecbe2eeb1f22cf2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt @@ -59,7 +59,7 @@ data class ImageInfo( ) /** - * Get the url of the encrypted thumbnail or of the thumbnail + * Get the url of the encrypted thumbnail or of the thumbnail. */ fun ImageInfo.getThumbnailUrl(): String? { return thumbnailFile?.url ?: thumbnailUrl diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconInfoContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconInfoContent.kt index f75704a89158b704dca114a22b13439c1ee1b8b0..f8b627e497549325636119f5dba9a59dc5f357a4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconInfoContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconInfoContent.kt @@ -32,7 +32,7 @@ import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultCon @JsonClass(generateAdapter = true) data class MessageBeaconInfoContent( /** - * Local message type, not from server + * Local message type, not from server. */ @Transient override val msgType: String = MessageType.MSGTYPE_BEACON_INFO, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt index 4a4ef46bc84b583d8050a0db242c8983469e3216..e261ab52066495786445e215d852e2d85e3fc7a6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt @@ -32,7 +32,7 @@ import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultCon @JsonClass(generateAdapter = true) data class MessageBeaconLocationDataContent( /** - * Local message type, not from server + * Local message type, not from server. */ @Transient override val msgType: String = MessageType.MSGTYPE_BEACON_LOCATION_DATA, @@ -42,13 +42,13 @@ data class MessageBeaconLocationDataContent( @Json(name = "m.new_content") override val newContent: Content? = null, /** - * See [MSC3488](https://github.com/matrix-org/matrix-doc/blob/matthew/location/proposals/3488-location.md) + * See [MSC3488](https://github.com/matrix-org/matrix-doc/blob/matthew/location/proposals/3488-location.md). */ @Json(name = "org.matrix.msc3488.location") val unstableLocationInfo: LocationInfo? = null, @Json(name = "m.location") val locationInfo: LocationInfo? = null, /** - * Exact time that the data in the event refers to (milliseconds since the UNIX epoch) + * Exact time that the data in the event refers to (milliseconds since the UNIX epoch). */ @Json(name = "org.matrix.msc3488.ts") val unstableTimestampMillis: Long? = null, @Json(name = "m.ts") val timestampMillis: Long? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageContentWithFormattedBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageContentWithFormattedBody.kt index aabf6173d7ecee0b7896cd6e1d53a7b3f367f5b6..58ea8db02dfd216d3b9cedd0f27193e2171ba3bf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageContentWithFormattedBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageContentWithFormattedBody.kt @@ -28,7 +28,7 @@ interface MessageContentWithFormattedBody : MessageContent { val formattedBody: String? /** - * Get the formattedBody, only if not blank and if the format is equal to "org.matrix.custom.html" + * Get the formattedBody, only if not blank and if the format is equal to "org.matrix.custom.html". */ val matrixFormattedBody: String? get() = formattedBody?.takeIf { it.isNotBlank() && format == MessageFormat.FORMAT_MATRIX_HTML } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageEndPollContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageEndPollContent.kt index 491b71477e472619bdef14faf08b14c98cb9b432..f0511903d0fec26aae24d136229b2cb2e54ec278 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageEndPollContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageEndPollContent.kt @@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent /** - * Class representing the org.matrix.msc3381.poll.end event content + * Class representing the org.matrix.msc3381.poll.end event content. */ @JsonClass(generateAdapter = true) data class MessageEndPollContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageInfoContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageInfoContent.kt index 369a1a1a46937d2effdeb30bcd326b84e69e5b70..e2b69eff333294e7c4c3ab184e5f9670d9c3efda 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageInfoContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageInfoContent.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.session.room.model.message /** - * A content with image information + * A content with image information. */ interface MessageImageInfoContent : MessageWithAttachmentContent { val info: ImageInfo? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt index 19cb20430d2968b3d3cad8f7f28f95c3be00f113..0a66a6e400d5b3a75a7549ad15863890d379dd71 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt @@ -42,12 +42,12 @@ data class MessageLocationContent( @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.new_content") override val newContent: Content? = null, /** - * See [MSC3488](https://github.com/matrix-org/matrix-doc/blob/matthew/location/proposals/3488-location.md) + * See [MSC3488](https://github.com/matrix-org/matrix-doc/blob/matthew/location/proposals/3488-location.md). */ @Json(name = "org.matrix.msc3488.location") val unstableLocationInfo: LocationInfo? = null, @Json(name = "m.location") val locationInfo: LocationInfo? = null, /** - * Exact time that the data in the event refers to (milliseconds since the UNIX epoch) + * Exact time that the data in the event refers to (milliseconds since the UNIX epoch). */ @Json(name = "org.matrix.msc3488.ts") val unstableTimestampMillis: Long? = null, @Json(name = "m.ts") val timestampMillis: Long? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessagePollContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessagePollContent.kt index 43c0c9006818342e9c4f531936df68299eba1688..f784f052839a03e1d2a59a3626b261e1d41980c4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessagePollContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessagePollContent.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultCon @JsonClass(generateAdapter = true) data class MessagePollContent( /** - * Local message type, not from server + * Local message type, not from server. */ @Transient override val msgType: String = MessageType.MSGTYPE_POLL_START, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessagePollResponseContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessagePollResponseContent.kt index 022915ed695d1a4cc1d88c4447f57333d0b436b3..32bfb710907df748b41287a8a2aebf5d138f9185 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessagePollResponseContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessagePollResponseContent.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultCon @JsonClass(generateAdapter = true) data class MessagePollResponseContent( /** - * Local message type, not from server + * Local message type, not from server. */ @Transient override val msgType: String = MessageType.MSGTYPE_POLL_RESPONSE, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt index 3d774cadb292591d62e137a0827be277b5d49932..f8c1c0d79876b99b83e7f11ed930d9c0c6528511 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt @@ -25,7 +25,7 @@ import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultCon @JsonClass(generateAdapter = true) data class MessageStickerContent( /** - * Set in local, not from server + * Set in local, not from server. */ @Transient override val msgType: String = MessageType.MSGTYPE_STICKER_LOCAL, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationKeyContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationKeyContent.kt index 1a15e056abe3e0ef1b7bb9d398739b401ad45ac4..a6b36ce6cb6ff53b8d8a0fde2e9743724a290f33 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationKeyContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationKeyContent.kt @@ -26,7 +26,7 @@ import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoKeyFa @JsonClass(generateAdapter = true) internal data class MessageVerificationKeyContent( /** - * The device’s ephemeral public key, as an unpadded base64 string + * The device’s ephemeral public key, as an unpadded base64 string. */ @Json(name = "key") override val key: String? = null, @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt index 95dfb6b8648be044e0ce439768176fe56cc85511..8d9dbee6b3ddbf5fc6c4e9f08953cab5ddf3ecd1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.api.session.room.model.message import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo /** - * Interface for message which can contains an encrypted file + * Interface for message which can contains an encrypted file. */ interface MessageWithAttachmentContent : MessageContent { /** @@ -36,7 +36,7 @@ interface MessageWithAttachmentContent : MessageContent { } /** - * Get the url of the encrypted file or of the file + * Get the url of the encrypted file or of the file. */ fun MessageWithAttachmentContent.getFileUrl() = encryptedFileInfo?.url ?: url diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt index b02b4d96adc7696ffe8ca16d54f02e4a375ad636..b9c2472197c2523136aba4620ccd0623916bf6b9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt @@ -64,7 +64,7 @@ data class VideoInfo( ) /** - * Get the url of the encrypted thumbnail or of the thumbnail + * Get the url of the encrypted thumbnail or of the thumbnail. */ fun VideoInfo.getThumbnailUrl(): String? { return thumbnailFile?.url ?: thumbnailUrl diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationContent.kt index 53b1fea873d5b43dd936a7b88c74dd528e9246b0..01f7425322b2471ff280655155f24d931b95a8d2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationContent.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.api.session.room.model.relation import org.matrix.android.sdk.api.session.events.model.RelationType interface RelationContent { - /** See [RelationType] for known possible values */ + /** See [RelationType] for known possible values. */ val type: String? val eventId: String? val inReplyTo: ReplyToContent? @@ -27,7 +27,7 @@ interface RelationContent { /** * This flag indicates that the message should be rendered as a reply - * fallback, when isFallingBack = false + * fallback, when isFallingBack = false. */ val isFallingBack: Boolean? } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationService.kt index 44098989084eb4d43435fc9f65960a93bd7ab0e4..0d094b835b3066a61df8299a46b7f9eea5c9074c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationService.kt @@ -82,7 +82,7 @@ interface RelationService { options: List<String>): Cancelable /** - * Edit a text message body. Limited to "m.text" contentType + * Edit a text message body. Limited to "m.text" contentType. * @param targetEvent The event to edit * @param newBodyText The edited body * @param compatibilityBodyText The text that will appear on clients that don't support yet edition @@ -107,7 +107,7 @@ interface RelationService { compatibilityBodyText: String = "* $newBodyText"): Cancelable /** - * Get the edit history of the given event + * Get the edit history of the given event. * The return list will contain the original event and all the editions of this event, done by the * same sender, sorted in the reverse order (so the original event is the latest element, and the * latest edition is the first element of the list) @@ -133,21 +133,21 @@ interface RelationService { ): Cancelable? /** - * Get the current EventAnnotationsSummary + * Get the current EventAnnotationsSummary. * @param eventId the eventId to look for EventAnnotationsSummary * @return the EventAnnotationsSummary found */ fun getEventAnnotationsSummary(eventId: String): EventAnnotationsSummary? /** - * Get a LiveData of EventAnnotationsSummary for the specified eventId + * Get a LiveData of EventAnnotationsSummary for the specified eventId. * @param eventId the eventId to look for EventAnnotationsSummary * @return the LiveData of EventAnnotationsSummary */ fun getEventAnnotationsSummaryLive(eventId: String): LiveData<Optional<EventAnnotationsSummary>> /** - * Creates a thread reply for an existing timeline event + * Creates a thread reply for an existing timeline event. * The replyInThreadText can be a Spannable and contains special spans (MatrixItemSpan) that will be translated * by the sdk into pills. * @param rootThreadEventId the root thread eventId diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoom.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoom.kt index 01f5d9cde86dcc68a21068e8f9cfd91e1647115b..2033f366ae3361ac4adda0643fb7a6567614554e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoom.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoom.kt @@ -79,13 +79,13 @@ data class PublicRoom( val avatarUrl: String? = null, /** - * Undocumented item + * Undocumented item. */ @Json(name = "m.federate") val isFederated: Boolean = false ) { /** - * Return the canonical alias, or the first alias from the list of aliases, or null + * Return the canonical alias, or the first alias from the list of aliases, or null. */ fun getPrimaryAlias(): String? { return canonicalAlias ?: aliases?.firstOrNull() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsFilter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsFilter.kt index 66ebc59464abc6043a9cf0966af5db259dbd37c0..cc0ce669b9658a0f21f1bc1cf73bd5e0145210d4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsFilter.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsFilter.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class to define a filter to retrieve public rooms + * Class to define a filter to retrieve public rooms. */ @JsonClass(generateAdapter = true) data class PublicRoomsFilter( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsParams.kt index 3af354a01dff8753dd8aa9d78c689f53779f9a35..c4227b5767f2117e640d1399ea98c1b9b23103c9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsParams.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class to pass parameters to get the public rooms list + * Class to pass parameters to get the public rooms list. */ @JsonClass(generateAdapter = true) data class PublicRoomsParams( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsResponse.kt index 82da8bc49bc385a1d49df48a407ec85c499150a7..5a33ba3cdf63d9337c6afc39e9cc427a299de4f2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/roomdirectory/PublicRoomsResponse.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing the public rooms request response + * Class representing the public rooms request response. */ @JsonClass(generateAdapter = true) data class PublicRoomsResponse( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/thirdparty/ThirdPartyProtocolInstance.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/thirdparty/ThirdPartyProtocolInstance.kt index 0ca04445898c86a57cdc0af4a3e84fd0f8af29c6..6a2dc4765009c12264c39ef9a0220d34569341cb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/thirdparty/ThirdPartyProtocolInstance.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/thirdparty/ThirdPartyProtocolInstance.kt @@ -46,13 +46,13 @@ data class ThirdPartyProtocolInstance( val networkId: String? = null, /** - * FIXDOC Not documented on matrix.org doc + * FIXDOC Not documented on matrix.org doc. */ @Json(name = "instance_id") val instanceId: String? = null, /** - * FIXDOC Not documented on matrix.org doc + * FIXDOC Not documented on matrix.org doc. */ @Json(name = "bot_user_id") val botUserId: String? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/tombstone/RoomTombstoneContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/tombstone/RoomTombstoneContent.kt index 9b607aa712c85406d5ce53ad5c1328c6d8f155d3..d0a976cd97fefff5f910a73ad94e692946cea08d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/tombstone/RoomTombstoneContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/tombstone/RoomTombstoneContent.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class to contains Tombstone information + * Class to contains Tombstone information. */ @JsonClass(generateAdapter = true) data class RoomTombstoneContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/notification/RoomNotificationState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/notification/RoomNotificationState.kt index ea59ff4d4899fecb1a33107f2f02055d2efd8905..919aed63eb906cfbee5e0e2d05c90d80ef2a8b93 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/notification/RoomNotificationState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/notification/RoomNotificationState.kt @@ -17,26 +17,26 @@ package org.matrix.android.sdk.api.session.room.notification /** - * Defines the room notification state + * Defines the room notification state. */ enum class RoomNotificationState { /** - * All the messages will trigger a noisy notification + * All the messages will trigger a noisy notification. */ ALL_MESSAGES_NOISY, /** - * All the messages will trigger a notification + * All the messages will trigger a notification. */ ALL_MESSAGES, /** - * Only the messages with user display name / user name will trigger notifications + * Only the messages with user display name / user name will trigger notifications. */ MENTIONS_ONLY, /** - * No notifications + * No notifications. */ MUTE } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/PowerLevelsHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/PowerLevelsHelper.kt index 99139723a82f15ce874d337f9b667fb653ccc47e..165a912b7fac0ed9898d38a45abf872b92938500 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/PowerLevelsHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/powerlevels/PowerLevelsHelper.kt @@ -32,7 +32,7 @@ import org.matrix.android.sdk.api.session.room.model.usersDefaultOrDefault class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) { /** - * Returns the user power level of a dedicated user Id + * Returns the user power level of a dedicated user Id. * * @param userId the user id * @return the power level @@ -44,7 +44,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) { } /** - * Returns the user power level of a dedicated user Id + * Returns the user power level of a dedicated user Id. * * @param userId the user id * @return the power level @@ -56,7 +56,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) { } /** - * Tell if an user can send an event of a certain type + * Tell if an user can send an event of a certain type. * * @param userId the id of the user to check for. * @param isState true if the event is a state event (ie. state key is not null) @@ -77,7 +77,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) { } /** - * Check if the user have the necessary power level to invite + * Check if the user have the necessary power level to invite. * @param userId the id of the user to check for. * @return true if able to invite */ @@ -87,7 +87,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) { } /** - * Check if the user have the necessary power level to ban + * Check if the user have the necessary power level to ban. * @param userId the id of the user to check for. * @return true if able to ban */ @@ -97,7 +97,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) { } /** - * Check if the user have the necessary power level to kick + * Check if the user have the necessary power level to kick (remove). * @param userId the id of the user to check for. * @return true if able to kick */ @@ -107,7 +107,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) { } /** - * Check if the user have the necessary power level to redact + * Check if the user have the necessary power level to redact. * @param userId the id of the user to check for. * @return true if able to redact */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/read/ReadService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/read/ReadService.kt index b037a3f3668846b4b6f54e9bbe99b2c9fe573cee..036628c02f53151ce68f2f9fdad1529ecb509539 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/read/ReadService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/read/ReadService.kt @@ -62,7 +62,7 @@ interface ReadService { fun getMyReadReceiptLive(): LiveData<Optional<String>> /** - * Get the eventId where the read receipt for the provided user is + * Get the eventId where the read receipt for the provided user is. * @param userId the id of the user to look for * * @return the eventId where the read receipt for the provided user is attached, or null if not found @@ -70,7 +70,7 @@ interface ReadService { fun getUserReadReceipt(userId: String): String? /** - * Returns a live list of read receipts for a given event + * Returns a live list of read receipts for a given event. * @param eventId: the event */ fun getEventReadReceiptsLive(eventId: String): LiveData<List<ReadReceipt>> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/DraftService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/DraftService.kt index a9481d71a2002ce3873cf840e5999681fafaa0bd..e03c89a12a6930d7fea27851632d24cd83dea6dc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/DraftService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/DraftService.kt @@ -22,22 +22,22 @@ import org.matrix.android.sdk.api.util.Optional interface DraftService { /** - * Save or update a draft to the room + * Save or update a draft to the room. */ suspend fun saveDraft(draft: UserDraft) /** - * Delete the last draft, basically just after sending the message + * Delete the last draft, basically just after sending the message. */ suspend fun deleteDraft() /** - * Return the current draft or null + * Return the current draft or null. */ fun getDraft(): UserDraft? /** - * Return the current draft if any, as a live data + * Return the current draft if any, as a live data. */ fun getDraftLive(): LiveData<Optional<UserDraft>> } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt index af7ab11df13452e52a9cf7ca9560e862dae3a6b5..4bb8abef8aaaff9c1b2292b10857a8799de9e4a5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt @@ -126,19 +126,19 @@ interface SendService { fun redactEvent(event: Event, reason: String?): Cancelable /** - * Schedule this message to be resent + * Schedule this message to be resent. * @param localEcho the unsent local echo */ fun resendTextMessage(localEcho: TimelineEvent): Cancelable /** - * Schedule this message to be resent + * Schedule this message to be resent. * @param localEcho the unsent local echo */ fun resendMediaMessage(localEcho: TimelineEvent): Cancelable /** - * Send a location event to the room + * Send a location event to the room. * @param latitude required latitude of the location * @param longitude required longitude of the location * @param uncertainty Accuracy of the location in meters @@ -156,23 +156,23 @@ interface SendService { fun sendLiveLocation(beaconInfoEventId: String, latitude: Double, longitude: Double, uncertainty: Double?): Cancelable /** - * Remove this failed message from the timeline + * Remove this failed message from the timeline. * @param localEcho the unsent local echo */ fun deleteFailedEcho(localEcho: TimelineEvent) /** - * Cancel sending a specific event. It has to be in one of the sending states + * Cancel sending a specific event. It has to be in one of the sending states. */ fun cancelSend(eventId: String) /** - * Resend all failed messages one by one (and keep order) + * Resend all failed messages one by one (and keep order). */ fun resendAllFailedMessages() /** - * Cancel all failed messages + * Cancel all failed messages. */ fun cancelAllFailedMessages() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/UserDraft.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/UserDraft.kt index a8c0de2fa50916659c5897b37c6236ec8caf3681..4ede1a66fc53a755917f0a493c16037fad70f400 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/UserDraft.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/UserDraft.kt @@ -21,7 +21,7 @@ package org.matrix.android.sdk.api.session.room.send * REGULAR: draft of a classical message * QUOTE: draft of a message which quotes another message * EDIT: draft of an edition of a message - * REPLY: draft of a reply of another message + * REPLY: draft of a reply of another message. */ sealed interface UserDraft { data class Regular(val content: String) : UserDraft diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/sender/SenderInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/sender/SenderInfo.kt index 9b73136fc3792237b77013c38a776ccedc349f49..4c308c355a02163f30f533fb221c027b85364a47 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/sender/SenderInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/sender/SenderInfo.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.util.replaceSpaceChars data class SenderInfo( val userId: String, /** - * Consider using [disambiguatedDisplayName] + * Consider using [disambiguatedDisplayName]. */ val displayName: String?, val isUniqueDisplayName: Boolean, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt index 98171795e2cb30307f80af2d7d63aaaa730217f7..f6b56128d39aa8782e254550b8ecfc0d52f4b3f9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt @@ -30,57 +30,57 @@ import org.matrix.android.sdk.api.util.Optional interface StateService { /** - * Update the topic of the room + * Update the topic of the room. */ suspend fun updateTopic(topic: String) /** - * Update the name of the room + * Update the name of the room. */ suspend fun updateName(name: String) /** - * Update the canonical alias of the room + * Update the canonical alias of the room. * @param alias the canonical alias, or null to reset the canonical alias of this room * @param altAliases the alternative aliases for this room. It should include the canonical alias if any. */ suspend fun updateCanonicalAlias(alias: String?, altAliases: List<String>) /** - * Update the history readability of the room + * Update the history readability of the room. */ suspend fun updateHistoryReadability(readability: RoomHistoryVisibility) /** - * Update the join rule and/or the guest access + * Update the join rule and/or the guest access. */ suspend fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?, allowList: List<RoomJoinRulesAllowEntry>? = null) /** - * Update the avatar of the room + * Update the avatar of the room. */ suspend fun updateAvatar(avatarUri: Uri, fileName: String) /** - * Delete the avatar of the room + * Delete the avatar of the room. */ suspend fun deleteAvatar() /** - * Stops sharing live location in the room + * Stops sharing live location in the room. * @param userId user id */ suspend fun stopLiveLocation(userId: String) /** - * Returns beacon info state event of a user + * Returns beacon info state event of a user. * @param userId user id who is sharing location * @param filterOnlyLive filters only ongoing live location sharing beacons if true else ended event is included */ suspend fun getLiveLocationBeaconInfo(userId: String, filterOnlyLive: Boolean): Event? /** - * Send a state event to the room + * Send a state event to the room. * @param eventType The type of event to send. * @param stateKey The state_key for the state to send. Can be an empty string. * @param body The content object of the event; the fields in this object will vary depending on the type of event @@ -89,23 +89,23 @@ interface StateService { suspend fun sendStateEvent(eventType: String, stateKey: String, body: JsonDict): String /** - * Get a state event of the room + * Get a state event of the room. */ fun getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event? /** - * Get a live state event of the room + * Get a live state event of the room. */ fun getStateEventLive(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData<Optional<Event>> /** - * Get state events of the room + * Get state events of the room. * @param eventTypes Set of eventType. If empty, all state events will be returned */ fun getStateEvents(eventTypes: Set<String>, stateKey: QueryStringValue = QueryStringValue.NoCondition): List<Event> /** - * Get live state events of the room + * Get live state events of the room. * @param eventTypes Set of eventType to observe. If empty, all state events will be observed */ fun getStateEventsLive(eventTypes: Set<String>, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData<List<Event>> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt index c625a7f0885196a70085fab71ab14a2cceb61a35..9e45fc126dbad4b82ddc4c3c8b011229c86d7ecc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateServiceExtension.kt @@ -23,7 +23,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent /** - * Return true if a room can be joined by anyone (RoomJoinRules.PUBLIC) + * Return true if a room can be joined by anyone (RoomJoinRules.PUBLIC). */ fun StateService.isPublic(): Boolean { return getStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.NoCondition) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/tags/TagsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/tags/TagsService.kt index 69fde61f90e44e142db07663d91ecfb04c289248..b6b82d84047b29a8839cb582a8ef7282d3b5c03c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/tags/TagsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/tags/TagsService.kt @@ -21,12 +21,12 @@ package org.matrix.android.sdk.api.session.room.tags */ interface TagsService { /** - * Add a tag to a room + * Add a tag to a room. */ suspend fun addTag(tag: String, order: Double?) /** - * Remove tag from a room + * Remove tag from a room. */ suspend fun deleteTag(tag: String) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/ThreadsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/ThreadsService.kt index 839cdff63badd9cb2052cb615e2ffec14f5d1875..9587be68f124f9129c29a86cef866158408d6085 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/ThreadsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/ThreadsService.kt @@ -28,24 +28,24 @@ import org.matrix.android.sdk.api.session.room.threads.model.ThreadSummary interface ThreadsService { /** - * Returns a [LiveData] list of all the [ThreadSummary] that exists at the room level + * Returns a [LiveData] list of all the [ThreadSummary] that exists at the room level. */ fun getAllThreadSummariesLive(): LiveData<List<ThreadSummary>> /** - * Returns a list of all the [ThreadSummary] that exists at the room level + * Returns a list of all the [ThreadSummary] that exists at the room level. */ fun getAllThreadSummaries(): List<ThreadSummary> /** * Enhance the provided ThreadSummary[List] by adding the latest - * message edition for that thread + * message edition for that thread. * @return the enhanced [List] with edited updates */ fun enhanceThreadWithEditions(threads: List<ThreadSummary>): List<ThreadSummary> /** - * Fetch all thread replies for the specified thread using the /relations api + * Fetch all thread replies for the specified thread using the /relations api. * @param rootThreadEventId the root thread eventId * @param from defines the token that will fetch from that position * @param limit defines the number of max results the api will respond with @@ -53,7 +53,7 @@ interface ThreadsService { suspend fun fetchThreadTimeline(rootThreadEventId: String, from: String, limit: Int) /** - * Fetch all thread summaries for the current room using the enhanced /messages api + * Fetch all thread summaries for the current room using the enhanced /messages api. */ suspend fun fetchThreadSummaries() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/local/ThreadsLocalService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/local/ThreadsLocalService.kt index f7b379e3821b04d1a920b993139b0a647c8a6757..b5cef3c62ba89ecfe2130a943237eb353c615719 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/local/ThreadsLocalService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/local/ThreadsLocalService.kt @@ -27,34 +27,34 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent interface ThreadsLocalService { /** - * Returns a [LiveData] list of all the thread root TimelineEvents that exists at the room level + * Returns a [LiveData] list of all the thread root TimelineEvents that exists at the room level. */ fun getAllThreadsLive(): LiveData<List<TimelineEvent>> /** - * Returns a list of all the thread root TimelineEvents that exists at the room level + * Returns a list of all the thread root TimelineEvents that exists at the room level. */ fun getAllThreads(): List<TimelineEvent> /** - * Returns a [LiveData] list of all the marked unread threads that exists at the room level + * Returns a [LiveData] list of all the marked unread threads that exists at the room level. */ fun getMarkedThreadNotificationsLive(): LiveData<List<TimelineEvent>> /** - * Returns a list of all the marked unread threads that exists at the room level + * Returns a list of all the marked unread threads that exists at the room level. */ fun getMarkedThreadNotifications(): List<TimelineEvent> /** - * Returns whether or not the current user is participating in the thread - * @param rootThreadEventId the eventId of the current thread + * Returns whether or not the current user is participating in the thread. + * @param rootThreadEventId the eventId of the current thread. */ fun isUserParticipatingInThread(rootThreadEventId: String): Boolean /** * Enhance the provided root thread TimelineEvent [List] by adding the latest - * message edition for that thread + * message edition for that thread. * @return the enhanced [List] with edited updates */ fun mapEventsWithEdition(threads: List<TimelineEvent>): List<TimelineEvent> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadSummary.kt index 017afba1baebee3b169a672542515b4ea55a81b8..1ef972e889be030601c086df4d0ecff7a5249839 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/threads/model/ThreadSummary.kt @@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.sender.SenderInfo /** - * The main thread Summary model, mainly used to display the thread list + * The main thread Summary model, mainly used to display the thread list. */ data class ThreadSummary(val roomId: String, val rootEvent: Event?, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/Timeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/Timeline.kt index d47a656798c45df853a592c8f04f6370d28f1bd2..1824d5dc6c587b950ce28bbf9aa0ebc9f6e0fec8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/Timeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/Timeline.kt @@ -100,23 +100,23 @@ interface Timeline { fun onTimelineUpdated(snapshot: List<TimelineEvent>) = Unit /** - * Called whenever an error we can't recover from occurred + * Called whenever an error we can't recover from occurred. */ fun onTimelineFailure(throwable: Throwable) = Unit /** - * Called when new events come through the sync + * Called when new events come through the sync. */ fun onNewTimelineEvents(eventIds: List<String>) = Unit /** - * Called when the pagination state has changed in one direction + * Called when the pagination state has changed in one direction. */ fun onStateUpdated(direction: Direction, state: PaginationState) = Unit } /** - * Pagination state + * Pagination state. */ data class PaginationState( val hasMoreToLoad: Boolean = true, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt index adbc8ab12a02ea8c1aa8196dde983a20d84abf11..b87bc25435cc249858ca133f763d2cce042e5c0c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt @@ -47,7 +47,7 @@ import org.matrix.android.sdk.api.util.ContentUtils.extractUsefulTextFromReply data class TimelineEvent( val root: Event, /** - * Uniquely identify an event, computed locally by the sdk + * Uniquely identify an event, computed locally by the sdk. */ val localId: Long, val eventId: String, @@ -103,12 +103,12 @@ data class TimelineEvent( } /** - * Tells if the event has been edited + * Tells if the event has been edited. */ fun TimelineEvent.hasBeenEdited() = annotations?.editSummary != null /** - * Get the latest known eventId for an edited event, or the eventId for an Event which has not been edited + * Get the latest known eventId for an edited event, or the eventId for an Event which has not been edited. */ fun TimelineEvent.getLatestEventId(): String { return annotations @@ -119,21 +119,21 @@ fun TimelineEvent.getLatestEventId(): String { } /** - * Get the relation content if any + * Get the relation content if any. */ fun TimelineEvent.getRelationContent(): RelationDefaultContent? { return root.getRelationContent() } /** - * Get the eventId which was edited by this event if any + * Get the eventId which was edited by this event if any. */ fun TimelineEvent.getEditedEventId(): String? { return getRelationContent()?.takeIf { it.type == RelationType.REPLACE }?.eventId } /** - * Get last MessageContent, after a possible edition + * Get last MessageContent, after a possible edition. */ fun TimelineEvent.getLastMessageContent(): MessageContent? { return when (root.getClearType()) { @@ -145,7 +145,7 @@ fun TimelineEvent.getLastMessageContent(): MessageContent? { } /** - * Returns true if it's a reply + * Returns true if it's a reply. */ fun TimelineEvent.isReply(): Boolean { return root.isReply() @@ -163,14 +163,14 @@ fun TimelineEvent.isSticker(): Boolean { } /** - * Returns whether or not the event is a root thread event + * Returns whether or not the event is a root thread event. */ fun TimelineEvent.isRootThread(): Boolean { return root.threadDetails?.isRootThread.orFalse() } /** - * Get the latest message body, after a possible edition, stripping the reply prefix if necessary + * Get the latest message body, after a possible edition, stripping the reply prefix if necessary. */ fun TimelineEvent.getTextEditableContent(): String { val lastContentBody = getLastMessageContent()?.body ?: return "" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt index a35a291d9b2342f385447efb167da54c221d3080..0f0c15b61382c3c8076aad49c26ebe0fbe80cfdb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt @@ -19,19 +19,19 @@ package org.matrix.android.sdk.api.session.room.timeline // TODO Move to internal, strange? data class TimelineEventFilters( /** - * A flag to filter edit events + * A flag to filter edit events. */ val filterEdits: Boolean = false, /** - * A flag to filter redacted events + * A flag to filter redacted events. */ val filterRedacted: Boolean = false, /** - * A flag to filter useless events, such as membership events without any change + * A flag to filter useless events, such as membership events without any change. */ val filterUseless: Boolean = false, /** - * A flag to filter by types. It should be used with [allowedTypes] field + * A flag to filter by types. It should be used with [allowedTypes] field. */ val filterTypes: Boolean = false, /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt index b45f3ecb71f5ff6ff90de643c6f9bdf93e1ad7ae..fd6732d0d13bbbcf2cec79fe4e5efa230e147cd0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt @@ -29,13 +29,17 @@ data class TimelineSettings( */ val buildReadReceipts: Boolean = true, /** - * The root thread eventId if this is a thread timeline, or null if this is NOT a thread timeline + * The root thread eventId if this is a thread timeline, or null if this is NOT a thread timeline. */ val rootThreadEventId: String? = null, + /** + * If true Sender Info shown in room will get the latest data information (avatar + displayName). + */ + val useLiveSenderInfo: Boolean = false, ) { /** - * Returns true if this is a thread timeline or false otherwise + * Returns true if this is a thread timeline or false otherwise. */ fun isThreadTimeline() = rootThreadEventId != null } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/typing/TypingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/typing/TypingService.kt index e69afa4fc8eb6740fdef34111f675915a81ed4b4..a462d5cba7fd864566ddca8de3e365aa44ebcf1b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/typing/TypingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/typing/TypingService.kt @@ -22,7 +22,7 @@ package org.matrix.android.sdk.api.session.room.typing interface TypingService { /** - * To call when user is typing a message in the room + * To call when user is typing a message in the room. * The SDK will handle the requests scheduling to the homeserver: * - No more than one typing request per 10s * - If not called after 10s, the SDK will notify the homeserver that the user is not typing anymore diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/uploads/UploadsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/uploads/UploadsService.kt index e2462d007d26109e38110147b56f3a7d43c32c97..b6fec9cd51232cee4c91df7d5e9d88f354590ee4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/uploads/UploadsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/uploads/UploadsService.kt @@ -22,7 +22,7 @@ package org.matrix.android.sdk.api.session.room.uploads interface UploadsService { /** - * Get a list of events containing URL sent to a room, from most recent to oldest one + * Get a list of events containing URL sent to a room, from most recent to oldest one. * @param numberOfEvents the expected number of events to retrieve. The result can contain less events. * @param since token to get next page, or null to get the first page */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/version/RoomVersionService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/version/RoomVersionService.kt index d806e6007e55ff82c0c911ac9e41b27b5cc846d6..4b6c907af01a9ae07d210288a2522ae45de9fcbb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/version/RoomVersionService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/version/RoomVersionService.kt @@ -18,28 +18,28 @@ package org.matrix.android.sdk.api.session.room.version interface RoomVersionService { /** - * Return the room version of this room + * Return the room version of this room. */ fun getRoomVersion(): String /** - * Upgrade to the given room version + * Upgrade to the given room version. * @return the replacement room id */ suspend fun upgradeToVersion(version: String): String /** - * Get the recommended room version for the current homeserver + * Get the recommended room version for the current homeserver. */ fun getRecommendedVersion(): String /** - * Ask if the user has enough power level to upgrade the room + * Ask if the user has enough power level to upgrade the room. */ fun userMayUpgradeRoom(userId: String): Boolean /** - * Return true if the current room version is declared unstable by the homeserver + * Return true if the current room version is declared unstable by the homeserver. */ fun isUsingUnstableRoomVersion(): Boolean } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/EncryptedSecretContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/EncryptedSecretContent.kt index 42682efb12b0344031764fa524b62af773305d1a..ddcecb466c385ae5422c732deae28b8bd60a753f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/EncryptedSecretContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/EncryptedSecretContent.kt @@ -29,7 +29,7 @@ import org.matrix.android.sdk.internal.session.user.accountdata.AccountDataConte */ @JsonClass(generateAdapter = true) data class EncryptedSecretContent( - /** unpadded base64-encoded ciphertext */ + /** unpadded base64-encoded ciphertext. */ @Json(name = "ciphertext") val ciphertext: String? = null, @Json(name = "mac") val mac: String? = null, @Json(name = "ephemeral") val ephemeral: String? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SecretStorageKeyContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SecretStorageKeyContent.kt index f7725be00725fbffc657e9cc185358d7a8a78692..e7f872e40054986934aba245ff2d672cb76ff4ce 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SecretStorageKeyContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SecretStorageKeyContent.kt @@ -51,7 +51,7 @@ data class KeyInfo( @JsonClass(generateAdapter = true) data class SecretStorageKeyContent( - /** Currently support m.secret_storage.v1.curve25519-aes-sha2 */ + /** Currently support m.secret_storage.v1.curve25519-aes-sha2. */ @Json(name = "algorithm") val algorithm: String? = null, @Json(name = "name") val name: String? = null, @Json(name = "passphrase") val passphrase: SsssPassphrase? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt index 721a2bc8af11f03577ac931014bdf1f869fbcb8c..528e07196693656b73440350bd77f8795c01b0b7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt @@ -98,12 +98,12 @@ interface SharedSecretStorageService { suspend fun storeSecret(name: String, secretBase64: String, keys: List<KeyRef>) /** - * Use this call to determine which SSSSKeySpec to use for requesting secret + * Use this call to determine which SSSSKeySpec to use for requesting secret. */ fun getAlgorithmsForSecret(name: String): List<KeyInfoResult> /** - * Get an encrypted secret from the shared storage + * Get an encrypted secret from the shared storage. * * @param name The name of the secret * @param keyId The id of the key that should be used to decrypt (null for default key) @@ -113,7 +113,7 @@ interface SharedSecretStorageService { suspend fun getSecret(name: String, keyId: String?, secretKey: SsssKeySpec): String /** - * Return true if SSSS is configured + * Return true if SSSS is configured. */ fun isRecoverySetup(): Boolean { return checkShouldBeAbleToAccessSecrets( @@ -131,7 +131,7 @@ interface SharedSecretStorageService { fun checkShouldBeAbleToAccessSecrets(secretNames: List<String>, keyId: String?): IntegrityResult - fun requestSecret(name: String, myOtherDeviceId: String) + suspend fun requestSecret(name: String, myOtherDeviceId: String) data class KeyRef( val keyId: String?, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt index 03efb9b3dbbbd4fca28b6a41491524db113cc32e..35a67b086578214d6af5cbae7600d9bc7fcf1603 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt @@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey import org.matrix.android.sdk.internal.crypto.keysbackup.deriveKey -/** Tag class */ +/** Tag class. */ interface SsssKeySpec data class RawBytesKeySpec( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/signout/SignOutService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/signout/SignOutService.kt index 4e4eba274e242cf076907dbe1c3db8d8385578fd..d64b2e6e92d71cb233054960a493255b955842e2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/signout/SignOutService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/signout/SignOutService.kt @@ -30,12 +30,12 @@ interface SignOutService { suspend fun signInAgain(password: String) /** - * Update the session with credentials received after SSO + * Update the session with credentials received after SSO. */ suspend fun updateCredentials(credentials: Credentials) /** - * Sign out, and release the session, clear all the session data, including crypto data + * Sign out, and release the session, clear all the session data, including crypto data. * @param signOutFromHomeserver true if the sign out request has to be done */ suspend fun signOut(signOutFromHomeserver: Boolean) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/JoinSpaceResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/JoinSpaceResult.kt index e8c69977c6a59c510a04129e975869f8bffa904f..a8a7ec61d7cad1a108f5dea06bda5615d8855e88 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/JoinSpaceResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/JoinSpaceResult.kt @@ -20,7 +20,7 @@ sealed class JoinSpaceResult { object Success : JoinSpaceResult() data class Fail(val error: Throwable) : JoinSpaceResult() - /** Success fully joined the space, but failed to join all or some of it's rooms */ + /** Success fully joined the space, but failed to join all or some of it's rooms. */ data class PartialSuccess(val failedRooms: Map<String, Throwable>) : JoinSpaceResult() fun isSuccess() = this is Success || this is PartialSuccess diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/Space.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/Space.kt index f0ed9daac5dc651cace526cb13484736e84e7eff..c9903886285c8349e396fa784bccd311cbe31a31 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/Space.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/Space.kt @@ -27,7 +27,7 @@ interface Space { val spaceId: String /** - * A current snapshot of [RoomSummary] associated with the space + * A current snapshot of [RoomSummary] associated with the space. */ fun spaceSummary(): RoomSummary? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt index afd26f7be54e10d545732d2131dc54a3d267556d..8f16b3b9c3fb7c711403af61b1feb9c67bbc341e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt @@ -29,13 +29,13 @@ typealias SpaceSummaryQueryParams = RoomSummaryQueryParams interface SpaceService { /** - * Create a space asynchronously + * Create a space asynchronously. * @return the spaceId of the created space */ suspend fun createSpace(params: CreateSpaceParams): String /** - * Just a shortcut for space creation for ease of use + * Just a shortcut for space creation for ease of use. */ suspend fun createSpace(name: String, topic: String?, @@ -44,7 +44,7 @@ interface SpaceService { roomAliasLocalPart: String? = null): String /** - * Get a space from a roomId + * Get a space from a roomId. * @param spaceId the roomId to look for. * @return a space with spaceId or null if room type is not space */ @@ -58,7 +58,7 @@ interface SpaceService { suspend fun peekSpace(spaceId: String): SpacePeekResult /** - * Get's information of a space by querying the server + * Get's information of a space by querying the server. * @param suggestedOnly If true, return only child events and rooms where the m.space.child event has suggested: true. * @param limit a client-defined limit to the maximum number of rooms to return per page. Must be a non-negative integer. * @param from: Optional. Pagination token given to retrieve the next set of rooms. Note that if a pagination token is provided, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildContent.kt index b55f90cef06ba4ab7cf6260b508eead7ed6989b2..215fcd9a54267228f6f087f34ab33c089a12f392 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceChildContent.kt @@ -20,11 +20,14 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** + * Example: + * <pre> * "content": { * "via": ["example.com"], * "order": "abcd", * "default": true * } + * </pre>. */ @JsonClass(generateAdapter = true) data class SpaceChildContent( @@ -56,7 +59,7 @@ data class SpaceChildContent( ) { /** * Orders which are not strings, or do not consist solely of ascii characters in the range \x20 (space) to \x7F (~), - * or consist of more than 50 characters, are forbidden and should be ignored if received.) + * or consist of more than 50 characters, are forbidden and should be ignored if received.). */ fun validOrder(): String? { return order diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceOrderContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceOrderContent.kt index a8578347c87de3d05f0a5d7619175e08fa14b880..47e276414ec6f9c7600cb9242bedf0140f270fd5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceOrderContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/model/SpaceOrderContent.kt @@ -20,12 +20,15 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.MatrixPatterns /** + * Example: + * <pre> * { * "type": "m.space_order", * "content": { * "order": "..." * } * } + * </pre>. */ @JsonClass(generateAdapter = true) data class SpaceOrderContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/statistics/StatisticEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/statistics/StatisticEvent.kt index 946792d31ef8731417fa377959b751983f4f8273..76755517ce25546e14c201be3880e94eb9e96b46 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/statistics/StatisticEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/statistics/StatisticEvent.kt @@ -17,11 +17,11 @@ package org.matrix.android.sdk.api.session.statistics /** - * Statistic Events. You can subscribe to received such events using [Session.Listener] + * Statistic Events. You can subscribe to received such events using [Session.Listener]. */ sealed interface StatisticEvent { /** - * Initial sync request, response downloading, and treatment (parsing and storage) of response + * Initial sync request, response downloading, and treatment (parsing and storage) of response. */ data class InitialSyncRequest(val requestDurationMs: Int, val downloadDurationMs: Int, @@ -29,7 +29,7 @@ sealed interface StatisticEvent { val nbOfJoinedRooms: Int) : StatisticEvent /** - * Incremental sync event + * Incremental sync event. */ data class SyncTreatment(val durationMs: Int, val afterPause: Boolean, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/FilterService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/FilterService.kt index 6d1d12f1bc68857d84cfea3951a4449e3f4982ee..bc592df47407b5b22969335172803409cc1c1aa1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/FilterService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/FilterService.kt @@ -22,13 +22,13 @@ interface FilterService { NoFilter, /** - * Filter for Element, will include only known event type + * Filter for Element, will include only known event type. */ ElementFilter } /** - * Configure the filter for the sync + * Configure the filter for the sync. */ fun setFilter(filterPreset: FilterPreset) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStrategy.kt index 461d816ea7ca34f91f53cf46595d40eab5d5f8f6..11f1093393969c642953bf7e4b08ef491908f03b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStrategy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStrategy.kt @@ -20,7 +20,7 @@ var initialSyncStrategy: InitialSyncStrategy = InitialSyncStrategy.Optimized() sealed class InitialSyncStrategy { /** - * Parse the result in its entirety + * Parse the result in its entirety. * Pros: * - Faster to handle parsed data * Cons: @@ -32,21 +32,21 @@ sealed class InitialSyncStrategy { /** * Optimized. - * First store the request result in a file, to avoid doing it again in case of crash + * First store the request result in a file, to avoid doing it again in case of crash. */ data class Optimized( /** - * Limit to reach to decide to split the init sync response into smaller files - * Empiric value: 1 megabytes + * Limit to reach to decide to split the init sync response into smaller files. + * Empiric value: 1 megabytes. */ val minSizeToSplit: Long = 1_048_576, // 1024 * 1024 /** - * Limit per room to reach to decide to store a join room ephemeral Events into a file - * Empiric value: 1 kilobytes + * Limit per room to reach to decide to store a join room ephemeral Events into a file. + * Empiric value: 1 kilobytes. */ val minSizeToStoreInFile: Long = 1024, /** - * Max number of rooms to insert at a time in database (to avoid too much RAM usage) + * Max number of rooms to insert at a time in database (to avoid too much RAM usage). */ val maxRoomsToInsert: Int = 100 ) : InitialSyncStrategy() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/DeviceListResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/DeviceListResponse.kt index c05e1e51878ea37d5a4fe3c540e107d020d11a91..929343e45d0ec4ec4be6cd52812f15b228ffbb75 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/DeviceListResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/DeviceListResponse.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.api.session.sync.model import com.squareup.moshi.JsonClass /** - * This class describes the device list response from a sync request + * This class describes the device list response from a sync request. */ @JsonClass(generateAdapter = true) data class DeviceListResponse( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/LazyRoomSyncEphemeral.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/LazyRoomSyncEphemeral.kt index 087a5f52dc5977913519ac7f67328bde96be97cb..5bd7719d0146379fc1949dfeab755c82c74abf79 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/LazyRoomSyncEphemeral.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/LazyRoomSyncEphemeral.kt @@ -20,6 +20,6 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = false) sealed class LazyRoomSyncEphemeral { - data class Parsed(val _roomSyncEphemeral: RoomSyncEphemeral) : LazyRoomSyncEphemeral() + data class Parsed(val roomSyncEphemeral: RoomSyncEphemeral) : LazyRoomSyncEphemeral() object Stored : LazyRoomSyncEphemeral() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSync.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSync.kt index e3d07602c7955f4c0eb894f90c345a0450df6f8b..e5ac0a39b234710e8cf206aa750c7449efbdfe8d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSync.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSync.kt @@ -48,7 +48,7 @@ data class RoomSync( @Json(name = "unread_notifications") val unreadNotifications: RoomSyncUnreadNotifications? = null, /** - * The room summary + * The room summary. */ @Json(name = "summary") val summary: RoomSyncSummary? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncSummary.kt index 7216a0c992f4f7e564513b0347d104490489dc67..050fa119bb7953f7b2f05fea229e2cbe5683154b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncSummary.kt @@ -36,12 +36,12 @@ data class RoomSyncSummary( @Json(name = "m.heroes") val heroes: List<String> = emptyList(), /** - * The number of m.room.members in state 'joined' (including the syncing user) (can be null) + * The number of m.room.members in state 'joined' (including the syncing user) (can be null). */ @Json(name = "m.joined_member_count") val joinedMembersCount: Int? = null, /** - * The number of m.room.members in state 'invited' (can be null) + * The number of m.room.members in state 'invited' (can be null). */ @Json(name = "m.invited_member_count") val invitedMembersCount: Int? = null ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncTimeline.kt index 82d29a52e2ff6ada48c240d8b72fd7d0fbf58329..4fc8adb7696326f762d46d4c5a2979cad0900384 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/RoomSyncTimeline.kt @@ -30,12 +30,12 @@ data class RoomSyncTimeline( @Json(name = "events") val events: List<Event>? = null, /** - * Boolean which tells whether there are more events on the server + * Boolean which tells whether there are more events on the server. */ @Json(name = "limited") val limited: Boolean = false, /** - * If the batch was limited then this is a token that can be supplied to the server to retrieve more events + * If the batch was limited then this is a token that can be supplied to the server to retrieve more events. */ @Json(name = "prev_batch") val prevToken: String? = null ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/SyncResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/SyncResponse.kt index d7dff72288f8ad64d513f3ac5b7e336f2e63b85a..c70964a513e3e5c361e4b2571a0cb37689657ee5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/SyncResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/model/SyncResponse.kt @@ -48,12 +48,12 @@ data class SyncResponse( @Json(name = "rooms") val rooms: RoomsSyncResponse? = null, /** - * Devices list update + * Devices list update. */ @Json(name = "device_lists") val deviceLists: DeviceListResponse? = null, /** - * One time keys management + * One time keys management. */ @Json(name = "device_one_time_keys_count") val deviceOneTimeKeysCount: DeviceOneTimeKeysCountSyncResponse? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationBadgeState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationBadgeState.kt index 8e861e73de1a279946c35d68aa8e7aab00ba3655..f3e92ad84315b4e12164ccaa292b8cd320e583f1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationBadgeState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationBadgeState.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.session.threads /** - * This class defines the state of a thread notification badge + * This class defines the state of a thread notification badge. */ data class ThreadNotificationBadgeState( val numberOfLocalUnreadThreads: Int = 0, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt index 8566d68aa52ab389dd4a89f9d6678e110fc795ba..c110802d23a77d4463efe2fd459da3e81c196e1a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadNotificationState.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.session.threads /** - * This class defines the state of a thread notification + * This class defines the state of a thread notification. */ enum class ThreadNotificationState { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadTimelineEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadTimelineEvent.kt index 7b433566b8df2029f6a112e52ef121ab76a6ef07..53f89cefab6fa635c03dadb6f513a918d18c1822 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadTimelineEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadTimelineEvent.kt @@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent /** * This class contains a thread TimelineEvent along with a boolean that - * determines if the current user has participated in that event + * determines if the current user has participated in that event. */ data class ThreadTimelineEvent( val timelineEvent: TimelineEvent, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt index 063abdb5a0d3e1d6474f8c1569c00481a3ef8918..0c5465e12a8ae51a8a018c89121ab8e4dbf68232 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt @@ -27,14 +27,14 @@ import org.matrix.android.sdk.api.util.Optional interface UserService { /** - * Get a user from a userId + * Get a user from a userId. * @param userId the userId to look for. * @return a user with userId or null */ fun getUser(userId: String): User? /** - * Try to resolve user from known users, or using profile api + * Try to resolve user from known users, or using profile api. */ suspend fun resolveUser(userId: String): User @@ -48,14 +48,14 @@ interface UserService { suspend fun searchUsersDirectory(search: String, limit: Int, excludedUserIds: Set<String>): List<User> /** - * Observe a live user from a userId + * Observe a live user from a userId. * @param userId the userId to look for. * @return a LiveData of user with userId */ fun getUserLive(userId: String): LiveData<Optional<User>> /** - * Observe a live list of users sorted alphabetically + * Observe a live list of users sorted alphabetically. * @return a Livedata of users */ fun getUsersLive(): LiveData<List<User>> @@ -69,19 +69,19 @@ interface UserService { fun getPagedUsersLive(filter: String? = null, excludedUserIds: Set<String>? = null): LiveData<PagedList<User>> /** - * Get list of ignored users + * Get list of ignored users. */ fun getIgnoredUsersLive(): LiveData<List<User>> /** - * Ignore users + * Ignore users. * Note: once done, for the change to take effect, you have to request an initial sync. - * This may be improved in the future + * This may be improved in the future. */ suspend fun ignoreUserIds(userIds: List<String>) /** - * Un-ignore some users + * Un-ignore some users. * Note: once done, for the change to take effect, you have to request an initial sync. */ suspend fun unIgnoreUserIds(userIds: List<String>) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt index 79c86f3f23165b67c166446b3a2f35c808670d5f..f231e88de0b57c283b9f3e7a74f539f22fac42fe 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt @@ -26,7 +26,7 @@ import org.matrix.android.sdk.api.util.JsonDict data class User( val userId: String, /** - * For usage in UI, consider converting to MatrixItem and call getBestName() + * For usage in UI, consider converting to MatrixItem and call getBestName(). */ val displayName: String? = null, val avatarUrl: String? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetPostAPIMediator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetPostAPIMediator.kt index d8fd00d9e1efd5789e21e2ba8baa8f5fbc2ddc19..edb49f4797f2ac9f6a1cb6862de12052ad03be20 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetPostAPIMediator.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetPostAPIMediator.kt @@ -47,7 +47,7 @@ interface WidgetPostAPIMediator { fun injectAPI() /** - * Send a boolean response + * Send a boolean response. * * @param response the response * @param eventData the modular data @@ -55,7 +55,7 @@ interface WidgetPostAPIMediator { fun sendBoolResponse(response: Boolean, eventData: JsonDict) /** - * Send an integer response + * Send an integer response. * * @param response the response * @param eventData the modular data @@ -63,7 +63,7 @@ interface WidgetPostAPIMediator { fun sendIntegerResponse(response: Int, eventData: JsonDict) /** - * Send an object response + * Send an object response. * * @param klass the class of the response * @param response the response @@ -72,14 +72,14 @@ interface WidgetPostAPIMediator { fun <T> sendObjectResponse(type: Type, response: T?, eventData: JsonDict) /** - * Send success + * Send success. * * @param eventData the modular data */ fun sendSuccess(eventData: JsonDict) /** - * Send an error + * Send an error. * * @param message the error message * @param eventData the modular data @@ -88,7 +88,7 @@ interface WidgetPostAPIMediator { interface Handler { /** - * Triggered when a widget is posting + * Triggered when a widget is posting. */ fun handleWidgetRequest(mediator: WidgetPostAPIMediator, eventData: JsonDict): Boolean } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetService.kt index 8f35ff0e4a4532c8efe5da900feb02e66e969664..b06f8f7bc6c682d5d1ec3a297d7ab2c4b0a2ffd5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/widgets/WidgetService.kt @@ -55,7 +55,7 @@ interface WidgetService { ): List<Widget> /** - * Return the computed URL of a widget + * Return the computed URL of a widget. */ fun getWidgetComputedUrl(widget: Widget, isLightTheme: Boolean): String? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/Hash.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/Hash.kt index 7465eed3aeb1504e9320dda9fcae87a298bfd4d7..22fdd1c610192c5ffbb161b4b57e595bd56f8263 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/Hash.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/Hash.kt @@ -20,7 +20,7 @@ import java.security.MessageDigest import java.util.Locale /** - * Compute a Hash of a String, using md5 algorithm + * Compute a Hash of a String, using md5 algorithm. */ fun String.md5() = try { val digest = MessageDigest.getInstance("md5") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt index 4f5f4f82d9357c375985888d8a3b08da7c48855d..8a29d003805072d445cee22c9249efbf6b2d97eb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt @@ -121,7 +121,7 @@ sealed class MatrixItem( abstract fun updateAvatar(newAvatar: String?): MatrixItem /** - * Return the prefix as defined in the matrix spec (and not extracted from the id) + * Return the prefix as defined in the matrix spec (and not extracted from the id). */ private fun getIdPrefix() = when (this) { is UserItem -> '@' diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixJsonParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixJsonParser.kt index 48a41667b2c669cf5af81a472a373f3d0ab5548c..9927dffa4692dc50f2fd201ead105bfb1a2439a1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixJsonParser.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixJsonParser.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Moshi import org.matrix.android.sdk.internal.di.MoshiProvider /** - * Entry point to get a Json parser + * Entry point to get a Json parser. */ object MatrixJsonParser { /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/TextContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/TextContent.kt index fe12d7b1cfd0cb8712f886ea07b35ede25e891da..2aa548e289a656ae6880ade176747bad125363a7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/TextContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/TextContent.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.util /** - * Contains a text and eventually a formatted text + * Contains a text and eventually a formatted text. */ data class TextContent( val text: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt index ebad859b05178c9b0b8ac79753045606448e9988..46fa63334cb9ed571eb94f33541de0045148cddf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt @@ -45,26 +45,26 @@ import retrofit2.http.Url */ internal interface AuthAPI { /** - * Get a Web client config file, using the name including the domain + * Get a Web client config file, using the name including the domain. */ @GET("config.{domain}.json") suspend fun getWebClientConfigDomain(@Path("domain") domain: String): WebClientConfig /** - * Get a Web client default config file + * Get a Web client default config file. */ @GET("config.json") suspend fun getWebClientConfig(): WebClientConfig /** - * Get the version information of the homeserver + * Get the version information of the homeserver. */ @GET(NetworkConstants.URI_API_PREFIX_PATH_ + "versions") suspend fun versions(): Versions /** - * Register to the homeserver, or get error 401 with a RegistrationFlowResponse object if registration is incomplete - * Ref: https://matrix.org/docs/spec/client_server/latest#account-registration-and-management + * Register to the homeserver, or get error 401 with a RegistrationFlowResponse object if registration is incomplete. + * Ref: https://matrix.org/docs/spec/client_server/latest#account-registration-and-management. */ @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "register") suspend fun register(@Body registrationParams: RegistrationParams): Credentials @@ -102,14 +102,14 @@ internal interface AuthAPI { @Body params: AddThreePidRegistrationParams): AddThreePidRegistrationResponse /** - * Validate 3pid + * Validate 3pid. */ @POST suspend fun validate3Pid(@Url url: String, @Body params: ValidationCodeBody): SuccessResult /** - * Get the supported login flow + * Get the supported login flow. * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-login */ @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/Constants.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/Constants.kt index 3742a429d2de65422fa494a1fda16a127a1628cf..97f8a9d512048c3774eec32c21b86dd37f5e5668 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/Constants.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/Constants.kt @@ -23,13 +23,13 @@ package org.matrix.android.sdk.internal.auth internal const val LOGIN_FALLBACK_PATH = "/_matrix/static/client/login/" /** - * Path to use when the client does not supported any or all registration flows - * Not documented + * Path to use when the client does not supported any or all registration flows. + * Not documented. */ internal const val REGISTER_FALLBACK_PATH = "/_matrix/static/client/register/" /** - * Path to use when the client want to connect using SSO + * Path to use when the client want to connect using SSO. * Ref: https://matrix.org/docs/spec/client_server/latest#sso-client-login */ internal const val SSO_REDIRECT_PATH = "/_matrix/client/r0/login/sso/redirect" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt index 8784d85c1073021869586ea00e1409f5fa38190b..f1cfe3fee5ec6095122af7466c6edccbd9088592 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt @@ -379,24 +379,33 @@ internal class DefaultAuthenticationService @Inject constructor( throw MatrixIdFailure.InvalidMatrixId } - return getWellknownTask.execute(GetWellknownTask.Params( - domain = matrixId.getDomain(), - homeServerConnectionConfig = homeServerConnectionConfig) + return getWellknownTask.execute( + GetWellknownTask.Params( + domain = matrixId.getDomain(), + homeServerConnectionConfig = homeServerConnectionConfig.orWellKnownDefaults() + ) ) } + private fun HomeServerConnectionConfig?.orWellKnownDefaults() = this ?: HomeServerConnectionConfig.Builder() + // server uri is ignored when doing a wellknown lookup as we use the matrix id domain instead + .withHomeServerUri("https://dummy.org") + .build() + override suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig, matrixId: String, password: String, initialDeviceName: String, deviceId: String?): Session { - return directLoginTask.execute(DirectLoginTask.Params( - homeServerConnectionConfig = homeServerConnectionConfig, - userId = matrixId, - password = password, - deviceName = initialDeviceName, - deviceId = deviceId - )) + return directLoginTask.execute( + DirectLoginTask.Params( + homeServerConnectionConfig = homeServerConnectionConfig, + userId = matrixId, + password = password, + deviceName = initialDeviceName, + deviceId = deviceId + ) + ) } private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/PendingSessionStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/PendingSessionStore.kt index 06954fa5c299baacd1f43e8eb018515edc0a54ab..7483e2c7d954039a4937c904f3a4313fd21e3633 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/PendingSessionStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/PendingSessionStore.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.auth import org.matrix.android.sdk.internal.auth.db.PendingSessionData /** - * Store for elements when doing login or registration + * Store for elements when doing login or registration. */ internal interface PendingSessionStore { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt index cc00c963ea1b2550254ccf5346a36f7f1cdbab4f..ba01146a4a7e450e18bf6f62f63193f6fe679110 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt @@ -39,7 +39,7 @@ internal class DefaultSessionCreator @Inject constructor( /** * Credentials can affect the homeServerConnectionConfig, override homeserver url and/or - * identity server url if provided in the credentials + * identity server url if provided in the credentials. */ override suspend fun createSession(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig): Session { // We can cleanup the pending session params diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt index c718fae3906e6226a43efeb8e1fcf21c00ff6bb4..df10e110d13828078ca0655393cdd281c668ecc2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt @@ -23,7 +23,7 @@ import org.matrix.android.sdk.api.auth.data.SsoIdentityProvider @JsonClass(generateAdapter = true) internal data class LoginFlowResponse( /** - * The homeserver's supported login types + * The homeserver's supported login types. */ @Json(name = "flows") val flows: List<LoginFlow>? @@ -39,7 +39,7 @@ internal data class LoginFlow( /** * Augments m.login.sso flow discovery definition to include metadata on the supported IDPs - * the client can show a button for each of the supported providers + * the client can show a button for each of the supported providers. * See MSC #2858 */ @Json(name = "identity_providers") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/WebClientConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/WebClientConfig.kt index 65c3dc64a69cbaeea8cfe2005bdac9fc38ac4beb..a993124a7e33a57895881ae6c59d91a62c74794c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/WebClientConfig.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/WebClientConfig.kt @@ -22,7 +22,7 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) internal data class WebClientConfig( /** - * This is now deprecated, but still used first, rather than value from "default_server_config" + * This is now deprecated, but still used first, rather than value from "default_server_config". */ @Json(name = "default_hs_url") val defaultHomeServerUrl: String?, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmMigration.kt index 59b6471a058ed54f7baa7731953ccf462a929932..88c6d04ee67f6f50c222241b6eb209c63be74c3c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmMigration.kt @@ -27,8 +27,8 @@ import javax.inject.Inject internal class AuthRealmMigration @Inject constructor() : RealmMigration { /** - * Forces all AuthRealmMigration instances to be equal - * Avoids Realm throwing when multiple instances of the migration are set + * Forces all AuthRealmMigration instances to be equal. + * Avoids Realm throwing when multiple instances of the migration are set. */ override fun equals(other: Any?) = other is AuthRealmMigration override fun hashCode() = 4000 diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmModule.kt index a92384b4edbe9def5c97184b98bfdd8517a15caa..dbf19776021e188b6c99cd82ed5a22d965bde098 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmModule.kt @@ -19,11 +19,13 @@ package org.matrix.android.sdk.internal.auth.db import io.realm.annotations.RealmModule /** - * Realm module for authentication classes + * Realm module for authentication classes. */ -@RealmModule(library = true, +@RealmModule( + library = true, classes = [ SessionParamsEntity::class, PendingSessionEntity::class - ]) + ] +) internal class AuthRealmModule diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/PendingSessionData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/PendingSessionData.kt index 6e13e947f4c65db24247964c7b459f8f5e5351a3..835070d4b78a93109e14a066aba3ce3cd83ec624 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/PendingSessionData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/PendingSessionData.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.auth.registration.ThreePidData import java.util.UUID /** - * This class holds all pending data when creating a session, either by login or by register + * This class holds all pending data when creating a session, either by login or by register. */ internal data class PendingSessionData( val homeServerConnectionConfig: HomeServerConnectionConfig, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/PendingSessionMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/PendingSessionMapper.kt index 8e4043c11b0acfb9b87f668a74211aaeb6ef9b16..1296ea7cc40ffa58fbfb727564b71bf47fc4c6ea 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/PendingSessionMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/PendingSessionMapper.kt @@ -44,7 +44,8 @@ internal class PendingSessionMapper @Inject constructor(moshi: Moshi) { resetPasswordData = resetPasswordData, currentSession = entity.currentSession, isRegistrationStarted = entity.isRegistrationStarted, - currentThreePidData = threePidData) + currentThreePidData = threePidData + ) } fun map(sessionData: PendingSessionData?): PendingSessionEntity? { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/SessionParamsMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/SessionParamsMapper.kt index 147c0e8be013ca8f7f4623f8805881de558c9167..86929b1afe7f7a9f93ff25b316139eedfd2773e9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/SessionParamsMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/SessionParamsMapper.kt @@ -54,6 +54,7 @@ internal class SessionParamsMapper @Inject constructor(moshi: Moshi) { sessionParams.userId, credentialsJson, homeServerConnectionConfigJson, - sessionParams.isTokenValid) + sessionParams.isTokenValid + ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordData.kt index 06fcacd51495f73e069c6a1ad4708457d9113240..a65ec38d6d851be2bfa9444bc38c351fba1059f3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/ResetPasswordData.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationResponse /** - * Container to store the data when a reset password is in the email validation step + * Container to store the data when a reset password is in the email validation step. */ @JsonClass(generateAdapter = true) internal data class ResetPasswordData( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt index f8d17b406adb843b2a3fae051184b82ef25984c5..2f05864d3bfb0252da8de2a399accd47edf75a9d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt @@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.auth.registration.RegisterThreePid /** - * Add a three Pid during authentication + * Add a three Pid during authentication. */ @JsonClass(generateAdapter = true) internal data class AddThreePidRegistrationParams( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AuthParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AuthParams.kt index cb17207741b9621c769f8a17e57dc52534b69462..6337a6e5c5b09bc7b360054439d4aa752af342bd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AuthParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AuthParams.kt @@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.auth.data.LoginFlowTypes /** - * Open class, parent to all possible authentication parameters + * Open class, parent to all possible authentication parameters. */ @JsonClass(generateAdapter = true) internal data class AuthParams( @@ -29,19 +29,19 @@ internal data class AuthParams( val type: String, /** - * Note: session can be null for reset password request + * Note: session can be null for reset password request. */ @Json(name = "session") val session: String?, /** - * parameter for "m.login.recaptcha" type + * parameter for "m.login.recaptcha" type. */ @Json(name = "response") val captchaResponse: String? = null, /** - * parameter for "m.login.email.identity" type + * parameter for "m.login.email.identity" type. */ @Json(name = "threepid_creds") val threePidCredentials: ThreePidCredentials? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt index 590b333e9008ec64d799db074f19f660bcfd6ec1..8f00f3440c02e2129ad1a0a378b6d5a0f3d7818c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt @@ -33,7 +33,7 @@ import org.matrix.android.sdk.internal.auth.SessionCreator import org.matrix.android.sdk.internal.auth.db.PendingSessionData /** - * This class execute the registration request and is responsible to keep the session of interactive authentication + * This class execute the registration request and is responsible to keep the session of interactive authentication. */ internal class DefaultRegistrationWizard( authAPI: AuthAPI, @@ -120,21 +120,25 @@ internal class DefaultRegistrationWizard( RegisterAddThreePidTask.Params( threePid, pendingSessionData.clientSecret, - pendingSessionData.sendAttempt)) + pendingSessionData.sendAttempt + ) + ) pendingSessionData = pendingSessionData.copy(sendAttempt = pendingSessionData.sendAttempt + 1) .also { pendingSessionStore.savePendingSessionData(it) } val params = RegistrationParams( auth = if (threePid is RegisterThreePid.Email) { - AuthParams.createForEmailIdentity(safeSession, + AuthParams.createForEmailIdentity( + safeSession, ThreePidCredentials( clientSecret = pendingSessionData.clientSecret, sid = response.sid ) ) } else { - AuthParams.createForMsisdnIdentity(safeSession, + AuthParams.createForMsisdnIdentity( + safeSession, ThreePidCredentials( clientSecret = pendingSessionData.clientSecret, sid = response.sid diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidData.kt index 43167062d553f1034b7d433f971ebb1f58221bbf..c8f71af3065192a56a5812e80d15d2ed49213b35 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidData.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.auth.registration.RegisterThreePid /** - * Container to store the data when a three pid is in validation step + * Container to store the data when a three pid is in validation step. */ @JsonClass(generateAdapter = true) internal data class ThreePidData( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt index 7dafacb3c06ad3b8202f0681dc8cf8a323eb3157..9b135c347d427728cd46d0f2fee3983cd93df6d8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt @@ -26,7 +26,7 @@ import timber.log.Timber import kotlin.coroutines.suspendCoroutine /** - * Handle a UIA challenge + * Handle a UIA challenge. * * @param failure the failure to handle * @param interceptor see doc in [UserInteractiveAuthInterceptor] diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ValidationCodeBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ValidationCodeBody.kt index ae71ae3a08a23120c956d64338669b15e6c11a64..72b3dc6103978fb7eb6d652a7a2c21af3c2337ba 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ValidationCodeBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ValidationCodeBody.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * This object is used to send a code received by SMS to validate Msisdn ownership + * This object is used to send a code received by SMS to validate Msisdn ownership. */ @JsonClass(generateAdapter = true) internal data class ValidationCodeBody( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt index d07d5ecd64b62ba4eef581183557a9d98404f7bf..cee4b12138ed45063314d4c0a8399ba44efd01ee 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Model for https://matrix.org/docs/spec/client_server/latest#get-matrix-client-versions + * Model for https://matrix.org/docs/spec/client_server/latest#get-matrix-client-versions. * * Ex: * <pre> @@ -55,14 +55,14 @@ private const val FEATURE_THREADS_MSC3440 = "org.matrix.msc3440" private const val FEATURE_THREADS_MSC3440_STABLE = "org.matrix.msc3440.stable" /** - * Return true if the SDK supports this homeserver version + * Return true if the SDK supports this homeserver version. */ internal fun Versions.isSupportedBySdk(): Boolean { return supportLazyLoadMembers() } /** - * Return true if the SDK supports this homeserver version for login and registration + * Return true if the SDK supports this homeserver version for login and registration. */ internal fun Versions.isLoginAndRegistrationSupportedBySdk(): Boolean { return !doesServerRequireIdentityServerParam() && @@ -71,15 +71,15 @@ internal fun Versions.isLoginAndRegistrationSupportedBySdk(): Boolean { } /** - * Indicate if the homeserver support MSC3440 for threads + * Indicate if the homeserver support MSC3440 for threads. */ internal fun Versions.doesServerSupportThreads(): Boolean { - return getMaxVersion() >= HomeServerVersion.v1_3_0 || - unstableFeatures?.get(FEATURE_THREADS_MSC3440_STABLE) ?: false + // TODO Check for v1.3 or whichever spec version formally specifies MSC3440. + return unstableFeatures?.get(FEATURE_THREADS_MSC3440_STABLE) ?: false } /** - * Return true if the server support the lazy loading of room members + * Return true if the server support the lazy loading of room members. * * @return true if the server support the lazy loading of room members */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt deleted file mode 100644 index aaf23d17b366723fb91587dcd88d8be1dbe6a938..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 - -import android.content.Context -import androidx.work.WorkerParameters -import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.api.failure.shouldBeRetried -import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState -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.internal.SessionManager -import org.matrix.android.sdk.internal.crypto.model.rest.ShareRequestCancellation -import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore -import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask -import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId -import org.matrix.android.sdk.internal.session.SessionComponent -import org.matrix.android.sdk.internal.util.time.Clock -import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker -import org.matrix.android.sdk.internal.worker.SessionWorkerParams -import javax.inject.Inject - -internal class CancelGossipRequestWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<CancelGossipRequestWorker.Params>(context, params, sessionManager, Params::class.java) { - - @JsonClass(generateAdapter = true) - internal data class Params( - override val sessionId: String, - val requestId: String, - val recipients: Map<String, List<String>>, - // The txnId for the sendToDevice request. Nullable for compatibility reasons, but MUST always be provided - // to use the same value if this worker is retried. - val txnId: String? = null, - override val lastFailureMessage: String? = null - ) : SessionWorkerParams { - companion object { - fun fromRequest(sessionId: String, request: OutgoingGossipingRequest): Params { - return Params( - sessionId = sessionId, - requestId = request.requestId, - recipients = request.recipients, - txnId = createUniqueTxnId(), - lastFailureMessage = null - ) - } - } - } - - @Inject lateinit var sendToDeviceTask: SendToDeviceTask - @Inject lateinit var cryptoStore: IMXCryptoStore - @Inject lateinit var credentials: Credentials - @Inject lateinit var clock: Clock - - override fun injectWith(injector: SessionComponent) { - injector.inject(this) - } - - override suspend fun doSafeWork(params: Params): Result { - // params.txnId should be provided in all cases now. But Params can be deserialized by - // the WorkManager from data serialized in a previous version of the application, so without the txnId field. - // So if not present, we create a txnId - val txnId = params.txnId ?: createUniqueTxnId() - val contentMap = MXUsersDevicesMap<Any>() - val toDeviceContent = ShareRequestCancellation( - requestingDeviceId = credentials.deviceId, - requestId = params.requestId - ) - cryptoStore.saveGossipingEvent(Event( - type = EventType.ROOM_KEY_REQUEST, - content = toDeviceContent.toContent(), - senderId = credentials.userId - ).also { - it.ageLocalTs = clock.epochMillis() - }) - - params.recipients.forEach { userToDeviceMap -> - userToDeviceMap.value.forEach { deviceId -> - contentMap.setObject(userToDeviceMap.key, deviceId, toDeviceContent) - } - } - - try { - cryptoStore.updateOutgoingGossipingRequestState(params.requestId, OutgoingGossipingRequestState.CANCELLING) - sendToDeviceTask.execute( - SendToDeviceTask.Params( - eventType = EventType.ROOM_KEY_REQUEST, - contentMap = contentMap, - transactionId = txnId - ) - ) - cryptoStore.updateOutgoingGossipingRequestState(params.requestId, OutgoingGossipingRequestState.CANCELLED) - return Result.success() - } catch (throwable: Throwable) { - return if (throwable.shouldBeRetried()) { - Result.retry() - } else { - cryptoStore.updateOutgoingGossipingRequestState(params.requestId, OutgoingGossipingRequestState.FAILED_TO_CANCEL) - buildErrorResult(params, throwable.localizedMessage ?: "error") - } - } - } - - override fun buildErrorParams(params: Params, message: String): Params { - return params.copy(lastFailureMessage = params.lastFailureMessage ?: message) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt index 73dfc468d97a2ba35189dfdb0ac7eaae954c1d96..b3e9eab9880b1f0fa8ec3d372940273abc42530b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt @@ -28,7 +28,7 @@ import javax.inject.Inject /** * The crypto module needs some information regarding rooms that are stored - * in the session DB, this class encapsulate this functionality + * in the session DB, this class encapsulate this functionality. */ internal class CryptoSessionInfoProvider @Inject constructor( @SessionDatabase private val monarchy: Monarchy diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index 54c9990bf623ffaf4b3ea88cb3488f264c67c7c9..11fa93dbe05753ac457afa7298de581415329123 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -42,12 +42,14 @@ import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.crypto.NewSessionListener +import org.matrix.android.sdk.api.session.crypto.OutgoingKeyRequest import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.keyshare.GossipingRequestListener +import org.matrix.android.sdk.api.session.crypto.model.AuditTrail import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import org.matrix.android.sdk.api.session.crypto.model.DevicesListResponse @@ -57,15 +59,13 @@ import org.matrix.android.sdk.api.session.crypto.model.MXDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.MXEncryptEventContentResult import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest -import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyShareRequest +import org.matrix.android.sdk.api.session.crypto.model.TrailType import org.matrix.android.sdk.api.session.events.model.Content 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.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent -import org.matrix.android.sdk.api.session.events.model.content.SecretSendEventContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility @@ -76,7 +76,6 @@ import org.matrix.android.sdk.internal.crypto.actions.MegolmSessionDataImporter import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction import org.matrix.android.sdk.internal.crypto.algorithms.IMXEncrypting import org.matrix.android.sdk.internal.crypto.algorithms.IMXGroupEncryption -import org.matrix.android.sdk.internal.crypto.algorithms.IMXWithHeldExtension import org.matrix.android.sdk.internal.crypto.algorithms.megolm.MXMegolmEncryptionFactory import org.matrix.android.sdk.internal.crypto.algorithms.olm.MXOlmEncryptionFactory import org.matrix.android.sdk.internal.crypto.crosssigning.DefaultCrossSigningService @@ -91,6 +90,7 @@ import org.matrix.android.sdk.internal.crypto.tasks.GetDevicesTask import org.matrix.android.sdk.internal.crypto.tasks.SetDeviceNameTask import org.matrix.android.sdk.internal.crypto.tasks.UploadKeysTask import org.matrix.android.sdk.internal.crypto.verification.DefaultVerificationService +import org.matrix.android.sdk.internal.crypto.verification.VerificationMessageProcessor import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.UserId @@ -156,9 +156,10 @@ internal class DefaultCryptoService @Inject constructor( private val crossSigningService: DefaultCrossSigningService, // - private val incomingGossipingRequestManager: IncomingGossipingRequestManager, + private val incomingKeyRequestManager: IncomingKeyRequestManager, + private val secretShareManager: SecretShareManager, // - private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager, + private val outgoingKeyRequestManager: OutgoingKeyRequestManager, // Actions private val setDeviceVerificationAction: SetDeviceVerificationAction, private val megolmSessionDataImporter: MegolmSessionDataImporter, @@ -178,6 +179,7 @@ internal class DefaultCryptoService @Inject constructor( private val taskExecutor: TaskExecutor, private val cryptoCoroutineScope: CoroutineScope, private val eventDecryptor: EventDecryptor, + private val verificationMessageProcessor: VerificationMessageProcessor, private val liveEventManager: Lazy<StreamEventsManager> ) : CryptoService { @@ -192,7 +194,7 @@ internal class DefaultCryptoService @Inject constructor( } } - fun onLiveEvent(roomId: String, event: Event) { + fun onLiveEvent(roomId: String, event: Event, isInitialSync: Boolean) { // handle state events if (event.isStateEvent()) { when (event.type) { @@ -201,9 +203,18 @@ internal class DefaultCryptoService @Inject constructor( EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event) } } + + // handle verification + if (!isInitialSync) { + if (event.type != null && verificationMessageProcessor.shouldProcess(event.type)) { + cryptoCoroutineScope.launch(coroutineDispatchers.dmVerif) { + verificationMessageProcessor.process(event) + } + } + } } - val gossipingBuffer = mutableListOf<Event>() +// val gossipingBuffer = mutableListOf<Event>() override fun setDeviceName(deviceId: String, deviceName: String, callback: MatrixCallback<Unit>) { setDeviceNameTask @@ -282,7 +293,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Provides the tracking status + * Provides the tracking status. * * @param userId the user id * @return the tracking status @@ -292,7 +303,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Tell if the MXCrypto is started + * Tell if the MXCrypto is started. * * @return true if the crypto is started */ @@ -379,35 +390,17 @@ internal class DefaultCryptoService @Inject constructor( // Open the store cryptoStore.open() - runCatching { -// if (isInitialSync) { -// // refresh the devices list for each known room members -// deviceListManager.invalidateAllDeviceLists() -// deviceListManager.refreshOutdatedDeviceLists() -// } else { - - // Why would we do that? it will be called at end of syn - incomingGossipingRequestManager.processReceivedGossipingRequests() -// } - }.fold( - { - isStarting.set(false) - isStarted.set(true) - }, - { - isStarting.set(false) - isStarted.set(false) - Timber.tag(loggerTag.value).e(it, "Start failed") - } - ) + isStarting.set(false) + isStarted.set(true) } /** - * Close the crypto + * Close the crypto. */ fun close() = runBlocking(coroutineDispatchers.crypto) { cryptoCoroutineScope.coroutineContext.cancelChildren(CancellationException("Closing crypto module")) - incomingGossipingRequestManager.close() + incomingKeyRequestManager.close() + outgoingKeyRequestManager.close() olmDevice.release() cryptoStore.close() } @@ -428,7 +421,7 @@ internal class DefaultCryptoService @Inject constructor( override fun crossSigningService() = crossSigningService /** - * A sync response has been received + * A sync response has been received. * * @param syncResponse the syncResponse */ @@ -472,21 +465,34 @@ internal class DefaultCryptoService @Inject constructor( } oneTimeKeysUploader.maybeUploadOneTimeKeys() - incomingGossipingRequestManager.processReceivedGossipingRequests() } - } - tryOrNull { - gossipingBuffer.toList().let { - cryptoStore.saveGossipingEvents(it) + // Process pending key requests + try { + if (toDevices.isEmpty()) { + // this is not blocking + outgoingKeyRequestManager.requireProcessAllPendingKeyRequests() + } else { + Timber.tag(loggerTag.value) + .w("Don't process key requests yet as there might be more to_device to catchup") + } + } catch (failure: Throwable) { + // just for safety but should not throw + Timber.tag(loggerTag.value).w("failed to process pending request") + } + + try { + incomingKeyRequestManager.processIncomingRequests() + } catch (failure: Throwable) { + // just for safety but should not throw + Timber.tag(loggerTag.value).w("failed to process incoming room key requests") } - gossipingBuffer.clear() } } } /** - * Find a device by curve25519 identity key + * Find a device by curve25519 identity key. * * @param senderKey the curve25519 key to match. * @param algorithm the encryption algorithm. @@ -500,7 +506,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Provides the device information for a user id and a device Id + * Provides the device information for a user id and a device Id. * * @param userId the user id * @param deviceId the device id @@ -530,7 +536,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Set the devices as known + * Set the devices as known. * * @param devices the devices. Note that the verified member of the devices in this list will not be updated by this method. * @param callback the asynchronous callback @@ -594,7 +600,7 @@ internal class DefaultCryptoService @Inject constructor( // (for now at least. Maybe we should alert the user somehow?) val existingAlgorithm = cryptoStore.getRoomAlgorithm(roomId) - if (existingAlgorithm == algorithm && roomEncryptorsStore.get(roomId) != null) { + if (existingAlgorithm == algorithm) { // ignore Timber.tag(loggerTag.value).e("setEncryptionInRoom() : Ignoring m.room.encryption for same alg ($algorithm) in $roomId") return false @@ -641,7 +647,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Tells if a room is encrypted with MXCRYPTO_ALGORITHM_MEGOLM + * Tells if a room is encrypted with MXCRYPTO_ALGORITHM_MEGOLM. * * @param roomId the room id * @return true if the room is encrypted with algorithm MXCRYPTO_ALGORITHM_MEGOLM @@ -712,8 +718,10 @@ internal class DefaultCryptoService @Inject constructor( }.foldToCallback(callback) } else { val algorithm = getEncryptionAlgorithm(roomId) - val reason = String.format(MXCryptoError.UNABLE_TO_ENCRYPT_REASON, - algorithm ?: MXCryptoError.NO_MORE_ALGORITHM_REASON) + val reason = String.format( + MXCryptoError.UNABLE_TO_ENCRYPT_REASON, + algorithm ?: MXCryptoError.NO_MORE_ALGORITHM_REASON + ) Timber.tag(loggerTag.value).e("encryptEventContent() : failed $reason") callback.onFailure(Failure.CryptoError(MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_ENCRYPT, reason))) } @@ -732,7 +740,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Decrypt an event + * Decrypt an event. * * @param event the raw event. * @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack. @@ -744,7 +752,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Decrypt an event asynchronously + * Decrypt an event asynchronously. * * @param event the raw event. * @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack. @@ -755,7 +763,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Decrypt an event + * Decrypt an event. * * @param event the raw event. * @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack. @@ -776,7 +784,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Handle the 'toDevice' event + * Handle the 'toDevice' event. * * @param event the event */ @@ -785,19 +793,25 @@ internal class DefaultCryptoService @Inject constructor( cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { when (event.getClearType()) { EventType.ROOM_KEY, EventType.FORWARDED_ROOM_KEY -> { - gossipingBuffer.add(event) // Keys are imported directly, not waiting for end of sync onRoomKeyEvent(event) } - EventType.REQUEST_SECRET, + EventType.REQUEST_SECRET -> { + secretShareManager.handleSecretRequest(event) + } EventType.ROOM_KEY_REQUEST -> { - // save audit trail - gossipingBuffer.add(event) - // Requests are stacked, and will be handled one by one at the end of the sync (onSyncComplete) - incomingGossipingRequestManager.onGossipingRequestEvent(event) + event.getClearContent().toModel<RoomKeyShareRequest>()?.let { req -> + // We'll always get these because we send room key requests to + // '*' (ie. 'all devices') which includes the sending device, + // so ignore requests from ourself because apart from it being + // very silly, it won't work because an Olm session cannot send + // messages to itself. + if (req.requestingDeviceId != deviceId) { // ignore self requests + event.senderId?.let { incomingKeyRequestManager.addNewIncomingRequest(it, req) } + } + } } EventType.SEND_SECRET -> { - gossipingBuffer.add(event) onSecretSendReceived(event) } EventType.ROOM_KEY_WITHHELD -> { @@ -835,50 +849,38 @@ internal class DefaultCryptoService @Inject constructor( val withHeldContent = event.getClearContent().toModel<RoomKeyWithHeldContent>() ?: return Unit.also { Timber.tag(loggerTag.value).i("Malformed onKeyWithHeldReceived() : missing fields") } - Timber.tag(loggerTag.value).i("onKeyWithHeldReceived() received from:${event.senderId}, content <$withHeldContent>") - val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(withHeldContent.roomId, withHeldContent.algorithm) - if (alg is IMXWithHeldExtension) { - alg.onRoomKeyWithHeldEvent(withHeldContent) - } else { - Timber.tag(loggerTag.value).e("onKeyWithHeldReceived() from:${event.senderId}: Unable to handle WithHeldContent for ${withHeldContent.algorithm}") - return + val senderId = event.senderId ?: return Unit.also { + Timber.tag(loggerTag.value).i("Malformed onKeyWithHeldReceived() : missing fields") } + withHeldContent.sessionId ?: return + withHeldContent.algorithm ?: return + withHeldContent.roomId ?: return + withHeldContent.senderKey ?: return + outgoingKeyRequestManager.onRoomKeyWithHeld( + sessionId = withHeldContent.sessionId, + algorithm = withHeldContent.algorithm, + roomId = withHeldContent.roomId, + senderKey = withHeldContent.senderKey, + fromDevice = withHeldContent.fromDevice, + event = Event( + type = EventType.ROOM_KEY_WITHHELD, + senderId = senderId, + content = event.getClearContent() + ) + ) } - private fun onSecretSendReceived(event: Event) { - Timber.tag(loggerTag.value).i("GOSSIP onSecretSend() from ${event.senderId} : onSecretSendReceived ${event.content?.get("sender_key")}") - if (!event.isEncrypted()) { - // secret send messages must be encrypted - Timber.tag(loggerTag.value).e("GOSSIP onSecretSend() :Received unencrypted secret send event") - return - } - - // Was that sent by us? - if (event.senderId != userId) { - Timber.tag(loggerTag.value).e("GOSSIP onSecretSend() : Ignore secret from other user ${event.senderId}") - return - } - - val secretContent = event.getClearContent().toModel<SecretSendEventContent>() ?: return - - val existingRequest = cryptoStore - .getOutgoingSecretKeyRequests().firstOrNull { it.requestId == secretContent.requestId } - - if (existingRequest == null) { - Timber.tag(loggerTag.value).i("GOSSIP onSecretSend() : Ignore secret that was not requested: ${secretContent.requestId}") - return - } - - if (!handleSDKLevelGossip(existingRequest.secretName, secretContent.secretValue)) { - // TODO Ask to application layer? - Timber.tag(loggerTag.value).v("onSecretSend() : secret not handled by SDK") + private suspend fun onSecretSendReceived(event: Event) { + secretShareManager.onSecretSendReceived(event) { secretName, secretValue -> + handleSDKLevelGossip(secretName, secretValue) } } /** - * Returns true if handled by SDK, otherwise should be sent to application layer + * Returns true if handled by SDK, otherwise should be sent to application layer. */ - private fun handleSDKLevelGossip(secretName: String?, secretValue: String): Boolean { + private fun handleSDKLevelGossip(secretName: String?, + secretValue: String): Boolean { return when (secretName) { MASTER_KEY_SSSS_NAME -> { crossSigningService.onSecretMSKGossip(secretValue) @@ -982,7 +984,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Export the crypto keys + * Export the crypto keys. * * @param password the password * @return the exported keys @@ -992,7 +994,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Export the crypto keys + * Export the crypto keys. * * @param password the password * @param anIterationCount the encryption iteration count (0 means no encryption) @@ -1011,7 +1013,7 @@ internal class DefaultCryptoService @Inject constructor( } /** - * Import the room keys + * Import the room keys. * * @param roomKeysAsArray the room keys as array. * @param password the password @@ -1093,6 +1095,12 @@ internal class DefaultCryptoService @Inject constructor( cryptoStore.setGlobalBlacklistUnverifiedDevices(block) } + override fun enableKeyGossiping(enable: Boolean) { + cryptoStore.enableKeyGossiping(enable) + } + + override fun isKeyGossipingEnabled() = cryptoStore.isKeyGossipingEnabled() + /** * Tells whether the client should ever send encrypted messages to unverified devices. * The default value is false. @@ -1156,52 +1164,17 @@ internal class DefaultCryptoService @Inject constructor( setRoomBlacklistUnverifiedDevices(roomId, false) } -// TODO Check if this method is still necessary - /** - * Cancel any earlier room key request - * - * @param requestBody requestBody - */ - override fun cancelRoomKeyRequest(requestBody: RoomKeyRequestBody) { - outgoingGossipingRequestManager.cancelRoomKeyRequest(requestBody) - } - /** * Re request the encryption keys required to decrypt an event. * * @param event the event to decrypt again. */ override fun reRequestRoomKeyForEvent(event: Event) { - val wireContent = event.content.toModel<EncryptedEventContent>() ?: return Unit.also { - Timber.tag(loggerTag.value).e("reRequestRoomKeyForEvent Failed to re-request key, null content") - } - - val requestBody = RoomKeyRequestBody( - algorithm = wireContent.algorithm, - roomId = event.roomId, - senderKey = wireContent.senderKey, - sessionId = wireContent.sessionId - ) - - outgoingGossipingRequestManager.resendRoomKeyRequest(requestBody) + outgoingKeyRequestManager.requestKeyForEvent(event, true) } override fun requestRoomKeyForEvent(event: Event) { - val wireContent = event.content.toModel<EncryptedEventContent>() ?: return Unit.also { - Timber.tag(loggerTag.value).e("requestRoomKeyForEvent Failed to request key, null content eventId: ${event.eventId}") - } - - cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { -// if (!isStarted()) { -// Timber.v("## CRYPTO | requestRoomKeyForEvent() : wait after e2e init") -// internalStart(false) -// } - roomDecryptorProvider - .getOrCreateRoomDecryptor(event.roomId, wireContent.algorithm) - ?.requestKeysForEvent(event, false) ?: run { - Timber.tag(loggerTag.value).v("requestRoomKeyForEvent() : No room decryptor for roomId:${event.roomId} algorithm:${wireContent.algorithm}") - } - } + outgoingKeyRequestManager.requestKeyForEvent(event, false) } /** @@ -1210,7 +1183,8 @@ internal class DefaultCryptoService @Inject constructor( * @param listener listener */ override fun addRoomKeysRequestListener(listener: GossipingRequestListener) { - incomingGossipingRequestManager.addRoomKeysRequestListener(listener) + incomingKeyRequestManager.addRoomKeysRequestListener(listener) + secretShareManager.addListener(listener) } /** @@ -1219,44 +1193,12 @@ internal class DefaultCryptoService @Inject constructor( * @param listener listener */ override fun removeRoomKeysRequestListener(listener: GossipingRequestListener) { - incomingGossipingRequestManager.removeRoomKeysRequestListener(listener) - } - -// private fun markOlmSessionForUnwedging(senderId: String, deviceInfo: CryptoDeviceInfo) { -// val deviceKey = deviceInfo.identityKey() -// -// val lastForcedDate = lastNewSessionForcedDates.getObject(senderId, deviceKey) ?: 0 -// val now = clock.epochMillis() -// if (now - lastForcedDate < CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS) { -// Timber.d("## CRYPTO | markOlmSessionForUnwedging: New session already forced with device at $lastForcedDate. Not forcing another") -// return -// } -// -// Timber.d("## CRYPTO | markOlmSessionForUnwedging from $senderId:${deviceInfo.deviceId}") -// lastNewSessionForcedDates.setObject(senderId, deviceKey, now) -// -// cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { -// ensureOlmSessionsForDevicesAction.handle(mapOf(senderId to listOf(deviceInfo)), force = true) -// -// // Now send a blank message on that session so the other side knows about it. -// // (The keyshare request is sent in the clear so that won't do) -// // We send this first such that, as long as the toDevice messages arrive in the -// // same order we sent them, the other end will get this first, set up the new session, -// // then get the keyshare request and send the key over this new session (because it -// // is the session it has most recently received a message on). -// val payloadJson = mapOf<String, Any>("type" to EventType.DUMMY) -// -// val encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo)) -// val sendToDeviceMap = MXUsersDevicesMap<Any>() -// sendToDeviceMap.setObject(senderId, deviceInfo.deviceId, encodedPayload) -// Timber.v("## CRYPTO | markOlmSessionForUnwedging() : sending to $senderId:${deviceInfo.deviceId}") -// val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap) -// sendToDeviceTask.execute(sendToDeviceParams) -// } -// } + incomingKeyRequestManager.removeRoomKeysRequestListener(listener) + secretShareManager.removeListener(listener) + } /** - * Provides the list of unknown devices + * Provides the list of unknown devices. * * @param devicesInRoom the devices map * @return the unknown devices map @@ -1300,27 +1242,41 @@ internal class DefaultCryptoService @Inject constructor( return "DefaultCryptoService of $userId ($deviceId)" } - override fun getOutgoingRoomKeyRequests(): List<OutgoingRoomKeyRequest> { + override fun getOutgoingRoomKeyRequests(): List<OutgoingKeyRequest> { return cryptoStore.getOutgoingRoomKeyRequests() } - override fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingRoomKeyRequest>> { + override fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingKeyRequest>> { return cryptoStore.getOutgoingRoomKeyRequestsPaged() } + override fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> { + return cryptoStore.getGossipingEvents() + .mapNotNull { + IncomingRoomKeyRequest.fromEvent(it) + } + } + override fun getIncomingRoomKeyRequestsPaged(): LiveData<PagedList<IncomingRoomKeyRequest>> { - return cryptoStore.getIncomingRoomKeyRequestsPaged() + return cryptoStore.getGossipingEventsTrail(TrailType.IncomingKeyRequest) { + IncomingRoomKeyRequest.fromEvent(it) + ?: IncomingRoomKeyRequest(localCreationTimestamp = 0L) + } } - override fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> { - return cryptoStore.getIncomingRoomKeyRequests() + /** + * If you registered a `GossipingRequestListener`, you will be notified of key request + * that was not accepted by the SDK. You can call back this manually to accept anyhow. + */ + override suspend fun manuallyAcceptRoomKeyRequest(request: IncomingRoomKeyRequest) { + incomingKeyRequestManager.manuallyAcceptRoomKeyRequest(request) } - override fun getGossipingEventsTrail(): LiveData<PagedList<Event>> { + override fun getGossipingEventsTrail(): LiveData<PagedList<AuditTrail>> { return cryptoStore.getGossipingEventsTrail() } - override fun getGossipingEvents(): List<Event> { + override fun getGossipingEvents(): List<AuditTrail> { return cryptoStore.getGossipingEvents() } @@ -1344,8 +1300,8 @@ internal class DefaultCryptoService @Inject constructor( loadRoomMembersTask.execute(LoadRoomMembersTask.Params(roomId)) } catch (failure: Throwable) { Timber.tag(loggerTag.value).e("prepareToEncrypt() : Failed to load room members") - callback.onFailure(failure) - return@launch + // we probably shouldn't block sending on that (but questionable) + // but some members won't be able to decrypt } val userIds = getRoomUserIds(roomId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt index 535999373b8434d21cd0a6c12cfe471b50a0c8ff..cd4e2a6d527663b4dd2a572ab20ce1cea4b969d1 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt @@ -102,7 +102,7 @@ internal class DeviceListManager @Inject constructor( } /** - * Tells if the key downloads should be tried + * Tells if the key downloads should be tried. * * @param userId the userId * @return true if the keys download can be retrieved @@ -124,7 +124,7 @@ internal class DeviceListManager @Inject constructor( } /** - * Clear the unavailable server lists + * Clear the unavailable server lists. */ private fun clearUnavailableServersList() { synchronized(notReadyToRetryHS) { @@ -167,7 +167,7 @@ internal class DeviceListManager @Inject constructor( } /** - * Update the devices list statuses + * Update the devices list statuses. * * @param changed the user ids list which have new devices * @param left the user ids list which left a room @@ -203,15 +203,14 @@ internal class DeviceListManager @Inject constructor( } /** - * This will flag each user whose devices we are tracking as in need of an - * + update + * This will flag each user whose devices we are tracking as in need of an update. */ fun invalidateAllDeviceLists() { handleDeviceListsChanges(cryptoStore.getDeviceTrackingStatuses().keys, emptyList()) } /** - * The keys download failed + * The keys download failed. * * @param userIds the user ids list */ @@ -315,10 +314,19 @@ internal class DeviceListManager @Inject constructor( } else { Timber.v("## CRYPTO | downloadKeys() : starts") val t0 = clock.epochMillis() - val result = doKeyDownloadForUsers(downloadUsers) - Timber.v("## CRYPTO | downloadKeys() : doKeyDownloadForUsers succeeds after ${clock.epochMillis() - t0} ms") - result.also { - it.addEntriesFromMap(stored) + try { + val result = doKeyDownloadForUsers(downloadUsers) + Timber.v("## CRYPTO | downloadKeys() : doKeyDownloadForUsers succeeds after ${clock.epochMillis() - t0} ms") + result.also { + it.addEntriesFromMap(stored) + } + } catch (failure: Throwable) { + Timber.w(failure, "## CRYPTO | downloadKeys() : doKeyDownloadForUsers failed after ${clock.epochMillis() - t0} ms") + if (forceDownload) { + throw failure + } else { + stored + } } } } @@ -543,7 +551,7 @@ internal class DeviceListManager @Inject constructor( companion object { /** - * State transition diagram for DeviceList.deviceTrackingStatus + * State transition diagram for DeviceList.deviceTrackingStatus. * <pre> * * | diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt index a09418964538a74890aa9cd1fa66e9c9809ea4e4..d6f881211c8c3f8848f6d1c840ff9503d90038da 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt @@ -70,7 +70,7 @@ internal class EventDecryptor @Inject constructor( private val wedgedDevices = mutableListOf<WedgedDeviceInfo>() /** - * Decrypt an event + * Decrypt an event. * * @param event the raw event. * @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack. @@ -82,7 +82,7 @@ internal class EventDecryptor @Inject constructor( } /** - * Decrypt an event asynchronously + * Decrypt an event asynchronously. * * @param event the raw event. * @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack. @@ -98,7 +98,7 @@ internal class EventDecryptor @Inject constructor( } /** - * Decrypt an event + * Decrypt an event. * * @param event the raw event. * @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipingWorkManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipingWorkManager.kt deleted file mode 100644 index a2c85e5ceb1e825e5f3d61481d14f3263a160691..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipingWorkManager.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 - -import androidx.work.BackoffPolicy -import androidx.work.Data -import androidx.work.ExistingWorkPolicy -import androidx.work.ListenableWorker -import androidx.work.OneTimeWorkRequest -import org.matrix.android.sdk.api.util.Cancelable -import org.matrix.android.sdk.internal.di.WorkManagerProvider -import org.matrix.android.sdk.internal.session.SessionScope -import org.matrix.android.sdk.internal.util.CancelableWork -import org.matrix.android.sdk.internal.worker.startChain -import java.util.UUID -import java.util.concurrent.TimeUnit -import javax.inject.Inject - -@SessionScope -internal class GossipingWorkManager @Inject constructor( - private val workManagerProvider: WorkManagerProvider -) { - - inline fun <reified W : ListenableWorker> createWork(data: Data, startChain: Boolean): OneTimeWorkRequest { - return workManagerProvider.matrixOneTimeWorkRequestBuilder<W>() - .setConstraints(WorkManagerProvider.workConstraints) - .startChain(startChain) - .setInputData(data) - .setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS) - .build() - } - - // Prevent sending queue to stay broken after app restart - // The unique queue id will stay the same as long as this object is instantiated - private val queueSuffixApp = UUID.randomUUID() - - fun postWork(workRequest: OneTimeWorkRequest, policy: ExistingWorkPolicy = ExistingWorkPolicy.APPEND): Cancelable { - workManagerProvider.workManager - .beginUniqueWork(this::class.java.name + "_$queueSuffixApp", policy, workRequest) - .enqueue() - - return CancelableWork(workManagerProvider.workManager, workRequest.id) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt deleted file mode 100644 index 1612caba9fa55cf3532be20e93e4e4f4bb7f7883..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt +++ /dev/null @@ -1,475 +0,0 @@ -/* - * 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 - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch -import org.matrix.android.sdk.api.MatrixCoroutineDispatchers -import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM -import org.matrix.android.sdk.api.crypto.MXCryptoConfig -import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME -import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME -import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME -import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME -import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey -import org.matrix.android.sdk.api.session.crypto.keyshare.GossipingRequestListener -import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject -import org.matrix.android.sdk.api.session.crypto.model.IncomingRequestCancellation -import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest -import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest -import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody -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.toModel -import org.matrix.android.sdk.api.util.toBase64NoPadding -import org.matrix.android.sdk.internal.crypto.algorithms.IMXGroupEncryption -import org.matrix.android.sdk.internal.crypto.model.rest.GossipingDefaultContent -import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore -import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId -import org.matrix.android.sdk.internal.di.SessionId -import org.matrix.android.sdk.internal.session.SessionScope -import org.matrix.android.sdk.internal.util.time.Clock -import org.matrix.android.sdk.internal.worker.WorkerParamsFactory -import timber.log.Timber -import java.util.concurrent.Executors -import javax.inject.Inject - -@SessionScope -internal class IncomingGossipingRequestManager @Inject constructor( - @SessionId private val sessionId: String, - private val credentials: Credentials, - private val cryptoStore: IMXCryptoStore, - private val cryptoConfig: MXCryptoConfig, - private val gossipingWorkManager: GossipingWorkManager, - private val roomEncryptorsStore: RoomEncryptorsStore, - private val roomDecryptorProvider: RoomDecryptorProvider, - private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val cryptoCoroutineScope: CoroutineScope, - private val clock: Clock, -) { - - private val executor = Executors.newSingleThreadExecutor() - - // list of IncomingRoomKeyRequests/IncomingRoomKeyRequestCancellations - // we received in the current sync. - private val receivedGossipingRequests = ArrayList<IncomingShareRequestCommon>() - private val receivedRequestCancellations = ArrayList<IncomingRequestCancellation>() - - // the listeners - private val gossipingRequestListeners: MutableSet<GossipingRequestListener> = HashSet() - - init { - receivedGossipingRequests.addAll(cryptoStore.getPendingIncomingGossipingRequests()) - } - - fun close() { - executor.shutdownNow() - } - - // Recently verified devices (map of deviceId and timestamp) - private val recentlyVerifiedDevices = HashMap<String, Long>() - - /** - * Called when a session has been verified. - * This information can be used by the manager to decide whether or not to fullfil gossiping requests - */ - fun onVerificationCompleteForDevice(deviceId: String) { - // For now we just keep an in memory cache - synchronized(recentlyVerifiedDevices) { - recentlyVerifiedDevices[deviceId] = clock.epochMillis() - } - } - - private fun hasBeenVerifiedLessThanFiveMinutesFromNow(deviceId: String): Boolean { - val verifTimestamp: Long? - synchronized(recentlyVerifiedDevices) { - verifTimestamp = recentlyVerifiedDevices[deviceId] - } - if (verifTimestamp == null) return false - - val age = clock.epochMillis() - verifTimestamp - - return age < FIVE_MINUTES_IN_MILLIS - } - - /** - * Called when we get an m.room_key_request event - * It must be called on CryptoThread - * - * @param event the announcement event. - */ - fun onGossipingRequestEvent(event: Event) { - val roomKeyShare = event.getClearContent().toModel<GossipingDefaultContent>() - Timber.i("## CRYPTO | GOSSIP onGossipingRequestEvent received type ${event.type} from user:${event.senderId}, content:$roomKeyShare") - // val ageLocalTs = event.unsignedData?.age?.let { clock.epochMillis() - it } - when (roomKeyShare?.action) { - GossipingToDeviceObject.ACTION_SHARE_REQUEST -> { - if (event.getClearType() == EventType.REQUEST_SECRET) { - IncomingSecretShareRequest.fromEvent(event, clock.epochMillis())?.let { - if (event.senderId == credentials.userId && it.deviceId == credentials.deviceId) { - // ignore, it was sent by me as * - Timber.v("## GOSSIP onGossipingRequestEvent type ${event.type} ignore remote echo") - } else { -// // save in DB -// cryptoStore.storeIncomingGossipingRequest(it, ageLocalTs) - receivedGossipingRequests.add(it) - } - } - } else if (event.getClearType() == EventType.ROOM_KEY_REQUEST) { - IncomingRoomKeyRequest.fromEvent(event, clock.epochMillis())?.let { - if (event.senderId == credentials.userId && it.deviceId == credentials.deviceId) { - // ignore, it was sent by me as * - Timber.v("## GOSSIP onGossipingRequestEvent type ${event.type} ignore remote echo") - } else { -// cryptoStore.storeIncomingGossipingRequest(it, ageLocalTs) - receivedGossipingRequests.add(it) - } - } - } - } - GossipingToDeviceObject.ACTION_SHARE_CANCELLATION -> { - IncomingRequestCancellation.fromEvent(event, clock.epochMillis())?.let { - receivedRequestCancellations.add(it) - } - } - else -> { - Timber.e("## GOSSIP onGossipingRequestEvent() : unsupported action ${roomKeyShare?.action}") - } - } - } - - /** - * Process any m.room_key_request or m.secret.request events which were queued up during the - * current sync. - * It must be called on CryptoThread - */ - fun processReceivedGossipingRequests() { - val roomKeyRequestsToProcess = receivedGossipingRequests.toList() - receivedGossipingRequests.clear() - - Timber.v("## CRYPTO | GOSSIP processReceivedGossipingRequests() : ${roomKeyRequestsToProcess.size} request to process") - - var receivedRequestCancellations: List<IncomingRequestCancellation>? = null - - synchronized(this.receivedRequestCancellations) { - if (this.receivedRequestCancellations.isNotEmpty()) { - receivedRequestCancellations = this.receivedRequestCancellations.toList() - this.receivedRequestCancellations.clear() - } - } - - executor.execute { - cryptoStore.storeIncomingGossipingRequests(roomKeyRequestsToProcess) - for (request in roomKeyRequestsToProcess) { - if (request is IncomingRoomKeyRequest) { - processIncomingRoomKeyRequest(request) - } else if (request is IncomingSecretShareRequest) { - processIncomingSecretShareRequest(request) - } - } - - receivedRequestCancellations?.forEach { request -> - Timber.v("## CRYPTO | GOSSIP processReceivedGossipingRequests() : m.room_key_request cancellation $request") - // 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 - // everything through. - if (request.userId == credentials.userId && request.deviceId == credentials.deviceId) { - // ignore remote echo - return@forEach - } - val matchingIncoming = cryptoStore.getIncomingRoomKeyRequest(request.userId ?: "", request.deviceId ?: "", request.requestId ?: "") - if (matchingIncoming == null) { - // ignore that? - return@forEach - } else { - // If it was accepted from this device, keep the information, do not mark as cancelled - if (matchingIncoming.state != GossipingRequestState.ACCEPTED) { - onRoomKeyRequestCancellation(request) - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.CANCELLED_BY_REQUESTER) - } - } - } - } - } - - private fun processIncomingRoomKeyRequest(request: IncomingRoomKeyRequest) { - val userId = request.userId ?: return - val deviceId = request.deviceId ?: return - val body = request.requestBody ?: return - val roomId = body.roomId ?: return - val alg = body.algorithm ?: return - - Timber.v("## CRYPTO | GOSSIP processIncomingRoomKeyRequest from $userId:$deviceId for $roomId / ${body.sessionId} id ${request.requestId}") - if (credentials.userId != userId) { - handleKeyRequestFromOtherUser(body, request, alg, roomId, userId, deviceId) - return - } - // TODO: should we queue up requests we don't yet have keys for, in case they turn up later? - // if we don't have a decryptor for this room/alg, we don't have - // the keys for the requested events, and can drop the requests. - val decryptor = roomDecryptorProvider.getRoomDecryptor(roomId, alg) - if (null == decryptor) { - Timber.w("## CRYPTO | GOSSIP processReceivedGossipingRequests() : room key request for unknown $alg in room $roomId") - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - return - } - if (!decryptor.hasKeysForKeyRequest(request)) { - Timber.w("## CRYPTO | GOSSIP processReceivedGossipingRequests() : room key request for unknown session ${body.sessionId!!}") - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - return - } - - if (credentials.deviceId == deviceId && credentials.userId == userId) { - Timber.v("## CRYPTO | GOSSIP processReceivedGossipingRequests() : oneself device - ignored") - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - return - } - request.share = Runnable { - decryptor.shareKeysWithDevice(request) - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.ACCEPTED) - } - request.ignore = Runnable { - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - } - // if the device is verified already, share the keys - val device = cryptoStore.getUserDevice(userId, deviceId) - if (device != null) { - if (device.isVerified) { - Timber.v("## CRYPTO | GOSSIP processReceivedGossipingRequests() : device is already verified: sharing keys") - request.share?.run() - return - } - - if (device.isBlocked) { - Timber.v("## CRYPTO | GOSSIP processReceivedGossipingRequests() : device is blocked -> ignored") - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - return - } - } - - // As per config we automatically discard untrusted devices request - if (cryptoConfig.discardRoomKeyRequestsFromUntrustedDevices) { - Timber.v("## CRYPTO | processReceivedGossipingRequests() : discardRoomKeyRequestsFromUntrustedDevices") - // At this point the device is unknown, we don't want to bother user with that - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - return - } - - // Pass to application layer to decide what to do - onRoomKeyRequest(request) - } - - private fun handleKeyRequestFromOtherUser(body: RoomKeyRequestBody, - request: IncomingRoomKeyRequest, - alg: String, - roomId: String, - userId: String, - deviceId: String) { - Timber.w("## CRYPTO | GOSSIP processReceivedGossipingRequests() : room key request from other user") - val senderKey = body.senderKey ?: return Unit - .also { Timber.w("missing senderKey") } - .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } - val sessionId = body.sessionId ?: return Unit - .also { Timber.w("missing sessionId") } - .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } - - if (alg != MXCRYPTO_ALGORITHM_MEGOLM) { - return Unit - .also { Timber.w("Only megolm is accepted here") } - .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } - } - - val roomEncryptor = roomEncryptorsStore.get(roomId) ?: return Unit - .also { Timber.w("no room Encryptor") } - .also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) } - - cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { - if (roomEncryptor is IMXGroupEncryption) { - val isSuccess = roomEncryptor.reshareKey(sessionId, userId, deviceId, senderKey) - - if (isSuccess) { - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.ACCEPTED) - } else { - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.UNABLE_TO_PROCESS) - } - } else { - Timber.e("## CRYPTO | handleKeyRequestFromOtherUser() from:$userId: Unable to handle IMXGroupEncryption.reshareKey for $alg") - } - } - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.RE_REQUESTED) - } - - private fun processIncomingSecretShareRequest(request: IncomingSecretShareRequest) { - val secretName = request.secretName ?: return Unit.also { - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - Timber.v("## CRYPTO | GOSSIP processIncomingSecretShareRequest() : Missing secret name") - } - - val userId = request.userId - if (userId == null || credentials.userId != userId) { - Timber.e("## CRYPTO | GOSSIP processIncomingSecretShareRequest() : Ignoring secret share request from other users") - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - return - } - - val deviceId = request.deviceId - ?: return Unit.also { - Timber.e("## CRYPTO | GOSSIP processIncomingSecretShareRequest() : Malformed request, no ") - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - } - - val device = cryptoStore.getUserDevice(userId, deviceId) - ?: return Unit.also { - Timber.e("## CRYPTO | GOSSIP processIncomingSecretShareRequest() : Received secret share request from unknown device ${request.deviceId}") - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - } - - if (!device.isVerified || device.isBlocked) { - Timber.v("## CRYPTO | GOSSIP processIncomingSecretShareRequest() : Ignoring secret share request from untrusted/blocked session $device") - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - return - } - - val isDeviceLocallyVerified = cryptoStore.getUserDevice(userId, deviceId)?.trustLevel?.isLocallyVerified() - - when (secretName) { - MASTER_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.master - SELF_SIGNING_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.selfSigned - USER_SIGNING_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.user - KEYBACKUP_SECRET_SSSS_NAME -> cryptoStore.getKeyBackupRecoveryKeyInfo()?.recoveryKey - ?.let { - extractCurveKeyFromRecoveryKey(it)?.toBase64NoPadding() - } - else -> null - }?.let { secretValue -> - Timber.i("## CRYPTO | GOSSIP processIncomingSecretShareRequest() : Sharing secret $secretName with $device locally trusted") - if (isDeviceLocallyVerified == true && hasBeenVerifiedLessThanFiveMinutesFromNow(deviceId)) { - val params = SendGossipWorker.Params( - sessionId = sessionId, - secretValue = secretValue, - requestUserId = request.userId, - requestDeviceId = request.deviceId, - requestId = request.requestId, - txnId = createUniqueTxnId() - ) - - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.ACCEPTING) - val workRequest = gossipingWorkManager.createWork<SendGossipWorker>(WorkerParamsFactory.toData(params), true) - gossipingWorkManager.postWork(workRequest) - } else { - Timber.v("## CRYPTO | GOSSIP processIncomingSecretShareRequest() : Can't share secret $secretName with $device, verification too old") - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - } - return - } - - Timber.v("## CRYPTO | GOSSIP processIncomingSecretShareRequest() : $secretName unknown at SDK level, asking to app layer") - - request.ignore = Runnable { - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) - } - - request.share = { secretValue -> - val params = SendGossipWorker.Params( - sessionId = userId, - secretValue = secretValue, - requestUserId = request.userId, - requestDeviceId = request.deviceId, - requestId = request.requestId, - txnId = createUniqueTxnId() - ) - - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.ACCEPTING) - val workRequest = gossipingWorkManager.createWork<SendGossipWorker>(WorkerParamsFactory.toData(params), true) - gossipingWorkManager.postWork(workRequest) - cryptoStore.updateGossipingRequestState(request, GossipingRequestState.ACCEPTED) - } - - onShareRequest(request) - } - - /** - * Dispatch onRoomKeyRequest - * - * @param request the request - */ - private fun onRoomKeyRequest(request: IncomingRoomKeyRequest) { - synchronized(gossipingRequestListeners) { - for (listener in gossipingRequestListeners) { - try { - listener.onRoomKeyRequest(request) - } catch (e: Exception) { - Timber.e(e, "## CRYPTO | onRoomKeyRequest() failed") - } - } - } - } - - /** - * Ask for a value to the listeners, and take the first one - */ - private fun onShareRequest(request: IncomingSecretShareRequest) { - synchronized(gossipingRequestListeners) { - for (listener in gossipingRequestListeners) { - try { - if (listener.onSecretShareRequest(request)) { - return - } - } catch (e: Exception) { - Timber.e(e, "## CRYPTO | GOSSIP onRoomKeyRequest() failed") - } - } - } - // Not handled, ignore - request.ignore?.run() - } - - /** - * A room key request cancellation has been received. - * - * @param request the cancellation request - */ - private fun onRoomKeyRequestCancellation(request: IncomingRequestCancellation) { - synchronized(gossipingRequestListeners) { - for (listener in gossipingRequestListeners) { - try { - listener.onRoomKeyRequestCancellation(request) - } catch (e: Exception) { - Timber.e(e, "## CRYPTO | GOSSIP onRoomKeyRequestCancellation() failed") - } - } - } - } - - fun addRoomKeysRequestListener(listener: GossipingRequestListener) { - synchronized(gossipingRequestListeners) { - gossipingRequestListeners.add(listener) - } - } - - fun removeRoomKeysRequestListener(listener: GossipingRequestListener) { - synchronized(gossipingRequestListeners) { - gossipingRequestListeners.remove(listener) - } - } - - companion object { - private const val FIVE_MINUTES_IN_MILLIS = 5 * 60 * 1000 - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingKeyRequestManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingKeyRequestManager.kt new file mode 100644 index 0000000000000000000000000000000000000000..13f2fb861abca650f8d9616b2b3592429293bbfa --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingKeyRequestManager.kt @@ -0,0 +1,463 @@ +/* + * Copyright 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.crypto + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.withContext +import org.matrix.android.sdk.api.MatrixCoroutineDispatchers +import org.matrix.android.sdk.api.auth.data.Credentials +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCryptoConfig +import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.logger.LoggerTag +import org.matrix.android.sdk.api.session.crypto.keyshare.GossipingRequestListener +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyShareRequest +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent +import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode +import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction +import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter +import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore +import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask +import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.task.SemaphoreCoroutineSequencer +import org.matrix.android.sdk.internal.util.time.Clock +import timber.log.Timber +import java.util.concurrent.Executors +import javax.inject.Inject +import kotlin.system.measureTimeMillis + +private val loggerTag = LoggerTag("IncomingKeyRequestManager", LoggerTag.CRYPTO) + +@SessionScope +internal class IncomingKeyRequestManager @Inject constructor( + private val credentials: Credentials, + private val cryptoStore: IMXCryptoStore, + private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction, + private val olmDevice: MXOlmDevice, + private val cryptoConfig: MXCryptoConfig, + private val messageEncrypter: MessageEncrypter, + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val sendToDeviceTask: SendToDeviceTask, + private val clock: Clock, +) { + + private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + private val outgoingRequestScope = CoroutineScope(SupervisorJob() + dispatcher) + val sequencer = SemaphoreCoroutineSequencer() + + private val incomingRequestBuffer = mutableListOf<ValidMegolmRequestBody>() + + // the listeners + private val gossipingRequestListeners: MutableSet<GossipingRequestListener> = HashSet() + + enum class MegolmRequestAction { + Request, Cancel + } + + data class ValidMegolmRequestBody( + val requestId: String, + val requestingUserId: String, + val requestingDeviceId: String, + val roomId: String, + val senderKey: String, + val sessionId: String, + val action: MegolmRequestAction + ) { + fun shortDbgString() = "Request from $requestingUserId|$requestingDeviceId for session $sessionId in room $roomId" + } + + private fun RoomKeyShareRequest.toValidMegolmRequest(senderId: String): ValidMegolmRequestBody? { + val deviceId = requestingDeviceId ?: return null + val body = body ?: return null + val roomId = body.roomId ?: return null + val sessionId = body.sessionId ?: return null + val senderKey = body.senderKey ?: return null + val requestId = this.requestId ?: return null + if (body.algorithm != MXCRYPTO_ALGORITHM_MEGOLM) return null + val action = when (this.action) { + "request" -> MegolmRequestAction.Request + "request_cancellation" -> MegolmRequestAction.Cancel + else -> null + } ?: return null + return ValidMegolmRequestBody( + requestId = requestId, + requestingUserId = senderId, + requestingDeviceId = deviceId, + roomId = roomId, + senderKey = senderKey, + sessionId = sessionId, + action = action + ) + } + + fun addNewIncomingRequest(senderId: String, request: RoomKeyShareRequest) { + if (!cryptoStore.isKeyGossipingEnabled()) { + Timber.tag(loggerTag.value) + .i("Ignore incoming key request as per crypto config in room ${request.body?.roomId}") + return + } + outgoingRequestScope.launch { + // It is important to handle requests in order + sequencer.post { + val validMegolmRequest = request.toValidMegolmRequest(senderId) ?: return@post Unit.also { + Timber.tag(loggerTag.value).w("Received key request for unknown algorithm ${request.body?.algorithm}") + } + + // is there already one like that? + val existing = incomingRequestBuffer.firstOrNull { it == validMegolmRequest } + if (existing == null) { + when (validMegolmRequest.action) { + MegolmRequestAction.Request -> { + // just add to the buffer + incomingRequestBuffer.add(validMegolmRequest) + } + MegolmRequestAction.Cancel -> { + // ignore, we can't cancel as it's not known (probably already processed) + // still notify app layer if it was passed up previously + IncomingRoomKeyRequest.fromRestRequest(senderId, request, clock)?.let { iReq -> + outgoingRequestScope.launch(coroutineDispatchers.computation) { + val listenersCopy = synchronized(gossipingRequestListeners) { + gossipingRequestListeners.toList() + } + listenersCopy.onEach { + tryOrNull { + withContext(coroutineDispatchers.main) { + it.onRequestCancelled(iReq) + } + } + } + } + } + } + } + } else { + when (validMegolmRequest.action) { + MegolmRequestAction.Request -> { + // it's already in buffer, nop keep existing + } + MegolmRequestAction.Cancel -> { + // discard the request in buffer + incomingRequestBuffer.remove(existing) + outgoingRequestScope.launch(coroutineDispatchers.computation) { + val listenersCopy = synchronized(gossipingRequestListeners) { + gossipingRequestListeners.toList() + } + listenersCopy.onEach { + IncomingRoomKeyRequest.fromRestRequest(senderId, request, clock)?.let { iReq -> + withContext(coroutineDispatchers.main) { + tryOrNull { it.onRequestCancelled(iReq) } + } + } + } + } + } + } + } + } + } + } + + fun processIncomingRequests() { + outgoingRequestScope.launch { + sequencer.post { + measureTimeMillis { + Timber.tag(loggerTag.value).v("processIncomingKeyRequests : ${incomingRequestBuffer.size} request to process") + incomingRequestBuffer.forEach { + // should not happen, we only store requests + if (it.action != MegolmRequestAction.Request) return@forEach + try { + handleIncomingRequest(it) + } catch (failure: Throwable) { + // ignore and continue, should not happen + Timber.tag(loggerTag.value).w(failure, "processIncomingKeyRequests : failed to process request $it") + } + } + incomingRequestBuffer.clear() + }.let { duration -> + Timber.tag(loggerTag.value).v("Finish processing incoming key request in $duration ms") + } + } + } + } + + private suspend fun handleIncomingRequest(request: ValidMegolmRequestBody) { + // We don't want to download keys, if we don't know the device yet we won't share any how? + val requestingDevice = + cryptoStore.getUserDevice(request.requestingUserId, request.requestingDeviceId) + ?: return Unit.also { + Timber.tag(loggerTag.value).d("Ignoring key request: ${request.shortDbgString()}") + } + + cryptoStore.saveIncomingKeyRequestAuditTrail( + request.requestId, + request.roomId, + request.sessionId, + request.senderKey, + MXCRYPTO_ALGORITHM_MEGOLM, + request.requestingUserId, + request.requestingDeviceId + ) + + val roomAlgorithm = // withContext(coroutineDispatchers.crypto) { + cryptoStore.getRoomAlgorithm(request.roomId) +// } + if (roomAlgorithm != MXCRYPTO_ALGORITHM_MEGOLM) { + // strange we received a request for a room that is not encrypted + // maybe a broken state? + Timber.tag(loggerTag.value).w("Received a key request in a room with unsupported alg:$roomAlgorithm , req:${request.shortDbgString()}") + return + } + + // Is it for one of our sessions? + if (request.requestingUserId == credentials.userId) { + Timber.tag(loggerTag.value).v("handling request from own user: megolm session ${request.sessionId}") + + if (request.requestingDeviceId == credentials.deviceId) { + // ignore it's a remote echo + return + } + // If it's verified we share from the early index we know + // if not we check if it was originaly shared or not + if (requestingDevice.isVerified) { + // we share from the earliest known chain index + shareMegolmKey(request, requestingDevice, null) + } else { + shareIfItWasPreviouslyShared(request, requestingDevice) + } + } else { + if (cryptoConfig.limitRoomKeyRequestsToMyDevices) { + Timber.tag(loggerTag.value).v("Ignore request from other user as per crypto config: ${request.shortDbgString()}") + return + } + Timber.tag(loggerTag.value).v("handling request from other user: megolm session ${request.sessionId}") + if (requestingDevice.isBlocked) { + // it's blocked, so send a withheld code + sendWithheldForRequest(request, WithHeldCode.BLACKLISTED) + } else { + shareIfItWasPreviouslyShared(request, requestingDevice) + } + } + } + + private suspend fun shareIfItWasPreviouslyShared(request: ValidMegolmRequestBody, requestingDevice: CryptoDeviceInfo) { + // we don't reshare unless it was previously shared with + val wasSessionSharedWithUser = withContext(coroutineDispatchers.crypto) { + cryptoStore.getSharedSessionInfo(request.roomId, request.sessionId, requestingDevice) + } + if (wasSessionSharedWithUser.found && wasSessionSharedWithUser.chainIndex != null) { + // we share from the index it was previously shared with + shareMegolmKey(request, requestingDevice, wasSessionSharedWithUser.chainIndex.toLong()) + } else { + val isOwnDevice = requestingDevice.userId == credentials.userId + sendWithheldForRequest(request, if (isOwnDevice) WithHeldCode.UNVERIFIED else WithHeldCode.UNAUTHORISED) + // if it's our device we could delegate to the app layer to decide + if (isOwnDevice) { + outgoingRequestScope.launch(coroutineDispatchers.computation) { + val listenersCopy = synchronized(gossipingRequestListeners) { + gossipingRequestListeners.toList() + } + val iReq = IncomingRoomKeyRequest( + userId = requestingDevice.userId, + deviceId = requestingDevice.deviceId, + requestId = request.requestId, + requestBody = RoomKeyRequestBody( + algorithm = MXCRYPTO_ALGORITHM_MEGOLM, + senderKey = request.senderKey, + sessionId = request.sessionId, + roomId = request.roomId + ), + localCreationTimestamp = clock.epochMillis() + ) + listenersCopy.onEach { + withContext(coroutineDispatchers.main) { + tryOrNull { it.onRoomKeyRequest(iReq) } + } + } + } + } + } + } + + private suspend fun sendWithheldForRequest(request: ValidMegolmRequestBody, code: WithHeldCode) { + Timber.tag(loggerTag.value) + .w("Send withheld $code for req: ${request.shortDbgString()}") + val withHeldContent = RoomKeyWithHeldContent( + roomId = request.roomId, + senderKey = request.senderKey, + algorithm = MXCRYPTO_ALGORITHM_MEGOLM, + sessionId = request.sessionId, + codeString = code.value, + fromDevice = credentials.deviceId + ) + + val params = SendToDeviceTask.Params( + EventType.ROOM_KEY_WITHHELD, + MXUsersDevicesMap<Any>().apply { + setObject(request.requestingUserId, request.requestingDeviceId, withHeldContent) + } + ) + try { + withContext(coroutineDispatchers.io) { + sendToDeviceTask.execute(params) + Timber.tag(loggerTag.value) + .d("Send withheld $code req: ${request.shortDbgString()}") + } + + cryptoStore.saveWithheldAuditTrail( + roomId = request.roomId, + sessionId = request.sessionId, + senderKey = request.senderKey, + algorithm = MXCRYPTO_ALGORITHM_MEGOLM, + code = code, + userId = request.requestingUserId, + deviceId = request.requestingDeviceId + ) + } catch (failure: Throwable) { + // Ignore it's not that important? + // do we want to fallback to a worker? + Timber.tag(loggerTag.value) + .w("Failed to send withheld $code req: ${request.shortDbgString()} reason:${failure.localizedMessage}") + } + } + + suspend fun manuallyAcceptRoomKeyRequest(request: IncomingRoomKeyRequest) { + request.requestId ?: return + request.deviceId ?: return + request.userId ?: return + request.requestBody?.roomId ?: return + request.requestBody.senderKey ?: return + request.requestBody.sessionId ?: return + val validReq = ValidMegolmRequestBody( + requestId = request.requestId, + requestingDeviceId = request.deviceId, + requestingUserId = request.userId, + roomId = request.requestBody.roomId, + senderKey = request.requestBody.senderKey, + sessionId = request.requestBody.sessionId, + action = MegolmRequestAction.Request + ) + val requestingDevice = + cryptoStore.getUserDevice(request.userId, request.deviceId) + ?: return Unit.also { + Timber.tag(loggerTag.value).d("Ignoring key request: ${validReq.shortDbgString()}") + } + + shareMegolmKey(validReq, requestingDevice, null) + } + + private suspend fun shareMegolmKey(validRequest: ValidMegolmRequestBody, + requestingDevice: CryptoDeviceInfo, + chainIndex: Long?): Boolean { + Timber.tag(loggerTag.value) + .d("try to re-share Megolm Key at index $chainIndex for ${validRequest.shortDbgString()}") + + val devicesByUser = mapOf(validRequest.requestingUserId to listOf(requestingDevice)) + val usersDeviceMap = try { + ensureOlmSessionsForDevicesAction.handle(devicesByUser) + } catch (failure: Throwable) { + Timber.tag(loggerTag.value) + .w("Failed to establish olm session") + sendWithheldForRequest(validRequest, WithHeldCode.NO_OLM) + return false + } + + val olmSessionResult = usersDeviceMap.getObject(requestingDevice.userId, requestingDevice.deviceId) + if (olmSessionResult?.sessionId == null) { + Timber.tag(loggerTag.value) + .w("reshareKey: no session with this device, probably because there were no one-time keys") + sendWithheldForRequest(validRequest, WithHeldCode.NO_OLM) + return false + } + val sessionHolder = try { + olmDevice.getInboundGroupSession(validRequest.sessionId, validRequest.senderKey, validRequest.roomId) + } catch (failure: Throwable) { + Timber.tag(loggerTag.value) + .e(failure, "shareKeysWithDevice: failed to get session ${validRequest.requestingUserId}") + // It's unavailable + sendWithheldForRequest(validRequest, WithHeldCode.UNAVAILABLE) + return false + } + + val export = sessionHolder.mutex.withLock { + sessionHolder.wrapper.exportKeys(chainIndex) + } ?: return false.also { + Timber.tag(loggerTag.value) + .e("shareKeysWithDevice: failed to export group session ${validRequest.sessionId}") + } + + val payloadJson = mapOf( + "type" to EventType.FORWARDED_ROOM_KEY, + "content" to export + ) + + val encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(requestingDevice)) + val sendToDeviceMap = MXUsersDevicesMap<Any>() + sendToDeviceMap.setObject(requestingDevice.userId, requestingDevice.deviceId, encodedPayload) + Timber.tag(loggerTag.value).d("reshareKey() : try sending session ${validRequest.sessionId} to ${requestingDevice.shortDebugString()}") + val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap) + return try { + sendToDeviceTask.execute(sendToDeviceParams) + Timber.tag(loggerTag.value) + .i("successfully re-shared session ${validRequest.sessionId} to ${requestingDevice.shortDebugString()}") + cryptoStore.saveForwardKeyAuditTrail( + validRequest.roomId, + validRequest.sessionId, + validRequest.senderKey, + MXCRYPTO_ALGORITHM_MEGOLM, + requestingDevice.userId, + requestingDevice.deviceId, + chainIndex + ) + true + } catch (failure: Throwable) { + Timber.tag(loggerTag.value) + .e(failure, "fail to re-share session ${validRequest.sessionId} to ${requestingDevice.shortDebugString()}") + false + } + } + + fun addRoomKeysRequestListener(listener: GossipingRequestListener) { + synchronized(gossipingRequestListeners) { + gossipingRequestListeners.add(listener) + } + } + + fun removeRoomKeysRequestListener(listener: GossipingRequestListener) { + synchronized(gossipingRequestListeners) { + gossipingRequestListeners.remove(listener) + } + } + + fun close() { + try { + outgoingRequestScope.cancel("User Terminate") + incomingRequestBuffer.clear() + } catch (failure: Throwable) { + Timber.tag(loggerTag.value).w("Failed to shutDown request manager") + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingShareRequestCommon.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingShareRequestCommon.kt deleted file mode 100644 index 97c369db3ec7cb48b1d9c0cffeefbeff995f5136..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingShareRequestCommon.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 - -internal interface IncomingShareRequestCommon { - /** - * The user id - */ - val userId: String? - - /** - * The device id - */ - val deviceId: String? - - /** - * The request id - */ - val requestId: String? - - val localCreationTimestamp: Long? -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt index 89e38cb7cfc418d88f7d1b27bc9d827bd497f2c9..e4a0f0376e04079a4cbc64c95972981b3f11c87a 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt @@ -32,7 +32,7 @@ import kotlin.math.min import kotlin.system.measureTimeMillis /** - * Utility class to import/export the crypto data + * Utility class to import/export the crypto data. */ internal object MXMegolmExportEncryption { private const val HEADER_LINE = "-----BEGIN MEGOLM SESSION DATA-----" @@ -66,7 +66,7 @@ internal object MXMegolmExportEncryption { } /** - * Decrypt a megolm key file + * Decrypt a megolm key file. * * @param data the data to decrypt * @param password the password. @@ -209,8 +209,8 @@ internal object MXMegolmExportEncryption { } /** - * Unbase64 an ascii-armoured megolm key file - * Strips the header and trailer lines, and unbase64s the content + * Unbase64 an ascii-armoured megolm key file. + * Strips the header and trailer lines, and unbase64s the content. * * @param data the input data * @return unbase64ed content @@ -302,7 +302,7 @@ internal object MXMegolmExportEncryption { } /** - * Derive the AES and HMAC-SHA-256 keys for the file + * Derive the AES and HMAC-SHA-256 keys for the file. * * @param salt salt for pbkdf * @param iterations number of pbkdf iterations diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt index 7eec83abddf0b501daab4a3cf860567b2d7bae1d..5620cbf7693dab07ec101ae72b0869b2bf4ff306 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt @@ -43,7 +43,6 @@ import org.matrix.olm.OlmOutboundGroupSession import org.matrix.olm.OlmSession import org.matrix.olm.OlmUtility import timber.log.Timber -import java.net.URLEncoder import javax.inject.Inject private val loggerTag = LoggerTag("MXOlmDevice", LoggerTag.CRYPTO) @@ -149,9 +148,9 @@ internal class MXOlmDevice @Inject constructor( } /** - * Returns an unpublished fallback key + * Returns an unpublished fallback key. * A call to markKeysAsPublished will mark it as published and this - * call will return null (until a call to generateFallbackKey is made) + * call will return null (until a call to generateFallbackKey is made). */ fun getFallbackKey(): MutableMap<String, MutableMap<String, String>>? { try { @@ -198,7 +197,7 @@ internal class MXOlmDevice @Inject constructor( } /** - * Release the instance + * Release the instance. */ fun release() { olmUtility?.releaseUtility() @@ -241,7 +240,7 @@ internal class MXOlmDevice @Inject constructor( } /** - * Generate some new one-time keys + * Generate some new one-time keys. * * @param numKeys number of keys to generate */ @@ -331,14 +330,6 @@ internal class MXOlmDevice @Inject constructor( Timber.tag(loggerTag.value).e(e, "## createInboundSession() : removeOneTimeKeys failed") } - Timber.tag(loggerTag.value).v("## createInboundSession() : ciphertext: $ciphertext") - try { - val sha256 = olmUtility!!.sha256(URLEncoder.encode(ciphertext, "utf-8")) - Timber.tag(loggerTag.value).v("## createInboundSession() :ciphertext: SHA256: $sha256") - } catch (e: Exception) { - Timber.tag(loggerTag.value).e(e, "## createInboundSession() :ciphertext: cannot encode ciphertext") - } - val olmMessage = OlmMessage() olmMessage.mCipherText = ciphertext olmMessage.mType = messageType.toLong() @@ -589,6 +580,13 @@ internal class MXOlmDevice @Inject constructor( // Inbound group session + sealed interface AddSessionResult { + data class Imported(val ratchetIndex: Int) : AddSessionResult + abstract class Failure : AddSessionResult + object NotImported : Failure() + data class NotImportedHigherIndex(val newIndex: Int) : Failure() + } + /** * Add an inbound group session to the session store. * @@ -607,7 +605,7 @@ internal class MXOlmDevice @Inject constructor( senderKey: String, forwardingCurve25519KeyChain: List<String>, keysClaimed: Map<String, String>, - exportFormat: Boolean): Boolean { + exportFormat: Boolean): AddSessionResult { val candidateSession = OlmInboundGroupSessionWrapper2(sessionKey, exportFormat) val existingSessionHolder = tryOrNull { getInboundGroupSession(sessionId, senderKey, roomId) } val existingSession = existingSessionHolder?.wrapper @@ -615,7 +613,7 @@ internal class MXOlmDevice @Inject constructor( if (existingSession != null) { Timber.tag(loggerTag.value).d("## addInboundGroupSession() check if known session is better than candidate session") try { - val existingFirstKnown = existingSession.firstKnownIndex ?: return false.also { + val existingFirstKnown = existingSession.firstKnownIndex ?: return AddSessionResult.NotImported.also { // This is quite unexpected, could throw if native was released? Timber.tag(loggerTag.value).e("## addInboundGroupSession() null firstKnownIndex on existing session") candidateSession.olmInboundGroupSession?.releaseSession() @@ -626,12 +624,12 @@ internal class MXOlmDevice @Inject constructor( if (newKnownFirstIndex != null && existingFirstKnown <= newKnownFirstIndex) { Timber.tag(loggerTag.value).d("## addInboundGroupSession() : ignore session our is better $senderKey/$sessionId") candidateSession.olmInboundGroupSession?.releaseSession() - return false + return AddSessionResult.NotImportedHigherIndex(newKnownFirstIndex.toInt()) } } catch (failure: Throwable) { Timber.tag(loggerTag.value).e("## addInboundGroupSession() Failed to add inbound: ${failure.localizedMessage}") candidateSession.olmInboundGroupSession?.releaseSession() - return false + return AddSessionResult.NotImported } } @@ -641,19 +639,19 @@ internal class MXOlmDevice @Inject constructor( val candidateOlmInboundSession = candidateSession.olmInboundGroupSession if (null == candidateOlmInboundSession) { Timber.tag(loggerTag.value).e("## addInboundGroupSession : invalid session <null>") - return false + return AddSessionResult.NotImported } try { if (candidateOlmInboundSession.sessionIdentifier() != sessionId) { Timber.tag(loggerTag.value).e("## addInboundGroupSession : ERROR: Mismatched group session ID from senderKey: $senderKey") candidateOlmInboundSession.releaseSession() - return false + return AddSessionResult.NotImported } } catch (e: Throwable) { candidateOlmInboundSession.releaseSession() Timber.tag(loggerTag.value).e(e, "## addInboundGroupSession : sessionIdentifier() failed") - return false + return AddSessionResult.NotImported } candidateSession.senderKey = senderKey @@ -667,7 +665,7 @@ internal class MXOlmDevice @Inject constructor( inboundGroupSessionStore.storeInBoundGroupSession(InboundGroupSessionHolder(candidateSession), sessionId, senderKey) } - return true + return AddSessionResult.Imported(candidateSession.firstKnownIndex?.toInt() ?: 0) } /** @@ -790,7 +788,7 @@ internal class MXOlmDevice @Inject constructor( if (timelineSet.contains(messageIndexKey)) { val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex) - Timber.tag(loggerTag.value).e("## decryptGroupMessage() : $reason") + Timber.tag(loggerTag.value).e("## decryptGroupMessage() timelineId=$timeline: $reason") throw MXCryptoError.Base(MXCryptoError.ErrorType.DUPLICATED_MESSAGE_INDEX, reason) } @@ -858,7 +856,7 @@ internal class MXOlmDevice @Inject constructor( } /** - * Search an OlmSession + * Search an OlmSession. * * @param theirDeviceIdentityKey the device key * @param sessionId the session Id diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MyDeviceInfoHolder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MyDeviceInfoHolder.kt index 9798d21576077b553c5f53efdf01b3cefce7d130..3d09c0469ba790e4322c9ded0c0d537a572a6d1a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MyDeviceInfoHolder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MyDeviceInfoHolder.kt @@ -34,7 +34,7 @@ internal class MyDeviceInfoHolder @Inject constructor( ) { // Our device keys /** - * my device info + * my device info. */ val myDevice: CryptoDeviceInfo diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ObjectSigner.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ObjectSigner.kt index 68dd17324bb6a4b795eafa5cb49fe263c7192e7e..ab562d954a1f520f3b17f6b77b770da8b31337ec 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ObjectSigner.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ObjectSigner.kt @@ -23,7 +23,7 @@ internal class ObjectSigner @Inject constructor(private val credentials: Credent private val olmDevice: MXOlmDevice) { /** - * Sign Object + * Sign Object. * * Example: * <pre> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt index aac6f67aea1ea95dd0aa698b4160865986b5f336..fe280416ea25eea43d5bdf4815fdfd67d0389e77 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt @@ -26,12 +26,12 @@ import javax.inject.Inject private val loggerTag = LoggerTag("OlmSessionStore", LoggerTag.CRYPTO) /** - * Keep the used olm session in memory and load them from the data layer when needed - * Access is synchronized for thread safety + * Keep the used olm session in memory and load them from the data layer when needed. + * Access is synchronized for thread safety. */ internal class OlmSessionStore @Inject constructor(private val store: IMXCryptoStore) { /** - * map of device key to list of olm sessions (it is possible to have several active sessions with a device) + * Map of device key to list of olm sessions (it is possible to have several active sessions with a device). */ private val olmSessions = HashMap<String, MutableList<OlmSessionWrapper>>() @@ -89,7 +89,7 @@ internal class OlmSessionStore @Inject constructor(private val store: IMXCryptoS } /** - * Retrieve the last used sessionId, regarding `lastReceivedMessageTs`, or null if no session exist + * Retrieve the last used sessionId, regarding `lastReceivedMessageTs`, or null if no session exist. * * @param deviceKey the public key of the other device. * @return last used sessionId, or null if not found @@ -110,7 +110,7 @@ internal class OlmSessionStore @Inject constructor(private val store: IMXCryptoS } /** - * Release all sessions and clear cache + * Release all sessions and clear cache. */ @Synchronized fun clear() { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequest.kt deleted file mode 100644 index 2438e011029ddc02628e7e41db1ee45b71f5a8c5..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequest.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 - -import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState - -internal interface OutgoingGossipingRequest { - val recipients: Map<String, List<String>> - val requestId: String - val state: OutgoingGossipingRequestState - // transaction id for the cancellation, if any - // var cancellationTxnId: String? -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequestManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequestManager.kt deleted file mode 100755 index e6f6ac505310250970da3e089484d8884f2c83c2..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequestManager.kt +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import org.matrix.android.sdk.api.MatrixCoroutineDispatchers -import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest -import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody -import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore -import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId -import org.matrix.android.sdk.internal.crypto.util.RequestIdHelper -import org.matrix.android.sdk.internal.di.SessionId -import org.matrix.android.sdk.internal.session.SessionScope -import org.matrix.android.sdk.internal.worker.WorkerParamsFactory -import timber.log.Timber -import javax.inject.Inject - -@SessionScope -internal class OutgoingGossipingRequestManager @Inject constructor( - @SessionId private val sessionId: String, - private val cryptoStore: IMXCryptoStore, - private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val cryptoCoroutineScope: CoroutineScope, - private val gossipingWorkManager: GossipingWorkManager) { - - /** - * Send off a room key request, if we haven't already done so. - * - * - * The `requestBody` is compared (with a deep-equality check) against - * previous queued or sent requests and if it matches, no change is made. - * Otherwise, a request is added to the pending list, and a job is started - * in the background to send it. - * - * @param requestBody requestBody - * @param recipients recipients - */ - fun sendRoomKeyRequest(requestBody: RoomKeyRequestBody, recipients: Map<String, List<String>>) { - cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { - cryptoStore.getOrAddOutgoingRoomKeyRequest(requestBody, recipients)?.let { - // Don't resend if it's already done, you need to cancel first (reRequest) - if (it.state == OutgoingGossipingRequestState.SENDING || it.state == OutgoingGossipingRequestState.SENT) { - Timber.v("## CRYPTO - GOSSIP sendOutgoingRoomKeyRequest() : we already request for that session: $it") - return@launch - } - - sendOutgoingGossipingRequest(it) - } - } - } - - fun sendSecretShareRequest(secretName: String, recipients: Map<String, List<String>>) { - cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { - // A bit dirty, but for better stability give other party some time to mark - // devices trusted :/ - delay(1500) - cryptoStore.getOrAddOutgoingSecretShareRequest(secretName, recipients)?.let { - // TODO check if there is already one that is being sent? - if (it.state == OutgoingGossipingRequestState.SENDING - /**|| it.state == OutgoingGossipingRequestState.SENT*/ - ) { - Timber.v("## CRYPTO - GOSSIP sendSecretShareRequest() : we are already sending for that session: $it") - return@launch - } - - sendOutgoingGossipingRequest(it) - } - } - } - - /** - * Cancel room key requests, if any match the given details - * - * @param requestBody requestBody - */ - fun cancelRoomKeyRequest(requestBody: RoomKeyRequestBody) { - cryptoCoroutineScope.launch(coroutineDispatchers.computation) { - cancelRoomKeyRequest(requestBody, false) - } - } - - /** - * Cancel room key requests, if any match the given details, and resend - * - * @param requestBody requestBody - */ - fun resendRoomKeyRequest(requestBody: RoomKeyRequestBody) { - cryptoCoroutineScope.launch(coroutineDispatchers.computation) { - cancelRoomKeyRequest(requestBody, true) - } - } - - /** - * Cancel room key requests, if any match the given details, and resend - * - * @param requestBody requestBody - * @param andResend true to resend the key request - */ - private fun cancelRoomKeyRequest(requestBody: RoomKeyRequestBody, andResend: Boolean) { - val req = cryptoStore.getOutgoingRoomKeyRequest(requestBody) // no request was made for this key - ?: return Unit.also { - Timber.v("## CRYPTO - GOSSIP cancelRoomKeyRequest() Unknown request $requestBody") - } - - sendOutgoingRoomKeyRequestCancellation(req, andResend) - } - - /** - * Send the outgoing key request. - * - * @param request the request - */ - private fun sendOutgoingGossipingRequest(request: OutgoingGossipingRequest) { - Timber.v("## CRYPTO - GOSSIP sendOutgoingGossipingRequest() : Requesting keys $request") - - val params = SendGossipRequestWorker.Params( - sessionId = sessionId, - keyShareRequest = request as? OutgoingRoomKeyRequest, - secretShareRequest = request as? OutgoingSecretRequest, - txnId = createUniqueTxnId() - ) - cryptoStore.updateOutgoingGossipingRequestState(request.requestId, OutgoingGossipingRequestState.SENDING) - val workRequest = gossipingWorkManager.createWork<SendGossipRequestWorker>(WorkerParamsFactory.toData(params), true) - gossipingWorkManager.postWork(workRequest) - } - - /** - * Given a OutgoingRoomKeyRequest, cancel it and delete the request record - * - * @param request the request - */ - private fun sendOutgoingRoomKeyRequestCancellation(request: OutgoingRoomKeyRequest, resend: Boolean = false) { - Timber.v("## CRYPTO - sendOutgoingRoomKeyRequestCancellation $request") - val params = CancelGossipRequestWorker.Params.fromRequest(sessionId, request) - cryptoStore.updateOutgoingGossipingRequestState(request.requestId, OutgoingGossipingRequestState.CANCELLING) - - val workRequest = gossipingWorkManager.createWork<CancelGossipRequestWorker>(WorkerParamsFactory.toData(params), true) - gossipingWorkManager.postWork(workRequest) - - if (resend) { - val reSendParams = SendGossipRequestWorker.Params( - sessionId = sessionId, - keyShareRequest = request.copy(requestId = RequestIdHelper.createUniqueRequestId()), - txnId = createUniqueTxnId() - ) - val reSendWorkRequest = gossipingWorkManager.createWork<SendGossipRequestWorker>(WorkerParamsFactory.toData(reSendParams), true) - gossipingWorkManager.postWork(reSendWorkRequest) - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingKeyRequestManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingKeyRequestManager.kt new file mode 100755 index 0000000000000000000000000000000000000000..d7652d07713b60ebf71fb6aae07cae5cf9ff2cf3 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingKeyRequestManager.kt @@ -0,0 +1,518 @@ +/* + * 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 + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.cancel +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.matrix.android.sdk.api.MatrixCoroutineDispatchers +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCryptoConfig +import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.logger.LoggerTag +import org.matrix.android.sdk.api.session.crypto.OutgoingKeyRequest +import org.matrix.android.sdk.api.session.crypto.OutgoingRoomKeyRequestState +import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyShareRequest +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.content.EncryptedEventContent +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.util.fromBase64 +import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore +import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask +import org.matrix.android.sdk.internal.di.SessionId +import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.task.SemaphoreCoroutineSequencer +import timber.log.Timber +import java.util.Stack +import java.util.concurrent.Executors +import javax.inject.Inject +import kotlin.system.measureTimeMillis + +private val loggerTag = LoggerTag("OutgoingKeyRequestManager", LoggerTag.CRYPTO) + +/** + * This class is responsible for sending key requests to other devices when a message failed to decrypt. + * It's lifecycle is based on the sync pulse: + * - You can post queries for session, or report when you got a session + * - At the end of the sync (onSyncComplete) it will then process all the posted request and send to devices + * If a request failed it will be retried at the end of the next sync + */ +@SessionScope +internal class OutgoingKeyRequestManager @Inject constructor( + @SessionId private val sessionId: String, + @UserId private val myUserId: String, + private val cryptoStore: IMXCryptoStore, + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val cryptoConfig: MXCryptoConfig, + private val inboundGroupSessionStore: InboundGroupSessionStore, + private val sendToDeviceTask: SendToDeviceTask, + private val deviceListManager: DeviceListManager, + private val perSessionBackupQueryRateLimiter: PerSessionBackupQueryRateLimiter) { + + private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + private val outgoingRequestScope = CoroutineScope(SupervisorJob() + dispatcher) + private val sequencer = SemaphoreCoroutineSequencer() + + // We only have one active key request per session, so we don't request if it's already requested + // But it could make sense to check more the backup, as it's evolving. + // We keep a stack as we consider that the key requested last is more likely to be on screen? + private val requestDiscardedBecauseAlreadySentThatCouldBeTriedWithBackup = Stack<Pair<String, String>>() + + fun requestKeyForEvent(event: Event, force: Boolean) { + val (targets, body) = getRoomKeyRequestTargetForEvent(event) ?: return + val index = ratchetIndexForMessage(event) ?: 0 + postRoomKeyRequest(body, targets, index, force) + } + + private fun getRoomKeyRequestTargetForEvent(event: Event): Pair<Map<String, List<String>>, RoomKeyRequestBody>? { + val sender = event.senderId ?: return null + val encryptedEventContent = event.content.toModel<EncryptedEventContent>() ?: return null.also { + Timber.tag(loggerTag.value).e("getRoomKeyRequestTargetForEvent Failed to re-request key, null content") + } + if (encryptedEventContent.algorithm != MXCRYPTO_ALGORITHM_MEGOLM) return null + + val senderDevice = encryptedEventContent.deviceId + val recipients = if (cryptoConfig.limitRoomKeyRequestsToMyDevices) { + mapOf( + myUserId to listOf("*") + ) + } else { + if (event.senderId == myUserId) { + mapOf( + myUserId to listOf("*") + ) + } else { + // for the case where you share the key with a device that has a broken olm session + // The other user might Re-shares a megolm session key with devices if the key has already been + // sent to them. + mapOf( + myUserId to listOf("*"), + + // We might not have deviceId in the future due to https://github.com/matrix-org/matrix-spec-proposals/pull/3700 + // so in this case query to all + sender to listOf(senderDevice ?: "*") + ) + } + } + + val requestBody = RoomKeyRequestBody( + roomId = event.roomId, + algorithm = encryptedEventContent.algorithm, + senderKey = encryptedEventContent.senderKey, + sessionId = encryptedEventContent.sessionId + ) + return recipients to requestBody + } + + private fun ratchetIndexForMessage(event: Event): Int? { + val encryptedContent = event.content.toModel<EncryptedEventContent>() ?: return null + if (encryptedContent.algorithm != MXCRYPTO_ALGORITHM_MEGOLM) return null + return encryptedContent.ciphertext?.fromBase64()?.inputStream()?.reader()?.let { + tryOrNull { + val megolmVersion = it.read() + if (megolmVersion != 3) return@tryOrNull null + /** Int tag */ + if (it.read() != 8) return@tryOrNull null + it.read() + } + } + } + + fun postRoomKeyRequest(requestBody: RoomKeyRequestBody, recipients: Map<String, List<String>>, fromIndex: Int, force: Boolean = false) { + outgoingRequestScope.launch { + sequencer.post { + internalQueueRequest(requestBody, recipients, fromIndex, force) + } + } + } + + /** + * Typically called when we the session as been imported or received meanwhile. + */ + fun postCancelRequestForSessionIfNeeded(sessionId: String, roomId: String, senderKey: String, fromIndex: Int) { + outgoingRequestScope.launch { + sequencer.post { + internalQueueCancelRequest(sessionId, roomId, senderKey, fromIndex) + } + } + } + + fun onSelfCrossSigningTrustChanged(newTrust: Boolean) { + if (newTrust) { + // we were previously not cross signed, but we are now + // so there is now more chances to get better replies for existing request + // Let's forget about sent request so that next time we try to decrypt we will resend requests + // We don't resend all because we don't want to generate a bulk of traffic + outgoingRequestScope.launch { + sequencer.post { + cryptoStore.deleteOutgoingRoomKeyRequestInState(OutgoingRoomKeyRequestState.SENT) + } + + sequencer.post { + delay(1000) + perSessionBackupQueryRateLimiter.refreshBackupInfoIfNeeded(true) + } + } + } + } + + fun onRoomKeyForwarded(sessionId: String, + algorithm: String, + roomId: String, + senderKey: String, + fromDevice: String?, + fromIndex: Int, + event: Event) { + Timber.tag(loggerTag.value).d("Key forwarded for $sessionId from ${event.senderId}|$fromDevice at index $fromIndex") + outgoingRequestScope.launch { + sequencer.post { + cryptoStore.updateOutgoingRoomKeyReply( + roomId = roomId, + sessionId = sessionId, + algorithm = algorithm, + senderKey = senderKey, + fromDevice = fromDevice, + // strip out encrypted stuff as it's just a trail? + event = event.copy( + type = event.getClearType(), + content = mapOf( + "chain_index" to fromIndex + ) + ) + ) + } + } + } + + fun onRoomKeyWithHeld(sessionId: String, + algorithm: String, + roomId: String, + senderKey: String, + fromDevice: String?, + event: Event) { + outgoingRequestScope.launch { + sequencer.post { + Timber.tag(loggerTag.value).d("Withheld received for $sessionId from ${event.senderId}|$fromDevice") + Timber.tag(loggerTag.value).v("Withheld content ${event.getClearContent()}") + + // We want to store withheld code from the sender of the message (owner of the megolm session), not from + // other devices that might gossip the key. If not the initial reason might be overridden + // by a request to one of our session. + event.getClearContent().toModel<RoomKeyWithHeldContent>()?.let { withheld -> + withContext(coroutineDispatchers.crypto) { + tryOrNull { + deviceListManager.downloadKeys(listOf(event.senderId ?: ""), false) + } + cryptoStore.getUserDeviceList(event.senderId ?: "") + .also { devices -> + Timber.tag(loggerTag.value) + .v("Withheld Devices for ${event.senderId} are ${devices.orEmpty().joinToString { it.identityKey() ?: "" }}") + } + ?.firstOrNull { + it.identityKey() == senderKey + } + }.also { + Timber.tag(loggerTag.value).v("Withheld device for sender key $senderKey is from ${it?.shortDebugString()}") + }?.let { + if (it.userId == event.senderId) { + if (fromDevice != null) { + if (it.deviceId == fromDevice) { + Timber.tag(loggerTag.value).v("Storing sender Withheld code ${withheld.code} for ${withheld.sessionId}") + cryptoStore.addWithHeldMegolmSession(withheld) + } + } else { + Timber.tag(loggerTag.value).v("Storing sender Withheld code ${withheld.code} for ${withheld.sessionId}") + cryptoStore.addWithHeldMegolmSession(withheld) + } + } + } + } + + // Here we store the replies from a given request + cryptoStore.updateOutgoingRoomKeyReply( + roomId = roomId, + sessionId = sessionId, + algorithm = algorithm, + senderKey = senderKey, + fromDevice = fromDevice, + event = event + ) + } + } + } + + /** + * Should be called after a sync, ideally if no catchup sync needed (as keys might arrive in those). + */ + fun requireProcessAllPendingKeyRequests() { + outgoingRequestScope.launch { + sequencer.post { + internalProcessPendingKeyRequests() + } + } + } + + private fun internalQueueCancelRequest(sessionId: String, roomId: String, senderKey: String, localKnownChainIndex: Int) { + // do we have known requests for that session?? + Timber.tag(loggerTag.value).v("Cancel Key Request if needed for $sessionId") + val knownRequest = cryptoStore.getOutgoingRoomKeyRequest( + algorithm = MXCRYPTO_ALGORITHM_MEGOLM, + roomId = roomId, + sessionId = sessionId, + senderKey = senderKey + ) + if (knownRequest.isEmpty()) return Unit.also { + Timber.tag(loggerTag.value).v("Handle Cancel Key Request for $sessionId -- Was not currently requested") + } + if (knownRequest.size > 1) { + // It's worth logging, there should be only one + Timber.tag(loggerTag.value).w("Found multiple requests for same sessionId $sessionId") + } + knownRequest.forEach { request -> + when (request.state) { + OutgoingRoomKeyRequestState.UNSENT -> { + if (request.fromIndex >= localKnownChainIndex) { + // we have a good index we can cancel + cryptoStore.deleteOutgoingRoomKeyRequest(request.requestId) + } + } + OutgoingRoomKeyRequestState.SENT -> { + // It was already sent, and index satisfied we can cancel + if (request.fromIndex >= localKnownChainIndex) { + cryptoStore.updateOutgoingRoomKeyRequestState(request.requestId, OutgoingRoomKeyRequestState.CANCELLATION_PENDING) + } + } + OutgoingRoomKeyRequestState.CANCELLATION_PENDING -> { + // It is already marked to be cancelled + } + OutgoingRoomKeyRequestState.CANCELLATION_PENDING_AND_WILL_RESEND -> { + if (request.fromIndex >= localKnownChainIndex) { + // we just want to cancel now + cryptoStore.updateOutgoingRoomKeyRequestState(request.requestId, OutgoingRoomKeyRequestState.CANCELLATION_PENDING) + } + } + OutgoingRoomKeyRequestState.SENT_THEN_CANCELED -> { + // was already canceled + // if we need a better index, should we resend? + } + } + } + } + + fun close() { + try { + outgoingRequestScope.cancel("User Terminate") + requestDiscardedBecauseAlreadySentThatCouldBeTriedWithBackup.clear() + } catch (failure: Throwable) { + Timber.tag(loggerTag.value).w("Failed to shutDown request manager") + } + } + + private fun internalQueueRequest(requestBody: RoomKeyRequestBody, recipients: Map<String, List<String>>, fromIndex: Int, force: Boolean) { + if (!cryptoStore.isKeyGossipingEnabled()) { + // we might want to try backup? + if (requestBody.roomId != null && requestBody.sessionId != null) { + requestDiscardedBecauseAlreadySentThatCouldBeTriedWithBackup.push(requestBody.roomId to requestBody.sessionId) + } + Timber.tag(loggerTag.value).d("discarding request for ${requestBody.sessionId} as gossiping is disabled") + return + } + + Timber.tag(loggerTag.value).d("Queueing key request for ${requestBody.sessionId} force:$force") + val existing = cryptoStore.getOutgoingRoomKeyRequest(requestBody) + Timber.tag(loggerTag.value).v("Queueing key request exiting is ${existing?.state}") + when (existing?.state) { + null -> { + // create a new one + cryptoStore.getOrAddOutgoingRoomKeyRequest(requestBody, recipients, fromIndex) + } + OutgoingRoomKeyRequestState.UNSENT -> { + // nothing it's new or not yet handled + } + OutgoingRoomKeyRequestState.SENT -> { + // it was already requested + Timber.tag(loggerTag.value).d("The session ${requestBody.sessionId} is already requested") + if (force) { + // update to UNSENT + Timber.tag(loggerTag.value).d(".. force to request ${requestBody.sessionId}") + cryptoStore.updateOutgoingRoomKeyRequestState(existing.requestId, OutgoingRoomKeyRequestState.CANCELLATION_PENDING_AND_WILL_RESEND) + } else { + if (existing.roomId != null && existing.sessionId != null) { + requestDiscardedBecauseAlreadySentThatCouldBeTriedWithBackup.push(existing.roomId to existing.sessionId) + } + } + } + OutgoingRoomKeyRequestState.CANCELLATION_PENDING -> { + // request is canceled only if I got the keys so what to do here... + if (force) { + cryptoStore.updateOutgoingRoomKeyRequestState(existing.requestId, OutgoingRoomKeyRequestState.CANCELLATION_PENDING_AND_WILL_RESEND) + } + } + OutgoingRoomKeyRequestState.CANCELLATION_PENDING_AND_WILL_RESEND -> { + // It's already going to resend + } + OutgoingRoomKeyRequestState.SENT_THEN_CANCELED -> { + if (force) { + cryptoStore.deleteOutgoingRoomKeyRequest(existing.requestId) + cryptoStore.getOrAddOutgoingRoomKeyRequest(requestBody, recipients, fromIndex) + } + } + } + + if (existing != null && existing.fromIndex >= fromIndex) { + // update the required index + cryptoStore.updateOutgoingRoomKeyRequiredIndex(existing.requestId, fromIndex) + } + } + + private suspend fun internalProcessPendingKeyRequests() { + val toProcess = cryptoStore.getOutgoingRoomKeyRequests(OutgoingRoomKeyRequestState.pendingStates()) + Timber.tag(loggerTag.value).v("Processing all pending key requests (found ${toProcess.size} pending)") + + measureTimeMillis { + toProcess.forEach { + when (it.state) { + OutgoingRoomKeyRequestState.UNSENT -> handleUnsentRequest(it) + OutgoingRoomKeyRequestState.CANCELLATION_PENDING -> handleRequestToCancel(it) + OutgoingRoomKeyRequestState.CANCELLATION_PENDING_AND_WILL_RESEND -> handleRequestToCancelWillResend(it) + OutgoingRoomKeyRequestState.SENT_THEN_CANCELED, + OutgoingRoomKeyRequestState.SENT -> { + // these are filtered out + } + } + } + }.let { + Timber.tag(loggerTag.value).v("Finish processing pending key request in $it ms") + } + + val maxBackupCallsBySync = 60 + var currentCalls = 0 + measureTimeMillis { + while (requestDiscardedBecauseAlreadySentThatCouldBeTriedWithBackup.isNotEmpty() && currentCalls < maxBackupCallsBySync) { + requestDiscardedBecauseAlreadySentThatCouldBeTriedWithBackup.pop().let { (roomId, sessionId) -> + // we want to rate limit that somehow :/ + perSessionBackupQueryRateLimiter.tryFromBackupIfPossible(sessionId, roomId) + } + currentCalls++ + } + }.let { + Timber.tag(loggerTag.value).v("Finish querying backup in $it ms") + } + } + + private suspend fun handleUnsentRequest(request: OutgoingKeyRequest) { + // In order to avoid generating to_device traffic, we can first check if the key is backed up + Timber.tag(loggerTag.value).v("Handling unsent request for megolm session ${request.sessionId} in ${request.roomId}") + val sessionId = request.sessionId ?: return + val roomId = request.roomId ?: return + if (perSessionBackupQueryRateLimiter.tryFromBackupIfPossible(sessionId, roomId)) { + // let's see what's the index + val knownIndex = tryOrNull { + inboundGroupSessionStore.getInboundGroupSession(sessionId, request.requestBody?.senderKey ?: "")?.wrapper?.firstKnownIndex + } + if (knownIndex != null && knownIndex <= request.fromIndex) { + // we found the key in backup with good enough index, so we can just mark as cancelled, no need to send request + Timber.tag(loggerTag.value).v("Megolm session $sessionId successfully restored from backup, do not send request") + cryptoStore.deleteOutgoingRoomKeyRequest(request.requestId) + return + } + } + + // we need to send the request + val toDeviceContent = RoomKeyShareRequest( + requestingDeviceId = cryptoStore.getDeviceId(), + requestId = request.requestId, + action = GossipingToDeviceObject.ACTION_SHARE_REQUEST, + body = request.requestBody + ) + val contentMap = MXUsersDevicesMap<Any>() + request.recipients.forEach { userToDeviceMap -> + userToDeviceMap.value.forEach { deviceId -> + contentMap.setObject(userToDeviceMap.key, deviceId, toDeviceContent) + } + } + + val params = SendToDeviceTask.Params( + eventType = EventType.ROOM_KEY_REQUEST, + contentMap = contentMap, + transactionId = request.requestId + ) + try { + withContext(coroutineDispatchers.io) { + sendToDeviceTask.executeRetry(params, 3) + } + Timber.tag(loggerTag.value).d("Key request sent for $sessionId in room $roomId to ${request.recipients}") + // The request was sent, so update state + cryptoStore.updateOutgoingRoomKeyRequestState(request.requestId, OutgoingRoomKeyRequestState.SENT) + // TODO update the audit trail + } catch (failure: Throwable) { + Timber.tag(loggerTag.value).v("Failed to request $sessionId targets:${request.recipients}") + } + } + + private suspend fun handleRequestToCancel(request: OutgoingKeyRequest): Boolean { + Timber.tag(loggerTag.value).v("handleRequestToCancel for megolm session ${request.sessionId}") + // we have to cancel this + val toDeviceContent = RoomKeyShareRequest( + requestingDeviceId = cryptoStore.getDeviceId(), + requestId = request.requestId, + action = GossipingToDeviceObject.ACTION_SHARE_CANCELLATION + ) + val contentMap = MXUsersDevicesMap<Any>() + request.recipients.forEach { userToDeviceMap -> + userToDeviceMap.value.forEach { deviceId -> + contentMap.setObject(userToDeviceMap.key, deviceId, toDeviceContent) + } + } + + val params = SendToDeviceTask.Params( + eventType = EventType.ROOM_KEY_REQUEST, + contentMap = contentMap, + transactionId = request.requestId + ) + return try { + withContext(coroutineDispatchers.io) { + sendToDeviceTask.executeRetry(params, 3) + } + // The request cancellation was sent, we don't delete yet because we want + // to keep trace of the sent replies + cryptoStore.updateOutgoingRoomKeyRequestState(request.requestId, OutgoingRoomKeyRequestState.SENT_THEN_CANCELED) + true + } catch (failure: Throwable) { + Timber.tag(loggerTag.value).v("Failed to cancel request ${request.requestId} for session $sessionId targets:${request.recipients}") + false + } + } + + private suspend fun handleRequestToCancelWillResend(request: OutgoingKeyRequest) { + if (handleRequestToCancel(request)) { + // this will create a new unsent request with no replies that will be process in the following call + cryptoStore.deleteOutgoingRoomKeyRequest(request.requestId) + request.requestBody?.let { cryptoStore.getOrAddOutgoingRoomKeyRequest(it, request.recipients, request.fromIndex) } + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingSecretRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingSecretRequest.kt deleted file mode 100755 index 2ba2f5c817add137c63fe7fdabaf9095de928026..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingSecretRequest.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 - -import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState - -/** - * Represents an outgoing room key request - */ -@JsonClass(generateAdapter = true) -internal class OutgoingSecretRequest( - // Secret Name - val secretName: String?, - // list of recipients for the request - override var recipients: Map<String, List<String>>, - // Unique id for this request. Used for both - // an id within the request for later pairing with a cancellation, and for - // the transaction id when sending the to_device messages to our local - override var requestId: String, - // current state of this request - override var state: OutgoingGossipingRequestState) : OutgoingGossipingRequest { - - // transaction id for the cancellation, if any -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/PerSessionBackupQueryRateLimiter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/PerSessionBackupQueryRateLimiter.kt new file mode 100644 index 0000000000000000000000000000000000000000..5f62e7be9dbd5839d35fe2c61e93cd078d0303c9 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/PerSessionBackupQueryRateLimiter.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.crypto + +import dagger.Lazy +import kotlinx.coroutines.withContext +import org.matrix.android.sdk.api.MatrixCoroutineDispatchers +import org.matrix.android.sdk.api.logger.LoggerTag +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult +import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo +import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult +import org.matrix.android.sdk.api.util.awaitCallback +import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService +import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore +import org.matrix.android.sdk.internal.util.time.Clock +import timber.log.Timber +import javax.inject.Inject + +// I keep the same name as OutgoingGossipingRequestManager to ease filtering of logs +private val loggerTag = LoggerTag("OutgoingGossipingRequestManager", LoggerTag.CRYPTO) + +/** + * Used to try to get the key for UISI messages before sending room key request. + * We are adding some rate limiting to avoid querying too much for a key not in backup. + * Nonetheless the backup can be updated so we might want to retry from time to time. + */ +internal class PerSessionBackupQueryRateLimiter @Inject constructor( + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val keysBackupService: Lazy<DefaultKeysBackupService>, + private val cryptoStore: IMXCryptoStore, + private val clock: Clock, +) { + + companion object { + const val MIN_TRY_BACKUP_PERIOD_MILLIS = 60 * 60_000 // 1 hour + } + + data class Info( + val megolmSessionId: String, + val roomId: String + ) + + data class LastTry( + val backupVersion: String, + val timestamp: Long + ) + + /** + * Remember what we already tried (a key not in backup or some server issue). + * We might want to retry from time to time as the backup could have been updated. + */ + private val lastFailureMap = mutableMapOf<Info, LastTry>() + + private var backupVersion: KeysVersionResult? = null + private var savedKeyBackupKeyInfo: SavedKeyBackupKeyInfo? = null + var backupWasCheckedFromServer: Boolean = false + val now = clock.epochMillis() + + fun refreshBackupInfoIfNeeded(force: Boolean = false) { + if (backupWasCheckedFromServer && !force) return + Timber.tag(loggerTag.value).v("Checking if can access a backup") + backupWasCheckedFromServer = true + val knownBackupSecret = cryptoStore.getKeyBackupRecoveryKeyInfo() + ?: return Unit.also { + Timber.tag(loggerTag.value).v("We don't have the backup secret!") + } + this.backupVersion = keysBackupService.get().keysBackupVersion + this.savedKeyBackupKeyInfo = knownBackupSecret + } + + suspend fun tryFromBackupIfPossible(sessionId: String, roomId: String): Boolean { + Timber.tag(loggerTag.value).v("tryFromBackupIfPossible for session:$sessionId in $roomId") + refreshBackupInfoIfNeeded() + val currentVersion = backupVersion + if (savedKeyBackupKeyInfo?.version == null || + currentVersion == null || + currentVersion.version != savedKeyBackupKeyInfo?.version) { + // We can't access the backup + Timber.tag(loggerTag.value).v("Can't get backup version info") + return false + } + val cacheKey = Info(sessionId, roomId) + val lastTry = lastFailureMap[cacheKey] + val shouldQuery = + lastTry == null || + lastTry.backupVersion != currentVersion.version || + (now - lastTry.timestamp) > MIN_TRY_BACKUP_PERIOD_MILLIS + + if (!shouldQuery) return false + + val successfullyImported = withContext(coroutineDispatchers.io) { + try { + awaitCallback<ImportRoomKeysResult> { + keysBackupService.get().restoreKeysWithRecoveryKey( + currentVersion, + savedKeyBackupKeyInfo?.recoveryKey ?: "", + roomId, + sessionId, + null, + it + ) + }.successfullyNumberOfImportedKeys + } catch (failure: Throwable) { + // Fail silently + Timber.tag(loggerTag.value).v("getFromBackup failed ${failure.localizedMessage}") + 0 + } + } + if (successfullyImported == 1) { + Timber.tag(loggerTag.value).v("Found key in backup session:$sessionId in $roomId") + lastFailureMap.remove(cacheKey) + return true + } else { + Timber.tag(loggerTag.value).v("Failed to find key in backup session:$sessionId in $roomId") + lastFailureMap[cacheKey] = LastTry(currentVersion.version, clock.epochMillis()) + return false + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt index dab806a5657c159f9e09d64f1745cbf440242d55..c2f494b4b3035b3e118ba8ca3b35edf91faf2d7b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt @@ -79,7 +79,7 @@ internal class RoomDecryptorProvider @Inject constructor( newSessionListeners.toList().forEach { try { it.onNewSession(roomId, senderKey, sessionId) - } catch (e: Throwable) { + } catch (ignore: Throwable) { } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomEncryptorsStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomEncryptorsStore.kt index ba97d9613303fe844d67087f407d14027ef84141..1a8c160d9c313c8fba72777234193a44dce431a8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomEncryptorsStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomEncryptorsStore.kt @@ -16,12 +16,21 @@ package org.matrix.android.sdk.internal.crypto +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_OLM import org.matrix.android.sdk.internal.crypto.algorithms.IMXEncrypting +import org.matrix.android.sdk.internal.crypto.algorithms.megolm.MXMegolmEncryptionFactory +import org.matrix.android.sdk.internal.crypto.algorithms.olm.MXOlmEncryptionFactory +import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.session.SessionScope import javax.inject.Inject @SessionScope -internal class RoomEncryptorsStore @Inject constructor() { +internal class RoomEncryptorsStore @Inject constructor( + private val cryptoStore: IMXCryptoStore, + private val megolmEncryptionFactory: MXMegolmEncryptionFactory, + private val olmEncryptionFactory: MXOlmEncryptionFactory, +) { // MXEncrypting instance for each room. private val roomEncryptors = mutableMapOf<String, IMXEncrypting>() @@ -34,7 +43,18 @@ internal class RoomEncryptorsStore @Inject constructor() { fun get(roomId: String): IMXEncrypting? { return synchronized(roomEncryptors) { - roomEncryptors[roomId] + val cache = roomEncryptors[roomId] + if (cache != null) { + return@synchronized cache + } else { + val alg: IMXEncrypting? = when (cryptoStore.getRoomAlgorithm(roomId)) { + MXCRYPTO_ALGORITHM_MEGOLM -> megolmEncryptionFactory.create(roomId) + MXCRYPTO_ALGORITHM_OLM -> olmEncryptionFactory.create(roomId) + else -> null + } + alg?.let { roomEncryptors.put(roomId, it) } + return@synchronized alg + } } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt new file mode 100644 index 0000000000000000000000000000000000000000..6fb6914206f9e97000915ab0262117c435278c27 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.crypto + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.withContext +import org.matrix.android.sdk.api.MatrixCoroutineDispatchers +import org.matrix.android.sdk.api.auth.data.Credentials +import org.matrix.android.sdk.api.logger.LoggerTag +import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey +import org.matrix.android.sdk.api.session.crypto.keyshare.GossipingRequestListener +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.SecretShareRequest +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.content.SecretSendEventContent +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.util.toBase64NoPadding +import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction +import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter +import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore +import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask +import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId +import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.util.time.Clock +import timber.log.Timber +import javax.inject.Inject + +private val loggerTag = LoggerTag("SecretShareManager", LoggerTag.CRYPTO) + +@SessionScope +internal class SecretShareManager @Inject constructor( + private val credentials: Credentials, + private val cryptoStore: IMXCryptoStore, + private val cryptoCoroutineScope: CoroutineScope, + private val messageEncrypter: MessageEncrypter, + private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction, + private val sendToDeviceTask: SendToDeviceTask, + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val clock: Clock, +) { + + companion object { + private const val SECRET_SHARE_WINDOW_DURATION = 5 * 60 * 1000 // 5 minutes + } + + /** + * Secret gossiping only occurs during a limited window period after interactive verification. + * We keep track of recent verification in memory for that purpose (no need to persist) + */ + private val recentlyVerifiedDevices = mutableMapOf<String, Long>() + private val verifMutex = Mutex() + + /** + * Secrets are exchanged as part of interactive verification, + * so we can just store in memory. + */ + private val outgoingSecretRequests = mutableListOf<SecretShareRequest>() + + // the listeners + private val gossipingRequestListeners: MutableSet<GossipingRequestListener> = HashSet() + + fun addListener(listener: GossipingRequestListener) { + synchronized(gossipingRequestListeners) { + gossipingRequestListeners.add(listener) + } + } + + fun removeListener(listener: GossipingRequestListener) { + synchronized(gossipingRequestListeners) { + gossipingRequestListeners.remove(listener) + } + } + + /** + * Called when a session has been verified. + * This information can be used by the manager to decide whether or not to fullfill gossiping requests. + * This should be called as fast as possible after a successful self interactive verification + */ + fun onVerificationCompleteForDevice(deviceId: String) { + // For now we just keep an in memory cache + cryptoCoroutineScope.launch { + verifMutex.withLock { + recentlyVerifiedDevices[deviceId] = clock.epochMillis() + } + } + } + + suspend fun handleSecretRequest(toDevice: Event) { + val request = toDevice.getClearContent().toModel<SecretShareRequest>() + ?: return Unit.also { + Timber.tag(loggerTag.value) + .w("handleSecretRequest() : malformed request") + } + +// val (action, requestingDeviceId, requestId, secretName) = it + val secretName = request.secretName ?: return Unit.also { + Timber.tag(loggerTag.value) + .v("handleSecretRequest() : Missing secret name") + } + + val userId = toDevice.senderId ?: return Unit.also { + Timber.tag(loggerTag.value) + .v("handleSecretRequest() : Missing senderId") + } + + if (userId != credentials.userId) { + // secrets are only shared between our own devices + Timber.tag(loggerTag.value) + .e("Ignoring secret share request from other users $userId") + return + } + + val deviceId = request.requestingDeviceId + ?: return Unit.also { + Timber.tag(loggerTag.value) + .w("handleSecretRequest() : malformed request norequestingDeviceId ") + } + + val device = cryptoStore.getUserDevice(credentials.userId, deviceId) + ?: return Unit.also { + Timber.tag(loggerTag.value) + .e("Received secret share request from unknown device $deviceId") + } + + val isRequestingDeviceTrusted = device.isVerified + val isRecentInteractiveVerification = hasBeenVerifiedLessThanFiveMinutesFromNow(device.deviceId) + if (isRequestingDeviceTrusted && isRecentInteractiveVerification) { + // we can share the secret + + val secretValue = when (secretName) { + MASTER_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.master + SELF_SIGNING_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.selfSigned + USER_SIGNING_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.user + KEYBACKUP_SECRET_SSSS_NAME -> cryptoStore.getKeyBackupRecoveryKeyInfo()?.recoveryKey + ?.let { + extractCurveKeyFromRecoveryKey(it)?.toBase64NoPadding() + } + else -> null + } + if (secretValue == null) { + Timber.tag(loggerTag.value) + .i("The secret is unknown $secretName, passing to app layer") + val toList = synchronized(gossipingRequestListeners) { gossipingRequestListeners.toList() } + toList.onEach { listener -> + listener.onSecretShareRequest(request) + } + return + } + + val payloadJson = mapOf( + "type" to EventType.SEND_SECRET, + "content" to mapOf( + "request_id" to request.requestId, + "secret" to secretValue + ) + ) + + // Is it possible that we don't have an olm session? + val devicesByUser = mapOf(device.userId to listOf(device)) + val usersDeviceMap = try { + ensureOlmSessionsForDevicesAction.handle(devicesByUser) + } catch (failure: Throwable) { + Timber.tag(loggerTag.value) + .w("Can't share secret ${request.secretName}: Failed to establish olm session") + return + } + + val olmSessionResult = usersDeviceMap.getObject(device.userId, device.deviceId) + if (olmSessionResult?.sessionId == null) { + Timber.tag(loggerTag.value) + .w("secret share: no session with this device $deviceId, probably because there were no one-time keys") + return + } + + val encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(device)) + val sendToDeviceMap = MXUsersDevicesMap<Any>() + sendToDeviceMap.setObject(device.userId, device.deviceId, encodedPayload) + val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap) + try { + // raise the retries for secret + sendToDeviceTask.executeRetry(sendToDeviceParams, 6) + Timber.tag(loggerTag.value) + .i("successfully shared secret $secretName to ${device.shortDebugString()}") + // TODO add a trail for that in audit logs + } catch (failure: Throwable) { + Timber.tag(loggerTag.value) + .e(failure, "failed to send shared secret $secretName to ${device.shortDebugString()}") + } + } else { + Timber.tag(loggerTag.value) + .d(" Received secret share request from un-authorised device ${device.deviceId}") + } + } + + private suspend fun hasBeenVerifiedLessThanFiveMinutesFromNow(deviceId: String): Boolean { + val verifTimestamp = verifMutex.withLock { + recentlyVerifiedDevices[deviceId] + } ?: return false + + val age = clock.epochMillis() - verifTimestamp + + return age < SECRET_SHARE_WINDOW_DURATION + } + + suspend fun requestSecretTo(deviceId: String, secretName: String) { + val cryptoDeviceInfo = cryptoStore.getUserDevice(credentials.userId, deviceId) ?: return Unit.also { + Timber.tag(loggerTag.value) + .d("Can't request secret for $secretName unknown device $deviceId") + } + val toDeviceContent = SecretShareRequest( + requestingDeviceId = credentials.deviceId, + secretName = secretName, + requestId = createUniqueTxnId() + ) + + verifMutex.withLock { + outgoingSecretRequests.add(toDeviceContent) + } + + val contentMap = MXUsersDevicesMap<Any>() + contentMap.setObject(cryptoDeviceInfo.userId, cryptoDeviceInfo.deviceId, toDeviceContent) + + val params = SendToDeviceTask.Params( + eventType = EventType.REQUEST_SECRET, + contentMap = contentMap + ) + try { + withContext(coroutineDispatchers.io) { + sendToDeviceTask.executeRetry(params, 3) + } + Timber.tag(loggerTag.value) + .d("Secret request sent for $secretName to ${cryptoDeviceInfo.shortDebugString()}") + // TODO update the audit trail + } catch (failure: Throwable) { + Timber.tag(loggerTag.value) + .w("Failed to request secret $secretName to ${cryptoDeviceInfo.shortDebugString()}") + } + } + + suspend fun onSecretSendReceived(toDevice: Event, handleGossip: ((name: String, value: String) -> Boolean)) { + Timber.tag(loggerTag.value) + .i("onSecretSend() from ${toDevice.senderId} : onSecretSendReceived ${toDevice.content?.get("sender_key")}") + if (!toDevice.isEncrypted()) { + // secret send messages must be encrypted + Timber.tag(loggerTag.value).e("onSecretSend() :Received unencrypted secret send event") + return + } + + // Was that sent by us? + if (toDevice.senderId != credentials.userId) { + Timber.tag(loggerTag.value).e("onSecretSend() : Ignore secret from other user ${toDevice.senderId}") + return + } + + val secretContent = toDevice.getClearContent().toModel<SecretSendEventContent>() ?: return + + val existingRequest = verifMutex.withLock { + outgoingSecretRequests.firstOrNull { it.requestId == secretContent.requestId } + } + + // As per spec: + // Clients should ignore m.secret.send events received from devices that it did not send an m.secret.request event to. + if (existingRequest?.secretName == null) { + Timber.tag(loggerTag.value).i("onSecretSend() : Ignore secret that was not requested: ${secretContent.requestId}") + return + } + // we don't need to cancel the request as we only request to one device + // just forget about the request now + verifMutex.withLock { + outgoingSecretRequests.remove(existingRequest) + } + + if (!handleGossip(existingRequest.secretName, secretContent.secretValue)) { + // TODO Ask to application layer? + Timber.tag(loggerTag.value).v("onSecretSend() : secret not handled by SDK") + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt deleted file mode 100644 index 3b43ad672b57e0544918e0d0b484d6aee3ebadb1..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 - -import android.content.Context -import androidx.work.WorkerParameters -import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.api.failure.shouldBeRetried -import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject -import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest -import org.matrix.android.sdk.api.session.crypto.model.RoomKeyShareRequest -import org.matrix.android.sdk.api.session.crypto.model.SecretShareRequest -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.internal.SessionManager -import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore -import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask -import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId -import org.matrix.android.sdk.internal.session.SessionComponent -import org.matrix.android.sdk.internal.util.time.Clock -import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker -import org.matrix.android.sdk.internal.worker.SessionWorkerParams -import timber.log.Timber -import javax.inject.Inject - -internal class SendGossipRequestWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<SendGossipRequestWorker.Params>(context, params, sessionManager, Params::class.java) { - - @JsonClass(generateAdapter = true) - internal data class Params( - override val sessionId: String, - val keyShareRequest: OutgoingRoomKeyRequest? = null, - val secretShareRequest: OutgoingSecretRequest? = null, - // The txnId for the sendToDevice request. Nullable for compatibility reasons, but MUST always be provided - // to use the same value if this worker is retried. - val txnId: String? = null, - override val lastFailureMessage: String? = null - ) : SessionWorkerParams - - @Inject lateinit var sendToDeviceTask: SendToDeviceTask - @Inject lateinit var cryptoStore: IMXCryptoStore - @Inject lateinit var credentials: Credentials - @Inject lateinit var clock: Clock - - override fun injectWith(injector: SessionComponent) { - injector.inject(this) - } - - override suspend fun doSafeWork(params: Params): Result { - // params.txnId should be provided in all cases now. But Params can be deserialized by - // the WorkManager from data serialized in a previous version of the application, so without the txnId field. - // So if not present, we create a txnId - val txnId = params.txnId ?: createUniqueTxnId() - val contentMap = MXUsersDevicesMap<Any>() - val eventType: String - val requestId: String - when { - params.keyShareRequest != null -> { - eventType = EventType.ROOM_KEY_REQUEST - requestId = params.keyShareRequest.requestId - val toDeviceContent = RoomKeyShareRequest( - requestingDeviceId = credentials.deviceId, - requestId = params.keyShareRequest.requestId, - action = GossipingToDeviceObject.ACTION_SHARE_REQUEST, - body = params.keyShareRequest.requestBody - ) - cryptoStore.saveGossipingEvent(Event( - type = eventType, - content = toDeviceContent.toContent(), - senderId = credentials.userId - ).also { - it.ageLocalTs = clock.epochMillis() - }) - - params.keyShareRequest.recipients.forEach { userToDeviceMap -> - userToDeviceMap.value.forEach { deviceId -> - contentMap.setObject(userToDeviceMap.key, deviceId, toDeviceContent) - } - } - } - params.secretShareRequest != null -> { - eventType = EventType.REQUEST_SECRET - requestId = params.secretShareRequest.requestId - val toDeviceContent = SecretShareRequest( - requestingDeviceId = credentials.deviceId, - requestId = params.secretShareRequest.requestId, - action = GossipingToDeviceObject.ACTION_SHARE_REQUEST, - secretName = params.secretShareRequest.secretName - ) - - cryptoStore.saveGossipingEvent(Event( - type = eventType, - content = toDeviceContent.toContent(), - senderId = credentials.userId - ).also { - it.ageLocalTs = clock.epochMillis() - }) - - params.secretShareRequest.recipients.forEach { userToDeviceMap -> - userToDeviceMap.value.forEach { deviceId -> - contentMap.setObject(userToDeviceMap.key, deviceId, toDeviceContent) - } - } - } - else -> { - return buildErrorResult(params, "Unknown empty gossiping request").also { - Timber.e("Unknown empty gossiping request: $params") - } - } - } - try { - cryptoStore.updateOutgoingGossipingRequestState(requestId, OutgoingGossipingRequestState.SENDING) - sendToDeviceTask.execute( - SendToDeviceTask.Params( - eventType = eventType, - contentMap = contentMap, - transactionId = txnId - ) - ) - cryptoStore.updateOutgoingGossipingRequestState(requestId, OutgoingGossipingRequestState.SENT) - return Result.success() - } catch (throwable: Throwable) { - return if (throwable.shouldBeRetried()) { - Result.retry() - } else { - cryptoStore.updateOutgoingGossipingRequestState(requestId, OutgoingGossipingRequestState.FAILED_TO_SEND) - buildErrorResult(params, throwable.localizedMessage ?: "error") - } - } - } - - override fun buildErrorParams(params: Params, message: String): Params { - return params.copy(lastFailureMessage = params.lastFailureMessage ?: message) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt deleted file mode 100644 index 113d71d387d40f643a46253273c6937393f8517b..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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 - -import android.content.Context -import androidx.work.WorkerParameters -import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.api.failure.shouldBeRetried -import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap -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.content.SecretSendEventContent -import org.matrix.android.sdk.api.session.events.model.toContent -import org.matrix.android.sdk.internal.SessionManager -import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction -import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter -import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore -import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask -import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId -import org.matrix.android.sdk.internal.session.SessionComponent -import org.matrix.android.sdk.internal.util.time.Clock -import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker -import org.matrix.android.sdk.internal.worker.SessionWorkerParams -import timber.log.Timber -import javax.inject.Inject - -internal class SendGossipWorker( - context: Context, - params: WorkerParameters, - sessionManager: SessionManager -) : SessionSafeCoroutineWorker<SendGossipWorker.Params>(context, params, sessionManager, Params::class.java) { - - @JsonClass(generateAdapter = true) - internal data class Params( - override val sessionId: String, - val secretValue: String, - val requestUserId: String?, - val requestDeviceId: String?, - val requestId: String?, - // The txnId for the sendToDevice request. Nullable for compatibility reasons, but MUST always be provided - // to use the same value if this worker is retried. - val txnId: String? = null, - override val lastFailureMessage: String? = null - ) : SessionWorkerParams - - @Inject lateinit var sendToDeviceTask: SendToDeviceTask - @Inject lateinit var cryptoStore: IMXCryptoStore - @Inject lateinit var credentials: Credentials - @Inject lateinit var messageEncrypter: MessageEncrypter - @Inject lateinit var ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction - @Inject lateinit var clock: Clock - - override fun injectWith(injector: SessionComponent) { - injector.inject(this) - } - - override suspend fun doSafeWork(params: Params): Result { - // params.txnId should be provided in all cases now. But Params can be deserialized by - // the WorkManager from data serialized in a previous version of the application, so without the txnId field. - // So if not present, we create a txnId - val txnId = params.txnId ?: createUniqueTxnId() - val eventType: String = EventType.SEND_SECRET - - val toDeviceContent = SecretSendEventContent( - requestId = params.requestId ?: "", - secretValue = params.secretValue - ) - - val requestingUserId = params.requestUserId ?: "" - val requestingDeviceId = params.requestDeviceId ?: "" - val deviceInfo = cryptoStore.getUserDevice(requestingUserId, requestingDeviceId) - ?: return buildErrorResult(params, "Unknown deviceInfo, cannot send message").also { - cryptoStore.updateGossipingRequestState( - requestUserId = params.requestUserId, - requestDeviceId = params.requestDeviceId, - requestId = params.requestId, - state = GossipingRequestState.FAILED_TO_ACCEPTED - ) - Timber.e("Unknown deviceInfo, cannot send message, sessionId: ${params.requestDeviceId}") - } - - val sendToDeviceMap = MXUsersDevicesMap<Any>() - - val devicesByUser = mapOf(requestingUserId to listOf(deviceInfo)) - val usersDeviceMap = ensureOlmSessionsForDevicesAction.handle(devicesByUser) - val olmSessionResult = usersDeviceMap.getObject(requestingUserId, requestingDeviceId) - if (olmSessionResult?.sessionId == null) { - // no session with this device, probably because there - // were no one-time keys. - return buildErrorResult(params, "no session with this device").also { - cryptoStore.updateGossipingRequestState( - requestUserId = params.requestUserId, - requestDeviceId = params.requestDeviceId, - requestId = params.requestId, - state = GossipingRequestState.FAILED_TO_ACCEPTED - ) - Timber.e("no session with this device $requestingDeviceId, probably because there were no one-time keys.") - } - } - - val payloadJson = mapOf( - "type" to EventType.SEND_SECRET, - "content" to toDeviceContent.toContent() - ) - - try { - val encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo)) - sendToDeviceMap.setObject(requestingUserId, requestingDeviceId, encodedPayload) - } catch (failure: Throwable) { - Timber.e("## Fail to encrypt gossip + ${failure.localizedMessage}") - } - - cryptoStore.saveGossipingEvent(Event( - type = eventType, - content = toDeviceContent.toContent(), - senderId = credentials.userId - ).also { - it.ageLocalTs = clock.epochMillis() - }) - - try { - sendToDeviceTask.execute( - SendToDeviceTask.Params( - eventType = EventType.ENCRYPTED, - contentMap = sendToDeviceMap, - transactionId = txnId - ) - ) - cryptoStore.updateGossipingRequestState( - requestUserId = params.requestUserId, - requestDeviceId = params.requestDeviceId, - requestId = params.requestId, - state = GossipingRequestState.ACCEPTED - ) - return Result.success() - } catch (throwable: Throwable) { - return if (throwable.shouldBeRetried()) { - Result.retry() - } else { - cryptoStore.updateGossipingRequestState( - requestUserId = params.requestUserId, - requestDeviceId = params.requestDeviceId, - requestId = params.requestId, - state = GossipingRequestState.FAILED_TO_ACCEPTED - ) - buildErrorResult(params, throwable.localizedMessage ?: "error") - } - } - } - - override fun buildErrorParams(params: Params, message: String): Params { - return params.copy(lastFailureMessage = params.lastFailureMessage ?: message) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt index fffc2b4d4bbd05e01432cb54a888ef29d9e1f10d..c728f1b6827a427dda5124d3398b9615b0b5bce2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt @@ -45,7 +45,7 @@ internal class EnsureOlmSessionsForDevicesAction @Inject constructor( /** * We want to synchronize a bit here, because we are iterating to check existing olm session and - * also adding some + * also adding some. */ suspend fun handle(devicesByUser: Map<String, List<CryptoDeviceInfo>>, force: Boolean = false): MXUsersDevicesMap<MXOlmSessionResult> { ensureMutex.withLock { @@ -137,10 +137,14 @@ internal class EnsureOlmSessionsForDevicesAction @Inject constructor( olmDevice.verifySignature(fingerprint, oneTimeKey.signalableJSONDictionary(), signature) isVerified = true } catch (e: Exception) { - Timber.tag(loggerTag.value).d(e, "verifyKeyAndStartSession() : Verify error for otk: ${oneTimeKey.signalableJSONDictionary()}," + - " signature:$signature fingerprint:$fingerprint") - Timber.tag(loggerTag.value).e("verifyKeyAndStartSession() : Verify error for ${deviceInfo.userId}|${deviceInfo.deviceId} " + - " - signable json ${oneTimeKey.signalableJSONDictionary()}") + Timber.tag(loggerTag.value).d( + e, "verifyKeyAndStartSession() : Verify error for otk: ${oneTimeKey.signalableJSONDictionary()}," + + " signature:$signature fingerprint:$fingerprint" + ) + Timber.tag(loggerTag.value).e( + "verifyKeyAndStartSession() : Verify error for ${deviceInfo.userId}|${deviceInfo.deviceId} " + + " - signable json ${oneTimeKey.signalableJSONDictionary()}" + ) errorMessage = e.message } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt index 86674b4ac55046bfd9499388e6c0a47973a93f82..22c4e59b1899dd3f23e74cf17ad2019f0df034e7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt @@ -17,12 +17,13 @@ package org.matrix.android.sdk.internal.crypto.actions import androidx.annotation.WorkerThread +import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.listeners.ProgressListener +import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult -import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.MXOlmDevice import org.matrix.android.sdk.internal.crypto.MegolmSessionData -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager +import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager import org.matrix.android.sdk.internal.crypto.RoomDecryptorProvider import org.matrix.android.sdk.internal.crypto.algorithms.megolm.MXMegolmDecryption import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore @@ -30,12 +31,13 @@ import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject -internal class MegolmSessionDataImporter @Inject constructor( - private val olmDevice: MXOlmDevice, - private val roomDecryptorProvider: RoomDecryptorProvider, - private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager, - private val cryptoStore: IMXCryptoStore, - private val clock: Clock, +private val loggerTag = LoggerTag("MegolmSessionDataImporter", LoggerTag.CRYPTO) + +internal class MegolmSessionDataImporter @Inject constructor(private val olmDevice: MXOlmDevice, + private val roomDecryptorProvider: RoomDecryptorProvider, + private val outgoingKeyRequestManager: OutgoingKeyRequestManager, + private val cryptoStore: IMXCryptoStore, + private val clock: Clock, ) { /** @@ -66,19 +68,23 @@ internal class MegolmSessionDataImporter @Inject constructor( if (null != decrypting) { try { val sessionId = megolmSessionData.sessionId - Timber.v("## importRoomKeys retrieve senderKey " + megolmSessionData.senderKey + " sessionId " + sessionId) + Timber.tag(loggerTag.value).v("## importRoomKeys retrieve senderKey ${megolmSessionData.senderKey} sessionId $sessionId") totalNumbersOfImportedKeys++ // cancel any outstanding room key requests for this session - val roomKeyRequestBody = RoomKeyRequestBody( - algorithm = megolmSessionData.algorithm, - roomId = megolmSessionData.roomId, - senderKey = megolmSessionData.senderKey, - sessionId = megolmSessionData.sessionId - ) - outgoingGossipingRequestManager.cancelRoomKeyRequest(roomKeyRequestBody) + Timber.tag(loggerTag.value).d("Imported megolm session $sessionId from backup=$fromBackup in ${megolmSessionData.roomId}") + outgoingKeyRequestManager.postCancelRequestForSessionIfNeeded( + megolmSessionData.sessionId ?: "", + megolmSessionData.roomId ?: "", + megolmSessionData.senderKey ?: "", + tryOrNull { + olmInboundGroupSessionWrappers + .firstOrNull { it.olmInboundGroupSession?.sessionIdentifier() == megolmSessionData.sessionId } + ?.firstKnownIndex?.toInt() + } ?: 0 + ) // Have another go at decrypting events sent with this session when (decrypting) { @@ -87,7 +93,7 @@ internal class MegolmSessionDataImporter @Inject constructor( } } } catch (e: Exception) { - Timber.e(e, "## importRoomKeys() : onNewSession failed") + Timber.tag(loggerTag.value).e(e, "## importRoomKeys() : onNewSession failed") } } @@ -109,7 +115,7 @@ internal class MegolmSessionDataImporter @Inject constructor( val t1 = clock.epochMillis() - Timber.v("## importMegolmSessionsData : sessions import " + (t1 - t0) + " ms (" + megolmSessionsData.size + " sessions)") + Timber.tag(loggerTag.value).v("## importMegolmSessionsData : sessions import " + (t1 - t0) + " ms (" + megolmSessionsData.size + " sessions)") return ImportRoomKeysResult(totalNumbersOfKeys, totalNumbersOfImportedKeys) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXDecrypting.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXDecrypting.kt index 2ea4e1dd29f5ddec3466990554233c345f4d0bcb..34006ecfde5910ff4b5684a4ec769ef0609a41e5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXDecrypting.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXDecrypting.kt @@ -17,19 +17,17 @@ package org.matrix.android.sdk.internal.crypto.algorithms import org.matrix.android.sdk.api.session.crypto.MXCryptoError -import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest -import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService /** - * An interface for decrypting data + * An interface for decrypting data. */ internal interface IMXDecrypting { /** - * Decrypt an event + * Decrypt an event. * * @param event the raw event. * @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack. @@ -44,23 +42,4 @@ internal interface IMXDecrypting { * @param event the key event. */ fun onRoomKeyEvent(event: Event, defaultKeysBackupService: DefaultKeysBackupService) {} - - /** - * Determine if we have the keys necessary to respond to a room key request - * - * @param request keyRequest - * @return true if we have the keys and could (theoretically) share - */ - fun hasKeysForKeyRequest(request: IncomingRoomKeyRequest): Boolean = false - - /** - * Send the response to a room key request. - * - * @param request keyRequest - */ - fun shareKeysWithDevice(request: IncomingRoomKeyRequest) {} - - fun shareSecretWithDevice(request: IncomingSecretShareRequest, secretValue: String) {} - - fun requestKeysForEvent(event: Event, withHeld: Boolean) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXEncrypting.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXEncrypting.kt index 5294429198a81868ee0914bc824466afe89321a4..1d8412020876990c6631da60b05743409f676f4d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXEncrypting.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXEncrypting.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.crypto.algorithms import org.matrix.android.sdk.api.session.events.model.Content /** - * An interface for encrypting data + * An interface for encrypting data. */ internal interface IMXEncrypting { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXWithHeldExtension.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXWithHeldExtension.kt deleted file mode 100644 index 585bcdbbdef98f5f542ef0af5156eceaacad2d27..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXWithHeldExtension.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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.algorithms - -import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent - -internal interface IMXWithHeldExtension { - fun onRoomKeyWithHeldEvent(withHeldInfo: RoomKeyWithHeldContent) -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt index 4c407c9eb967a8e251ad065ac108eb4d569f0630..8321b73b758c2baa34dc780cddf5bbc22199b1cb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt @@ -17,51 +17,32 @@ package org.matrix.android.sdk.internal.crypto.algorithms.megolm import dagger.Lazy -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.withLock -import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.crypto.NewSessionListener import org.matrix.android.sdk.api.session.crypto.model.ForwardedRoomKeyContent -import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult -import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody 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.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent -import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent import org.matrix.android.sdk.api.session.events.model.toModel -import org.matrix.android.sdk.internal.crypto.DeviceListManager import org.matrix.android.sdk.internal.crypto.MXOlmDevice -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager -import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction -import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter +import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager import org.matrix.android.sdk.internal.crypto.algorithms.IMXDecrypting -import org.matrix.android.sdk.internal.crypto.algorithms.IMXWithHeldExtension import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore -import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.session.StreamEventsManager import timber.log.Timber private val loggerTag = LoggerTag("MXMegolmDecryption", LoggerTag.CRYPTO) -internal class MXMegolmDecryption(private val userId: String, - private val olmDevice: MXOlmDevice, - private val deviceListManager: DeviceListManager, - private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager, - private val messageEncrypter: MessageEncrypter, - private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction, - private val cryptoStore: IMXCryptoStore, - private val sendToDeviceTask: SendToDeviceTask, - private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val cryptoCoroutineScope: CoroutineScope, - private val liveEventManager: Lazy<StreamEventsManager> -) : IMXDecrypting, IMXWithHeldExtension { +internal class MXMegolmDecryption( + private val olmDevice: MXOlmDevice, + private val outgoingKeyRequestManager: OutgoingKeyRequestManager, + private val cryptoStore: IMXCryptoStore, + private val liveEventManager: Lazy<StreamEventsManager> +) : IMXDecrypting { var newSessionListener: NewSessionListener? = null @@ -73,10 +54,7 @@ internal class MXMegolmDecryption(private val userId: String, @Throws(MXCryptoError::class) override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult { - // If cross signing is enabled, we don't send request until the keys are trusted - // There could be a race effect here when xsigning is enabled, we should ensure that keys was downloaded once - val requestOnFail = cryptoStore.getMyCrossSigningInfo()?.isTrusted() == true - return decryptEvent(event, timeline, requestOnFail) + return decryptEvent(event, timeline, true) } @Throws(MXCryptoError::class) @@ -96,11 +74,13 @@ internal class MXMegolmDecryption(private val userId: String, } return runCatching { - olmDevice.decryptGroupMessage(encryptedEventContent.ciphertext, + olmDevice.decryptGroupMessage( + encryptedEventContent.ciphertext, event.roomId, timeline, encryptedEventContent.sessionId, - encryptedEventContent.senderKey) + encryptedEventContent.senderKey + ) } .fold( { olmDecryptionResult -> @@ -124,27 +104,27 @@ internal class MXMegolmDecryption(private val userId: String, if (throwable is MXCryptoError.OlmError) { // TODO Check the value of .message if (throwable.olmException.message == "UNKNOWN_MESSAGE_INDEX") { - // addEventToPendingList(event, timeline) - // The session might has been partially withheld (and only pass ratcheted) + // So we know that session, but it's ratcheted and we can't decrypt at that index + + if (requestKeysOnFail) { + requestKeysForEvent(event) + } + // Check if partially withheld val withHeldInfo = cryptoStore.getWithHeldMegolmSession(event.roomId, encryptedEventContent.sessionId) if (withHeldInfo != null) { - if (requestKeysOnFail) { - requestKeysForEvent(event, true) - } // Encapsulate as withHeld exception - throw MXCryptoError.Base(MXCryptoError.ErrorType.KEYS_WITHHELD, + throw MXCryptoError.Base( + MXCryptoError.ErrorType.KEYS_WITHHELD, withHeldInfo.code?.value ?: "", - withHeldInfo.reason) - } - - if (requestKeysOnFail) { - requestKeysForEvent(event, false) + withHeldInfo.reason + ) } throw MXCryptoError.Base( MXCryptoError.ErrorType.UNKNOWN_MESSAGE_INDEX, "UNKNOWN_MESSAGE_INDEX", - null) + null + ) } val reason = String.format(MXCryptoError.OLM_REASON, throwable.olmException.message) @@ -153,28 +133,26 @@ internal class MXMegolmDecryption(private val userId: String, throw MXCryptoError.Base( MXCryptoError.ErrorType.OLM, reason, - detailedReason) + detailedReason + ) } if (throwable is MXCryptoError.Base) { - if ( - /** if the session is unknown*/ - throwable.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID - ) { + if (throwable.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID) { + // Check if it was withheld by sender to enrich error code val withHeldInfo = cryptoStore.getWithHeldMegolmSession(event.roomId, encryptedEventContent.sessionId) if (withHeldInfo != null) { if (requestKeysOnFail) { - requestKeysForEvent(event, true) + requestKeysForEvent(event) } // Encapsulate as withHeld exception - throw MXCryptoError.Base(MXCryptoError.ErrorType.KEYS_WITHHELD, + throw MXCryptoError.Base( + MXCryptoError.ErrorType.KEYS_WITHHELD, withHeldInfo.code?.value ?: "", withHeldInfo.reason) - } else { - // This is un-used in Matrix Android SDK2, not sure if needed - // addEventToPendingList(event, timeline) - if (requestKeysOnFail) { - requestKeysForEvent(event, false) - } + } + + if (requestKeysOnFail) { + requestKeysForEvent(event) } } } @@ -190,55 +168,10 @@ internal class MXMegolmDecryption(private val userId: String, * * @param event the event */ - override fun requestKeysForEvent(event: Event, withHeld: Boolean) { - val sender = event.senderId ?: return - val encryptedEventContent = event.content.toModel<EncryptedEventContent>() - val senderDevice = encryptedEventContent?.deviceId ?: return - - val recipients = if (event.senderId == userId || withHeld) { - mapOf( - userId to listOf("*") - ) - } else { - // for the case where you share the key with a device that has a broken olm session - // The other user might Re-shares a megolm session key with devices if the key has already been - // sent to them. - mapOf( - userId to listOf("*"), - sender to listOf(senderDevice) - ) - } - - val requestBody = RoomKeyRequestBody( - roomId = event.roomId, - algorithm = encryptedEventContent.algorithm, - senderKey = encryptedEventContent.senderKey, - sessionId = encryptedEventContent.sessionId - ) - - outgoingGossipingRequestManager.sendRoomKeyRequest(requestBody, recipients) + private fun requestKeysForEvent(event: Event) { + outgoingKeyRequestManager.requestKeyForEvent(event, false) } -// /** -// * Add an event to the list of those we couldn't decrypt the first time we -// * saw them. -// * -// * @param event the event to try to decrypt later -// * @param timelineId the timeline identifier -// */ -// private fun addEventToPendingList(event: Event, timelineId: String) { -// val encryptedEventContent = event.content.toModel<EncryptedEventContent>() ?: return -// val pendingEventsKey = "${encryptedEventContent.senderKey}|${encryptedEventContent.sessionId}" -// -// val timeline = pendingEvents.getOrPut(pendingEventsKey) { HashMap() } -// val events = timeline.getOrPut(timelineId) { ArrayList() } -// -// if (event !in events) { -// Timber.v("## CRYPTO | addEventToPendingList() : add Event ${event.eventId} in room id ${event.roomId}") -// events.add(event) -// } -// } - /** * Handle a key event. * @@ -258,6 +191,11 @@ internal class MXMegolmDecryption(private val userId: String, return } if (event.getClearType() == EventType.FORWARDED_ROOM_KEY) { + if (!cryptoStore.isKeyGossipingEnabled()) { + Timber.tag(loggerTag.value) + .i("onRoomKeyEvent(), ignore forward adding as per crypto config : ${roomKeyContent.roomId}|${roomKeyContent.sessionId}") + return + } Timber.tag(loggerTag.value).i("onRoomKeyEvent(), forward adding key : ${roomKeyContent.roomId}|${roomKeyContent.sessionId}") val forwardedRoomKeyContent = event.getClearContent().toModel<ForwardedRoomKeyContent>() ?: return @@ -298,32 +236,63 @@ internal class MXMegolmDecryption(private val userId: String, } Timber.tag(loggerTag.value).i("onRoomKeyEvent addInboundGroupSession ${roomKeyContent.sessionId}") - val added = olmDevice.addInboundGroupSession(roomKeyContent.sessionId, + val addSessionResult = olmDevice.addInboundGroupSession( + roomKeyContent.sessionId, roomKeyContent.sessionKey, roomKeyContent.roomId, senderKey, forwardingCurve25519KeyChain, keysClaimed, - exportFormat) - - if (added) { - defaultKeysBackupService.maybeBackupKeys() + exportFormat + ) - val content = RoomKeyRequestBody( - algorithm = roomKeyContent.algorithm, - roomId = roomKeyContent.roomId, - sessionId = roomKeyContent.sessionId, - senderKey = senderKey - ) + when (addSessionResult) { + is MXOlmDevice.AddSessionResult.Imported -> addSessionResult.ratchetIndex + is MXOlmDevice.AddSessionResult.NotImportedHigherIndex -> addSessionResult.newIndex + else -> null + }?.let { index -> + if (event.getClearType() == EventType.FORWARDED_ROOM_KEY) { + val fromDevice = (event.content?.get("sender_key") as? String)?.let { senderDeviceIdentityKey -> + cryptoStore.getUserDeviceList(event.senderId ?: "") + ?.firstOrNull { + it.identityKey() == senderDeviceIdentityKey + } + }?.deviceId + + outgoingKeyRequestManager.onRoomKeyForwarded( + sessionId = roomKeyContent.sessionId, + algorithm = roomKeyContent.algorithm ?: "", + roomId = roomKeyContent.roomId, + senderKey = senderKey, + fromIndex = index, + fromDevice = fromDevice, + event = event) + + cryptoStore.saveIncomingForwardKeyAuditTrail( + roomId = roomKeyContent.roomId, + sessionId = roomKeyContent.sessionId, + senderKey = senderKey, + algorithm = roomKeyContent.algorithm ?: "", + userId = event.senderId ?: "", + deviceId = fromDevice ?: "", + chainIndex = index.toLong()) + + // The index is used to decide if we cancel sent request or if we wait for a better key + outgoingKeyRequestManager.postCancelRequestForSessionIfNeeded(roomKeyContent.sessionId, roomKeyContent.roomId, senderKey, index) + } + } - outgoingGossipingRequestManager.cancelRoomKeyRequest(content) + if (addSessionResult is MXOlmDevice.AddSessionResult.Imported) { + Timber.tag(loggerTag.value) + .d("onRoomKeyEvent(${event.getClearType()}) : Added megolm session ${roomKeyContent.sessionId} in ${roomKeyContent.roomId}") + defaultKeysBackupService.maybeBackupKeys() onNewSession(roomKeyContent.roomId, senderKey, roomKeyContent.sessionId) } } /** - * Check if the some messages can be decrypted with a new session + * Check if the some messages can be decrypted with a new session. * * @param roomId the room id where the new Megolm session has been created for, may be null when importing from external sessions * @param senderKey the session sender key @@ -333,77 +302,4 @@ internal class MXMegolmDecryption(private val userId: String, Timber.tag(loggerTag.value).v("ON NEW SESSION $sessionId - $senderKey") newSessionListener?.onNewSession(roomId, senderKey, sessionId) } - - override fun hasKeysForKeyRequest(request: IncomingRoomKeyRequest): Boolean { - val roomId = request.requestBody?.roomId ?: return false - val senderKey = request.requestBody.senderKey ?: return false - val sessionId = request.requestBody.sessionId ?: return false - return olmDevice.hasInboundSessionKeys(roomId, senderKey, sessionId) - } - - override fun shareKeysWithDevice(request: IncomingRoomKeyRequest) { - // sanity checks - if (request.requestBody == null) { - return - } - val userId = request.userId ?: return - - cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { - val body = request.requestBody - val sessionHolder = try { - olmDevice.getInboundGroupSession(body.sessionId, body.senderKey, body.roomId) - } catch (failure: Throwable) { - Timber.tag(loggerTag.value).e(failure, "shareKeysWithDevice: failed to get session for request $body") - return@launch - } - - val export = sessionHolder.mutex.withLock { - sessionHolder.wrapper.exportKeys() - } ?: return@launch Unit.also { - Timber.tag(loggerTag.value).e("shareKeysWithDevice: failed to export group session ${body.sessionId}") - } - - runCatching { deviceListManager.downloadKeys(listOf(userId), false) } - .mapCatching { - val deviceId = request.deviceId - val deviceInfo = cryptoStore.getUserDevice(userId, deviceId ?: "") - if (deviceInfo == null) { - throw RuntimeException() - } else { - val devicesByUser = mapOf(userId to listOf(deviceInfo)) - val usersDeviceMap = ensureOlmSessionsForDevicesAction.handle(devicesByUser) - val olmSessionResult = usersDeviceMap.getObject(userId, deviceId) - if (olmSessionResult?.sessionId == null) { - // no session with this device, probably because there - // were no one-time keys. - Timber.tag(loggerTag.value).e("no session with this device $deviceId, probably because there were no one-time keys.") - return@mapCatching - } - Timber.tag(loggerTag.value).i("shareKeysWithDevice() : sharing session ${body.sessionId} with device $userId:$deviceId") - - val payloadJson = mapOf( - "type" to EventType.FORWARDED_ROOM_KEY, - "content" to export - ) - - val encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo)) - val sendToDeviceMap = MXUsersDevicesMap<Any>() - sendToDeviceMap.setObject(userId, deviceId, encodedPayload) - Timber.tag(loggerTag.value).i("shareKeysWithDevice() : sending ${body.sessionId} to $userId:$deviceId") - val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap) - try { - sendToDeviceTask.execute(sendToDeviceParams) - } catch (failure: Throwable) { - Timber.tag(loggerTag.value).e(failure, "shareKeysWithDevice() : Failed to send ${body.sessionId} to $userId:$deviceId") - } - } - } - } - } - - override fun onRoomKeyWithHeldEvent(withHeldInfo: RoomKeyWithHeldContent) { - cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { - cryptoStore.addWithHeldMegolmSession(withHeldInfo) - } - } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt index 3eba04b9f1840e55bc743d1de7fd7e146037c00e..096773a9594772d050829bf9cf7a62a9d073d844 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryptionFactory.kt @@ -17,45 +17,24 @@ package org.matrix.android.sdk.internal.crypto.algorithms.megolm import dagger.Lazy -import kotlinx.coroutines.CoroutineScope -import org.matrix.android.sdk.api.MatrixCoroutineDispatchers -import org.matrix.android.sdk.internal.crypto.DeviceListManager import org.matrix.android.sdk.internal.crypto.MXOlmDevice -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager -import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction -import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter +import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore -import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask -import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.StreamEventsManager import javax.inject.Inject internal class MXMegolmDecryptionFactory @Inject constructor( - @UserId private val userId: String, private val olmDevice: MXOlmDevice, - private val deviceListManager: DeviceListManager, - private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager, - private val messageEncrypter: MessageEncrypter, - private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction, + private val outgoingKeyRequestManager: OutgoingKeyRequestManager, private val cryptoStore: IMXCryptoStore, - private val sendToDeviceTask: SendToDeviceTask, - private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val cryptoCoroutineScope: CoroutineScope, private val eventsManager: Lazy<StreamEventsManager> ) { fun create(): MXMegolmDecryption { return MXMegolmDecryption( - userId, olmDevice, - deviceListManager, - outgoingGossipingRequestManager, - messageEncrypter, - ensureOlmSessionsForDevicesAction, + outgoingKeyRequestManager, cryptoStore, - sendToDeviceTask, - coroutineDispatchers, - cryptoCoroutineScope, eventsManager) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt index b31b5e8a645e055e264fae305769db3535101cc8..79e907945fc9e403590f2377097aad29857e700d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt @@ -28,7 +28,6 @@ import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.api.session.crypto.model.forEach import org.matrix.android.sdk.api.session.events.model.Content -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.content.RoomKeyWithHeldContent import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode @@ -80,7 +79,7 @@ internal class MXMegolmEncryption( } // Default rotation periods - // TODO: Make it configurable via parameters + // TODO Make it configurable via parameters // Session rotation periods private var sessionRotationPeriodMsgs: Int = 100 private var sessionRotationPeriodMs: Int = 7 * 24 * 3600 * 1000 @@ -161,7 +160,7 @@ internal class MXMegolmEncryption( } /** - * Ensure the outbound session + * Ensure the outbound session. * * @param devicesInRoom the devices list */ @@ -197,7 +196,7 @@ internal class MXMegolmEncryption( } /** - * Share the device key to a list of users + * Share the device key to a list of users. * * @param session the session info * @param devicesByUsers the devices map @@ -226,7 +225,7 @@ internal class MXMegolmEncryption( } /** - * Share the device keys of a an user + * Share the device keys of a an user. * * @param session the session info * @param devicesByUser the devices map @@ -285,25 +284,14 @@ internal class MXMegolmEncryption( // attempted to share with) rather than the contentMap (those we did // share with), because we don't want to try to claim a one-time-key // for dead devices on every message. - val gossipingEventBuffer = arrayListOf<Event>() - for ((userId, devicesToShareWith) in devicesByUser) { + for ((_, devicesToShareWith) in devicesByUser) { for (deviceInfo in devicesToShareWith) { session.sharedWithHelper.markedSessionAsShared(deviceInfo, chainIndex) - gossipingEventBuffer.add( - Event( - type = EventType.ROOM_KEY, - senderId = myUserId, - content = submap.apply { - this["session_key"] = "" - // we add a fake key for trail - this["_dest"] = "$userId|${deviceInfo.deviceId}" - } - )) + // XXX is it needed to add it to the audit trail? + // For now decided that no, we are more interested by forward trail } } - cryptoStore.saveGossipingEvents(gossipingEventBuffer) - if (haveTargets) { t0 = clock.epochMillis() Timber.tag(loggerTag.value).i("shareUserDevicesKey() ${session.sessionId} : has target") @@ -337,15 +325,17 @@ internal class MXMegolmEncryption( sessionId: String, senderKey: String?, code: WithHeldCode) { - Timber.tag(loggerTag.value).d("notifyKeyWithHeld() :sending withheld for session:$sessionId and code $code to" + - " ${targets.joinToString { "${it.userId}|${it.deviceId}" }}" + Timber.tag(loggerTag.value).d( + "notifyKeyWithHeld() :sending withheld for session:$sessionId and code $code to" + + " ${targets.joinToString { "${it.userId}|${it.deviceId}" }}" ) val withHeldContent = RoomKeyWithHeldContent( roomId = roomId, senderKey = senderKey, algorithm = MXCRYPTO_ALGORITHM_MEGOLM, sessionId = sessionId, - codeString = code.value + codeString = code.value, + fromDevice = myDeviceId ) val params = SendToDeviceTask.Params( EventType.ROOM_KEY_WITHHELD, @@ -366,7 +356,7 @@ internal class MXMegolmEncryption( } /** - * process the pending encryptions + * process the pending encryptions. */ private fun encryptContent(session: MXOutboundSessionInfo, eventType: String, eventContent: Content): Content { // Everything is in place, encrypt all pending events diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt index 59d78c3e05c8036a98b33720c24c14dd88868258..61ad345c62ca1b62d3ac399f19ea8d59849b7187 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt @@ -36,6 +36,7 @@ internal class SharedWithHelper( userId = deviceInfo.userId, deviceId = deviceInfo.deviceId, deviceIdentityKey = deviceInfo.identityKey() ?: "", - chainIndex = chainIndex) + chainIndex = chainIndex + ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt index 0db8700852fba67366db25d80614c5346d2e397c..1e66fe84c96b51135a72e267ae18e0f271468af5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt @@ -45,20 +45,26 @@ internal class MXOlmDecryption( override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult { val olmEventContent = event.content.toModel<OlmEventContent>() ?: run { Timber.tag(loggerTag.value).e("## decryptEvent() : bad event format") - throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_EVENT_FORMAT, - MXCryptoError.BAD_EVENT_FORMAT_TEXT_REASON) + throw MXCryptoError.Base( + MXCryptoError.ErrorType.BAD_EVENT_FORMAT, + MXCryptoError.BAD_EVENT_FORMAT_TEXT_REASON + ) } val cipherText = olmEventContent.ciphertext ?: run { Timber.tag(loggerTag.value).e("## decryptEvent() : missing cipher text") - throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_CIPHER_TEXT, - MXCryptoError.MISSING_CIPHER_TEXT_REASON) + throw MXCryptoError.Base( + MXCryptoError.ErrorType.MISSING_CIPHER_TEXT, + MXCryptoError.MISSING_CIPHER_TEXT_REASON + ) } val senderKey = olmEventContent.senderKey ?: run { Timber.tag(loggerTag.value).e("## decryptEvent() : missing sender key") - throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_SENDER_KEY, - MXCryptoError.MISSING_SENDER_KEY_TEXT_REASON) + throw MXCryptoError.Base( + MXCryptoError.ErrorType.MISSING_SENDER_KEY, + MXCryptoError.MISSING_SENDER_KEY_TEXT_REASON + ) } val messageAny = cipherText[olmDevice.deviceCurve25519Key] ?: run { @@ -98,52 +104,70 @@ internal class MXOlmDecryption( } if (olmPayloadContent.recipient != userId) { - Timber.tag(loggerTag.value).e("## decryptEvent() : Event ${event.eventId}:" + - " Intended recipient ${olmPayloadContent.recipient} does not match our id $userId") - throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_RECIPIENT, - String.format(MXCryptoError.BAD_RECIPIENT_REASON, olmPayloadContent.recipient)) + Timber.tag(loggerTag.value).e( + "## decryptEvent() : Event ${event.eventId}:" + + " Intended recipient ${olmPayloadContent.recipient} does not match our id $userId" + ) + throw MXCryptoError.Base( + MXCryptoError.ErrorType.BAD_RECIPIENT, + String.format(MXCryptoError.BAD_RECIPIENT_REASON, olmPayloadContent.recipient) + ) } val recipientKeys = olmPayloadContent.recipientKeys ?: run { - Timber.tag(loggerTag.value).e("## decryptEvent() : Olm event (id=${event.eventId}) contains no 'recipient_keys'" + - " property; cannot prevent unknown-key attack") - throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_PROPERTY, - String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "recipient_keys")) + Timber.tag(loggerTag.value).e( + "## decryptEvent() : Olm event (id=${event.eventId}) contains no 'recipient_keys'" + + " property; cannot prevent unknown-key attack" + ) + throw MXCryptoError.Base( + MXCryptoError.ErrorType.MISSING_PROPERTY, + String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "recipient_keys") + ) } val ed25519 = recipientKeys["ed25519"] if (ed25519 != olmDevice.deviceEd25519Key) { Timber.tag(loggerTag.value).e("## decryptEvent() : Event ${event.eventId}: Intended recipient ed25519 key $ed25519 did not match ours") - throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_RECIPIENT_KEY, - MXCryptoError.BAD_RECIPIENT_KEY_REASON) + throw MXCryptoError.Base( + MXCryptoError.ErrorType.BAD_RECIPIENT_KEY, + MXCryptoError.BAD_RECIPIENT_KEY_REASON + ) } if (olmPayloadContent.sender.isNullOrBlank()) { Timber.tag(loggerTag.value) .e("## decryptEvent() : Olm event (id=${event.eventId}) contains no 'sender' property; cannot prevent unknown-key attack") - throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_PROPERTY, - String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "sender")) + throw MXCryptoError.Base( + MXCryptoError.ErrorType.MISSING_PROPERTY, + String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "sender") + ) } if (olmPayloadContent.sender != event.senderId) { Timber.tag(loggerTag.value) .e("Event ${event.eventId}: sender ${olmPayloadContent.sender} does not match reported sender ${event.senderId}") - throw MXCryptoError.Base(MXCryptoError.ErrorType.FORWARDED_MESSAGE, - String.format(MXCryptoError.FORWARDED_MESSAGE_REASON, olmPayloadContent.sender)) + throw MXCryptoError.Base( + MXCryptoError.ErrorType.FORWARDED_MESSAGE, + String.format(MXCryptoError.FORWARDED_MESSAGE_REASON, olmPayloadContent.sender) + ) } if (olmPayloadContent.roomId != event.roomId) { Timber.tag(loggerTag.value) .e("## decryptEvent() : Event ${event.eventId}: room ${olmPayloadContent.roomId} does not match reported room ${event.roomId}") - throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_ROOM, - String.format(MXCryptoError.BAD_ROOM_REASON, olmPayloadContent.roomId)) + throw MXCryptoError.Base( + MXCryptoError.ErrorType.BAD_ROOM, + String.format(MXCryptoError.BAD_ROOM_REASON, olmPayloadContent.roomId) + ) } val keys = olmPayloadContent.keys ?: run { Timber.tag(loggerTag.value).e("## decryptEvent failed : null keys") - throw MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_DECRYPT, - MXCryptoError.MISSING_CIPHER_TEXT_REASON) + throw MXCryptoError.Base( + MXCryptoError.ErrorType.UNABLE_TO_DECRYPT, + MXCryptoError.MISSING_CIPHER_TEXT_REASON + ) } return MXEventDecryptionResult( @@ -241,8 +265,4 @@ internal class MXOlmDecryption( return res["payload"] } - - override fun requestKeysForEvent(event: Event, withHeld: Boolean) { - // nop - } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt index 972176e25b7bd3357e5d26231201a0a742c39521..d5c5e85e41a1e37ed5ff6874fb040f47666edb4b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryptionFactory.kt @@ -26,6 +26,7 @@ internal class MXOlmDecryptionFactory @Inject constructor(private val olmDevice: fun create(): MXOlmDecryption { return MXOlmDecryption( olmDevice, - userId) + userId + ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt index c842c5404151adbcce729b5f4fc24f1d1559c81e..3c9706abe18e31ddadeb5c39cf9b8332cf65c895 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt @@ -38,7 +38,7 @@ internal class MXOlmEncryption( override suspend fun encryptEventContent(eventContent: Content, eventType: String, userIds: List<String>): Content { // pick the list of recipients based on the membership list. // - // TODO: there is a race condition here! What if a new user turns up + // TODO there is a race condition here! What if a new user turns up ensureSession(userIds) val deviceInfos = ArrayList<CryptoDeviceInfo>() for (userId in userIds) { @@ -68,7 +68,7 @@ internal class MXOlmEncryption( } /** - * Ensure that the session + * Ensure that the session. * * @param users the user ids list */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt index 50ce2d2bf3d02a65f509b3e05b7b0998950000a8..44e55900e4ada7db382ba541a5c51989a72a3d68 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryptionFactory.kt @@ -38,6 +38,7 @@ internal class MXOlmEncryptionFactory @Inject constructor(private val olmDevice: cryptoStore, messageEncrypter, deviceListManager, - ensureOlmSessionsForUsersAction) + ensureOlmSessionsForUsersAction + ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/EncryptionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/EncryptionResult.kt index 80090cf4a8a4612dbe698cc9dfa738fe772747e4..95254bd67987bdb9643e53d0eaac73dc92dd6a78 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/EncryptionResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/EncryptionResult.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.crypto.attachments import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo /** - * Define the result of an encryption file + * Define the result of an encryption file. */ internal data class EncryptionResult( val encryptedFileInfo: EncryptedFileInfo, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt index 65bbb0c4125ef7f5a2f50a5fa1d51f10c75cc4c3..b4cbd15109b5ca457ee426472dc50f7a319aa69c 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt @@ -227,7 +227,7 @@ internal object MXEncryptedAttachments { } /** - * Decrypt an attachment + * Decrypt an attachment. * * @param attachmentStream the attachment stream. Will be closed after this method call. * @param elementToDecrypt the elementToDecrypt info diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/CrossSigningOlm.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/CrossSigningOlm.kt new file mode 100644 index 0000000000000000000000000000000000000000..4fa355cd2a787511b5463d9abf70e526a35a3376 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/CrossSigningOlm.kt @@ -0,0 +1,93 @@ +/* + * Copyright 2022 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.crosssigning + +import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore +import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.util.JsonCanonicalizer +import org.matrix.olm.OlmPkSigning +import org.matrix.olm.OlmUtility +import javax.inject.Inject + +/** + * Holds the OlmPkSigning for cross signing. + * Can be injected without having to get the full cross signing service + */ +@SessionScope +internal class CrossSigningOlm @Inject constructor( + private val cryptoStore: IMXCryptoStore, +) { + + enum class KeyType { + SELF, + USER, + MASTER + } + + var olmUtility: OlmUtility = OlmUtility() + + var masterPkSigning: OlmPkSigning? = null + var userPkSigning: OlmPkSigning? = null + var selfSigningPkSigning: OlmPkSigning? = null + + fun release() { + olmUtility.releaseUtility() + listOf(masterPkSigning, userPkSigning, selfSigningPkSigning).forEach { it?.releaseSigning() } + } + + fun signObject(type: KeyType, strToSign: String): Map<String, String> { + val myKeys = cryptoStore.getMyCrossSigningInfo() + val pubKey = when (type) { + KeyType.SELF -> myKeys?.selfSigningKey() + KeyType.USER -> myKeys?.userKey() + KeyType.MASTER -> myKeys?.masterKey() + }?.unpaddedBase64PublicKey + val pkSigning = when (type) { + KeyType.SELF -> selfSigningPkSigning + KeyType.USER -> userPkSigning + KeyType.MASTER -> masterPkSigning + } + if (pubKey == null || pkSigning == null) { + throw Throwable("Cannot sign from this account, public and/or privateKey Unknown $type|$pkSigning") + } + val signature = pkSigning.sign(strToSign) + return mapOf( + "ed25519:$pubKey" to signature + ) + } + + fun verifySignature(type: KeyType, signable: JsonDict, signatures: Map<String, Map<String, String>>) { + val myKeys = cryptoStore.getMyCrossSigningInfo() + ?: throw NoSuchElementException("Cross Signing not configured") + val myUserID = myKeys.userId + val pubKey = when (type) { + KeyType.SELF -> myKeys.selfSigningKey() + KeyType.USER -> myKeys.userKey() + KeyType.MASTER -> myKeys.masterKey() + }?.unpaddedBase64PublicKey ?: throw NoSuchElementException("Cross Signing not configured") + val signaturesMadeByMyKey = signatures[myUserID] // Signatures made by me + ?.get("ed25519:$pubKey") + + if (signaturesMadeByMyKey.isNullOrBlank()) { + throw IllegalArgumentException("Not signed with my key $type") + } + + // Check that Alice USK signature of Bob MSK is valid + olmUtility.verifyEd25519Signature(signaturesMadeByMyKey, pubKey, JsonCanonicalizer.getCanonicalJson(Map::class.java, signable)) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt index ba1718688fd33c907d552a80d588e77d6df61ff5..6c198abc2ed7db270b448dca000cb632468f3095 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt @@ -38,6 +38,7 @@ import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.fromBase64 import org.matrix.android.sdk.internal.crypto.DeviceListManager +import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager import org.matrix.android.sdk.internal.crypto.model.rest.UploadSignatureQueryBuilder import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.InitializeCrossSigningTask @@ -53,7 +54,6 @@ import org.matrix.android.sdk.internal.util.JsonCanonicalizer import org.matrix.android.sdk.internal.util.logLimit import org.matrix.android.sdk.internal.worker.WorkerParamsFactory import org.matrix.olm.OlmPkSigning -import org.matrix.olm.OlmUtility import timber.log.Timber import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -70,19 +70,14 @@ internal class DefaultCrossSigningService @Inject constructor( private val coroutineDispatchers: MatrixCoroutineDispatchers, private val cryptoCoroutineScope: CoroutineScope, private val workManagerProvider: WorkManagerProvider, + private val outgoingKeyRequestManager: OutgoingKeyRequestManager, + private val crossSigningOlm: CrossSigningOlm, private val updateTrustWorkerDataRepository: UpdateTrustWorkerDataRepository ) : CrossSigningService, DeviceListManager.UserDevicesUpdateListener { - private var olmUtility: OlmUtility? = null - - private var masterPkSigning: OlmPkSigning? = null - private var userPkSigning: OlmPkSigning? = null - private var selfSigningPkSigning: OlmPkSigning? = null - init { try { - olmUtility = OlmUtility() // Try to get stored keys if they exist cryptoStore.getMyCrossSigningInfo()?.let { mxCrossSigningInfo -> @@ -95,7 +90,7 @@ internal class DefaultCrossSigningService @Inject constructor( ?.let { privateKeySeed -> val pkSigning = OlmPkSigning() if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.masterKey()?.unpaddedBase64PublicKey) { - masterPkSigning = pkSigning + crossSigningOlm.masterPkSigning = pkSigning Timber.i("## CrossSigning - Loading master key success") } else { Timber.w("## CrossSigning - Public master key does not match the private key") @@ -108,7 +103,7 @@ internal class DefaultCrossSigningService @Inject constructor( ?.let { privateKeySeed -> val pkSigning = OlmPkSigning() if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.userKey()?.unpaddedBase64PublicKey) { - userPkSigning = pkSigning + crossSigningOlm.userPkSigning = pkSigning Timber.i("## CrossSigning - Loading User Signing key success") } else { Timber.w("## CrossSigning - Public User key does not match the private key") @@ -121,7 +116,7 @@ internal class DefaultCrossSigningService @Inject constructor( ?.let { privateKeySeed -> val pkSigning = OlmPkSigning() if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.selfSigningKey()?.unpaddedBase64PublicKey) { - selfSigningPkSigning = pkSigning + crossSigningOlm.selfSigningPkSigning = pkSigning Timber.i("## CrossSigning - Loading Self Signing key success") } else { Timber.w("## CrossSigning - Public Self Signing key does not match the private key") @@ -143,8 +138,7 @@ internal class DefaultCrossSigningService @Inject constructor( } fun release() { - olmUtility?.releaseUtility() - listOf(masterPkSigning, userPkSigning, selfSigningPkSigning).forEach { it?.releaseSigning() } + crossSigningOlm.release() deviceListManager.removeListener(this) } @@ -153,10 +147,10 @@ internal class DefaultCrossSigningService @Inject constructor( } /** - * - Make 3 key pairs (MSK, USK, SSK) - * - Save the private keys with proper security - * - Sign the keys and upload them - * - Sign the current device with SSK and sign MSK with device key (migration) and upload signatures + * - Make 3 key pairs (MSK, USK, SSK) + * - Save the private keys with proper security + * - Sign the keys and upload them + * - Sign the current device with SSK and sign MSK with device key (migration) and upload signatures. */ override fun initializeCrossSigning(uiaInterceptor: UserInteractiveAuthInterceptor?, callback: MatrixCallback<Unit>) { Timber.d("## CrossSigning initializeCrossSigning") @@ -177,9 +171,9 @@ internal class DefaultCrossSigningService @Inject constructor( cryptoStore.setMyCrossSigningInfo(crossSigningInfo) setUserKeysAsTrusted(userId, true) cryptoStore.storePrivateKeysInfo(data.masterKeyPK, data.userKeyPK, data.selfSigningKeyPK) - masterPkSigning = OlmPkSigning().apply { initWithSeed(data.masterKeyPK.fromBase64()) } - userPkSigning = OlmPkSigning().apply { initWithSeed(data.userKeyPK.fromBase64()) } - selfSigningPkSigning = OlmPkSigning().apply { initWithSeed(data.selfSigningKeyPK.fromBase64()) } + crossSigningOlm.masterPkSigning = OlmPkSigning().apply { initWithSeed(data.masterKeyPK.fromBase64()) } + crossSigningOlm.userPkSigning = OlmPkSigning().apply { initWithSeed(data.userKeyPK.fromBase64()) } + crossSigningOlm.selfSigningPkSigning = OlmPkSigning().apply { initWithSeed(data.selfSigningKeyPK.fromBase64()) } callback.onSuccess(Unit) } @@ -198,8 +192,8 @@ internal class DefaultCrossSigningService @Inject constructor( val pkSigning = OlmPkSigning() try { if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.masterKey()?.unpaddedBase64PublicKey) { - masterPkSigning?.releaseSigning() - masterPkSigning = pkSigning + crossSigningOlm.masterPkSigning?.releaseSigning() + crossSigningOlm.masterPkSigning = pkSigning Timber.i("## CrossSigning - Loading MSK success") cryptoStore.storeMSKPrivateKey(mskPrivateKey) return @@ -225,8 +219,8 @@ internal class DefaultCrossSigningService @Inject constructor( val pkSigning = OlmPkSigning() try { if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.selfSigningKey()?.unpaddedBase64PublicKey) { - selfSigningPkSigning?.releaseSigning() - selfSigningPkSigning = pkSigning + crossSigningOlm.selfSigningPkSigning?.releaseSigning() + crossSigningOlm.selfSigningPkSigning = pkSigning Timber.i("## CrossSigning - Loading SSK success") cryptoStore.storeSSKPrivateKey(sskPrivateKey) return @@ -252,8 +246,8 @@ internal class DefaultCrossSigningService @Inject constructor( val pkSigning = OlmPkSigning() try { if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.userKey()?.unpaddedBase64PublicKey) { - userPkSigning?.releaseSigning() - userPkSigning = pkSigning + crossSigningOlm.userPkSigning?.releaseSigning() + crossSigningOlm.userPkSigning = pkSigning Timber.i("## CrossSigning - Loading USK success") cryptoStore.storeUSKPrivateKey(uskPrivateKey) return @@ -282,8 +276,8 @@ internal class DefaultCrossSigningService @Inject constructor( val pkSigning = OlmPkSigning() try { if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.masterKey()?.unpaddedBase64PublicKey) { - masterPkSigning?.releaseSigning() - masterPkSigning = pkSigning + crossSigningOlm.masterPkSigning?.releaseSigning() + crossSigningOlm.masterPkSigning = pkSigning masterKeyIsTrusted = true Timber.i("## CrossSigning - Loading master key success") } else { @@ -299,8 +293,8 @@ internal class DefaultCrossSigningService @Inject constructor( val pkSigning = OlmPkSigning() try { if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.userKey()?.unpaddedBase64PublicKey) { - userPkSigning?.releaseSigning() - userPkSigning = pkSigning + crossSigningOlm.userPkSigning?.releaseSigning() + crossSigningOlm.userPkSigning = pkSigning userKeyIsTrusted = true Timber.i("## CrossSigning - Loading master key success") } else { @@ -316,8 +310,8 @@ internal class DefaultCrossSigningService @Inject constructor( val pkSigning = OlmPkSigning() try { if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.selfSigningKey()?.unpaddedBase64PublicKey) { - selfSigningPkSigning?.releaseSigning() - selfSigningPkSigning = pkSigning + crossSigningOlm.selfSigningPkSigning?.releaseSigning() + crossSigningOlm.selfSigningPkSigning = pkSigning selfSignedKeyIsTrusted = true Timber.i("## CrossSigning - Loading master key success") } else { @@ -353,6 +347,7 @@ internal class DefaultCrossSigningService @Inject constructor( * │ │ * │ │ * └──▶ USK ────────────┘ + * . */ override fun isUserTrusted(otherUserId: String): Boolean { return cryptoStore.getCrossSigningInfo(userId)?.isTrusted() == true @@ -363,7 +358,7 @@ internal class DefaultCrossSigningService @Inject constructor( } /** - * Will not force a download of the key, but will verify signatures trust chain + * Will not force a download of the key, but will verify signatures trust chain. */ override fun checkUserTrust(otherUserId: String): UserTrustResult { Timber.v("## CrossSigning checkUserTrust for $otherUserId") @@ -405,7 +400,11 @@ internal class DefaultCrossSigningService @Inject constructor( // Check that Alice USK signature of Bob MSK is valid try { - olmUtility!!.verifyEd25519Signature(masterKeySignaturesMadeByMyUserKey, myUserKey.unpaddedBase64PublicKey, otherMasterKey.canonicalSignable()) + crossSigningOlm.olmUtility.verifyEd25519Signature( + masterKeySignaturesMadeByMyUserKey, + myUserKey.unpaddedBase64PublicKey, + otherMasterKey.canonicalSignable() + ) } catch (failure: Throwable) { return UserTrustResult.InvalidSignature(myUserKey, masterKeySignaturesMadeByMyUserKey) } @@ -459,7 +458,7 @@ internal class DefaultCrossSigningService @Inject constructor( if (potentialDevice != null && potentialDevice.isVerified) { // Check signature validity? try { - olmUtility?.verifyEd25519Signature(value, potentialDevice.fingerprint(), myMasterKey.canonicalSignable()) + crossSigningOlm.olmUtility.verifyEd25519Signature(value, potentialDevice.fingerprint(), myMasterKey.canonicalSignable()) isMaterKeyTrusted = true return@forEach } catch (failure: Throwable) { @@ -488,7 +487,11 @@ internal class DefaultCrossSigningService @Inject constructor( // Check that Alice USK signature of Alice MSK is valid try { - olmUtility!!.verifyEd25519Signature(userKeySignaturesMadeByMyMasterKey, myMasterKey.unpaddedBase64PublicKey, myUserKey.canonicalSignable()) + crossSigningOlm.olmUtility.verifyEd25519Signature( + userKeySignaturesMadeByMyMasterKey, + myMasterKey.unpaddedBase64PublicKey, + myUserKey.canonicalSignable() + ) } catch (failure: Throwable) { return UserTrustResult.InvalidSignature(myUserKey, userKeySignaturesMadeByMyMasterKey) } @@ -507,7 +510,11 @@ internal class DefaultCrossSigningService @Inject constructor( // Check that Alice USK signature of Alice MSK is valid try { - olmUtility!!.verifyEd25519Signature(ssKeySignaturesMadeByMyMasterKey, myMasterKey.unpaddedBase64PublicKey, mySSKey.canonicalSignable()) + crossSigningOlm.olmUtility.verifyEd25519Signature( + ssKeySignaturesMadeByMyMasterKey, + myMasterKey.unpaddedBase64PublicKey, + mySSKey.canonicalSignable() + ) } catch (failure: Throwable) { return UserTrustResult.InvalidSignature(mySSKey, ssKeySignaturesMadeByMyMasterKey) } @@ -560,14 +567,16 @@ internal class DefaultCrossSigningService @Inject constructor( return@launch } val userPubKey = myKeys.userKey()?.unpaddedBase64PublicKey - if (userPubKey == null || userPkSigning == null) { + if (userPubKey == null || crossSigningOlm.userPkSigning == null) { callback.onFailure(Throwable("## CrossSigning - Cannot sign from this account, privateKeyUnknown $userPubKey")) return@launch } // Sign the other MasterKey with our UserSigning key - val newSignature = JsonCanonicalizer.getCanonicalJson(Map::class.java, - otherMasterKeys.signalableJSONDictionary()).let { userPkSigning?.sign(it) } + val newSignature = JsonCanonicalizer.getCanonicalJson( + Map::class.java, + otherMasterKeys.signalableJSONDictionary() + ).let { crossSigningOlm.userPkSigning?.sign(it) } if (newSignature == null) { // race?? @@ -614,13 +623,13 @@ internal class DefaultCrossSigningService @Inject constructor( } val ssPubKey = myKeys.selfSigningKey()?.unpaddedBase64PublicKey - if (ssPubKey == null || selfSigningPkSigning == null) { + if (ssPubKey == null || crossSigningOlm.selfSigningPkSigning == null) { callback.onFailure(Throwable("Cannot sign from this account, public and/or privateKey Unknown $ssPubKey")) return@launch } // Sign with self signing - val newSignature = selfSigningPkSigning?.sign(device.canonicalSignable()) + val newSignature = crossSigningOlm.selfSigningPkSigning?.sign(device.canonicalSignable()) if (newSignature == null) { // race?? @@ -684,7 +693,8 @@ internal class DefaultCrossSigningService @Inject constructor( val otherSSKSignature = otherDevice.signatures?.get(otherUserId)?.get("ed25519:${otherKeys.selfSigningKey()?.unpaddedBase64PublicKey}") ?: return legacyFallbackTrust( locallyTrusted, - DeviceTrustResult.MissingDeviceSignature(otherDeviceId, otherKeys.selfSigningKey() + DeviceTrustResult.MissingDeviceSignature( + otherDeviceId, otherKeys.selfSigningKey() ?.unpaddedBase64PublicKey ?: "" ) @@ -692,7 +702,11 @@ internal class DefaultCrossSigningService @Inject constructor( // Check bob's device is signed by bob's SSK try { - olmUtility!!.verifyEd25519Signature(otherSSKSignature, otherKeys.selfSigningKey()?.unpaddedBase64PublicKey, otherDevice.canonicalSignable()) + crossSigningOlm.olmUtility.verifyEd25519Signature( + otherSSKSignature, + otherKeys.selfSigningKey()?.unpaddedBase64PublicKey, + otherDevice.canonicalSignable() + ) } catch (e: Throwable) { return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.InvalidDeviceSignature(otherDeviceId, otherSSKSignature, e)) } @@ -733,7 +747,8 @@ internal class DefaultCrossSigningService @Inject constructor( val otherSSKSignature = otherDevice.signatures?.get(otherKeys.userId)?.get("ed25519:${otherKeys.selfSigningKey()?.unpaddedBase64PublicKey}") ?: return legacyFallbackTrust( locallyTrusted, - DeviceTrustResult.MissingDeviceSignature(otherDevice.deviceId, otherKeys.selfSigningKey() + DeviceTrustResult.MissingDeviceSignature( + otherDevice.deviceId, otherKeys.selfSigningKey() ?.unpaddedBase64PublicKey ?: "" ) @@ -741,7 +756,11 @@ internal class DefaultCrossSigningService @Inject constructor( // Check bob's device is signed by bob's SSK try { - olmUtility!!.verifyEd25519Signature(otherSSKSignature, otherKeys.selfSigningKey()?.unpaddedBase64PublicKey, otherDevice.canonicalSignable()) + crossSigningOlm.olmUtility.verifyEd25519Signature( + otherSSKSignature, + otherKeys.selfSigningKey()?.unpaddedBase64PublicKey, + otherDevice.canonicalSignable() + ) } catch (e: Throwable) { return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.InvalidDeviceSignature(otherDevice.deviceId, otherSSKSignature, e)) } @@ -781,7 +800,8 @@ internal class DefaultCrossSigningService @Inject constructor( // If it's me, recheck trust of all users and devices? val users = ArrayList<String>() if (otherUserId == userId && currentTrust != trusted) { -// reRequestAllPendingRoomKeyRequest() + // notify key requester + outgoingKeyRequestManager.onSelfCrossSigningTrustChanged(trusted) cryptoStore.updateUsersTrust { users.add(it) checkUserTrust(it).isVerified() @@ -796,19 +816,4 @@ internal class DefaultCrossSigningService @Inject constructor( } } } - -// private fun reRequestAllPendingRoomKeyRequest() { -// cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { -// Timber.d("## CrossSigning - reRequest pending outgoing room key requests") -// cryptoStore.getOutgoingRoomKeyRequests().forEach { -// it.requestBody?.let { requestBody -> -// if (cryptoStore.getInboundGroupSession(requestBody.sessionId ?: "", requestBody.senderKey ?: "") == null) { -// outgoingRoomKeyRequestManager.resendRoomKeyRequest(requestBody) -// } else { -// outgoingRoomKeyRequestManager.cancelRoomKeyRequest(requestBody) -// } -// } -// } -// } -// } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt index e63a6dc791c2a541688380de45c3eb9f57bd1374..5ea4695da29b4bcf73a372cc338c6b88909db9b2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt @@ -54,6 +54,7 @@ import org.matrix.android.sdk.internal.crypto.MXOlmDevice import org.matrix.android.sdk.internal.crypto.MegolmSessionData import org.matrix.android.sdk.internal.crypto.ObjectSigner import org.matrix.android.sdk.internal.crypto.actions.MegolmSessionDataImporter +import org.matrix.android.sdk.internal.crypto.crosssigning.CrossSigningOlm import org.matrix.android.sdk.internal.crypto.keysbackup.model.SignalableMegolmBackupAuthData import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.BackupKeysResult import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody @@ -63,16 +64,11 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.RoomKeysBack import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.UpdateKeysBackupVersionBody import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.CreateKeysBackupVersionTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.DeleteBackupTask -import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.DeleteRoomSessionDataTask -import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.DeleteRoomSessionsDataTask -import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.DeleteSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetKeysBackupLastVersionTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetKeysBackupVersionTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetRoomSessionDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetRoomSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetSessionsDataTask -import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionDataTask -import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2 @@ -107,21 +103,17 @@ internal class DefaultKeysBackupService @Inject constructor( private val cryptoStore: IMXCryptoStore, private val olmDevice: MXOlmDevice, private val objectSigner: ObjectSigner, + private val crossSigningOlm: CrossSigningOlm, // Actions private val megolmSessionDataImporter: MegolmSessionDataImporter, // Tasks 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 @@ -168,58 +160,76 @@ internal class DefaultKeysBackupService @Inject constructor( override fun prepareKeysBackupVersion(password: String?, progressListener: ProgressListener?, callback: MatrixCallback<MegolmBackupCreationInfo>) { - cryptoCoroutineScope.launch(coroutineDispatchers.main) { - runCatching { - withContext(coroutineDispatchers.crypto) { - val olmPkDecryption = OlmPkDecryption() - val signalableMegolmBackupAuthData = if (password != null) { - // Generate a private key from the password - val backgroundProgressListener = if (progressListener == null) { - null - } else { - object : ProgressListener { - override fun onProgress(progress: Int, total: Int) { - uiHandler.post { - try { - progressListener.onProgress(progress, total) - } catch (e: Exception) { - Timber.e(e, "prepareKeysBackupVersion: onProgress failure") - } + cryptoCoroutineScope.launch(coroutineDispatchers.io) { + try { + val olmPkDecryption = OlmPkDecryption() + val signalableMegolmBackupAuthData = if (password != null) { + // Generate a private key from the password + val backgroundProgressListener = if (progressListener == null) { + null + } else { + object : ProgressListener { + override fun onProgress(progress: Int, total: Int) { + uiHandler.post { + try { + progressListener.onProgress(progress, total) + } catch (e: Exception) { + Timber.e(e, "prepareKeysBackupVersion: onProgress failure") } } } } + } + val generatePrivateKeyResult = generatePrivateKeyWithPassword(password, backgroundProgressListener) + SignalableMegolmBackupAuthData( + publicKey = olmPkDecryption.setPrivateKey(generatePrivateKeyResult.privateKey), + privateKeySalt = generatePrivateKeyResult.salt, + privateKeyIterations = generatePrivateKeyResult.iterations + ) + } else { + val publicKey = olmPkDecryption.generateKey() + SignalableMegolmBackupAuthData( + publicKey = publicKey + ) + } - val generatePrivateKeyResult = generatePrivateKeyWithPassword(password, backgroundProgressListener) - SignalableMegolmBackupAuthData( - publicKey = olmPkDecryption.setPrivateKey(generatePrivateKeyResult.privateKey), - privateKeySalt = generatePrivateKeyResult.salt, - privateKeyIterations = generatePrivateKeyResult.iterations - ) - } else { - val publicKey = olmPkDecryption.generateKey() + val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableMegolmBackupAuthData.signalableJSONDictionary()) - SignalableMegolmBackupAuthData( - publicKey = publicKey - ) - } + val signatures = mutableMapOf<String, MutableMap<String, String>>() - val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableMegolmBackupAuthData.signalableJSONDictionary()) + val deviceSignature = objectSigner.signObject(canonicalJson) + deviceSignature.forEach { (userID, content) -> + signatures[userID] = content.toMutableMap() + } - val signedMegolmBackupAuthData = MegolmBackupAuthData( - publicKey = signalableMegolmBackupAuthData.publicKey, - privateKeySalt = signalableMegolmBackupAuthData.privateKeySalt, - privateKeyIterations = signalableMegolmBackupAuthData.privateKeyIterations, - signatures = objectSigner.signObject(canonicalJson) - ) + // If we have cross signing add signature, will throw if cross signing not properly configured + try { + val crossSign = crossSigningOlm.signObject(CrossSigningOlm.KeyType.MASTER, canonicalJson) + signatures[credentials.userId]?.putAll(crossSign) + } catch (failure: Throwable) { + // ignore and log + Timber.w(failure, "prepareKeysBackupVersion: failed to sign with cross signing keys") + } - MegolmBackupCreationInfo( - algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, - authData = signedMegolmBackupAuthData, - recoveryKey = computeRecoveryKey(olmPkDecryption.privateKey()) - ) + val signedMegolmBackupAuthData = MegolmBackupAuthData( + publicKey = signalableMegolmBackupAuthData.publicKey, + privateKeySalt = signalableMegolmBackupAuthData.privateKeySalt, + privateKeyIterations = signalableMegolmBackupAuthData.privateKeyIterations, + signatures = signatures + ) + val creationInfo = MegolmBackupCreationInfo( + algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, + authData = signedMegolmBackupAuthData, + recoveryKey = computeRecoveryKey(olmPkDecryption.privateKey()) + ) + uiHandler.post { + callback.onSuccess(creationInfo) + } + } catch (failure: Throwable) { + uiHandler.post { + callback.onFailure(failure) } - }.foldToCallback(callback) + } } } @@ -267,41 +277,39 @@ internal class DefaultKeysBackupService @Inject constructor( } override fun deleteBackup(version: String, callback: MatrixCallback<Unit>?) { - cryptoCoroutineScope.launch(coroutineDispatchers.main) { - withContext(coroutineDispatchers.crypto) { - // If we're currently backing up to this backup... stop. - // (We start using it automatically in createKeysBackupVersion so this is symmetrical). - if (keysBackupVersion != null && version == keysBackupVersion?.version) { - resetKeysBackupData() - keysBackupVersion = null - keysBackupStateManager.state = KeysBackupState.Unknown - } + cryptoCoroutineScope.launch(coroutineDispatchers.io) { + // If we're currently backing up to this backup... stop. + // (We start using it automatically in createKeysBackupVersion so this is symmetrical). + if (keysBackupVersion != null && version == keysBackupVersion?.version) { + resetKeysBackupData() + keysBackupVersion = null + keysBackupStateManager.state = KeysBackupState.Unknown + } - deleteBackupTask - .configureWith(DeleteBackupTask.Params(version)) { - this.callback = object : MatrixCallback<Unit> { - private fun eventuallyRestartBackup() { - // Do not stay in KeysBackupState.Unknown but check what is available on the homeserver - if (state == KeysBackupState.Unknown) { - checkAndStartKeysBackup() - } + deleteBackupTask + .configureWith(DeleteBackupTask.Params(version)) { + this.callback = object : MatrixCallback<Unit> { + private fun eventuallyRestartBackup() { + // Do not stay in KeysBackupState.Unknown but check what is available on the homeserver + if (state == KeysBackupState.Unknown) { + checkAndStartKeysBackup() } + } - override fun onSuccess(data: Unit) { - eventuallyRestartBackup() + override fun onSuccess(data: Unit) { + eventuallyRestartBackup() - uiHandler.post { callback?.onSuccess(Unit) } - } + uiHandler.post { callback?.onSuccess(Unit) } + } - override fun onFailure(failure: Throwable) { - eventuallyRestartBackup() + override fun onFailure(failure: Throwable) { + eventuallyRestartBackup() - uiHandler.post { callback?.onFailure(failure) } - } + uiHandler.post { callback?.onFailure(failure) } } } - .executeBy(taskExecutor) - } + } + .executeBy(taskExecutor) } } @@ -339,6 +347,10 @@ internal class DefaultKeysBackupService @Inject constructor( override fun backupAllGroupSessions(progressListener: ProgressListener?, callback: MatrixCallback<Unit>?) { + if (!isEnabled || backupOlmPkEncryption == null || keysBackupVersion == null) { + callback?.onFailure(Throwable("Backup not enabled")) + return + } // Get a status right now getBackupProgress(object : ProgressListener { override fun onProgress(progress: Int, total: Int) { @@ -427,18 +439,41 @@ internal class DefaultKeysBackupService @Inject constructor( for ((keyId, mySignature) in mySigs) { // XXX: is this how we're supposed to get the device id? - var deviceId: String? = null + var deviceOrCrossSigningKeyId: String? = null val components = keyId.split(":") if (components.size == 2) { - deviceId = components[1] + deviceOrCrossSigningKeyId = components[1] } - if (deviceId != null) { - val device = cryptoStore.getUserDevice(userId, deviceId) + // Let's check if it's my master key + val myMSKPKey = cryptoStore.getMyCrossSigningInfo()?.masterKey()?.unpaddedBase64PublicKey + if (deviceOrCrossSigningKeyId == myMSKPKey) { + // we have to check if we can trust + + var isSignatureValid = false + try { + crossSigningOlm.verifySignature(CrossSigningOlm.KeyType.MASTER, authData.signalableJSONDictionary(), authData.signatures) + isSignatureValid = true + } catch (failure: Throwable) { + Timber.w(failure, "getKeysBackupTrust: Bad signature from my user MSK") + } + val mskTrusted = cryptoStore.getMyCrossSigningInfo()?.masterKey()?.trustLevel?.isVerified() == true + if (isSignatureValid && mskTrusted) { + keysBackupVersionTrustIsUsable = true + } + val signature = KeysBackupVersionTrustSignature.UserSignature( + keyId = deviceOrCrossSigningKeyId, + cryptoCrossSigningKey = cryptoStore.getMyCrossSigningInfo()?.masterKey(), + valid = isSignatureValid + ) + + keysBackupVersionTrustSignatures.add(signature) + } else if (deviceOrCrossSigningKeyId != null) { + val device = cryptoStore.getUserDevice(userId, deviceOrCrossSigningKeyId) var isSignatureValid = false if (device == null) { - Timber.v("getKeysBackupTrust: Signature from unknown device $deviceId") + Timber.v("getKeysBackupTrust: Signature from unknown device $deviceOrCrossSigningKeyId") } else { val fingerprint = device.fingerprint() if (fingerprint != null) { @@ -455,8 +490,8 @@ internal class DefaultKeysBackupService @Inject constructor( } } - val signature = KeysBackupVersionTrustSignature( - deviceId = deviceId, + val signature = KeysBackupVersionTrustSignature.DeviceSignature( + deviceId = deviceOrCrossSigningKeyId, device = device, valid = isSignatureValid, ) @@ -480,10 +515,11 @@ internal class DefaultKeysBackupService @Inject constructor( if (authData == null) { Timber.w("trustKeyBackupVersion:trust: Key backup is missing required data") - - callback.onFailure(IllegalArgumentException("Missing element")) + uiHandler.post { + callback.onFailure(IllegalArgumentException("Missing element")) + } } else { - cryptoCoroutineScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.io) { val updateKeysBackupVersionBody = withContext(coroutineDispatchers.crypto) { // Get current signatures, or create an empty set val myUserSignatures = authData.signatures?.get(userId).orEmpty().toMutableMap() @@ -516,7 +552,8 @@ internal class DefaultKeysBackupService @Inject constructor( UpdateKeysBackupVersionBody( algorithm = keysBackupVersion.algorithm, authData = newMegolmBackupAuthDataWithNewSignature.toJsonDict(), - version = keysBackupVersion.version) + version = keysBackupVersion.version + ) } // And send it to the homeserver @@ -535,11 +572,15 @@ internal class DefaultKeysBackupService @Inject constructor( checkAndStartWithKeysBackupVersion(newKeysBackupVersion) - callback.onSuccess(data) + uiHandler.post { + callback.onSuccess(data) + } } override fun onFailure(failure: Throwable) { - callback.onFailure(failure) + uiHandler.post { + callback.onFailure(failure) + } } } } @@ -553,15 +594,14 @@ internal class DefaultKeysBackupService @Inject constructor( callback: MatrixCallback<Unit>) { Timber.v("trustKeysBackupVersionWithRecoveryKey: version ${keysBackupVersion.version}") - cryptoCoroutineScope.launch(coroutineDispatchers.main) { - val isValid = withContext(coroutineDispatchers.crypto) { - isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion) - } + cryptoCoroutineScope.launch(coroutineDispatchers.io) { + val isValid = isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion) if (!isValid) { Timber.w("trustKeyBackupVersionWithRecoveryKey: Invalid recovery key.") - - callback.onFailure(IllegalArgumentException("Invalid recovery key or password")) + uiHandler.post { + callback.onFailure(IllegalArgumentException("Invalid recovery key or password")) + } } else { trustKeysBackupVersion(keysBackupVersion, true, callback) } @@ -573,15 +613,14 @@ internal class DefaultKeysBackupService @Inject constructor( callback: MatrixCallback<Unit>) { Timber.v("trustKeysBackupVersionWithPassphrase: version ${keysBackupVersion.version}") - cryptoCoroutineScope.launch(coroutineDispatchers.main) { - val recoveryKey = withContext(coroutineDispatchers.crypto) { - recoveryKeyFromPassword(password, keysBackupVersion, null) - } + cryptoCoroutineScope.launch(coroutineDispatchers.io) { + val recoveryKey = recoveryKeyFromPassword(password, keysBackupVersion, null) if (recoveryKey == null) { Timber.w("trustKeysBackupVersionWithPassphrase: Key backup is missing required data") - - callback.onFailure(IllegalArgumentException("Missing element")) + uiHandler.post { + callback.onFailure(IllegalArgumentException("Missing element")) + } } else { // Check trust using the recovery key trustKeysBackupVersionWithRecoveryKey(keysBackupVersion, recoveryKey, callback) @@ -592,30 +631,28 @@ internal class DefaultKeysBackupService @Inject constructor( override fun onSecretKeyGossip(secret: String) { Timber.i("## CrossSigning - onSecretKeyGossip") - cryptoCoroutineScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.io) { try { - when (val keysBackupLastVersionResult = getKeysBackupLastVersionTask.execute(Unit)) { - KeysBackupLastVersionResult.NoKeysBackup -> { - Timber.d("No keys backup found") - } - is KeysBackupLastVersionResult.KeysBackup -> { - val keysBackupVersion = keysBackupLastVersionResult.keysVersionResult - val recoveryKey = computeRecoveryKey(secret.fromBase64()) - if (isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion)) { - awaitCallback<Unit> { - trustKeysBackupVersion(keysBackupVersion, true, it) - } - val importResult = awaitCallback<ImportRoomKeysResult> { - restoreKeysWithRecoveryKey(keysBackupVersion, recoveryKey, null, null, null, it) - } - withContext(coroutineDispatchers.crypto) { - cryptoStore.saveBackupRecoveryKey(recoveryKey, keysBackupVersion.version) - } - Timber.i("onSecretKeyGossip: Recovered keys $importResult") - } else { - Timber.e("onSecretKeyGossip: Recovery key is not valid ${keysBackupVersion.version}") + val keysBackupVersion = getKeysBackupLastVersionTask.execute(Unit).toKeysVersionResult() + ?: return@launch Unit.also { + Timber.d("Failed to get backup last version") } + val recoveryKey = computeRecoveryKey(secret.fromBase64()) + if (isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion)) { + awaitCallback<Unit> { + trustKeysBackupVersion(keysBackupVersion, true, it) + } + // we don't want to start immediately downloading all as it can take very long + +// val importResult = awaitCallback<ImportRoomKeysResult> { +// restoreKeysWithRecoveryKey(keysBackupVersion, recoveryKey, null, null, null, it) +// } + withContext(coroutineDispatchers.crypto) { + cryptoStore.saveBackupRecoveryKey(recoveryKey, keysBackupVersion.version) } + Timber.i("onSecretKeyGossip: saved valid backup key") + } else { + Timber.e("onSecretKeyGossip: Recovery key is not valid ${keysBackupVersion.version}") } } catch (failure: Throwable) { Timber.e("onSecretKeyGossip: failed to trust key backup version ${keysBackupVersion?.version}") @@ -624,7 +661,7 @@ internal class DefaultKeysBackupService @Inject constructor( } /** - * Get public key from a Recovery key + * Get public key from a Recovery key. * * @param recoveryKey the recovery key * @return the corresponding public key, from Olm @@ -678,9 +715,9 @@ internal class DefaultKeysBackupService @Inject constructor( callback: MatrixCallback<ImportRoomKeysResult>) { Timber.v("restoreKeysWithRecoveryKey: From backup version: ${keysVersionResult.version}") - cryptoCoroutineScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.io) { runCatching { - val decryption = withContext(coroutineDispatchers.crypto) { + val decryption = withContext(coroutineDispatchers.computation) { // Check if the recovery is valid before going any further if (!isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysVersionResult)) { Timber.e("restoreKeysWithRecoveryKey: Invalid recovery key for this keys version") @@ -719,14 +756,18 @@ internal class DefaultKeysBackupService @Inject constructor( } } } - Timber.v("restoreKeysWithRecoveryKey: Decrypted ${sessionsData.size} keys out" + - " of $sessionsFromHsCount from the backup store on the homeserver") + Timber.v( + "restoreKeysWithRecoveryKey: Decrypted ${sessionsData.size} keys out" + + " of $sessionsFromHsCount from the backup store on the homeserver" + ) // Do not trigger a backup for them if they come from the backup version we are using val backUp = keysVersionResult.version != keysBackupVersion?.version if (backUp) { - Timber.v("restoreKeysWithRecoveryKey: Those keys will be backed up" + - " to backup version: ${keysBackupVersion?.version}") + Timber.v( + "restoreKeysWithRecoveryKey: Those keys will be backed up" + + " to backup version: ${keysBackupVersion?.version}" + ) } // Import them into the crypto store @@ -749,7 +790,19 @@ internal class DefaultKeysBackupService @Inject constructor( } result } - }.foldToCallback(callback) + }.foldToCallback(object : MatrixCallback<ImportRoomKeysResult> { + override fun onSuccess(data: ImportRoomKeysResult) { + uiHandler.post { + callback.onSuccess(data) + } + } + + override fun onFailure(failure: Throwable) { + uiHandler.post { + callback.onFailure(failure) + } + } + }) } } @@ -761,7 +814,7 @@ internal class DefaultKeysBackupService @Inject constructor( callback: MatrixCallback<ImportRoomKeysResult>) { Timber.v("[MXKeyBackup] restoreKeyBackup with password: From backup version: ${keysBackupVersion.version}") - cryptoCoroutineScope.launch(coroutineDispatchers.main) { + cryptoCoroutineScope.launch(coroutineDispatchers.io) { runCatching { val progressListener = if (stepProgressListener != null) { object : ProgressListener { @@ -786,13 +839,25 @@ internal class DefaultKeysBackupService @Inject constructor( restoreKeysWithRecoveryKey(keysBackupVersion, recoveryKey, roomId, sessionId, stepProgressListener, it) } } - }.foldToCallback(callback) + }.foldToCallback(object : MatrixCallback<ImportRoomKeysResult> { + override fun onSuccess(data: ImportRoomKeysResult) { + uiHandler.post { + callback.onSuccess(data) + } + } + + override fun onFailure(failure: Throwable) { + uiHandler.post { + callback.onFailure(failure) + } + } + }) } } /** * Same method as [RoomKeysRestClient.getRoomKey] except that it accepts nullable - * parameters and always returns a KeysBackupData object through the Callback + * parameters and always returns a KeysBackupData object through the Callback. */ private suspend fun getKeys(sessionId: String?, roomId: String?, @@ -801,19 +866,27 @@ internal class DefaultKeysBackupService @Inject constructor( // Get key for the room and for the session val data = getRoomSessionDataTask.execute(GetRoomSessionDataTask.Params(roomId, sessionId, version)) // Convert to KeysBackupData - KeysBackupData(mutableMapOf( - roomId to RoomKeysBackupData(mutableMapOf( - sessionId to data - )) - )) + KeysBackupData( + mutableMapOf( + roomId to RoomKeysBackupData( + mutableMapOf( + sessionId to data + ) + ) + ) + ) } else if (roomId != null) { // Get all keys for the room - val data = getRoomSessionsDataTask.execute(GetRoomSessionsDataTask.Params(roomId, version)) + val data = withContext(coroutineDispatchers.io) { + getRoomSessionsDataTask.execute(GetRoomSessionsDataTask.Params(roomId, version)) + } // Convert to KeysBackupData KeysBackupData(mutableMapOf(roomId to data)) } else { // Get all keys - getSessionsDataTask.execute(GetSessionsDataTask.Params(version)) + withContext(coroutineDispatchers.io) { + getSessionsDataTask.execute(GetSessionsDataTask.Params(version)) + } } } @@ -838,7 +911,7 @@ internal class DefaultKeysBackupService @Inject constructor( } /** - * Do a backup if there are new keys, with a delay + * Do a backup if there are new keys, with a delay. */ fun maybeBackupKeys() { when { @@ -1149,7 +1222,7 @@ internal class DefaultKeysBackupService @Inject constructor( } /** - * Update the DB with data fetch from the server + * Update the DB with data fetch from the server. */ private fun onServerDataRetrieved(count: Int?, etag: String?) { cryptoStore.setKeysBackupData(KeysBackupDataEntity() @@ -1178,7 +1251,7 @@ internal class DefaultKeysBackupService @Inject constructor( } /** - * Send a chunk of keys to backup + * Send a chunk of keys to backup. */ @UiThread private fun backupKeys() { @@ -1189,7 +1262,6 @@ internal class DefaultKeysBackupService @Inject constructor( Timber.v("backupKeys: Invalid configuration") backupAllGroupSessionsCallback?.onFailure(IllegalStateException("Invalid configuration")) resetBackupAllGroupSessionsListeners() - return } @@ -1326,7 +1398,8 @@ internal class DefaultKeysBackupService @Inject constructor( "sender_key" to sessionData.senderKey, "sender_claimed_keys" to sessionData.senderClaimedKeys, "forwarding_curve25519_key_chain" to (sessionData.forwardingCurve25519KeyChain.orEmpty()), - "session_key" to sessionData.sessionKey) + "session_key" to sessionData.sessionKey + ) val json = MoshiProvider.providesMoshi() .adapter(Map::class.java) @@ -1354,7 +1427,8 @@ internal class DefaultKeysBackupService @Inject constructor( sessionData = mapOf( "ciphertext" to encryptedSessionBackupData.mCipherText, "mac" to encryptedSessionBackupData.mMac, - "ephemeral" to encryptedSessionBackupData.mEphemeralKey) + "ephemeral" to encryptedSessionBackupData.mEphemeralKey + ) ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt index 4d5b38acbf18fabdd3d3f0537faae556933fe77a..d5bab3318094b6485167893b736f7ea2ad579aaa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt @@ -59,7 +59,7 @@ internal fun generatePrivateKeyWithPassword(password: String, } /** - * Retrieve a private key from {password, salt, iterations} + * Retrieve a private key from {password, salt, iterations}. * * @param password the password used to generated the private key. * @param salt the salt. @@ -143,7 +143,7 @@ internal fun deriveKey(password: String, } /** - * Generate a 32 chars salt + * Generate a 32 chars salt. */ private fun generateSalt(): String { val salt = buildString { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt index 8464b33526fe4abaac5bcfe167c10b18a9f48257..ea23be59237de603f6c6ce4b649f4b709e3ef22f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt @@ -50,7 +50,7 @@ internal interface RoomKeysApi { suspend fun createKeysBackupVersion(@Body createKeysBackupVersionBody: CreateKeysBackupVersionBody): KeysVersion /** - * Get the key backup last version + * Get the key backup last version. * If not supported by the server, an error is returned: {"errcode":"M_NOT_FOUND","error":"No backup found"} */ @GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/version") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt index a6bd8f8aaa564f24878ea04f1bd6aabe44e6caba..2d483893c09e460b6ff26e9a0b90dfd77c622db7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt @@ -23,13 +23,13 @@ import org.matrix.android.sdk.api.util.JsonDict @JsonClass(generateAdapter = true) internal data class CreateKeysBackupVersionBody( /** - * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined + * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined. */ @Json(name = "algorithm") override val algorithm: String, /** - * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" + * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2". * see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData] */ @Json(name = "auth_data") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt index 898b357c51791b19f75be713db7675665c6b46cc..19581a686bb1e24add093cfe33335d23fa1ae82f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt @@ -41,17 +41,17 @@ import org.matrix.android.sdk.internal.di.MoshiProvider internal interface KeysAlgorithmAndData { /** - * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined + * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined. */ val algorithm: String /** - * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData] + * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData]. */ val authData: JsonDict /** - * Facility method to convert authData to a MegolmBackupAuthData object + * Facility method to convert authData to a MegolmBackupAuthData object. */ fun getAuthDataAsMegolmBackupAuthData(): MegolmBackupAuthData? { return MoshiProvider.providesMoshi() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt index 3f2def84d556d244a063efb714d27f33ff5f3255..a4b8f811e46412ea85b5d4c611cba569965a729a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt @@ -29,7 +29,7 @@ internal data class UpdateKeysBackupVersionBody( override val algorithm: String, /** - * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" + * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2". * see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData] */ @Json(name = "auth_data") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt index 7f1b03b9324a0ad8e898bd0827589e5d0420e9a3..f90522b03632c4ec8d3da19c7967dae14e5298a7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionDataTask.kt @@ -40,7 +40,8 @@ internal class DefaultDeleteRoomSessionDataTask @Inject constructor( roomKeysApi.deleteRoomSessionData( params.roomId, params.sessionId, - params.version) + params.version + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt index 394cc861d625008d44c8a6e8ca19e1f928dda3ea..7db33e0c46b9cdf52be81f4972619940c8784961 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/DeleteRoomSessionsDataTask.kt @@ -38,7 +38,8 @@ internal class DefaultDeleteRoomSessionsDataTask @Inject constructor( return executeRequest(globalErrorReceiver) { roomKeysApi.deleteRoomSessionsData( params.roomId, - params.version) + params.version + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt index ff515ed80fa34df7256e639be9c4cdda94edde84..df8e6bfebfc5303884230da52d86b6db1dbde87f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionDataTask.kt @@ -41,7 +41,8 @@ internal class DefaultGetRoomSessionDataTask @Inject constructor( roomKeysApi.getRoomSessionData( params.roomId, params.sessionId, - params.version) + params.version + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt index 1b4fe2d96622719d80b6becd3d489b749312c2f5..f9ea078ef2bc11f87133f60f92b434b9fcee6f03 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetRoomSessionsDataTask.kt @@ -39,7 +39,8 @@ internal class DefaultGetRoomSessionsDataTask @Inject constructor( return executeRequest(globalErrorReceiver) { roomKeysApi.getRoomSessionsData( params.roomId, - params.version) + params.version + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt index 180aaecf82000b020b7c67d78bfc69357ebeae5b..637c6ddeb70d28c847b9fb182f12f0dab187eca5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreRoomSessionDataTask.kt @@ -44,7 +44,8 @@ internal class DefaultStoreRoomSessionDataTask @Inject constructor( params.roomId, params.sessionId, params.version, - params.keyBackupData) + params.keyBackupData + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt index d1aa9d2eb03831701c3c71a0d5cdefa8814b24ba..09e52da7555b906259ad11bb078d098b3b2dc101 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreRoomSessionsDataTask.kt @@ -42,7 +42,8 @@ internal class DefaultStoreRoomSessionsDataTask @Inject constructor( roomKeysApi.storeRoomSessionsData( params.roomId, params.version, - params.roomKeysBackupData) + params.roomKeysBackupData + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt index 3dbeafe9dee2cb866e98c33b04e762fd5713119c..47f2578c4375bb9c6f2f88a55c8e0943b5d5b274 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt @@ -40,7 +40,8 @@ internal class DefaultStoreSessionsDataTask @Inject constructor( return executeRequest(globalErrorReceiver) { roomKeysApi.storeSessionsData( params.version, - params.keysBackupData) + params.keysBackupData + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58.kt index 0e746f289b8c921a4876c1a1d1d2202dceb27bee..407e034acbdf80313eee9d9ec94329980f0305ec 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58.kt @@ -39,7 +39,7 @@ private const val ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqr private val BASE = BigInteger.valueOf(58) /** - * Encode a byte array to a human readable string with base58 chars + * Encode a byte array to a human readable string with base58 chars. */ internal fun base58encode(input: ByteArray): String { var bi = BigInteger(1, input) @@ -62,7 +62,7 @@ internal fun base58encode(input: ByteArray): String { } /** - * Decode a base58 String to a byte array + * Decode a base58 String to a byte array. */ internal fun base58decode(input: String): ByteArray { var result = decodeToBigInteger(input).toByteArray() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXKey.kt index cff713bf8f72ed1f2e6d6edb7127f0beb1a65f7f..6bfa56ae8df7cfec01d60f6b474c091314f6fdd8 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXKey.kt @@ -36,13 +36,13 @@ internal data class MXKey( val value: String, /** - * signature user Id to [deviceid][signature] + * signature user Id to [deviceid][signature]. */ private val signatures: Map<String, Map<String, String>>, /** * We have to store the original json because it can contain other fields - * that we don't support yet but they would be needed to check signatures + * that we don't support yet but they would be needed to check signatures. */ private val rawMap: JsonDict ) { @@ -57,7 +57,7 @@ internal data class MXKey( } /** - * Returns a signature for an user Id and a signkey + * Returns a signature for an user Id and a signkey. * * @param userId the user id * @param signkey the sign key @@ -81,7 +81,7 @@ internal data class MXKey( // const val KEY_ED_25519_TYPE = "ed25519" /** - * Convert a map to a MXKey + * Convert a map to a MXKey. * * @param map the map to convert * diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXOlmSessionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXOlmSessionResult.kt index 671827799e273bae75e9e29a4d61e366047c613f..666ab2d678c8c4c3195605594c11bc07db8c50d3 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXOlmSessionResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXOlmSessionResult.kt @@ -21,7 +21,7 @@ import java.io.Serializable internal data class MXOlmSessionResult( /** - * the device + * the device. */ val deviceInfo: CryptoDeviceInfo, /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper.kt index 45ffcc66064c2d831611410e375cfda52dfca10d..ecb29466800f20e430facdf4aa40798f9ced8f8c 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper.kt @@ -60,7 +60,7 @@ internal class OlmInboundGroupSessionWrapper : Serializable { } /** - * Constructor + * Constructor. * * @param sessionKey the session key * @param isImported true if it is an imported session key @@ -101,7 +101,7 @@ internal class OlmInboundGroupSessionWrapper : Serializable { } /** - * Export the inbound group session keys + * Export the inbound group session keys. * * @return the inbound group session as MegolmSessionData if the operation succeeds */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper2.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper2.kt index 1f671aa896228c1f02d9aaf500b6f5801682b9e8..289c169d6d142ddfaee52badaed4f97f551c0ec4 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper2.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper2.kt @@ -57,7 +57,7 @@ internal class OlmInboundGroupSessionWrapper2 : Serializable { } /** - * Constructor + * Constructor. * * @param sessionKey the session key * @param isImported true if it is an imported session key @@ -104,7 +104,7 @@ internal class OlmInboundGroupSessionWrapper2 : Serializable { } /** - * Export the inbound group session keys + * Export the inbound group session keys. * @param index the index to export. If null, the first known index will be used * * @return the inbound group session as MegolmSessionData if the operation succeeds diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt index d7ce553f39aebfbba1f97fbb4161edc6987bcb31..a1e58ead0cb325e9f221b3a24e97a5f65ca55e54 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt @@ -20,7 +20,7 @@ import kotlinx.coroutines.sync.Mutex import org.matrix.olm.OlmSession /** - * Encapsulate a OlmSession and a last received message Timestamp + * Encapsulate a OlmSession and a last received message Timestamp. */ internal data class OlmSessionWrapper( // The associated olm session. @@ -32,7 +32,7 @@ internal data class OlmSessionWrapper( ) { /** - * Notify that a message has been received on this olm session so that it updates `lastReceivedMessageTs` + * Notify that a message has been received on this olm session so that it updates `lastReceivedMessageTs`. */ fun onMessageReceived(currentTimeMillis: Long) { lastReceivedMessageTs = currentTimeMillis diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeleteDeviceParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeleteDeviceParams.kt index f636ab890d92224cfa236e658cf281fe3401d5a8..c26c6107c4eeb53fa346e4b969d13123d787ec01 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeleteDeviceParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeleteDeviceParams.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * This class provides the parameter to delete a device + * This class provides the parameter to delete a device. */ @JsonClass(generateAdapter = true) internal data class DeleteDeviceParams( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyChangesResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyChangesResponse.kt index f0ed77a1e335d82faab9e682522c7fe05c59aae7..5d432eca8cf362293f380d3701941a3d905e239b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyChangesResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyChangesResponse.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * This class describes the key changes response + * This class describes the key changes response. */ @JsonClass(generateAdapter = true) internal data class KeyChangesResponse( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt index 7a5773bf24d02b25de8d01aec4b9a30b0a2abfd1..9fdeda01c9db3093be37c53f78eae27458df7711 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt @@ -35,25 +35,25 @@ internal data class KeyVerificationAccept( override val transactionId: String? = null, /** - * The key agreement protocol that Bob’s device has selected to use, out of the list proposed by Alice’s device + * The key agreement protocol that Bob’s device has selected to use, out of the list proposed by Alice’s device. */ @Json(name = "key_agreement_protocol") override val keyAgreementProtocol: String? = null, /** - * The hash algorithm that Bob’s device has selected to use, out of the list proposed by Alice’s device + * The hash algorithm that Bob’s device has selected to use, out of the list proposed by Alice’s device. */ @Json(name = "hash") override val hash: String? = null, /** - * The message authentication code that Bob’s device has selected to use, out of the list proposed by Alice’s device + * The message authentication code that Bob’s device has selected to use, out of the list proposed by Alice’s device. */ @Json(name = "message_authentication_code") override val messageAuthenticationCode: String? = null, /** - * An array of short authentication string methods that Bob’s client (and Bob) understands. Must be a subset of the list proposed by Alice’s device + * An array of short authentication string methods that Bob’s client (and Bob) understands. Must be a subset of the list proposed by Alice’s device. */ @Json(name = "short_authentication_string") override val shortAuthenticationStrings: List<String>? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationCancel.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationCancel.kt index 90272bf0e4bfafae0c50235603d7428972b18f61..2858ef3eed8b8ee12de9110cda089dd7ea5256d7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationCancel.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationCancel.kt @@ -27,18 +27,18 @@ import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoCance @JsonClass(generateAdapter = true) internal data class KeyVerificationCancel( /** - * the transaction ID of the verification to cancel + * the transaction ID of the verification to cancel. */ @Json(name = "transaction_id") override val transactionId: String? = null, /** - * machine-readable reason for cancelling, see #CancelCode + * machine-readable reason for cancelling, see #CancelCode. */ override val code: String? = null, /** - * human-readable reason for cancelling. This should only be used if the receiving client does not understand the code given. + * human-readable reason for cancelling. This should only be used if the receiving client does not understand the code given. */ override val reason: String? = null ) : SendToDeviceObject, VerificationInfoCancel { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationKey.kt index 19d8c32ddf7c9f2df333d198f69f68397dfdda30..a833148b9d7e4a271e8899b31d48a4bfb8af959e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationKey.kt @@ -27,12 +27,12 @@ import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoKeyFa @JsonClass(generateAdapter = true) internal data class KeyVerificationKey( /** - * the ID of the transaction that the message is part of + * The ID of the transaction that the message is part of. */ @Json(name = "transaction_id") override val transactionId: String? = null, /** - * The device’s ephemeral public key, as an unpadded base64 string + * The device’s ephemeral public key, as an unpadded base64 string. */ @Json(name = "key") override val key: String? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeysQueryBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeysQueryBody.kt index 4f98be9da3d7891e0bb333a339458d392198dbed..dc570820f2848e7b09fb0e0839a854eb47c87827 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeysQueryBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeysQueryBody.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * This class represents the body to /keys/query + * This class represents the body to /keys/query. */ @JsonClass(generateAdapter = true) internal data class KeysQueryBody( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeysUploadResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeysUploadResponse.kt index 3d0ea8677f03394e980df1890bb4cd9aac104892..c445f55ba78753994bd11845a46f4b64d44dfcd3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeysUploadResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeysUploadResponse.kt @@ -31,7 +31,7 @@ internal data class KeysUploadResponse( val oneTimeKeyCounts: Map<String, Int>? = null ) { /** - * Helper methods to extract information from 'oneTimeKeyCounts' + * Helper methods to extract information from 'oneTimeKeyCounts'. * * @param algorithm the expected algorithm * @return the time key counts diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RestKeyInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RestKeyInfo.kt index 66247d07d1e02c4b135909a58a860bc7b9bbdd02..cdcbe5ffe208c9d806777075b8c19775f4ce7840 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RestKeyInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RestKeyInfo.kt @@ -23,7 +23,7 @@ import org.matrix.android.sdk.internal.crypto.model.CryptoInfoMapper @JsonClass(generateAdapter = true) internal data class RestKeyInfo( /** - * The user who owns the key + * The user who owns the key. */ @Json(name = "user_id") val userId: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ShareRequestCancellation.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ShareRequestCancellation.kt index a96534fc3af1ac4f72b49297f4ac6d3c83f78c1e..ea9b451ed66da5d0200dfc5b03dfe32564ead20e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ShareRequestCancellation.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ShareRequestCancellation.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject.Companion.ACTION_SHARE_CANCELLATION /** - * Class representing a room key request cancellation content + * Class representing a room key request cancellation content. */ @JsonClass(generateAdapter = true) internal data class ShareRequestCancellation( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SignatureUploadResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SignatureUploadResponse.kt index fb92b67fc47a9317badd12d009fb096470916019..f89426d91bbf84a38f06683462ea11700d8619d6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SignatureUploadResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SignatureUploadResponse.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Upload Signature response + * Upload Signature response. */ @JsonClass(generateAdapter = true) internal data class SignatureUploadResponse( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UploadSignatureQueryBuilder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UploadSignatureQueryBuilder.kt index dd0ce47cd36162ffd15e2a1d1d4f12026e69a8b2..1c1e223bc8411408254567e09a2b9e722fd2744c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UploadSignatureQueryBuilder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UploadSignatureQueryBuilder.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.toRest /** - * Helper class to build CryptoApi#uploadSignatures params + * Helper class to build CryptoApi#uploadSignatures params. */ internal data class UploadSignatureQueryBuilder( private val deviceInfoList: MutableList<CryptoDeviceInfo> = mutableListOf(), diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/repository/WarnOnUnknownDeviceRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/repository/WarnOnUnknownDeviceRepository.kt index deec8b1b3c00f86cc7e94f61fa666f1f1b3d3477..d699950e4fa889239da3c1230368f84e6cf6455b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/repository/WarnOnUnknownDeviceRepository.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/repository/WarnOnUnknownDeviceRepository.kt @@ -22,7 +22,7 @@ import javax.inject.Inject @SessionScope internal class WarnOnUnknownDeviceRepository @Inject constructor() { - // TODO: set it back to true by default. Need UI + // TODO set it back to true by default. Need UI // Warn the user if some new devices are detected while encrypting a message. private var warnOnUnknownDevices = false diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt index 8c877593e74424183ce18b0e8510d198a36b688a..1ded9c6c7e32b83f11870cd6cca18470746ec0ee 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt @@ -40,7 +40,7 @@ import org.matrix.android.sdk.api.session.securestorage.SsssKeySpec import org.matrix.android.sdk.api.session.securestorage.SsssPassphrase import org.matrix.android.sdk.api.util.fromBase64 import org.matrix.android.sdk.api.util.toBase64NoPadding -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager +import org.matrix.android.sdk.internal.crypto.SecretShareManager import org.matrix.android.sdk.internal.crypto.keysbackup.generatePrivateKeyWithPassword import org.matrix.android.sdk.internal.crypto.tools.HkdfSha256 import org.matrix.android.sdk.internal.crypto.tools.withOlmDecryption @@ -57,7 +57,7 @@ import kotlin.experimental.and internal class DefaultSharedSecretStorageService @Inject constructor( @UserId private val userId: String, private val accountDataService: SessionAccountDataService, - private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager, + private val secretShareManager: SecretShareManager, private val coroutineDispatchers: MatrixCoroutineDispatchers, private val cryptoCoroutineScope: CoroutineScope ) : SharedSecretStorageService { @@ -213,7 +213,8 @@ internal class DefaultSharedSecretStorageService @Inject constructor( secretKey.privateKey, ByteArray(32) { 0.toByte() }, secretName.toByteArray(), - 64) + 64 + ) // The first 32 bytes are used as the AES key, and the next 32 bytes are used as the MAC key val aesKey = pseudoRandomKey.copyOfRange(0, 32) @@ -255,7 +256,8 @@ internal class DefaultSharedSecretStorageService @Inject constructor( secretKey.privateKey, ByteArray(32) { 0.toByte() }, secretName.toByteArray(), - 64) + 64 + ) // The first 32 bytes are used as the AES key, and the next 32 bytes are used as the MAC key val aesKey = pseudoRandomKey.copyOfRange(0, 32) @@ -378,10 +380,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( return IntegrityResult.Success(keyInfo.content.passphrase != null) } - override fun requestSecret(name: String, myOtherDeviceId: String) { - outgoingGossipingRequestManager.sendSecretShareRequest( - name, - mapOf(userId to listOf(myOtherDeviceId)) - ) + override suspend fun requestSecret(name: String, myOtherDeviceId: String) { + secretShareManager.requestSecretTo(myOtherDeviceId, name) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt index 8bedb78808f0e793f93df89f7069fae7a538768d..480009dbce0c45c56a29916eba6229df1abbbc68 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt @@ -19,23 +19,22 @@ package org.matrix.android.sdk.internal.crypto.store import androidx.lifecycle.LiveData import androidx.paging.PagedList import org.matrix.android.sdk.api.session.crypto.NewSessionListener +import org.matrix.android.sdk.api.session.crypto.OutgoingKeyRequest +import org.matrix.android.sdk.api.session.crypto.OutgoingRoomKeyRequestState import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo +import org.matrix.android.sdk.api.session.crypto.model.AuditTrail import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo -import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody +import org.matrix.android.sdk.api.session.crypto.model.TrailType import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent +import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode import org.matrix.android.sdk.api.util.Optional -import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon -import org.matrix.android.sdk.internal.crypto.OutgoingSecretRequest import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2 import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper @@ -44,7 +43,7 @@ import org.matrix.olm.OlmAccount import org.matrix.olm.OlmOutboundGroupSession /** - * the crypto data store + * The crypto data store. */ internal interface IMXCryptoStore { @@ -82,6 +81,15 @@ internal interface IMXCryptoStore { */ fun setGlobalBlacklistUnverifiedDevices(block: Boolean) + /** + * Enable or disable key gossiping. + * Default is true. + * If set to false this device won't send key_request nor will accept key forwarded + */ + fun enableKeyGossiping(enable: Boolean) + + fun isKeyGossipingEnabled(): Boolean + /** * Provides the rooms ids list in which the messages are not encrypted for the unverified devices. * @@ -97,24 +105,24 @@ internal interface IMXCryptoStore { fun setRoomsListBlacklistUnverifiedDevices(roomIds: List<String>) /** - * Get the current keys backup version + * Get the current keys backup version. */ fun getKeyBackupVersion(): String? /** - * Set the current keys backup version + * Set the current keys backup version. * * @param keyBackupVersion the keys backup version or null to delete it */ fun setKeyBackupVersion(keyBackupVersion: String?) /** - * Get the current keys backup local data + * Get the current keys backup local data. */ fun getKeysBackupData(): KeysBackupDataEntity? /** - * Set the keys backup local data + * Set the keys backup local data. * * @param keysBackupData the keys backup local data, or null to erase data */ @@ -125,18 +133,6 @@ internal interface IMXCryptoStore { */ fun getDeviceTrackingStatuses(): Map<String, Int> - /** - * @return the pending IncomingRoomKeyRequest requests - */ - fun getPendingIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> - - fun getPendingIncomingGossipingRequests(): List<IncomingShareRequestCommon> - - fun storeIncomingGossipingRequest(request: IncomingShareRequestCommon, ageLocalTS: Long?) - - fun storeIncomingGossipingRequests(requests: List<IncomingShareRequestCommon>) -// fun getPendingIncomingSecretShareRequests(): List<IncomingSecretShareRequest> - /** * Indicate if the store contains data for the passed account. * @@ -150,12 +146,12 @@ internal interface IMXCryptoStore { fun deleteStore() /** - * open any existing crypto store + * open any existing crypto store. */ fun open() /** - * Close the store + * Close the store. */ fun close() @@ -243,10 +239,10 @@ internal interface IMXCryptoStore { fun getRoomAlgorithm(roomId: String): String? /** - * This is a bit different than isRoomEncrypted - * A room is encrypted when there is a m.room.encryption state event in the room (malformed/invalid or not) - * But the crypto layer has additional guaranty to ensure that encryption would never been reverted - * It's defensive coding out of precaution (if ever state is reset) + * This is a bit different than isRoomEncrypted. + * A room is encrypted when there is a m.room.encryption state event in the room (malformed/invalid or not). + * But the crypto layer has additional guaranty to ensure that encryption would never been reverted. + * It's defensive coding out of precaution (if ever state is reset). */ fun roomWasOnceEncrypted(roomId: String): Boolean @@ -282,7 +278,7 @@ internal interface IMXCryptoStore { fun getDeviceSession(sessionId: String, deviceKey: String): OlmSessionWrapper? /** - * Retrieve the last used sessionId, regarding `lastReceivedMessageTs`, or null if no session exist + * Retrieve the last used sessionId, regarding `lastReceivedMessageTs`, or null if no session exist. * * @param deviceKey the public key of the other device. * @return last used sessionId, or null if not found @@ -306,17 +302,17 @@ internal interface IMXCryptoStore { fun getInboundGroupSession(sessionId: String, senderKey: String): OlmInboundGroupSessionWrapper2? /** - * Get the current outbound group session for this encrypted room + * Get the current outbound group session for this encrypted room. */ fun getCurrentOutboundGroupSessionForRoom(roomId: String): OutboundGroupSessionWrapper? /** - * Get the current outbound group session for this encrypted room + * Get the current outbound group session for this encrypted room. */ fun storeCurrentOutboundGroupSessionForRoom(roomId: String, outboundGroupSession: OlmOutboundGroupSession?) /** - * Remove an inbound group session + * Remove an inbound group session. * * @param sessionId the session identifier. * @param senderKey the base64-encoded curve25519 key of the sender. @@ -356,7 +352,7 @@ internal interface IMXCryptoStore { fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int /** - * Save the device statuses + * Save the device statuses. * * @param deviceTrackingStatuses the device tracking statuses */ @@ -372,12 +368,14 @@ internal interface IMXCryptoStore { fun getDeviceTrackingStatus(userId: String, defaultValue: Int): Int /** - * Look for an existing outgoing room key request, and if none is found, return null + * Look for an existing outgoing room key request, and if none is found, return null. * * @param requestBody the request body * @return an OutgoingRoomKeyRequest instance or null */ - fun getOutgoingRoomKeyRequest(requestBody: RoomKeyRequestBody): OutgoingRoomKeyRequest? + fun getOutgoingRoomKeyRequest(requestBody: RoomKeyRequestBody): OutgoingKeyRequest? + fun getOutgoingRoomKeyRequest(requestId: String): OutgoingKeyRequest? + fun getOutgoingRoomKeyRequest(roomId: String, sessionId: String, algorithm: String, senderKey: String): List<OutgoingKeyRequest> /** * Look for an existing outgoing room key request, and if none is found, add a new one. @@ -385,39 +383,59 @@ internal interface IMXCryptoStore { * @param request the request * @return either the same instance as passed in, or the existing one. */ - fun getOrAddOutgoingRoomKeyRequest(requestBody: RoomKeyRequestBody, recipients: Map<String, List<String>>): OutgoingRoomKeyRequest? - - fun getOrAddOutgoingSecretShareRequest(secretName: String, recipients: Map<String, List<String>>): OutgoingSecretRequest? - - fun saveGossipingEvent(event: Event) = saveGossipingEvents(listOf(event)) - - fun saveGossipingEvents(events: List<Event>) - - fun updateGossipingRequestState(request: IncomingShareRequestCommon, state: GossipingRequestState) { - updateGossipingRequestState( - requestUserId = request.userId, - requestDeviceId = request.deviceId, - requestId = request.requestId, - state = state - ) - } - - fun updateGossipingRequestState(requestUserId: String?, - requestDeviceId: String?, - requestId: String?, - state: GossipingRequestState) - - /** - * Search an IncomingRoomKeyRequest - * - * @param userId the user id - * @param deviceId the device id - * @param requestId the request id - * @return an IncomingRoomKeyRequest if it exists, else null - */ - fun getIncomingRoomKeyRequest(userId: String, deviceId: String, requestId: String): IncomingRoomKeyRequest? - - fun updateOutgoingGossipingRequestState(requestId: String, state: OutgoingGossipingRequestState) + fun getOrAddOutgoingRoomKeyRequest(requestBody: RoomKeyRequestBody, recipients: Map<String, List<String>>, fromIndex: Int): OutgoingKeyRequest + fun updateOutgoingRoomKeyRequestState(requestId: String, newState: OutgoingRoomKeyRequestState) + fun updateOutgoingRoomKeyRequiredIndex(requestId: String, newIndex: Int) + fun updateOutgoingRoomKeyReply( + roomId: String, + sessionId: String, + algorithm: String, + senderKey: String, + fromDevice: String?, + event: Event) + + fun deleteOutgoingRoomKeyRequest(requestId: String) + fun deleteOutgoingRoomKeyRequestInState(state: OutgoingRoomKeyRequestState) + + fun saveIncomingKeyRequestAuditTrail( + requestId: String, + roomId: String, + sessionId: String, + senderKey: String, + algorithm: String, + fromUser: String, + fromDevice: String + ) + + fun saveWithheldAuditTrail( + roomId: String, + sessionId: String, + senderKey: String, + algorithm: String, + code: WithHeldCode, + userId: String, + deviceId: String + ) + + fun saveForwardKeyAuditTrail( + roomId: String, + sessionId: String, + senderKey: String, + algorithm: String, + userId: String, + deviceId: String, + chainIndex: Long? + ) + + fun saveIncomingForwardKeyAuditTrail( + roomId: String, + sessionId: String, + senderKey: String, + algorithm: String, + userId: String, + deviceId: String, + chainIndex: Long? + ) fun addNewSessionListener(listener: NewSessionListener) @@ -428,7 +446,7 @@ internal interface IMXCryptoStore { // ============================================= /** - * Gets the current crosssigning info + * Gets the current crosssigning info. */ fun getMyCrossSigningInfo(): MXCrossSigningInfo? @@ -477,17 +495,15 @@ internal interface IMXCryptoStore { fun getSharedWithInfo(roomId: String?, sessionId: String): MXUsersDevicesMap<Int> // Dev tools - fun getOutgoingRoomKeyRequests(): List<OutgoingRoomKeyRequest> - fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingRoomKeyRequest>> - fun getOutgoingSecretKeyRequests(): List<OutgoingSecretRequest> - fun getOutgoingSecretRequest(secretName: String): OutgoingSecretRequest? - fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> - fun getIncomingRoomKeyRequestsPaged(): LiveData<PagedList<IncomingRoomKeyRequest>> - fun getGossipingEventsTrail(): LiveData<PagedList<Event>> - fun getGossipingEvents(): List<Event> + fun getOutgoingRoomKeyRequests(): List<OutgoingKeyRequest> + fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingKeyRequest>> + fun getGossipingEventsTrail(): LiveData<PagedList<AuditTrail>> + fun <T> getGossipingEventsTrail(type: TrailType, mapper: ((AuditTrail) -> T)): LiveData<PagedList<T>> + fun getGossipingEvents(): List<AuditTrail> fun setDeviceKeysUploaded(uploaded: Boolean) fun areDeviceKeysUploaded(): Boolean fun tidyUpDataBase() fun logDbUsageInfo() + fun getOutgoingRoomKeyRequests(inStates: Set<OutgoingRoomKeyRequestState>): List<OutgoingKeyRequest> } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt index b841e9c6e58a2843322d40b5168b68a8331f2a86..2d66ce1488f125cc44235f3d7eee64da86d5c7ea 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt @@ -26,7 +26,7 @@ import java.util.zip.GZIPInputStream import java.util.zip.GZIPOutputStream /** - * Get realm, invoke the action, close realm, and return the result of the action + * Get realm, invoke the action, close realm, and return the result of the action. */ internal fun <T> doWithRealm(realmConfiguration: RealmConfiguration, action: (Realm) -> T): T { return Realm.getInstance(realmConfiguration).use { realm -> @@ -35,7 +35,7 @@ internal fun <T> doWithRealm(realmConfiguration: RealmConfiguration, action: (Re } /** - * Get realm, do the query, copy from realm, close realm, and return the copied result + * Get realm, do the query, copy from realm, close realm, and return the copied result. */ internal fun <T : RealmObject> doRealmQueryAndCopy(realmConfiguration: RealmConfiguration, action: (Realm) -> T?): T? { return Realm.getInstance(realmConfiguration).use { realm -> @@ -44,7 +44,7 @@ internal fun <T : RealmObject> doRealmQueryAndCopy(realmConfiguration: RealmConf } /** - * Get realm, do the list query, copy from realm, close realm, and return the copied result + * Get realm, do the list query, copy from realm, close realm, and return the copied result. */ internal fun <T : RealmObject> doRealmQueryAndCopyList(realmConfiguration: RealmConfiguration, action: (Realm) -> Iterable<T>): Iterable<T> { return Realm.getInstance(realmConfiguration).use { realm -> @@ -53,7 +53,7 @@ internal fun <T : RealmObject> doRealmQueryAndCopyList(realmConfiguration: Realm } /** - * Get realm instance, invoke the action in a transaction and close realm + * Get realm instance, invoke the action in a transaction and close realm. */ internal fun doRealmTransaction(realmConfiguration: RealmConfiguration, action: (Realm) -> Unit) { Realm.getInstance(realmConfiguration).use { realm -> @@ -68,7 +68,7 @@ internal fun doRealmTransactionAsync(realmConfiguration: RealmConfiguration, act } /** - * Serialize any Serializable object, zip it and convert to Base64 String + * Serialize any Serializable object, zip it and convert to Base64 String. */ internal fun serializeForRealm(o: Any?): String? { if (o == null) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt index a509315e7af28f04a9f07c2ed585aae6546659b5..533ab70bba3ce0095825a10deae8f83d7df07d06 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt @@ -24,37 +24,40 @@ import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.RealmConfiguration import io.realm.Sort +import io.realm.kotlin.createObject import io.realm.kotlin.where import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.NewSessionListener +import org.matrix.android.sdk.api.session.crypto.OutgoingKeyRequest +import org.matrix.android.sdk.api.session.crypto.OutgoingRoomKeyRequestState import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo +import org.matrix.android.sdk.api.session.crypto.model.AuditTrail import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo -import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest -import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest +import org.matrix.android.sdk.api.session.crypto.model.ForwardInfo +import org.matrix.android.sdk.api.session.crypto.model.IncomingKeyRequestInfo import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult -import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody +import org.matrix.android.sdk.api.session.crypto.model.TrailType +import org.matrix.android.sdk.api.session.crypto.model.WithheldInfo import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent -import org.matrix.android.sdk.api.session.room.send.SendState +import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional -import org.matrix.android.sdk.internal.crypto.GossipRequestType -import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon -import org.matrix.android.sdk.internal.crypto.OutgoingSecretRequest import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2 import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper +import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntity +import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntityFields +import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailMapper import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntity import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMapper @@ -63,10 +66,6 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntity import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntity import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFields -import org.matrix.android.sdk.internal.crypto.store.db.model.GossipingEventEntity -import org.matrix.android.sdk.internal.crypto.store.db.model.GossipingEventEntityFields -import org.matrix.android.sdk.internal.crypto.store.db.model.IncomingGossipingRequestEntity -import org.matrix.android.sdk.internal.crypto.store.db.model.IncomingGossipingRequestEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntity import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntity import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSessionEntity @@ -74,8 +73,8 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSess import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntity import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.OutboundGroupSessionInfoEntity -import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingGossipingRequestEntity -import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingGossipingRequestEntityFields +import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingKeyRequestEntity +import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingKeyRequestEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntity import org.matrix.android.sdk.internal.crypto.store.db.model.TrustLevelEntity import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntity @@ -89,7 +88,6 @@ import org.matrix.android.sdk.internal.crypto.store.db.query.get 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.crypto.util.RequestIdHelper -import org.matrix.android.sdk.internal.database.mapper.ContentMapper import org.matrix.android.sdk.internal.database.tools.RealmDebugTools import org.matrix.android.sdk.internal.di.CryptoDatabase import org.matrix.android.sdk.internal.di.DeviceId @@ -106,6 +104,8 @@ import java.util.concurrent.Executors import java.util.concurrent.TimeUnit import javax.inject.Inject +private val loggerTag = LoggerTag("RealmCryptoStore", LoggerTag.CRYPTO) + @SessionScope internal class RealmCryptoStore @Inject constructor( @CryptoDatabase private val realmConfiguration: RealmConfiguration, @@ -233,7 +233,7 @@ internal class RealmCryptoStore @Inject constructor( } /** - * Olm account access should be synchronized + * Olm account access should be synchronized. */ override fun <T> doWithOlmAccount(block: (OlmAccount) -> T): T { return olmAccount!!.let { olmAccount -> @@ -273,12 +273,13 @@ internal class RealmCryptoStore @Inject constructor( } override fun deviceWithIdentityKey(identityKey: String): CryptoDeviceInfo? { - return doWithRealm(realmConfiguration) { - it.where<DeviceInfoEntity>() - .equalTo(DeviceInfoEntityFields.IDENTITY_KEY, identityKey) - .findFirst() - ?.let { deviceInfo -> - CryptoMapper.mapToModel(deviceInfo) + return doWithRealm(realmConfiguration) { realm -> + realm.where<DeviceInfoEntity>() + .contains(DeviceInfoEntityFields.KEYS_MAP_JSON, identityKey) + .findAll() + .mapNotNull { CryptoMapper.mapToModel(it) } + .firstOrNull { + it.identityKey() == identityKey } } } @@ -743,14 +744,23 @@ internal class RealmCryptoStore @Inject constructor( if (sessionIdentifier != null) { val key = OlmInboundGroupSessionEntity.createPrimaryKey(sessionIdentifier, session.senderKey) - val realmOlmInboundGroupSession = OlmInboundGroupSessionEntity().apply { - primaryKey = key - sessionId = sessionIdentifier - senderKey = session.senderKey - putInboundGroupSession(session) - } + val existing = realm.where<OlmInboundGroupSessionEntity>() + .equalTo(OlmInboundGroupSessionEntityFields.PRIMARY_KEY, key) + .findFirst() + + if (existing != null) { + // we want to keep the existing backup status + existing.putInboundGroupSession(session) + } else { + val realmOlmInboundGroupSession = OlmInboundGroupSessionEntity().apply { + primaryKey = key + sessionId = sessionIdentifier + senderKey = session.senderKey + putInboundGroupSession(session) + } - realm.insertOrUpdate(realmOlmInboundGroupSession) + realm.insertOrUpdate(realmOlmInboundGroupSession) + } } } } @@ -805,7 +815,7 @@ internal class RealmCryptoStore @Inject constructor( /** * Note: the result will be only use to export all the keys and not to use the OlmInboundGroupSessionWrapper2, - * so there is no need to use or update `inboundGroupSessionToRelease` for native memory management + * so there is no need to use or update `inboundGroupSessionToRelease` for native memory management. */ override fun getInboundGroupSessions(): List<OlmInboundGroupSessionWrapper2> { return doWithRealm(realmConfiguration) { @@ -879,18 +889,33 @@ internal class RealmCryptoStore @Inject constructor( return } - doRealmTransaction(realmConfiguration) { + doRealmTransaction(realmConfiguration) { realm -> olmInboundGroupSessionWrappers.forEach { olmInboundGroupSessionWrapper -> try { + val sessionIdentifier = olmInboundGroupSessionWrapper.olmInboundGroupSession?.sessionIdentifier() val key = OlmInboundGroupSessionEntity.createPrimaryKey( - olmInboundGroupSessionWrapper.olmInboundGroupSession?.sessionIdentifier(), + sessionIdentifier, olmInboundGroupSessionWrapper.senderKey ) - it.where<OlmInboundGroupSessionEntity>() + val existing = realm.where<OlmInboundGroupSessionEntity>() .equalTo(OlmInboundGroupSessionEntityFields.PRIMARY_KEY, key) .findFirst() - ?.backedUp = true + + if (existing != null) { + existing.backedUp = true + } else { + // ... might be in cache but not yet persisted, create a record to persist backedup state + val realmOlmInboundGroupSession = OlmInboundGroupSessionEntity().apply { + primaryKey = key + sessionId = sessionIdentifier + senderKey = olmInboundGroupSessionWrapper.senderKey + putInboundGroupSession(olmInboundGroupSessionWrapper) + backedUp = true + } + + realm.insertOrUpdate(realmOlmInboundGroupSession) + } } catch (e: OlmException) { Timber.e(e, "OlmException") } @@ -929,6 +954,18 @@ internal class RealmCryptoStore @Inject constructor( } } + override fun enableKeyGossiping(enable: Boolean) { + doRealmTransaction(realmConfiguration) { + it.where<CryptoMetadataEntity>().findFirst()?.globalEnableKeyGossiping = enable + } + } + + override fun isKeyGossipingEnabled(): Boolean { + return doWithRealm(realmConfiguration) { + it.where<CryptoMetadataEntity>().findFirst()?.globalEnableKeyGossiping + } ?: true + } + override fun getGlobalBlacklistUnverifiedDevices(): Boolean { return doWithRealm(realmConfiguration) { it.where<CryptoMetadataEntity>().findFirst()?.globalBlacklistUnverifiedDevices @@ -1010,12 +1047,13 @@ internal class RealmCryptoStore @Inject constructor( ?: defaultValue } - override fun getOutgoingRoomKeyRequest(requestBody: RoomKeyRequestBody): OutgoingRoomKeyRequest? { + override fun getOutgoingRoomKeyRequest(requestBody: RoomKeyRequestBody): OutgoingKeyRequest? { return monarchy.fetchAllCopiedSync { realm -> - realm.where<OutgoingGossipingRequestEntity>() - .equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name) - }.mapNotNull { - it.toOutgoingGossipingRequest() as? OutgoingRoomKeyRequest + realm.where<OutgoingKeyRequestEntity>() + .equalTo(OutgoingKeyRequestEntityFields.ROOM_ID, requestBody.roomId) + .equalTo(OutgoingKeyRequestEntityFields.MEGOLM_SESSION_ID, requestBody.sessionId) + }.map { + it.toOutgoingKeyRequest() }.firstOrNull { it.requestBody?.algorithm == requestBody.algorithm && it.requestBody?.roomId == requestBody.roomId && @@ -1024,41 +1062,37 @@ internal class RealmCryptoStore @Inject constructor( } } - override fun getOutgoingSecretRequest(secretName: String): OutgoingSecretRequest? { + override fun getOutgoingRoomKeyRequest(requestId: String): OutgoingKeyRequest? { return monarchy.fetchAllCopiedSync { realm -> - realm.where<OutgoingGossipingRequestEntity>() - .equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.SECRET.name) - .equalTo(OutgoingGossipingRequestEntityFields.REQUESTED_INFO_STR, secretName) - }.mapNotNull { - it.toOutgoingGossipingRequest() as? OutgoingSecretRequest + realm.where<OutgoingKeyRequestEntity>() + .equalTo(OutgoingKeyRequestEntityFields.REQUEST_ID, requestId) + }.map { + it.toOutgoingKeyRequest() }.firstOrNull() } - override fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> { + override fun getOutgoingRoomKeyRequest(roomId: String, sessionId: String, algorithm: String, senderKey: String): List<OutgoingKeyRequest> { + // TODO this annoying we have to load all return monarchy.fetchAllCopiedSync { realm -> - realm.where<IncomingGossipingRequestEntity>() - .equalTo(IncomingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name) - }.mapNotNull { - it.toIncomingGossipingRequest() as? IncomingRoomKeyRequest + realm.where<OutgoingKeyRequestEntity>() + .equalTo(OutgoingKeyRequestEntityFields.ROOM_ID, roomId) + .equalTo(OutgoingKeyRequestEntityFields.MEGOLM_SESSION_ID, sessionId) + }.map { + it.toOutgoingKeyRequest() + }.filter { + it.requestBody?.algorithm == algorithm && + it.requestBody?.senderKey == senderKey } } - override fun getIncomingRoomKeyRequestsPaged(): LiveData<PagedList<IncomingRoomKeyRequest>> { + override fun getGossipingEventsTrail(): LiveData<PagedList<AuditTrail>> { val realmDataSourceFactory = monarchy.createDataSourceFactory { realm -> - realm.where<IncomingGossipingRequestEntity>() - .equalTo(IncomingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name) - .sort(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, Sort.DESCENDING) + realm.where<AuditTrailEntity>().sort(AuditTrailEntityFields.AGE_LOCAL_TS, Sort.DESCENDING) } val dataSourceFactory = realmDataSourceFactory.map { - it.toIncomingGossipingRequest() as? IncomingRoomKeyRequest - ?: IncomingRoomKeyRequest( - requestBody = null, - deviceId = "", - userId = "", - requestId = "", - state = GossipingRequestState.NONE, - localCreationTimestamp = 0 - ) + AuditTrailMapper.map(it) + // mm we can't map not null... + ?: createUnknownTrail() } return monarchy.findAllPagedWithChanges( realmDataSourceFactory, @@ -1073,12 +1107,33 @@ internal class RealmCryptoStore @Inject constructor( ) } - override fun getGossipingEventsTrail(): LiveData<PagedList<Event>> { + private fun createUnknownTrail() = AuditTrail( + clock.epochMillis(), + TrailType.Unknown, + IncomingKeyRequestInfo( + "", + "", + "", + "", + "", + "", + "", + ) + ) + + override fun <T> getGossipingEventsTrail(type: TrailType, mapper: ((AuditTrail) -> T)): LiveData<PagedList<T>> { val realmDataSourceFactory = monarchy.createDataSourceFactory { realm -> - realm.where<GossipingEventEntity>().sort(GossipingEventEntityFields.AGE_LOCAL_TS, Sort.DESCENDING) + realm.where<AuditTrailEntity>() + .equalTo(AuditTrailEntityFields.TYPE, type.name) + .sort(AuditTrailEntityFields.AGE_LOCAL_TS, Sort.DESCENDING) } - val dataSourceFactory = realmDataSourceFactory.map { it.toModel() } - val trail = monarchy.findAllPagedWithChanges( + val dataSourceFactory = realmDataSourceFactory.map { entity -> + (AuditTrailMapper.map(entity) + // mm we can't map not null... + ?: createUnknownTrail() + ).let { mapper.invoke(it) } + } + return monarchy.findAllPagedWithChanges( realmDataSourceFactory, LivePagedListBuilder( dataSourceFactory, @@ -1089,28 +1144,36 @@ internal class RealmCryptoStore @Inject constructor( .build() ) ) - return trail } - override fun getGossipingEvents(): List<Event> { + override fun getGossipingEvents(): List<AuditTrail> { return monarchy.fetchAllCopiedSync { realm -> - realm.where<GossipingEventEntity>() - }.map { - it.toModel() + realm.where<AuditTrailEntity>() + }.mapNotNull { + AuditTrailMapper.map(it) } } - override fun getOrAddOutgoingRoomKeyRequest(requestBody: RoomKeyRequestBody, recipients: Map<String, List<String>>): OutgoingRoomKeyRequest? { + override fun getOrAddOutgoingRoomKeyRequest(requestBody: RoomKeyRequestBody, + recipients: Map<String, List<String>>, + fromIndex: Int): OutgoingKeyRequest { // Insert the request and return the one passed in parameter - var request: OutgoingRoomKeyRequest? = null + lateinit var request: OutgoingKeyRequest doRealmTransaction(realmConfiguration) { realm -> - val existing = realm.where<OutgoingGossipingRequestEntity>() - .equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name) + val existing = realm.where<OutgoingKeyRequestEntity>() + .equalTo(OutgoingKeyRequestEntityFields.MEGOLM_SESSION_ID, requestBody.sessionId) + .equalTo(OutgoingKeyRequestEntityFields.ROOM_ID, requestBody.roomId) .findAll() - .mapNotNull { - it.toOutgoingGossipingRequest() as? OutgoingRoomKeyRequest - }.firstOrNull { + .map { + it.toOutgoingKeyRequest() + }.also { + if (it.size > 1) { + // there should be one or zero but not more, worth warning + Timber.tag(loggerTag.value).w("There should not be more than one active key request per session") + } + } + .firstOrNull { it.requestBody?.algorithm == requestBody.algorithm && it.requestBody?.sessionId == requestBody.sessionId && it.requestBody?.senderKey == requestBody.senderKey && @@ -1118,13 +1181,14 @@ internal class RealmCryptoStore @Inject constructor( } if (existing == null) { - request = realm.createObject(OutgoingGossipingRequestEntity::class.java).apply { + request = realm.createObject(OutgoingKeyRequestEntity::class.java).apply { this.requestId = RequestIdHelper.createUniqueRequestId() this.setRecipients(recipients) - this.requestState = OutgoingGossipingRequestState.UNSENT - this.type = GossipRequestType.KEY - this.requestedInfoStr = requestBody.toJson() - }.toOutgoingGossipingRequest() as? OutgoingRoomKeyRequest + this.requestedIndex = fromIndex + this.requestState = OutgoingRoomKeyRequestState.UNSENT + this.setRequestBody(requestBody) + this.creationTimeStamp = clock.epochMillis() + }.toOutgoingKeyRequest() } else { request = existing } @@ -1132,285 +1196,176 @@ internal class RealmCryptoStore @Inject constructor( return request } - override fun getOrAddOutgoingSecretShareRequest(secretName: String, recipients: Map<String, List<String>>): OutgoingSecretRequest? { - var request: OutgoingSecretRequest? = null - - // Insert the request and return the one passed in parameter + override fun updateOutgoingRoomKeyRequestState(requestId: String, newState: OutgoingRoomKeyRequestState) { doRealmTransaction(realmConfiguration) { realm -> - val existing = realm.where<OutgoingGossipingRequestEntity>() - .equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.SECRET.name) - .equalTo(OutgoingGossipingRequestEntityFields.REQUESTED_INFO_STR, secretName) - .findAll() - .mapNotNull { - it.toOutgoingGossipingRequest() as? OutgoingSecretRequest - }.firstOrNull() - if (existing == null) { - request = realm.createObject(OutgoingGossipingRequestEntity::class.java).apply { - this.type = GossipRequestType.SECRET - setRecipients(recipients) - this.requestState = OutgoingGossipingRequestState.UNSENT - this.requestId = RequestIdHelper.createUniqueRequestId() - this.requestedInfoStr = secretName - }.toOutgoingGossipingRequest() as? OutgoingSecretRequest - } else { - request = existing - } - } - - return request - } - - override fun saveGossipingEvents(events: List<Event>) { - monarchy.writeAsync { realm -> - val now = clock.epochMillis() - events.forEach { event -> - val ageLocalTs = event.unsignedData?.age?.let { now - it } ?: now - val entity = GossipingEventEntity( - type = event.type, - sender = event.senderId, - ageLocalTs = ageLocalTs, - content = ContentMapper.map(event.content) - ).apply { - sendState = SendState.SYNCED - decryptionResultJson = MoshiProvider.providesMoshi().adapter(OlmDecryptionResult::class.java).toJson(event.mxDecryptionResult) - decryptionErrorCode = event.mCryptoError?.name - } - realm.insertOrUpdate(entity) - } + realm.where<OutgoingKeyRequestEntity>() + .equalTo(OutgoingKeyRequestEntityFields.REQUEST_ID, requestId) + .findFirst()?.apply { + this.requestState = newState + if (newState == OutgoingRoomKeyRequestState.UNSENT) { + // clear the old replies + this.replies.deleteAllFromRealm() + } + } } } -// override fun getOutgoingRoomKeyRequestByState(states: Set<ShareRequestState>): OutgoingRoomKeyRequest? { -// val statesIndex = states.map { it.ordinal }.toTypedArray() -// return doRealmQueryAndCopy(realmConfiguration) { realm -> -// realm.where<GossipingEventEntity>() -// .equalTo(GossipingEventEntityFields.SENDER, credentials.userId) -// .findAll() -// .filter {entity -> -// states.any { it == entity.requestState} -// } -// }.mapNotNull { -// ContentMapper.map(it.content)?.toModel<OutgoingSecretRequest>() -// } -// ?.toOutgoingRoomKeyRequest() -// } -// -// override fun getOutgoingSecretShareRequestByState(states: Set<ShareRequestState>): OutgoingSecretRequest? { -// val statesIndex = states.map { it.ordinal }.toTypedArray() -// return doRealmQueryAndCopy(realmConfiguration) { -// it.where<OutgoingSecretRequestEntity>() -// .`in`(OutgoingSecretRequestEntityFields.STATE, statesIndex) -// .findFirst() -// } -// ?.toOutgoingSecretRequest() -// } - -// override fun updateOutgoingRoomKeyRequest(request: OutgoingRoomKeyRequest) { -// doRealmTransaction(realmConfiguration) { -// val obj = OutgoingRoomKeyRequestEntity().apply { -// requestId = request.requestId -// cancellationTxnId = request.cancellationTxnId -// state = request.state.ordinal -// putRecipients(request.recipients) -// putRequestBody(request.requestBody) -// } -// -// it.insertOrUpdate(obj) -// } -// } - -// override fun deleteOutgoingRoomKeyRequest(transactionId: String) { -// doRealmTransaction(realmConfiguration) { -// it.where<OutgoingRoomKeyRequestEntity>() -// .equalTo(OutgoingRoomKeyRequestEntityFields.REQUEST_ID, transactionId) -// .findFirst() -// ?.deleteFromRealm() -// } -// } - -// override fun storeIncomingRoomKeyRequest(incomingRoomKeyRequest: IncomingRoomKeyRequest?) { -// if (incomingRoomKeyRequest == null) { -// return -// } -// -// doRealmTransaction(realmConfiguration) { -// // Delete any previous store request with the same parameters -// it.where<IncomingRoomKeyRequestEntity>() -// .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.userId -// deviceId = incomingRoomKeyRequest.deviceId -// requestId = incomingRoomKeyRequest.requestId -// putRequestBody(incomingRoomKeyRequest.requestBody) -// } -// } -// } - -// override fun deleteIncomingRoomKeyRequest(incomingRoomKeyRequest: IncomingShareRequestCommon) { -// doRealmTransaction(realmConfiguration) { -// it.where<GossipingEventEntity>() -// .equalTo(GossipingEventEntityFields.TYPE, EventType.ROOM_KEY_REQUEST) -// .notEqualTo(GossipingEventEntityFields.SENDER, credentials.userId) -// .findAll() -// .filter { -// ContentMapper.map(it.content).toModel<IncomingRoomKeyRequest>()?.let { -// -// } -// } -// // .equalTo(IncomingRoomKeyRequestEntityFields.USER_ID, incomingRoomKeyRequest.userId) -// // .equalTo(IncomingRoomKeyRequestEntityFields.DEVICE_ID, incomingRoomKeyRequest.deviceId) -// // .equalTo(IncomingRoomKeyRequestEntityFields.REQUEST_ID, incomingRoomKeyRequest.requestId) -// // .findAll() -// // .deleteAllFromRealm() -// } -// } - - override fun updateGossipingRequestState(requestUserId: String?, - requestDeviceId: String?, - requestId: String?, - state: GossipingRequestState) { + override fun updateOutgoingRoomKeyRequiredIndex(requestId: String, newIndex: Int) { doRealmTransaction(realmConfiguration) { realm -> - realm.where<IncomingGossipingRequestEntity>() - .equalTo(IncomingGossipingRequestEntityFields.OTHER_USER_ID, requestUserId) - .equalTo(IncomingGossipingRequestEntityFields.OTHER_DEVICE_ID, requestDeviceId) - .equalTo(IncomingGossipingRequestEntityFields.REQUEST_ID, requestId) - .findAll().forEach { - it.requestState = state + realm.where<OutgoingKeyRequestEntity>() + .equalTo(OutgoingKeyRequestEntityFields.REQUEST_ID, requestId) + .findFirst()?.apply { + this.requestedIndex = newIndex } } } - override fun updateOutgoingGossipingRequestState(requestId: String, state: OutgoingGossipingRequestState) { + override fun updateOutgoingRoomKeyReply(roomId: String, + sessionId: String, + algorithm: String, + senderKey: String, + fromDevice: String?, + event: Event) { doRealmTransaction(realmConfiguration) { realm -> - realm.where<OutgoingGossipingRequestEntity>() - .equalTo(OutgoingGossipingRequestEntityFields.REQUEST_ID, requestId) - .findAll().forEach { - it.requestState = state + realm.where<OutgoingKeyRequestEntity>() + .equalTo(OutgoingKeyRequestEntityFields.ROOM_ID, roomId) + .equalTo(OutgoingKeyRequestEntityFields.MEGOLM_SESSION_ID, sessionId) + .findAll().firstOrNull { entity -> + entity.toOutgoingKeyRequest().let { + it.requestBody?.senderKey == senderKey && + it.requestBody?.algorithm == algorithm + } + }?.apply { + event.senderId?.let { addReply(it, fromDevice, event) } } } } - override fun getIncomingRoomKeyRequest(userId: String, deviceId: String, requestId: String): IncomingRoomKeyRequest? { - return doWithRealm(realmConfiguration) { realm -> - realm.where<IncomingGossipingRequestEntity>() - .equalTo(IncomingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name) - .equalTo(IncomingGossipingRequestEntityFields.OTHER_DEVICE_ID, deviceId) - .equalTo(IncomingGossipingRequestEntityFields.OTHER_USER_ID, userId) - .findAll() - .mapNotNull { entity -> - entity.toIncomingGossipingRequest() as? IncomingRoomKeyRequest - } - .firstOrNull() + override fun deleteOutgoingRoomKeyRequest(requestId: String) { + doRealmTransaction(realmConfiguration) { realm -> + realm.where<OutgoingKeyRequestEntity>() + .equalTo(OutgoingKeyRequestEntityFields.REQUEST_ID, requestId) + .findFirst()?.deleteOnCascade() } } - override fun getPendingIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> { - return doWithRealm(realmConfiguration) { - it.where<IncomingGossipingRequestEntity>() - .equalTo(IncomingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name) - .equalTo(IncomingGossipingRequestEntityFields.REQUEST_STATE_STR, GossipingRequestState.PENDING.name) + override fun deleteOutgoingRoomKeyRequestInState(state: OutgoingRoomKeyRequestState) { + doRealmTransaction(realmConfiguration) { realm -> + realm.where<OutgoingKeyRequestEntity>() + .equalTo(OutgoingKeyRequestEntityFields.REQUEST_STATE_STR, state.name) .findAll() - .map { entity -> - IncomingRoomKeyRequest( - userId = entity.otherUserId, - deviceId = entity.otherDeviceId, - requestId = entity.requestId, - requestBody = entity.getRequestedKeyInfo(), - localCreationTimestamp = entity.localCreationTimestamp - ) - } + // I delete like this because I want to cascade delete replies? + .onEach { it.deleteOnCascade() } } } - override fun getPendingIncomingGossipingRequests(): List<IncomingShareRequestCommon> { - return doWithRealm(realmConfiguration) { - it.where<IncomingGossipingRequestEntity>() - .equalTo(IncomingGossipingRequestEntityFields.REQUEST_STATE_STR, GossipingRequestState.PENDING.name) - .findAll() - .mapNotNull { entity -> - when (entity.type) { - GossipRequestType.KEY -> { - IncomingRoomKeyRequest( - userId = entity.otherUserId, - deviceId = entity.otherDeviceId, - requestId = entity.requestId, - requestBody = entity.getRequestedKeyInfo(), - localCreationTimestamp = entity.localCreationTimestamp - ) - } - GossipRequestType.SECRET -> { - IncomingSecretShareRequest( - userId = entity.otherUserId, - deviceId = entity.otherDeviceId, - requestId = entity.requestId, - secretName = entity.getRequestedSecretName(), - localCreationTimestamp = entity.localCreationTimestamp - ) - } - } - } + override fun saveIncomingKeyRequestAuditTrail( + requestId: String, + roomId: String, + sessionId: String, + senderKey: String, + algorithm: String, + fromUser: String, + fromDevice: String) { + monarchy.writeAsync { realm -> + val now = clock.epochMillis() + realm.createObject<AuditTrailEntity>().apply { + this.ageLocalTs = now + this.type = TrailType.IncomingKeyRequest.name + val info = IncomingKeyRequestInfo( + roomId = roomId, + sessionId = sessionId, + senderKey = senderKey, + alg = algorithm, + userId = fromUser, + deviceId = fromDevice, + requestId = requestId + ) + MoshiProvider.providesMoshi().adapter(IncomingKeyRequestInfo::class.java).toJson(info)?.let { + this.contentJson = it + } + } } } - override fun storeIncomingGossipingRequest(request: IncomingShareRequestCommon, ageLocalTS: Long?) { - doRealmTransactionAsync(realmConfiguration) { realm -> - - // After a clear cache, we might have a - - realm.createObject(IncomingGossipingRequestEntity::class.java).let { - it.otherDeviceId = request.deviceId - it.otherUserId = request.userId - it.requestId = request.requestId ?: "" - it.requestState = GossipingRequestState.PENDING - it.localCreationTimestamp = ageLocalTS ?: clock.epochMillis() - if (request is IncomingSecretShareRequest) { - it.type = GossipRequestType.SECRET - it.requestedInfoStr = request.secretName - } else if (request is IncomingRoomKeyRequest) { - it.type = GossipRequestType.KEY - it.requestedInfoStr = request.requestBody?.toJson() + override fun saveWithheldAuditTrail(roomId: String, + sessionId: String, + senderKey: String, + algorithm: String, + code: WithHeldCode, + userId: String, + deviceId: String) { + monarchy.writeAsync { realm -> + val now = clock.epochMillis() + realm.createObject<AuditTrailEntity>().apply { + this.ageLocalTs = now + this.type = TrailType.OutgoingKeyWithheld.name + val info = WithheldInfo( + roomId = roomId, + sessionId = sessionId, + senderKey = senderKey, + alg = algorithm, + code = code, + userId = userId, + deviceId = deviceId + ) + MoshiProvider.providesMoshi().adapter(WithheldInfo::class.java).toJson(info)?.let { + this.contentJson = it } } } } - override fun storeIncomingGossipingRequests(requests: List<IncomingShareRequestCommon>) { - doRealmTransactionAsync(realmConfiguration) { realm -> - requests.forEach { request -> - // After a clear cache, we might have a - realm.createObject(IncomingGossipingRequestEntity::class.java).let { - it.otherDeviceId = request.deviceId - it.otherUserId = request.userId - it.requestId = request.requestId ?: "" - it.requestState = GossipingRequestState.PENDING - it.localCreationTimestamp = request.localCreationTimestamp ?: clock.epochMillis() - if (request is IncomingSecretShareRequest) { - it.type = GossipRequestType.SECRET - it.requestedInfoStr = request.secretName - } else if (request is IncomingRoomKeyRequest) { - it.type = GossipRequestType.KEY - it.requestedInfoStr = request.requestBody?.toJson() - } + override fun saveForwardKeyAuditTrail(roomId: String, + sessionId: String, + senderKey: String, + algorithm: String, + userId: String, + deviceId: String, + chainIndex: Long?) { + saveForwardKeyTrail(roomId, sessionId, senderKey, algorithm, userId, deviceId, chainIndex, false) + } + + override fun saveIncomingForwardKeyAuditTrail(roomId: String, + sessionId: String, + senderKey: String, + algorithm: String, + userId: String, + deviceId: String, + chainIndex: Long?) { + saveForwardKeyTrail(roomId, sessionId, senderKey, algorithm, userId, deviceId, chainIndex, true) + } + + private fun saveForwardKeyTrail(roomId: String, + sessionId: String, + senderKey: String, + algorithm: String, + userId: String, + deviceId: String, + chainIndex: Long?, + incoming: Boolean + ) { + monarchy.writeAsync { realm -> + val now = clock.epochMillis() + realm.createObject<AuditTrailEntity>().apply { + this.ageLocalTs = now + this.type = if (incoming) TrailType.IncomingKeyForward.name else TrailType.OutgoingKeyForward.name + val info = ForwardInfo( + roomId = roomId, + sessionId = sessionId, + senderKey = senderKey, + alg = algorithm, + userId = userId, + deviceId = deviceId, + chainIndex = chainIndex + ) + MoshiProvider.providesMoshi().adapter(ForwardInfo::class.java).toJson(info)?.let { + this.contentJson = it } } } } -// override fun getPendingIncomingSecretShareRequests(): List<IncomingSecretShareRequest> { -// return doRealmQueryAndCopyList(realmConfiguration) { -// it.where<GossipingEventEntity>() -// .findAll() -// }.map { -// it.toIncomingSecretShareRequest() -// } -// } - /* ========================================================================================== * Cross Signing * ========================================================================================== */ @@ -1513,37 +1468,34 @@ internal class RealmCryptoStore @Inject constructor( } } - override fun getOutgoingRoomKeyRequests(): List<OutgoingRoomKeyRequest> { + override fun getOutgoingRoomKeyRequests(): List<OutgoingKeyRequest> { return monarchy.fetchAllMappedSync({ realm -> realm - .where(OutgoingGossipingRequestEntity::class.java) - .equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name) + .where(OutgoingKeyRequestEntity::class.java) }, { entity -> - entity.toOutgoingGossipingRequest() as? OutgoingRoomKeyRequest + entity.toOutgoingKeyRequest() }) .filterNotNull() } - override fun getOutgoingSecretKeyRequests(): List<OutgoingSecretRequest> { + override fun getOutgoingRoomKeyRequests(inStates: Set<OutgoingRoomKeyRequestState>): List<OutgoingKeyRequest> { return monarchy.fetchAllMappedSync({ realm -> realm - .where(OutgoingGossipingRequestEntity::class.java) - .equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.SECRET.name) + .where(OutgoingKeyRequestEntity::class.java) + .`in`(OutgoingKeyRequestEntityFields.REQUEST_STATE_STR, inStates.map { it.name }.toTypedArray()) }, { entity -> - entity.toOutgoingGossipingRequest() as? OutgoingSecretRequest + entity.toOutgoingKeyRequest() }) .filterNotNull() } - override fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingRoomKeyRequest>> { + override fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingKeyRequest>> { val realmDataSourceFactory = monarchy.createDataSourceFactory { realm -> realm - .where(OutgoingGossipingRequestEntity::class.java) - .equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name) + .where(OutgoingKeyRequestEntity::class.java) } val dataSourceFactory = realmDataSourceFactory.map { - it.toOutgoingGossipingRequest() as? OutgoingRoomKeyRequest - ?: OutgoingRoomKeyRequest(requestBody = null, requestId = "?", recipients = emptyMap(), state = OutgoingGossipingRequestState.CANCELLED) + it.toOutgoingKeyRequest() } val trail = monarchy.findAllPagedWithChanges( realmDataSourceFactory, @@ -1715,33 +1667,27 @@ internal class RealmCryptoStore @Inject constructor( } /** - * Some entries in the DB can get a bit out of control with time - * So we need to tidy up a bit + * Some entries in the DB can get a bit out of control with time. + * So we need to tidy up a bit. */ override fun tidyUpDataBase() { val prevWeekTs = clock.epochMillis() - 7 * 24 * 60 * 60 * 1_000 doRealmTransaction(realmConfiguration) { realm -> - // Only keep one week history - realm.where<IncomingGossipingRequestEntity>() - .lessThan(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, prevWeekTs) + // Clean the old ones? + realm.where<OutgoingKeyRequestEntity>() + .lessThan(OutgoingKeyRequestEntityFields.CREATION_TIME_STAMP, prevWeekTs) .findAll() - .also { Timber.i("## Crypto Clean up ${it.size} IncomingGossipingRequestEntity") } + .also { Timber.i("## Crypto Clean up ${it.size} OutgoingKeyRequestEntity") } .deleteAllFromRealm() - // Clean the cancelled ones? - realm.where<OutgoingGossipingRequestEntity>() - .equalTo(OutgoingGossipingRequestEntityFields.REQUEST_STATE_STR, OutgoingGossipingRequestState.CANCELLED.name) - .equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name) - .findAll() - .also { Timber.i("## Crypto Clean up ${it.size} OutgoingGossipingRequestEntity") } - .deleteAllFromRealm() + // Only keep one month history - // Only keep one week history - realm.where<GossipingEventEntity>() - .lessThan(GossipingEventEntityFields.AGE_LOCAL_TS, prevWeekTs) + val prevMonthTs = clock.epochMillis() - 4 * 7 * 24 * 60 * 60 * 1_000L + realm.where<AuditTrailEntity>() + .lessThan(AuditTrailEntityFields.AGE_LOCAL_TS, prevMonthTs) .findAll() - .also { Timber.i("## Crypto Clean up ${it.size} GossipingEventEntityFields") } + .also { Timber.i("## Crypto Clean up ${it.size} AuditTrailEntity") } .deleteAllFromRealm() // Can we do something for WithHeldSessionEntity? @@ -1749,7 +1695,7 @@ internal class RealmCryptoStore @Inject constructor( } /** - * Prints out database info + * Prints out database info. */ override fun logDbUsageInfo() { RealmDebugTools(realmConfiguration).logInfo("Crypto") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt index 32f24c5d2e7897c92f5017315ee6ada4d7e50cb2..02c2a27decd9ae64f27246599e66d233ecf0724b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt @@ -33,6 +33,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo013 import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo014 import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo015 +import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo016 import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject @@ -41,8 +42,8 @@ internal class RealmCryptoStoreMigration @Inject constructor( private val clock: Clock, ) : RealmMigration { /** - * Forces all RealmCryptoStoreMigration instances to be equal - * Avoids Realm throwing when multiple instances of the migration are set + * Forces all RealmCryptoStoreMigration instances to be equal. + * Avoids Realm throwing when multiple instances of the migration are set. */ override fun equals(other: Any?) = other is RealmCryptoStoreMigration override fun hashCode() = 5000 @@ -50,7 +51,7 @@ internal class RealmCryptoStoreMigration @Inject constructor( // 0, 1, 2: legacy Riot-Android // 3: migrate to RiotX schema // 4, 5, 6, 7, 8, 9: migrations from RiotX (which was previously 1, 2, 3, 4, 5, 6) - val schemaVersion = 15L + val schemaVersion = 16L override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) { Timber.d("Migrating Realm Crypto from $oldVersion to $newVersion") @@ -70,5 +71,6 @@ internal class RealmCryptoStoreMigration @Inject constructor( if (oldVersion < 13) MigrateCryptoTo013(realm).perform() if (oldVersion < 14) MigrateCryptoTo014(realm).perform() if (oldVersion < 15) MigrateCryptoTo015(realm).perform() + if (oldVersion < 16) MigrateCryptoTo016(realm).perform() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreModule.kt index a2f2f8e97ae65ecb8785c38607fd97364595cc25..6696cf8281d02939f9849f6e58fd1314060c221a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreModule.kt @@ -17,28 +17,29 @@ package org.matrix.android.sdk.internal.crypto.store.db import io.realm.annotations.RealmModule +import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntity import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntity import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntity import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntity import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntity -import org.matrix.android.sdk.internal.crypto.store.db.model.GossipingEventEntity -import org.matrix.android.sdk.internal.crypto.store.db.model.IncomingGossipingRequestEntity import org.matrix.android.sdk.internal.crypto.store.db.model.KeyInfoEntity +import org.matrix.android.sdk.internal.crypto.store.db.model.KeyRequestReplyEntity import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntity import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntity import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSessionEntity import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntity import org.matrix.android.sdk.internal.crypto.store.db.model.OutboundGroupSessionInfoEntity -import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingGossipingRequestEntity +import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingKeyRequestEntity import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntity import org.matrix.android.sdk.internal.crypto.store.db.model.TrustLevelEntity import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntity import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntity /** - * Realm module for Crypto store classes + * Realm module for Crypto store classes. */ -@RealmModule(library = true, +@RealmModule( + library = true, classes = [ CryptoMetadataEntity::class, CryptoRoomEntity::class, @@ -50,12 +51,13 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEnti KeyInfoEntity::class, CrossSigningInfoEntity::class, TrustLevelEntity::class, - GossipingEventEntity::class, - IncomingGossipingRequestEntity::class, - OutgoingGossipingRequestEntity::class, + AuditTrailEntity::class, + OutgoingKeyRequestEntity::class, + KeyRequestReplyEntity::class, MyDeviceLastSeenInfoEntity::class, WithHeldSessionEntity::class, SharedSessionEntity::class, OutboundGroupSessionInfoEntity::class - ]) + ] +) internal class RealmCryptoStoreModule diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CrossSigningKeysMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CrossSigningKeysMapper.kt index 5e4b9b96da8ac3739606c62883b084d9818cad9e..8b7bf9c26b29183e2a93a61617572f11e035296a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CrossSigningKeysMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CrossSigningKeysMapper.kt @@ -27,11 +27,13 @@ import javax.inject.Inject internal class CrossSigningKeysMapper @Inject constructor(moshi: Moshi) { - private val signaturesAdapter = moshi.adapter<Map<String, Map<String, String>>>(Types.newParameterizedType( - Map::class.java, - String::class.java, - Any::class.java - )) + private val signaturesAdapter = moshi.adapter<Map<String, Map<String, String>>>( + Types.newParameterizedType( + Map::class.java, + String::class.java, + Any::class.java + ) + ) fun update(keyInfo: KeyInfoEntity, cryptoCrossSigningKey: CryptoCrossSigningKey) { // update signatures? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo004.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo004.kt index 52d0124c2bc3d386bcff82216ca20c290afb2c72..e5bdd2aa9b7c436396832b9d412e1374ca1d7199 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo004.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo004.kt @@ -72,16 +72,20 @@ internal class MigrateCryptoTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) ?.addField(CryptoMetadataEntityFields.X_SIGN_SELF_SIGNED_PRIVATE_KEY, String::class.java) val moshi = Moshi.Builder().add(SerializeNulls.JSON_ADAPTER_FACTORY).build() - val listMigrationAdapter = moshi.adapter<List<String>>(Types.newParameterizedType( - List::class.java, - String::class.java, - Any::class.java - )) - val mapMigrationAdapter = moshi.adapter<JsonDict>(Types.newParameterizedType( - Map::class.java, - String::class.java, - Any::class.java - )) + val listMigrationAdapter = moshi.adapter<List<String>>( + Types.newParameterizedType( + List::class.java, + String::class.java, + Any::class.java + ) + ) + val mapMigrationAdapter = moshi.adapter<JsonDict>( + Types.newParameterizedType( + Map::class.java, + String::class.java, + Any::class.java + ) + ) realm.schema.get("DeviceInfoEntity") ?.addField(DeviceInfoEntityFields.USER_ID, String::class.java) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo005.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo005.kt index e1d759876708ad992e6b817118da8df298a690c6..8ec2932a8f6dbaefcd07b184bb13df53206460de 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo005.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo005.kt @@ -17,9 +17,6 @@ package org.matrix.android.sdk.internal.crypto.store.db.migration import io.realm.DynamicRealm -import org.matrix.android.sdk.internal.crypto.store.db.model.GossipingEventEntityFields -import org.matrix.android.sdk.internal.crypto.store.db.model.IncomingGossipingRequestEntityFields -import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingGossipingRequestEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator internal class MigrateCryptoTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) { @@ -29,38 +26,37 @@ internal class MigrateCryptoTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) realm.schema.remove("IncomingRoomKeyRequestEntity") // Not need to migrate existing request, just start fresh? - realm.schema.create("GossipingEventEntity") - .addField(GossipingEventEntityFields.TYPE, String::class.java) - .addIndex(GossipingEventEntityFields.TYPE) - .addField(GossipingEventEntityFields.CONTENT, String::class.java) - .addField(GossipingEventEntityFields.SENDER, String::class.java) - .addIndex(GossipingEventEntityFields.SENDER) - .addField(GossipingEventEntityFields.DECRYPTION_RESULT_JSON, String::class.java) - .addField(GossipingEventEntityFields.DECRYPTION_ERROR_CODE, String::class.java) - .addField(GossipingEventEntityFields.AGE_LOCAL_TS, Long::class.java) - .setNullable(GossipingEventEntityFields.AGE_LOCAL_TS, true) - .addField(GossipingEventEntityFields.SEND_STATE_STR, String::class.java) + .addField("type", String::class.java) + .addIndex("type") + .addField("content", String::class.java) + .addField("sender", String::class.java) + .addIndex("sender") + .addField("decryptionResultJson", String::class.java) + .addField("decryptionErrorCode", String::class.java) + .addField("ageLocalTs", Long::class.java) + .setNullable("ageLocalTs", true) + .addField("sendStateStr", String::class.java) realm.schema.create("IncomingGossipingRequestEntity") - .addField(IncomingGossipingRequestEntityFields.REQUEST_ID, String::class.java) - .addIndex(IncomingGossipingRequestEntityFields.REQUEST_ID) - .addField(IncomingGossipingRequestEntityFields.TYPE_STR, String::class.java) - .addIndex(IncomingGossipingRequestEntityFields.TYPE_STR) - .addField(IncomingGossipingRequestEntityFields.OTHER_USER_ID, String::class.java) - .addField(IncomingGossipingRequestEntityFields.REQUESTED_INFO_STR, String::class.java) - .addField(IncomingGossipingRequestEntityFields.OTHER_DEVICE_ID, String::class.java) - .addField(IncomingGossipingRequestEntityFields.REQUEST_STATE_STR, String::class.java) - .addField(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, Long::class.java) - .setNullable(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, true) + .addField("requestId", String::class.java) + .addIndex("requestId") + .addField("typeStr", String::class.java) + .addIndex("typeStr") + .addField("otherUserId", String::class.java) + .addField("requestedInfoStr", String::class.java) + .addField("otherDeviceId", String::class.java) + .addField("requestStateStr", String::class.java) + .addField("localCreationTimestamp", Long::class.java) + .setNullable("localCreationTimestamp", true) realm.schema.create("OutgoingGossipingRequestEntity") - .addField(OutgoingGossipingRequestEntityFields.REQUEST_ID, String::class.java) - .addIndex(OutgoingGossipingRequestEntityFields.REQUEST_ID) - .addField(OutgoingGossipingRequestEntityFields.RECIPIENTS_DATA, String::class.java) - .addField(OutgoingGossipingRequestEntityFields.REQUESTED_INFO_STR, String::class.java) - .addField(OutgoingGossipingRequestEntityFields.TYPE_STR, String::class.java) - .addIndex(OutgoingGossipingRequestEntityFields.TYPE_STR) - .addField(OutgoingGossipingRequestEntityFields.REQUEST_STATE_STR, String::class.java) + .addField("requestId", String::class.java) + .addIndex("requestId") + .addField("recipientsData", String::class.java) + .addField("requestedInfoStr", String::class.java) + .addField("typeStr", String::class.java) + .addIndex("typeStr") + .addField("requestStateStr", String::class.java) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo007.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo007.kt index 718b9787d268684a16dec7d8784869bbd2569880..0e221e78f33c6ebed166ad8cae78bab4de7d2f79 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo007.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo007.kt @@ -42,7 +42,7 @@ internal class MigrateCryptoTo007(realm: DynamicRealm) : RealmMigrator(realm, 7) val jsonSignatures = crossSigningKeysMapper.serializeSignatures(objectSignatures) it.setString(KeyInfoEntityFields.SIGNATURES, jsonSignatures) } - } catch (failure: Throwable) { + } catch (ignore: Throwable) { } // Migrate frozen classes diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo016.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo016.kt new file mode 100644 index 0000000000000000000000000000000000000000..5a14ebf85ae5b0f93df9ef91d8a7770f189747d8 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo016.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022 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.store.db.migration + +import io.realm.DynamicRealm +import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntityFields +import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntityFields +import org.matrix.android.sdk.internal.crypto.store.db.model.KeyRequestReplyEntityFields +import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingKeyRequestEntityFields +import org.matrix.android.sdk.internal.util.database.RealmMigrator + +internal class MigrateCryptoTo016(realm: DynamicRealm) : RealmMigrator(realm, 16) { + + override fun doMigrate(realm: DynamicRealm) { + realm.schema.remove("OutgoingGossipingRequestEntity") + realm.schema.remove("IncomingGossipingRequestEntity") + realm.schema.remove("GossipingEventEntity") + + // No need to migrate existing request, just start fresh + + val replySchema = realm.schema.create("KeyRequestReplyEntity") + .addField(KeyRequestReplyEntityFields.SENDER_ID, String::class.java) + .addField(KeyRequestReplyEntityFields.FROM_DEVICE, String::class.java) + .addField(KeyRequestReplyEntityFields.EVENT_JSON, String::class.java) + + realm.schema.create("OutgoingKeyRequestEntity") + .addField(OutgoingKeyRequestEntityFields.REQUEST_ID, String::class.java) + .addIndex(OutgoingKeyRequestEntityFields.REQUEST_ID) + .addField(OutgoingKeyRequestEntityFields.MEGOLM_SESSION_ID, String::class.java) + .addIndex(OutgoingKeyRequestEntityFields.MEGOLM_SESSION_ID) + .addRealmListField(OutgoingKeyRequestEntityFields.REPLIES.`$`, replySchema) + .addField(OutgoingKeyRequestEntityFields.RECIPIENTS_DATA, String::class.java) + .addField(OutgoingKeyRequestEntityFields.REQUEST_STATE_STR, String::class.java) + .addIndex(OutgoingKeyRequestEntityFields.REQUEST_STATE_STR) + .addField(OutgoingKeyRequestEntityFields.REQUESTED_INFO_STR, String::class.java) + .addField(OutgoingKeyRequestEntityFields.ROOM_ID, String::class.java) + .addIndex(OutgoingKeyRequestEntityFields.ROOM_ID) + .addField(OutgoingKeyRequestEntityFields.REQUESTED_INDEX, Integer::class.java) + .addField(OutgoingKeyRequestEntityFields.CREATION_TIME_STAMP, Long::class.java) + .setNullable(OutgoingKeyRequestEntityFields.CREATION_TIME_STAMP, true) + + realm.schema.create("AuditTrailEntity") + .addField(AuditTrailEntityFields.AGE_LOCAL_TS, Long::class.java) + .setNullable(AuditTrailEntityFields.AGE_LOCAL_TS, true) + .addField(AuditTrailEntityFields.CONTENT_JSON, String::class.java) + .addField(AuditTrailEntityFields.TYPE, String::class.java) + .addIndex(AuditTrailEntityFields.TYPE) + + realm.schema.get("CryptoMetadataEntity") + ?.addField(CryptoMetadataEntityFields.GLOBAL_ENABLE_KEY_GOSSIPING, Boolean::class.java) + ?.transform { + // set the default value to true + it.setBoolean(CryptoMetadataEntityFields.GLOBAL_ENABLE_KEY_GOSSIPING, true) + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingRequestState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/AuditTrailEntity.kt similarity index 60% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingRequestState.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/AuditTrailEntity.kt index d9a6f4fcba1af402522b1b29ead0466f4e008630..2e0e9c8c8ba4d2efec66697a563153c01bcadc93 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingRequestState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/AuditTrailEntity.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright 2022 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. @@ -14,18 +14,15 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.session.crypto.model +package org.matrix.android.sdk.internal.crypto.store.db.model -enum class GossipingRequestState { - NONE, - PENDING, - REJECTED, - ACCEPTING, - ACCEPTED, - FAILED_TO_ACCEPTED, +import io.realm.RealmObject +import io.realm.annotations.Index - // USER_REJECTED, - UNABLE_TO_PROCESS, - CANCELLED_BY_REQUESTER, - RE_REQUESTED +internal open class AuditTrailEntity( + var ageLocalTs: Long? = null, + @Index var type: String? = null, + var contentJson: String? = null +) : RealmObject() { + companion object } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/AuditTrailMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/AuditTrailMapper.kt new file mode 100644 index 0000000000000000000000000000000000000000..80ae4a8d0d39ec3c79f8dc99cb51b19b303670d8 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/AuditTrailMapper.kt @@ -0,0 +1,82 @@ +/* + * Copyright 2022 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.store.db.model + +import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.crypto.model.AuditTrail +import org.matrix.android.sdk.api.session.crypto.model.ForwardInfo +import org.matrix.android.sdk.api.session.crypto.model.IncomingKeyRequestInfo +import org.matrix.android.sdk.api.session.crypto.model.TrailType +import org.matrix.android.sdk.api.session.crypto.model.UnknownInfo +import org.matrix.android.sdk.api.session.crypto.model.WithheldInfo +import org.matrix.android.sdk.internal.di.MoshiProvider + +internal object AuditTrailMapper { + + fun map(entity: AuditTrailEntity): AuditTrail? { + val contentJson = entity.contentJson ?: return null + return when (entity.type) { + TrailType.OutgoingKeyForward.name -> { + val info = tryOrNull { + MoshiProvider.providesMoshi().adapter(ForwardInfo::class.java).fromJson(contentJson) + } ?: return null + AuditTrail( + ageLocalTs = entity.ageLocalTs ?: 0, + type = TrailType.OutgoingKeyForward, + info = info + ) + } + TrailType.OutgoingKeyWithheld.name -> { + val info = tryOrNull { + MoshiProvider.providesMoshi().adapter(WithheldInfo::class.java).fromJson(contentJson) + } ?: return null + AuditTrail( + ageLocalTs = entity.ageLocalTs ?: 0, + type = TrailType.OutgoingKeyWithheld, + info = info + ) + } + TrailType.IncomingKeyRequest.name -> { + val info = tryOrNull { + MoshiProvider.providesMoshi().adapter(IncomingKeyRequestInfo::class.java).fromJson(contentJson) + } ?: return null + AuditTrail( + ageLocalTs = entity.ageLocalTs ?: 0, + type = TrailType.IncomingKeyRequest, + info = info + ) + } + TrailType.IncomingKeyForward.name -> { + val info = tryOrNull { + MoshiProvider.providesMoshi().adapter(ForwardInfo::class.java).fromJson(contentJson) + } ?: return null + AuditTrail( + ageLocalTs = entity.ageLocalTs ?: 0, + type = TrailType.IncomingKeyForward, + info = info + ) + } + else -> { + AuditTrail( + ageLocalTs = entity.ageLocalTs ?: 0, + type = TrailType.Unknown, + info = UnknownInfo + ) + } + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMapper.kt index c71d5e73a228b1f755ee703c350466943e8d9661..ca41930f80eb5902d237ac18654719c9fd88506a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMapper.kt @@ -27,21 +27,27 @@ import timber.log.Timber internal object CryptoMapper { private val moshi = Moshi.Builder().add(SerializeNulls.JSON_ADAPTER_FACTORY).build() - private val listMigrationAdapter = moshi.adapter<List<String>>(Types.newParameterizedType( - List::class.java, - String::class.java, - Any::class.java - )) - private val mapMigrationAdapter = moshi.adapter<JsonDict>(Types.newParameterizedType( - Map::class.java, - String::class.java, - Any::class.java - )) - private val mapOfStringMigrationAdapter = moshi.adapter<Map<String, Map<String, String>>>(Types.newParameterizedType( - Map::class.java, - String::class.java, - Any::class.java - )) + private val listMigrationAdapter = moshi.adapter<List<String>>( + Types.newParameterizedType( + List::class.java, + String::class.java, + Any::class.java + ) + ) + private val mapMigrationAdapter = moshi.adapter<JsonDict>( + Types.newParameterizedType( + Map::class.java, + String::class.java, + Any::class.java + ) + ) + private val mapOfStringMigrationAdapter = moshi.adapter<Map<String, Map<String, String>>>( + Types.newParameterizedType( + Map::class.java, + String::class.java, + Any::class.java + ) + ) internal fun mapToEntity(deviceInfo: CryptoDeviceInfo): DeviceInfoEntity { return DeviceInfoEntity(primaryKey = DeviceInfoEntity.createPrimaryKey(deviceInfo.userId, deviceInfo.deviceId)) @@ -91,11 +97,13 @@ internal object CryptoMapper { }, keys = deviceInfoEntity.keysMapJson?.let { try { - moshi.adapter<Map<String, String>>(Types.newParameterizedType( - Map::class.java, - String::class.java, - Any::class.java - )).fromJson(it) + moshi.adapter<Map<String, String>>( + Types.newParameterizedType( + Map::class.java, + String::class.java, + Any::class.java + ) + ).fromJson(it) } catch (failure: Throwable) { Timber.e(failure) null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMetadataEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMetadataEntity.kt index 35ae86db8bb00b034d0d8bed75898fb7e5a7f3cf..63ed0e537e45eaddd479b3223e43c19178a2b3f3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMetadataEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMetadataEntity.kt @@ -33,6 +33,8 @@ internal open class CryptoMetadataEntity( var deviceSyncToken: String? = null, // Settings for blacklisting unverified devices. var globalBlacklistUnverifiedDevices: Boolean = false, + // setting to enable or disable key gossiping + var globalEnableKeyGossiping: Boolean = true, // The keys backup version currently used. Null means no backup. var backupVersion: String? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/GossipingEventEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/GossipingEventEntity.kt deleted file mode 100644 index a024e092b7c40e0f2644a016395f8385cdaa9ee2..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/GossipingEventEntity.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.store.db.model - -import com.squareup.moshi.JsonDataException -import io.realm.RealmObject -import io.realm.annotations.Index -import org.matrix.android.sdk.api.session.crypto.MXCryptoError -import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult -import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult -import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.api.session.room.send.SendState -import org.matrix.android.sdk.internal.database.mapper.ContentMapper -import org.matrix.android.sdk.internal.di.MoshiProvider -import timber.log.Timber - -/** - * Keep track of gossiping event received in toDevice messages - * (room key request, or sss secret sharing, as well as cancellations) - * - */ -internal open class GossipingEventEntity(@Index var type: String? = "", - var content: String? = null, - @Index var sender: String? = null, - var decryptionResultJson: String? = null, - var decryptionErrorCode: String? = null, - var ageLocalTs: Long? = null) : RealmObject() { - - private var sendStateStr: String = SendState.UNKNOWN.name - - var sendState: SendState - get() { - return SendState.valueOf(sendStateStr) - } - set(value) { - sendStateStr = value.name - } - - companion object - - fun setDecryptionResult(result: MXEventDecryptionResult) { - val decryptionResult = OlmDecryptionResult( - payload = result.clearEvent, - senderKey = result.senderCurve25519Key, - keysClaimed = result.claimedEd25519Key?.let { mapOf("ed25519" to it) }, - forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain - ) - val adapter = MoshiProvider.providesMoshi().adapter<OlmDecryptionResult>(OlmDecryptionResult::class.java) - decryptionResultJson = adapter.toJson(decryptionResult) - decryptionErrorCode = null - } - - fun toModel(): Event { - return Event( - type = this.type ?: "", - content = ContentMapper.map(this.content), - senderId = this.sender - ).also { - it.ageLocalTs = this.ageLocalTs - it.sendState = this.sendState - this.decryptionResultJson?.let { json -> - try { - it.mxDecryptionResult = MoshiProvider.providesMoshi().adapter(OlmDecryptionResult::class.java).fromJson(json) - } catch (t: JsonDataException) { - Timber.e(t, "Failed to parse decryption result") - } - } - // TODO get the full crypto error object - it.mCryptoError = this.decryptionErrorCode?.let { errorCode -> - MXCryptoError.ErrorType.valueOf(errorCode) - } - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/IncomingGossipingRequestEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/IncomingGossipingRequestEntity.kt deleted file mode 100644 index f05c8853c8dc60aa68416f82efed3b98b689dc7f..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/IncomingGossipingRequestEntity.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.store.db.model - -import io.realm.RealmObject -import io.realm.annotations.Index -import org.matrix.android.sdk.api.extensions.tryOrNull -import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest -import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest -import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody -import org.matrix.android.sdk.internal.crypto.GossipRequestType -import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon - -internal open class IncomingGossipingRequestEntity(@Index var requestId: String? = "", - @Index var typeStr: String? = null, - var otherUserId: String? = null, - var requestedInfoStr: String? = null, - var otherDeviceId: String? = null, - var localCreationTimestamp: Long? = null -) : RealmObject() { - - fun getRequestedSecretName(): String? = if (type == GossipRequestType.SECRET) { - requestedInfoStr - } else null - - fun getRequestedKeyInfo(): RoomKeyRequestBody? = if (type == GossipRequestType.KEY) { - RoomKeyRequestBody.fromJson(requestedInfoStr) - } else null - - var type: GossipRequestType - get() { - return tryOrNull { typeStr?.let { GossipRequestType.valueOf(it) } } ?: GossipRequestType.KEY - } - set(value) { - typeStr = value.name - } - - private var requestStateStr: String = GossipingRequestState.NONE.name - - var requestState: GossipingRequestState - get() { - return tryOrNull { GossipingRequestState.valueOf(requestStateStr) } - ?: GossipingRequestState.NONE - } - set(value) { - requestStateStr = value.name - } - - companion object - - fun toIncomingGossipingRequest(): IncomingShareRequestCommon { - return when (type) { - GossipRequestType.KEY -> { - IncomingRoomKeyRequest( - requestBody = getRequestedKeyInfo(), - deviceId = otherDeviceId, - userId = otherUserId, - requestId = requestId, - state = requestState, - localCreationTimestamp = localCreationTimestamp - ) - } - GossipRequestType.SECRET -> { - IncomingSecretShareRequest( - secretName = getRequestedSecretName(), - deviceId = otherDeviceId, - userId = otherUserId, - requestId = requestId, - localCreationTimestamp = localCreationTimestamp - ) - } - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/KeyRequestReplyEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/KeyRequestReplyEntity.kt new file mode 100644 index 0000000000000000000000000000000000000000..0c7cf79e788a6b3dcbab91e35c73c179e028fd4e --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/KeyRequestReplyEntity.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2022 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.store.db.model + +import io.realm.RealmObject +import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.internal.di.MoshiProvider + +internal open class KeyRequestReplyEntity( + var senderId: String? = null, + var fromDevice: String? = null, + var eventJson: String? = null +) : RealmObject() { + companion object + + fun getEvent(): Event? { + return eventJson?.let { + MoshiProvider.providesMoshi().adapter(Event::class.java).fromJson(it) + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/MyDeviceLastSeenInfoEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/MyDeviceLastSeenInfoEntity.kt index 222711f9acf60a068ef5d1aa58ffb3b563d87375..74a81d5b01a045328d01edd8b4749cb1a7782084 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/MyDeviceLastSeenInfoEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/MyDeviceLastSeenInfoEntity.kt @@ -20,13 +20,13 @@ import io.realm.RealmObject import io.realm.annotations.PrimaryKey internal open class MyDeviceLastSeenInfoEntity( - /**The device id*/ + /** The device id. */ @PrimaryKey var deviceId: String? = null, - /** The device display name*/ + /** The device display name. */ var displayName: String? = null, /** The last time this device has been seen. */ var lastSeenTs: Long? = null, - /** The last ip address*/ + /** The last ip address. */ var lastSeenIp: String? = null ) : RealmObject() { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingGossipingRequestEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingGossipingRequestEntity.kt deleted file mode 100644 index 0e1278967eb4adcb1be665856498c62e6110b555..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingGossipingRequestEntity.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.store.db.model - -import com.squareup.moshi.JsonAdapter -import com.squareup.moshi.Types -import io.realm.RealmObject -import io.realm.annotations.Index -import org.matrix.android.sdk.api.extensions.tryOrNull -import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState -import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest -import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody -import org.matrix.android.sdk.internal.crypto.GossipRequestType -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequest -import org.matrix.android.sdk.internal.crypto.OutgoingSecretRequest -import org.matrix.android.sdk.internal.di.MoshiProvider - -internal open class OutgoingGossipingRequestEntity( - @Index var requestId: String? = null, - var recipientsData: String? = null, - var requestedInfoStr: String? = null, - @Index var typeStr: String? = null -) : RealmObject() { - - fun getRequestedSecretName(): String? = if (type == GossipRequestType.SECRET) { - requestedInfoStr - } else null - - fun getRequestedKeyInfo(): RoomKeyRequestBody? = if (type == GossipRequestType.KEY) { - RoomKeyRequestBody.fromJson(requestedInfoStr) - } else null - - var type: GossipRequestType - get() { - return tryOrNull { typeStr?.let { GossipRequestType.valueOf(it) } } ?: GossipRequestType.KEY - } - set(value) { - typeStr = value.name - } - - private var requestStateStr: String = OutgoingGossipingRequestState.UNSENT.name - - var requestState: OutgoingGossipingRequestState - get() { - return tryOrNull { OutgoingGossipingRequestState.valueOf(requestStateStr) } - ?: OutgoingGossipingRequestState.UNSENT - } - set(value) { - requestStateStr = value.name - } - - companion object { - - private val recipientsDataMapper: JsonAdapter<Map<String, List<String>>> = - MoshiProvider - .providesMoshi() - .adapter<Map<String, List<String>>>( - Types.newParameterizedType(Map::class.java, String::class.java, List::class.java) - ) - } - - fun toOutgoingGossipingRequest(): OutgoingGossipingRequest { - return when (type) { - GossipRequestType.KEY -> { - OutgoingRoomKeyRequest( - requestBody = getRequestedKeyInfo(), - recipients = getRecipients().orEmpty(), - requestId = requestId ?: "", - state = requestState - ) - } - GossipRequestType.SECRET -> { - OutgoingSecretRequest( - secretName = getRequestedSecretName(), - recipients = getRecipients().orEmpty(), - requestId = requestId ?: "", - state = requestState - ) - } - } - } - - private fun getRecipients(): Map<String, List<String>>? { - return this.recipientsData?.let { recipientsDataMapper.fromJson(it) } - } - - fun setRecipients(recipients: Map<String, List<String>>) { - this.recipientsData = recipientsDataMapper.toJson(recipients) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingKeyRequestEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingKeyRequestEntity.kt new file mode 100644 index 0000000000000000000000000000000000000000..7a8ba188093879501e5033e7066debdc34f7f6f1 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingKeyRequestEntity.kt @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2022 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.store.db.model + +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Types +import io.realm.RealmList +import io.realm.RealmObject +import io.realm.annotations.Index +import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.crypto.OutgoingKeyRequest +import org.matrix.android.sdk.api.session.crypto.OutgoingRoomKeyRequestState +import org.matrix.android.sdk.api.session.crypto.RequestReply +import org.matrix.android.sdk.api.session.crypto.RequestResult +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody +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.content.RoomKeyWithHeldContent +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.internal.di.MoshiProvider + +internal open class OutgoingKeyRequestEntity( + @Index var requestId: String? = null, + var requestedIndex: Int? = null, + var recipientsData: String? = null, + var requestedInfoStr: String? = null, + var creationTimeStamp: Long? = null, + // de-normalization for better query (if not have to query all and parse json) + @Index var roomId: String? = null, + @Index var megolmSessionId: String? = null, + + var replies: RealmList<KeyRequestReplyEntity> = RealmList() +) : RealmObject() { + + @Index private var requestStateStr: String = OutgoingRoomKeyRequestState.UNSENT.name + + companion object { + + private val recipientsDataMapper: JsonAdapter<Map<String, List<String>>> = + MoshiProvider + .providesMoshi() + .adapter( + Types.newParameterizedType(Map::class.java, String::class.java, List::class.java) + ) + } + + private fun getRequestedKeyInfo(): RoomKeyRequestBody? = RoomKeyRequestBody.fromJson(requestedInfoStr) + + fun setRequestBody(body: RoomKeyRequestBody) { + requestedInfoStr = body.toJson() + roomId = body.roomId + megolmSessionId = body.sessionId + } + + var requestState: OutgoingRoomKeyRequestState + get() { + return tryOrNull { OutgoingRoomKeyRequestState.valueOf(requestStateStr) } + ?: OutgoingRoomKeyRequestState.UNSENT + } + set(value) { + requestStateStr = value.name + } + + private fun getRecipients(): Map<String, List<String>>? { + return this.recipientsData?.let { recipientsDataMapper.fromJson(it) } + } + + fun setRecipients(recipients: Map<String, List<String>>) { + this.recipientsData = recipientsDataMapper.toJson(recipients) + } + + fun addReply(userId: String, fromDevice: String?, event: Event) { + val newReply = KeyRequestReplyEntity( + senderId = userId, + fromDevice = fromDevice, + eventJson = MoshiProvider.providesMoshi().adapter(Event::class.java).toJson(event) + ) + replies.add(newReply) + } + + fun toOutgoingKeyRequest(): OutgoingKeyRequest { + return OutgoingKeyRequest( + requestBody = getRequestedKeyInfo(), + recipients = getRecipients().orEmpty(), + requestId = requestId ?: "", + fromIndex = requestedIndex ?: 0, + state = requestState, + results = replies.mapNotNull { entity -> + val userId = entity.senderId ?: return@mapNotNull null + val result = entity.eventJson?.let { + MoshiProvider.providesMoshi().adapter(Event::class.java).fromJson(it) + }?.let { event -> + eventToResult(event) + } ?: return@mapNotNull null + RequestReply( + userId = userId, + fromDevice = entity.fromDevice, + result = result + ) + } + ) + } + + private fun eventToResult(event: Event): RequestResult? { + return when (event.getClearType()) { + EventType.ROOM_KEY_WITHHELD -> { + event.content.toModel<RoomKeyWithHeldContent>()?.code?.let { + RequestResult.Failure(it) + } + } + EventType.FORWARDED_ROOM_KEY -> { + RequestResult.Success((event.content?.get("chain_index") as? Number)?.toInt() ?: 0) + } + else -> null + } + } +} + +internal fun OutgoingKeyRequestEntity.deleteOnCascade() { + replies.deleteAllFromRealm() + deleteFromRealm() +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/CryptoRoomEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/CryptoRoomEntityQueries.kt index 5750cc1f67675cf1bd21468154f062108681597e..68c49740716d71cbdedada983132cf191e195f1b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/CryptoRoomEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/CryptoRoomEntityQueries.kt @@ -23,14 +23,14 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntity import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntityFields /** - * Get or create a room + * Get or create a room. */ internal fun CryptoRoomEntity.Companion.getOrCreate(realm: Realm, roomId: String): CryptoRoomEntity { return getById(realm, roomId) ?: realm.createObject(roomId) } /** - * Get a room + * Get a room. */ internal fun CryptoRoomEntity.Companion.getById(realm: Realm, roomId: String): CryptoRoomEntity? { return realm.where<CryptoRoomEntity>() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/DeviceInfoEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/DeviceInfoEntityQueries.kt index c9523d63ce3b3aae57d268a2fb5ec99048708301..0a922e79bceb25296897215b9d5da3442f9b3ba7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/DeviceInfoEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/DeviceInfoEntityQueries.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFie import org.matrix.android.sdk.internal.crypto.store.db.model.createPrimaryKey /** - * Get or create a device info + * Get or create a device info. */ internal fun DeviceInfoEntity.Companion.getOrCreate(realm: Realm, userId: String, deviceId: String): DeviceInfoEntity { val key = DeviceInfoEntity.createPrimaryKey(userId, deviceId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/UserEntitiesQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/UserEntitiesQueries.kt index 5a3b8e53975c4f45891b7b8d4ddd1915804a4366..73c399743998c1fee687d1a972a4c2333efb8460 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/UserEntitiesQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/UserEntitiesQueries.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.deleteOnCascade /** - * Get or create a user + * Get or create a user. */ internal fun UserEntity.Companion.getOrCreate(realm: Realm, userId: String): UserEntity { return realm.where<UserEntity>() @@ -34,7 +34,7 @@ internal fun UserEntity.Companion.getOrCreate(realm: Realm, userId: String): Use } /** - * Delete a user + * Delete a user. */ internal fun UserEntity.Companion.delete(realm: Realm, userId: String) { realm.where<UserEntity>() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt index 1e395796a98a3c147cb00a9b118e071d8a0f1f6f..394c6189681ca919ebc27e78efd6fa6e6e6f2096 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt @@ -15,6 +15,7 @@ */ package org.matrix.android.sdk.internal.crypto.tasks +import dagger.Lazy import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.model.MXEncryptEventContentResult @@ -39,7 +40,7 @@ internal interface EncryptEventTask : Task<EncryptEventTask.Params, Event> { internal class DefaultEncryptEventTask @Inject constructor( private val localEchoRepository: LocalEchoRepository, - private val cryptoService: CryptoService + private val cryptoService: Lazy<CryptoService> ) : EncryptEventTask { override suspend fun execute(params: EncryptEventTask.Params): Event { // don't want to wait for any query @@ -59,7 +60,7 @@ internal class DefaultEncryptEventTask @Inject constructor( // try { // let it throws awaitCallback<MXEncryptEventContentResult> { - cryptoService.encryptEventContent(localMutableContent, localEvent.type, params.roomId, it) + cryptoService.get().encryptEventContent(localMutableContent, localEvent.type, params.roomId, it) }.let { result -> val modifiedContent = HashMap(result.eventContent) params.keepKeys?.forEach { toKeep -> @@ -80,7 +81,7 @@ internal class DefaultEncryptEventTask @Inject constructor( ).toContent(), forwardingCurve25519KeyChain = emptyList(), senderCurve25519Key = result.eventContent["sender_key"] as? String, - claimedEd25519Key = cryptoService.getMyDevice().fingerprint() + claimedEd25519Key = cryptoService.get().getMyDevice().fingerprint() ) } else { null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendEventTask.kt index bdfe818c6206afec42c5c7bc9257671c988a99f9..50efe51bc1bb1502d58f7156f863f6bbb46c56ac 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendEventTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendEventTask.kt @@ -15,6 +15,7 @@ */ package org.matrix.android.sdk.internal.crypto.tasks +import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.internal.network.GlobalErrorReceiver @@ -46,7 +47,9 @@ internal class DefaultSendEventTask @Inject constructor( params.event.roomId ?.takeIf { params.encrypt } ?.let { roomId -> - loadRoomMembersTask.execute(LoadRoomMembersTask.Params(roomId)) + tryOrNull { + loadRoomMembersTask.execute(LoadRoomMembersTask.Params(roomId)) + } } val event = handleEncryption(params) @@ -66,6 +69,7 @@ internal class DefaultSendEventTask @Inject constructor( } } catch (e: Throwable) { // localEchoRepository.updateSendState(params.event.eventId!!, SendState.UNDELIVERED) + Timber.w(e, "Unable to send the Event") throw e } } @@ -73,11 +77,13 @@ internal class DefaultSendEventTask @Inject constructor( @Throws private suspend fun handleEncryption(params: SendEventTask.Params): Event { if (params.encrypt && !params.event.isEncrypted()) { - return encryptEventTask.execute(EncryptEventTask.Params( - params.event.roomId ?: "", - params.event, - listOf("m.relates_to") - )) + return encryptEventTask.execute( + EncryptEventTask.Params( + params.event.roomId ?: "", + params.event, + listOf("m.relates_to") + ) + ) } return params.event } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt index c4a6ba27d6834db29cbd9e5e5193f62874889518..7c52c62d92f218ebb593b577aee2724da54ba319 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt @@ -47,7 +47,7 @@ internal class DefaultSendVerificationMessageTask @Inject constructor( localEchoRepository.updateSendState(localId, event.roomId, SendState.SENDING) val response = executeRequest(globalErrorReceiver) { roomAPI.send( - localId, + txId = localId, roomId = event.roomId ?: "", content = event.content, eventType = event.type ?: "" @@ -64,11 +64,13 @@ internal class DefaultSendVerificationMessageTask @Inject constructor( private suspend fun handleEncryption(params: SendVerificationMessageTask.Params): Event { if (cryptoSessionInfoProvider.isRoomEncrypted(params.event.roomId ?: "")) { try { - return encryptEventTask.execute(EncryptEventTask.Params( - params.event.roomId ?: "", - params.event, - listOf("m.relates_to") - )) + return encryptEventTask.execute( + EncryptEventTask.Params( + params.event.roomId ?: "", + params.event, + listOf("m.relates_to") + ) + ) } catch (throwable: Throwable) { // We said it's ok to send verification request in clear } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSignaturesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSignaturesTask.kt index e03e353cb1caa3dff8ec5e64b88e4b434631a4fd..18d8b265589a6affbc98975d0c597a5c858f9402 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSignaturesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSignaturesTask.kt @@ -15,7 +15,6 @@ */ package org.matrix.android.sdk.internal.crypto.tasks -import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest @@ -34,20 +33,15 @@ internal class DefaultUploadSignaturesTask @Inject constructor( ) : UploadSignaturesTask { override suspend fun execute(params: UploadSignaturesTask.Params) { - try { - val response = executeRequest( - globalErrorReceiver, - canRetry = true, - maxRetriesCount = 10 - ) { - cryptoApi.uploadSignatures(params.signatures) - } - if (response.failures?.isNotEmpty() == true) { - throw Throwable(response.failures.toString()) - } - return - } catch (f: Failure) { - throw f + val response = executeRequest( + globalErrorReceiver, + canRetry = true, + maxRetriesCount = 10 + ) { + cryptoApi.uploadSignatures(params.signatures) + } + if (response.failures?.isNotEmpty() == true) { + throw Throwable(response.failures.toString()) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt index 0a0df11bd339b6e5264f3554bd2d62b9fa65d7f0..e539867a040361a9f968d2a6ea574d2994fdc3ae 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt @@ -36,7 +36,7 @@ internal interface UploadSigningKeysTask : Task<UploadSigningKeysTask.Params, Un // the SSK val selfSignedKey: CryptoCrossSigningKey, /** - * Authorisation info (User Interactive flow) + * Authorisation info (User Interactive flow). */ val userAuthParam: UIABaseAuth? ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tools/HkdfSha256.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tools/HkdfSha256.kt index b230f0d02954336bf62b8ca8f72f8917ff4ae4aa..4ab7e0e30c7bc589a052ddaeb756ab2becd90d40 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tools/HkdfSha256.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tools/HkdfSha256.kt @@ -33,7 +33,7 @@ internal object HkdfSha256 { } /** - * HkdfSha256-Extract(salt, IKM) -> PRK + * HkdfSha256-Extract(salt, IKM) -> PRK. * * @param salt optional salt value (a non-secret random value); * if not provided, it is set to a string of HashLen (size in octets) zeros. @@ -45,7 +45,7 @@ internal object HkdfSha256 { } /** - * HkdfSha256-Expand(PRK, info, L) -> OKM + * HkdfSha256-Expand(PRK, info, L) -> OKM. * * @param prk a pseudorandom key of at least HashLen bytes (usually, the output from the extract step) * @param info optional context and application specific information (can be empty) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultIncomingSASDefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultIncomingSASDefaultVerificationTransaction.kt index 68f1cf62d52968af554d7b2d7681723dd404ea56..a9d5cf1191d2dce87dd12969b4c066d5b5b2cf15 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultIncomingSASDefaultVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultIncomingSASDefaultVerificationTransaction.kt @@ -23,8 +23,8 @@ import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerific import org.matrix.android.sdk.api.session.crypto.verification.SasMode import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.events.model.EventType -import org.matrix.android.sdk.internal.crypto.IncomingGossipingRequestManager -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager +import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager +import org.matrix.android.sdk.internal.crypto.SecretShareManager import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import timber.log.Timber @@ -35,8 +35,8 @@ internal class DefaultIncomingSASDefaultVerificationTransaction( override val deviceId: String?, private val cryptoStore: IMXCryptoStore, crossSigningService: CrossSigningService, - outgoingGossipingRequestManager: OutgoingGossipingRequestManager, - incomingGossipingRequestManager: IncomingGossipingRequestManager, + outgoingKeyRequestManager: OutgoingKeyRequestManager, + secretShareManager: SecretShareManager, deviceFingerprint: String, transactionId: String, otherUserID: String, @@ -47,13 +47,14 @@ internal class DefaultIncomingSASDefaultVerificationTransaction( deviceId, cryptoStore, crossSigningService, - outgoingGossipingRequestManager, - incomingGossipingRequestManager, + outgoingKeyRequestManager, + secretShareManager, deviceFingerprint, transactionId, otherUserID, null, - isIncoming = true), + isIncoming = true +), IncomingSasVerificationTransaction { override val uxState: IncomingSasVerificationTransaction.UxState diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultOutgoingSASDefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultOutgoingSASDefaultVerificationTransaction.kt index e0d912a9a62a1e544b3bc8273ec65e736871fac2..ddb8ed232ba1bdc865cbfa313aa3f80d09e269d8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultOutgoingSASDefaultVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultOutgoingSASDefaultVerificationTransaction.kt @@ -20,8 +20,8 @@ import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.OutgoingSasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.events.model.EventType -import org.matrix.android.sdk.internal.crypto.IncomingGossipingRequestManager -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager +import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager +import org.matrix.android.sdk.internal.crypto.SecretShareManager import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import timber.log.Timber @@ -32,8 +32,8 @@ internal class DefaultOutgoingSASDefaultVerificationTransaction( deviceId: String?, cryptoStore: IMXCryptoStore, crossSigningService: CrossSigningService, - outgoingGossipingRequestManager: OutgoingGossipingRequestManager, - incomingGossipingRequestManager: IncomingGossipingRequestManager, + outgoingKeyRequestManager: OutgoingKeyRequestManager, + secretShareManager: SecretShareManager, deviceFingerprint: String, transactionId: String, otherUserId: String, @@ -44,13 +44,14 @@ internal class DefaultOutgoingSASDefaultVerificationTransaction( deviceId, cryptoStore, crossSigningService, - outgoingGossipingRequestManager, - incomingGossipingRequestManager, + outgoingKeyRequestManager, + secretShareManager, deviceFingerprint, transactionId, otherUserId, otherDeviceId, - isIncoming = false), + isIncoming = false +), OutgoingSasVerificationTransaction { override val uxState: OutgoingSasVerificationTransaction.UxState diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt index d62ca5503d953aac844e79b5369213dd9dc92a39..6da674d6e4aa1ca996e7b5a1134ded5e686a1a7a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt @@ -59,9 +59,9 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageVerification import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationStartContent import org.matrix.android.sdk.api.session.room.model.message.ValidVerificationDone import org.matrix.android.sdk.internal.crypto.DeviceListManager -import org.matrix.android.sdk.internal.crypto.IncomingGossipingRequestManager import org.matrix.android.sdk.internal.crypto.MyDeviceInfoHolder -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager +import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager +import org.matrix.android.sdk.internal.crypto.SecretShareManager import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationAccept import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationCancel @@ -95,8 +95,8 @@ internal class DefaultVerificationService @Inject constructor( @UserId private val userId: String, @DeviceId private val deviceId: String?, private val cryptoStore: IMXCryptoStore, - private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager, - private val incomingGossipingRequestManager: IncomingGossipingRequestManager, + private val outgoingKeyRequestManager: OutgoingKeyRequestManager, + private val secretShareManager: SecretShareManager, private val myDeviceInfoHolder: Lazy<MyDeviceInfoHolder>, private val deviceListManager: DeviceListManager, private val setDeviceVerificationAction: SetDeviceVerificationAction, @@ -551,8 +551,8 @@ internal class DefaultVerificationService @Inject constructor( deviceId, cryptoStore, crossSigningService, - outgoingGossipingRequestManager, - incomingGossipingRequestManager, + outgoingKeyRequestManager, + secretShareManager, myDeviceInfoHolder.get().myDevice.fingerprint()!!, startReq.transactionId, otherUserId, @@ -771,8 +771,15 @@ internal class DefaultVerificationService @Inject constructor( return } + val roomId = event.roomId + if (roomId == null) { + Timber.e("## SAS Verification missing roomId for event") + // TODO cancel? + return + } + handleReadyReceived(event.senderId, readyReq) { - verificationTransportRoomMessageFactory.createTransport(event.roomId!!, it) + verificationTransportRoomMessageFactory.createTransport(roomId, it) } } @@ -814,21 +821,15 @@ internal class DefaultVerificationService @Inject constructor( getExistingTransaction(userId, doneReq.transactionId) ?: getOldTransaction(userId, doneReq.transactionId) ?.let { vt -> - val otherDeviceId = vt.otherDeviceId + val otherDeviceId = vt.otherDeviceId ?: return@let if (!crossSigningService.canCrossSign()) { - outgoingGossipingRequestManager.sendSecretShareRequest( - MASTER_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*")) - ) - outgoingGossipingRequestManager.sendSecretShareRequest( - SELF_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*")) - ) - outgoingGossipingRequestManager.sendSecretShareRequest( - USER_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*")) - ) + cryptoCoroutineScope.launch { + secretShareManager.requestSecretTo(otherDeviceId, MASTER_KEY_SSSS_NAME) + secretShareManager.requestSecretTo(otherDeviceId, SELF_SIGNING_KEY_SSSS_NAME) + secretShareManager.requestSecretTo(otherDeviceId, USER_SIGNING_KEY_SSSS_NAME) + secretShareManager.requestSecretTo(otherDeviceId, KEYBACKUP_SECRET_SSSS_NAME) + } } - outgoingGossipingRequestManager.sendSecretShareRequest( - KEYBACKUP_SECRET_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*")) - ) } } } @@ -922,8 +923,8 @@ internal class DefaultVerificationService @Inject constructor( otherUserId = senderId, otherDeviceId = readyReq.fromDevice, crossSigningService = crossSigningService, - outgoingGossipingRequestManager = outgoingGossipingRequestManager, - incomingGossipingRequestManager = incomingGossipingRequestManager, + outgoingKeyRequestManager = outgoingKeyRequestManager, + secretShareManager = secretShareManager, cryptoStore = cryptoStore, qrCodeData = qrCodeData, userId = userId, @@ -1124,8 +1125,8 @@ internal class DefaultVerificationService @Inject constructor( deviceId, cryptoStore, crossSigningService, - outgoingGossipingRequestManager, - incomingGossipingRequestManager, + outgoingKeyRequestManager, + secretShareManager, myDeviceInfoHolder.get().myDevice.fingerprint()!!, txID, otherUserId, @@ -1188,6 +1189,7 @@ internal class DefaultVerificationService @Inject constructor( } .distinct() + requestsForUser.add(verificationRequest) transport.sendVerificationRequest(methodValues, validLocalId, otherUserId, roomId, null) { syncedId, info -> // We need to update with the syncedID updatePendingRequest( @@ -1199,7 +1201,6 @@ internal class DefaultVerificationService @Inject constructor( ) } - requestsForUser.add(verificationRequest) dispatchRequestAdded(verificationRequest) return verificationRequest @@ -1323,8 +1324,8 @@ internal class DefaultVerificationService @Inject constructor( deviceId, cryptoStore, crossSigningService, - outgoingGossipingRequestManager, - incomingGossipingRequestManager, + outgoingKeyRequestManager, + secretShareManager, myDeviceInfoHolder.get().myDevice.fingerprint()!!, transactionId, otherUserId, @@ -1465,8 +1466,8 @@ internal class DefaultVerificationService @Inject constructor( otherUserId = otherUserId, otherDeviceId = otherDeviceId, crossSigningService = crossSigningService, - outgoingGossipingRequestManager = outgoingGossipingRequestManager, - incomingGossipingRequestManager = incomingGossipingRequestManager, + outgoingKeyRequestManager = outgoingKeyRequestManager, + secretShareManager = secretShareManager, cryptoStore = cryptoStore, qrCodeData = qrCodeData, userId = userId, @@ -1484,7 +1485,7 @@ internal class DefaultVerificationService @Inject constructor( } /** - * This string must be unique for the pair of users performing verification for the duration that the transaction is valid + * This string must be unique for the pair of users performing verification for the duration that the transaction is valid. */ private fun createUniqueIDForTransaction(otherUserId: String, otherDeviceID: String): String { return buildString { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationTransaction.kt index 69d9388c5ff6754ee4229193c0acef99e8f3c4e9..27bc7643957340efc11441530427c8c9f4c3c3d8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationTransaction.kt @@ -20,19 +20,19 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningServic import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState -import org.matrix.android.sdk.internal.crypto.IncomingGossipingRequestManager -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager +import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager +import org.matrix.android.sdk.internal.crypto.SecretShareManager import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction import timber.log.Timber /** - * Generic interactive key verification transaction + * Generic interactive key verification transaction. */ internal abstract class DefaultVerificationTransaction( private val setDeviceVerificationAction: SetDeviceVerificationAction, private val crossSigningService: CrossSigningService, - private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager, - private val incomingGossipingRequestManager: IncomingGossipingRequestManager, + private val outgoingKeyRequestManager: OutgoingKeyRequestManager, + private val secretShareManager: SecretShareManager, private val userId: String, override val transactionId: String, override val otherUserId: String, @@ -86,7 +86,7 @@ internal abstract class DefaultVerificationTransaction( } if (otherUserId == userId) { - incomingGossipingRequestManager.onVerificationCompleteForDevice(otherDeviceId!!) + secretShareManager.onVerificationCompleteForDevice(otherDeviceId!!) // If me it's reasonable to sign and upload the device signature // Notice that i might not have the private keys, so may not be able to do it @@ -105,8 +105,10 @@ internal abstract class DefaultVerificationTransaction( private fun setDeviceVerified(userId: String, deviceId: String) { // TODO should not override cross sign status - setDeviceVerificationAction.handle(DeviceTrustLevel(crossSigningVerified = false, locallyVerified = true), + setDeviceVerificationAction.handle( + DeviceTrustLevel(crossSigningVerified = false, locallyVerified = true), userId, - deviceId) + deviceId + ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SASDefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SASDefaultVerificationTransaction.kt index 4bf01a28095a6cbf390dc43b5d82623726f1e0d3..68dd57478e62af81575a51f90ea3c1c7d6253343 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SASDefaultVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SASDefaultVerificationTransaction.kt @@ -23,8 +23,8 @@ import org.matrix.android.sdk.api.session.crypto.verification.SasMode import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.events.model.EventType -import org.matrix.android.sdk.internal.crypto.IncomingGossipingRequestManager -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager +import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager +import org.matrix.android.sdk.internal.crypto.SecretShareManager import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.extensions.toUnsignedInt @@ -42,8 +42,8 @@ internal abstract class SASDefaultVerificationTransaction( open val deviceId: String?, private val cryptoStore: IMXCryptoStore, crossSigningService: CrossSigningService, - outgoingGossipingRequestManager: OutgoingGossipingRequestManager, - incomingGossipingRequestManager: IncomingGossipingRequestManager, + outgoingKeyRequestManager: OutgoingKeyRequestManager, + secretShareManager: SecretShareManager, private val deviceFingerprint: String, transactionId: String, otherUserId: String, @@ -52,13 +52,14 @@ internal abstract class SASDefaultVerificationTransaction( ) : DefaultVerificationTransaction( setDeviceVerificationAction, crossSigningService, - outgoingGossipingRequestManager, - incomingGossipingRequestManager, + outgoingKeyRequestManager, + secretShareManager, userId, transactionId, otherUserId, otherDeviceId, - isIncoming), + isIncoming +), SasVerificationTransaction { companion object { @@ -131,7 +132,7 @@ internal abstract class SASDefaultVerificationTransaction( /** * To be called by the client when the user has verified that - * both short codes do match + * both short codes do match. */ override fun userHasVerifiedShortCode() { Timber.v("## SAS short code verified by user for id:$transactionId") @@ -297,9 +298,11 @@ internal abstract class SASDefaultVerificationTransaction( return } - trust(otherMasterKeyIsVerified, + trust( + otherMasterKeyIsVerified, verifiedDevices, - eventuallyMarkMyMasterKeyAsTrusted = otherMasterKey?.trustLevel?.isVerified() == false) + eventuallyMarkMyMasterKeyAsTrusted = otherMasterKey?.trustLevel?.isVerified() == false + ) } override fun cancel() { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SendVerificationMessageWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SendVerificationMessageWorker.kt deleted file mode 100644 index 0a175ae3ca22a971dab0c84119fde3789b18aa60..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SendVerificationMessageWorker.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.verification - -import android.content.Context -import androidx.work.Data -import androidx.work.WorkerParameters -import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.failure.shouldBeRetried -import org.matrix.android.sdk.internal.SessionManager -import org.matrix.android.sdk.internal.crypto.tasks.SendVerificationMessageTask -import org.matrix.android.sdk.internal.session.SessionComponent -import org.matrix.android.sdk.internal.session.room.send.CancelSendTracker -import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository -import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker -import org.matrix.android.sdk.internal.worker.SessionWorkerParams -import timber.log.Timber -import javax.inject.Inject - -/** - * Possible previous worker: None - * Possible next worker : None - */ -internal class SendVerificationMessageWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<SendVerificationMessageWorker.Params>(context, params, sessionManager, Params::class.java) { - - @JsonClass(generateAdapter = true) - internal data class Params( - override val sessionId: String, - val eventId: String, - override val lastFailureMessage: String? = null - ) : SessionWorkerParams - - @Inject lateinit var sendVerificationMessageTask: SendVerificationMessageTask - @Inject lateinit var localEchoRepository: LocalEchoRepository - @Inject lateinit var cancelSendTracker: CancelSendTracker - - override fun injectWith(injector: SessionComponent) { - injector.inject(this) - } - - override suspend fun doSafeWork(params: Params): Result { - val localEvent = localEchoRepository.getUpToDateEcho(params.eventId) ?: return buildErrorResult(params, "Event not found") - val localEventId = localEvent.eventId ?: "" - val roomId = localEvent.roomId ?: "" - - if (cancelSendTracker.isCancelRequestedFor(localEventId, roomId)) { - return Result.success() - .also { - cancelSendTracker.markCancelled(localEventId, roomId) - Timber.e("## SendEvent: Event sending has been cancelled $localEventId") - } - } - - return try { - val resultEventId = sendVerificationMessageTask.execute( - SendVerificationMessageTask.Params( - event = localEvent - ) - ) - - Result.success(Data.Builder().putString(localEventId, resultEventId).build()) - } catch (throwable: Throwable) { - if (throwable.shouldBeRetried()) { - Result.retry() - } else { - buildErrorResult(params, throwable.localizedMessage ?: "error") - } - } - } - - override fun buildErrorParams(params: Params, message: String): Params { - return params.copy(lastFailureMessage = params.lastFailureMessage ?: message) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoAccept.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoAccept.kt index 79aabba59db0dd216f18156d1e8265e5c0edb013..3ddb0ca758038f50c9520931c3890b69327702b2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoAccept.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoAccept.kt @@ -17,28 +17,28 @@ package org.matrix.android.sdk.internal.crypto.verification internal interface VerificationInfoAccept : VerificationInfo<ValidVerificationInfoAccept> { /** - * The key agreement protocol that Bob’s device has selected to use, out of the list proposed by Alice’s device + * The key agreement protocol that Bob’s device has selected to use, out of the list proposed by Alice’s device. */ val keyAgreementProtocol: String? /** - * The hash algorithm that Bob’s device has selected to use, out of the list proposed by Alice’s device + * The hash algorithm that Bob’s device has selected to use, out of the list proposed by Alice’s device. */ val hash: String? /** - * The message authentication code that Bob’s device has selected to use, out of the list proposed by Alice’s device + * The message authentication code that Bob’s device has selected to use, out of the list proposed by Alice’s device. */ val messageAuthenticationCode: String? /** - * An array of short authentication string methods that Bob’s client (and Bob) understands. Must be a subset of the list proposed by Alice’s device + * An array of short authentication string methods that Bob’s client (and Bob) understands. Must be a subset of the list proposed by Alice’s device. */ val shortAuthenticationStrings: List<String>? /** * The hash (encoded as unpadded base64) of the concatenation of the device’s ephemeral public key (QB, encoded as unpadded base64) - * and the canonical JSON representation of the m.key.verification.start message. + * and the canonical JSON representation of the m.key.verification.start message. */ var commitment: String? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoCancel.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoCancel.kt index 35c05ac05863b006176479df504dd47063ce8194..20e2cdcd33f90db975b42fea5a0ae649fcea46a8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoCancel.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoCancel.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.crypto.verification internal interface VerificationInfoCancel : VerificationInfo<ValidVerificationInfoCancel> { /** - * machine-readable reason for cancelling, see [CancelCode] + * machine-readable reason for cancelling, see [CancelCode]. */ val code: String? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoKey.kt index 23c117d8441d3d6905d6f0380a7d1d87c735fce5..2885b81a12fa2598b30f5bdceac7ab52e1ac38ce 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoKey.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.internal.crypto.verification */ internal interface VerificationInfoKey : VerificationInfo<ValidVerificationInfoKey> { /** - * The device’s ephemeral public key, as an unpadded base64 string + * The device’s ephemeral public key, as an unpadded base64 string. */ val key: String? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoMac.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoMac.kt index 5515acc2f1eb0e473c42b5092326d65698337889..d6f1d7e4dbdbf3ddf551536b138d58cdf2cd89cd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoMac.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoMac.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.crypto.verification internal interface VerificationInfoMac : VerificationInfo<ValidVerificationInfoMac> { /** - * A map of key ID to the MAC of the key, as an unpadded base64 string, calculated using the MAC key + * A map of key ID to the MAC of the key, as an unpadded base64 string, calculated using the MAC key. */ val mac: Map<String, String>? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoReady.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoReady.kt index 327c09dabff9581f5eb21fa249e0823fd2e14b6b..2e397eee08ff113b138e165a693cb268eb2c3c28 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoReady.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoReady.kt @@ -27,12 +27,12 @@ import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationI internal interface VerificationInfoReady : VerificationInfo<ValidVerificationInfoReady> { /** - * The ID of the device that sent the m.key.verification.ready message + * The ID of the device that sent the m.key.verification.ready message. */ val fromDevice: String? /** - * An array of verification methods that the device supports + * An array of verification methods that the device supports. */ val methods: List<String>? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoStart.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoStart.kt index 40c96dfa9591dc5e32fa62890060376f7e5c5230..d71bd7359ee8a5cc932f58d20a5ec0faff38e67a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoStart.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoStart.kt @@ -24,7 +24,7 @@ internal interface VerificationInfoStart : VerificationInfo<ValidVerificationInf val method: String? /** - * Alice’s device ID + * Alice’s device ID. */ val fromDevice: String? @@ -57,7 +57,7 @@ internal interface VerificationInfoStart : VerificationInfo<ValidVerificationInf val shortAuthenticationStrings: List<String>? /** - * Shared secret, when starting verification with QR code + * Shared secret, when starting verification with QR code. */ val sharedSecret: String? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt index ec4e1aa65cb58ac337f8345286ebb16723c515f6..303b6c5839ffbe23dbbd3edfd98490ed7953eee1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt @@ -15,13 +15,9 @@ */ package org.matrix.android.sdk.internal.crypto.verification -import io.realm.Realm -import org.matrix.android.sdk.api.session.crypto.MXCryptoError -import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.crypto.verification.VerificationService 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.LocalEcho import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent @@ -29,22 +25,18 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationReadyContent import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationRequestContent import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationStartContent -import org.matrix.android.sdk.internal.crypto.EventDecryptor -import org.matrix.android.sdk.internal.database.model.EventInsertType import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.di.UserId -import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject internal class VerificationMessageProcessor @Inject constructor( - private val eventDecryptor: EventDecryptor, - private val clock: Clock, private val verificationService: DefaultVerificationService, @UserId private val userId: String, - @DeviceId private val deviceId: String? -) : EventInsertLiveProcessor { + @DeviceId private val deviceId: String?, + private val clock: Clock, +) { private val transactionsHandledByOtherDevice = ArrayList<String>() @@ -60,40 +52,20 @@ internal class VerificationMessageProcessor @Inject constructor( EventType.ENCRYPTED ) - override fun shouldProcess(eventId: String, eventType: String, insertType: EventInsertType): Boolean { - if (insertType != EventInsertType.INCREMENTAL_SYNC) { - return false - } - return allowedTypes.contains(eventType) && !LocalEcho.isLocalEchoId(eventId) + fun shouldProcess(eventType: String): Boolean { + return allowedTypes.contains(eventType) } - override suspend fun process(realm: Realm, event: Event) { - Timber.v("## SAS Verification live observer: received msgId: ${event.eventId} msgtype: ${event.type} from ${event.senderId}") + suspend fun process(event: Event) { + Timber.v("## SAS Verification live observer: received msgId: ${event.eventId} msgtype: ${event.getClearType()} from ${event.senderId}") // If the request is in the future by more than 5 minutes or more than 10 minutes in the past, // the message should be ignored by the receiver. - if (!VerificationService.isValidRequest(event.ageLocalTs ?: event.originServerTs, clock.epochMillis())) return Unit.also { - Timber.d("## SAS Verification live observer: msgId: ${event.eventId} is outdated") + if (event.ageLocalTs != null && !VerificationService.isValidRequest(event.ageLocalTs, clock.epochMillis())) return Unit.also { + Timber.d("## SAS Verification live observer: msgId: ${event.eventId} is outdated age:$event.ageLocalTs ms") } - // decrypt if needed? - if (event.isEncrypted() && event.mxDecryptionResult == null) { - // TODO use a global event decryptor? attache to session and that listen to new sessionId? - // for now decrypt sync - try { - val result = eventDecryptor.decryptEvent(event, "") - event.mxDecryptionResult = OlmDecryptionResult( - payload = result.clearEvent, - senderKey = result.senderCurve25519Key, - keysClaimed = result.claimedEd25519Key?.let { mapOf("ed25519" to it) }, - forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain - ) - } catch (e: MXCryptoError) { - Timber.e("## SAS Failed to decrypt event: ${event.eventId}") - verificationService.onPotentiallyInterestingEventRoomFailToDecrypt(event) - } - } Timber.v("## SAS Verification live observer: received msgId: ${event.eventId} type: ${event.getClearType()}") // Relates to is not encrypted @@ -102,7 +74,6 @@ internal class VerificationMessageProcessor @Inject constructor( if (event.senderId == userId) { // If it's send from me, we need to keep track of Requests or Start // done from another device of mine - if (EventType.MESSAGE == event.getClearType()) { val msgType = event.getClearContent().toModel<MessageContent>()?.msgType if (MessageType.MSGTYPE_VERIFICATION_REQUEST == msgType) { @@ -137,6 +108,8 @@ internal class VerificationMessageProcessor @Inject constructor( transactionsHandledByOtherDevice.remove(it) verificationService.onRoomRequestHandledByOtherDevice(event) } + } else if (EventType.ENCRYPTED == event.getClearType()) { + verificationService.onPotentiallyInterestingEventRoomFailToDecrypt(event) } Timber.v("## SAS Verification ignoring message sent by me: ${event.eventId} type: ${event.getClearType()}") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransport.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransport.kt index c326dd0fc30fa3d147cac81cecd1713063ba8232..c12aea9d52df4c51baab15eceddcc829cb35ea1d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransport.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransport.kt @@ -26,7 +26,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxStat internal interface VerificationTransport { /** - * Sends a message + * Sends a message. */ fun <T> sendToOther(type: String, verificationInfo: VerificationInfo<T>, @@ -53,7 +53,7 @@ internal interface VerificationTransport { onDone: (() -> Unit)?) /** - * Creates an accept message suitable for this transport + * Creates an accept message suitable for this transport. */ fun createAccept(tid: String, keyAgreementProtocol: String, @@ -66,7 +66,7 @@ internal interface VerificationTransport { pubKey: String): VerificationInfoKey /** - * Create start for SAS verification + * Create start for SAS verification. */ fun createStartForSas(fromDevice: String, transactionId: String, @@ -76,7 +76,7 @@ internal interface VerificationTransport { shortAuthenticationStrings: List<String>): VerificationInfoStart /** - * Create start for QR code verification + * Create start for QR code verification. */ fun createStartForQrCode(fromDevice: String, transactionId: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessage.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessage.kt index 325a6f0ba2daef51f2dbc5914a1bce98d31de627..e32828af23850154040aa9db82f8e738153de544 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessage.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessage.kt @@ -15,14 +15,8 @@ */ package org.matrix.android.sdk.internal.crypto.verification -import androidx.lifecycle.Observer -import androidx.work.BackoffPolicy -import androidx.work.Data -import androidx.work.ExistingWorkPolicy -import androidx.work.Operation -import androidx.work.WorkInfo import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoRequest @@ -45,27 +39,28 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageVerification import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_RECIPROCATE import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_SAS -import org.matrix.android.sdk.internal.di.WorkManagerProvider +import org.matrix.android.sdk.internal.crypto.tasks.SendVerificationMessageTask import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory +import org.matrix.android.sdk.internal.task.SemaphoreCoroutineSequencer import org.matrix.android.sdk.internal.util.time.Clock -import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker -import org.matrix.android.sdk.internal.worker.WorkerParamsFactory import timber.log.Timber -import java.util.UUID -import java.util.concurrent.TimeUnit +import java.util.concurrent.Executors internal class VerificationTransportRoomMessage( - private val workManagerProvider: WorkManagerProvider, - private val sessionId: String, + private val sendVerificationMessageTask: SendVerificationMessageTask, private val userId: String, private val userDeviceId: String?, private val roomId: String, private val localEchoEventFactory: LocalEchoEventFactory, private val tx: DefaultVerificationTransaction?, - private val coroutineScope: CoroutineScope, + cryptoCoroutineScope: CoroutineScope, private val clock: Clock, ) : VerificationTransport { + private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + private val verificationSenderScope = CoroutineScope(cryptoCoroutineScope.coroutineContext + dispatcher) + private val sequencer = SemaphoreCoroutineSequencer() + override fun <T> sendToOther(type: String, verificationInfo: VerificationInfo<T>, nextState: VerificationTxState, @@ -79,70 +74,22 @@ internal class VerificationTransportRoomMessage( content = verificationInfo.toEventContent()!! ) - val workerParams = WorkerParamsFactory.toData( - SendVerificationMessageWorker.Params( - sessionId = sessionId, - eventId = event.eventId ?: "" - ) - ) - val enqueueInfo = enqueueSendWork(workerParams) - - // I cannot just listen to the given work request, because when used in a uniqueWork, - // The callback is called while it is still Running ... - -// Futures.addCallback(enqueueInfo.first.result, object : FutureCallback<Operation.State.SUCCESS> { -// override fun onSuccess(result: Operation.State.SUCCESS?) { -// if (onDone != null) { -// onDone() -// } else { -// tx?.state = nextState -// } -// } -// -// override fun onFailure(t: Throwable) { -// Timber.e("## SAS verification [${tx?.transactionId}] failed to send toDevice in state : ${tx?.state}, reason: ${t.localizedMessage}") -// tx?.cancel(onErrorReason) -// } -// }, listenerExecutor) - - val workLiveData = workManagerProvider.workManager - .getWorkInfosForUniqueWorkLiveData(uniqueQueueName()) - - val observer = object : Observer<List<WorkInfo>> { - override fun onChanged(workInfoList: List<WorkInfo>?) { - workInfoList - ?.firstOrNull { it.id == enqueueInfo.second } - ?.let { wInfo -> - when (wInfo.state) { - WorkInfo.State.FAILED -> { - tx?.cancel(onErrorReason) - workLiveData.removeObserver(this) - } - WorkInfo.State.SUCCEEDED -> { - if (SessionSafeCoroutineWorker.hasFailed(wInfo.outputData)) { - Timber.e("## SAS verification [${tx?.transactionId}] failed to send verification message in state : ${tx?.state}") - tx?.cancel(onErrorReason) - } else { - if (onDone != null) { - onDone() - } else { - tx?.state = nextState - } - } - workLiveData.removeObserver(this) - } - else -> { - // nop - } - } - } + verificationSenderScope.launch { + sequencer.post { + try { + val params = SendVerificationMessageTask.Params(event) + sendVerificationMessageTask.executeRetry(params, 5) + // Do I need to update local echo state to sent? + if (onDone != null) { + onDone() + } else { + tx?.state = nextState + } + } catch (failure: Throwable) { + tx?.cancel(onErrorReason) + } } } - - // TODO listen to DB to get synced info - coroutineScope.launch(Dispatchers.Main) { - workLiveData.observeForever(observer) - } } override fun sendVerificationRequest(supportedMethods: List<String>, @@ -173,60 +120,24 @@ internal class VerificationTransportRoomMessage( val content = info.toContent() val event = createEventAndLocalEcho( - localId, - EventType.MESSAGE, - roomId, - content - ) - - val workerParams = WorkerParamsFactory.toData( - SendVerificationMessageWorker.Params( - sessionId = sessionId, - eventId = event.eventId ?: "" - ) + localId = localId, + type = EventType.MESSAGE, + roomId = roomId, + content = content ) - val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder<SendVerificationMessageWorker>() - .setConstraints(WorkManagerProvider.workConstraints) - .setInputData(workerParams) - .setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS) - .build() - - workManagerProvider.workManager - .beginUniqueWork("${roomId}_VerificationWork", ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest) - .enqueue() - - // I cannot just listen to the given work request, because when used in a uniqueWork, - // The callback is called while it is still Running ... - - val workLiveData = workManagerProvider.workManager - .getWorkInfosForUniqueWorkLiveData("${roomId}_VerificationWork") - - val observer = object : Observer<List<WorkInfo>> { - override fun onChanged(workInfoList: List<WorkInfo>?) { - workInfoList - ?.filter { it.state == WorkInfo.State.SUCCEEDED } - ?.firstOrNull { it.id == workRequest.id } - ?.let { wInfo -> - if (SessionSafeCoroutineWorker.hasFailed(wInfo.outputData)) { - callback(null, null) - } else { - val eventId = wInfo.outputData.getString(localId) - if (eventId != null) { - callback(eventId, validInfo) - } else { - callback(null, null) - } - } - workLiveData.removeObserver(this) - } + verificationSenderScope.launch { + val params = SendVerificationMessageTask.Params(event) + sequencer.post { + try { + val eventId = sendVerificationMessageTask.executeRetry(params, 5) + // Do I need to update local echo state to sent? + callback(eventId, validInfo) + } catch (failure: Throwable) { + callback(null, null) + } } } - - // TODO listen to DB to get synced info - coroutineScope.launch(Dispatchers.Main) { - workLiveData.observeForever(observer) - } } override fun cancelTransaction(transactionId: String, otherUserId: String, otherUserDeviceId: String?, code: CancelCode) { @@ -236,13 +147,17 @@ internal class VerificationTransportRoomMessage( roomId = roomId, content = MessageVerificationCancelContent.create(transactionId, code).toContent() ) - val workerParams = WorkerParamsFactory.toData( - SendVerificationMessageWorker.Params( - sessionId = sessionId, - eventId = event.eventId ?: "" - ) - ) - enqueueSendWork(workerParams) + + verificationSenderScope.launch { + sequencer.post { + try { + val params = SendVerificationMessageTask.Params(event) + sendVerificationMessageTask.executeRetry(params, 5) + } catch (failure: Throwable) { + Timber.w(failure, "Failed to cancel verification transaction") + } + } + } } override fun done(transactionId: String, @@ -258,47 +173,21 @@ internal class VerificationTransportRoomMessage( ) ).toContent() ) - val workerParams = WorkerParamsFactory.toData( - SendVerificationMessageWorker.Params( - sessionId = sessionId, - eventId = event.eventId ?: "" - ) - ) - val enqueueInfo = enqueueSendWork(workerParams) - - val workLiveData = workManagerProvider.workManager - .getWorkInfosForUniqueWorkLiveData(uniqueQueueName()) - val observer = object : Observer<List<WorkInfo>> { - override fun onChanged(workInfoList: List<WorkInfo>?) { - workInfoList - ?.filter { it.state == WorkInfo.State.SUCCEEDED } - ?.firstOrNull { it.id == enqueueInfo.second } - ?.let { _ -> - onDone?.invoke() - workLiveData.removeObserver(this) - } + verificationSenderScope.launch { + sequencer.post { + try { + val params = SendVerificationMessageTask.Params(event) + sendVerificationMessageTask.executeRetry(params, 5) + } catch (failure: Throwable) { + Timber.w(failure, "Failed to complete (done) verification") + // should we call onDone? + } finally { + onDone?.invoke() + } } } - - // TODO listen to DB to get synced info - coroutineScope.launch(Dispatchers.Main) { - workLiveData.observeForever(observer) - } } - private fun enqueueSendWork(workerParams: Data): Pair<Operation, UUID> { - val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder<SendVerificationMessageWorker>() - .setConstraints(WorkManagerProvider.workConstraints) - .setInputData(workerParams) - .setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS) - .build() - return workManagerProvider.workManager - .beginUniqueWork(uniqueQueueName(), ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest) - .enqueue() to workRequest.id - } - - private fun uniqueQueueName() = "${roomId}_VerificationWork" - override fun createAccept(tid: String, keyAgreementProtocol: String, hash: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessageFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessageFactory.kt index b1b7ad7a98eb34cbf85ff214e5cef255d271ec2b..345948e6087b94fab6e3df857e57354a10962048 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessageFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessageFactory.kt @@ -16,39 +16,35 @@ package org.matrix.android.sdk.internal.crypto.verification +import kotlinx.coroutines.CoroutineScope +import org.matrix.android.sdk.internal.crypto.tasks.SendVerificationMessageTask import org.matrix.android.sdk.internal.di.DeviceId -import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.UserId -import org.matrix.android.sdk.internal.di.WorkManagerProvider import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory -import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.util.time.Clock import javax.inject.Inject internal class VerificationTransportRoomMessageFactory @Inject constructor( - private val workManagerProvider: WorkManagerProvider, - @SessionId - private val sessionId: String, + private val sendVerificationMessageTask: SendVerificationMessageTask, @UserId private val userId: String, @DeviceId private val deviceId: String?, private val localEchoEventFactory: LocalEchoEventFactory, - private val taskExecutor: TaskExecutor, + private val cryptoCoroutineScope: CoroutineScope, private val clock: Clock, ) { fun createTransport(roomId: String, tx: DefaultVerificationTransaction?): VerificationTransportRoomMessage { return VerificationTransportRoomMessage( - workManagerProvider, - sessionId, - userId, - deviceId, - roomId, - localEchoEventFactory, - tx, - taskExecutor.executorScope, - clock + sendVerificationMessageTask = sendVerificationMessageTask, + userId = userId, + userDeviceId = deviceId, + roomId = roomId, + localEchoEventFactory = localEchoEventFactory, + tx = tx, + cryptoCoroutineScope = cryptoCoroutineScope, + clock = clock, ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt index 06f0b367980a26838f0d853b58028bb5b352911b..b1ad4d87b6a56acec89926cb826b7692ea48e96d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt @@ -22,8 +22,8 @@ import org.matrix.android.sdk.api.session.crypto.verification.QrCodeVerification import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.util.fromBase64 -import org.matrix.android.sdk.internal.crypto.IncomingGossipingRequestManager -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager +import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager +import org.matrix.android.sdk.internal.crypto.SecretShareManager import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64Safe import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore @@ -37,8 +37,8 @@ internal class DefaultQrCodeVerificationTransaction( override val otherUserId: String, override var otherDeviceId: String?, private val crossSigningService: CrossSigningService, - outgoingGossipingRequestManager: OutgoingGossipingRequestManager, - incomingGossipingRequestManager: IncomingGossipingRequestManager, + outgoingKeyRequestManager: OutgoingKeyRequestManager, + secretShareManager: SecretShareManager, private val cryptoStore: IMXCryptoStore, // Not null only if other user is able to scan QR code private val qrCodeData: QrCodeData?, @@ -48,13 +48,14 @@ internal class DefaultQrCodeVerificationTransaction( ) : DefaultVerificationTransaction( setDeviceVerificationAction, crossSigningService, - outgoingGossipingRequestManager, - incomingGossipingRequestManager, + outgoingKeyRequestManager, + secretShareManager, userId, transactionId, otherUserId, otherDeviceId, - isIncoming), + isIncoming +), QrCodeVerificationTransaction { override val qrCodeText: String? diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/QrCodeData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/QrCodeData.kt index 0ac57db9bc779bc11b5bf9267b94f0856c7fb0a6..f308807e0432bd845fb2475404d72ec303b6227d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/QrCodeData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/QrCodeData.kt @@ -21,34 +21,34 @@ package org.matrix.android.sdk.internal.crypto.verification.qrcode */ internal sealed class QrCodeData( /** - * the event ID or transaction_id of the associated verification + * the event ID or transaction_id of the associated verification. */ open val transactionId: String, /** - * First key (32 bytes, in base64 no padding) + * First key (32 bytes, in base64 no padding). */ val firstKey: String, /** - * Second key (32 bytes, in base64 no padding) + * Second key (32 bytes, in base64 no padding). */ val secondKey: String, /** - * a random shared secret (in base64 no padding) + * a random shared secret (in base64 no padding). */ open val sharedSecret: String ) { /** - * verifying another user with cross-signing - * QR code verification mode: 0x00 + * Verifying another user with cross-signing + * QR code verification mode: 0x00. */ data class VerifyingAnotherUser( override val transactionId: String, /** - * the user's own master cross-signing public key + * the user's own master cross-signing public key. */ val userMasterCrossSigningPublicKey: String, /** - * what the device thinks the other user's master cross-signing key is + * what the device thinks the other user's master cross-signing key is. */ val otherUserMasterCrossSigningPublicKey: String, override val sharedSecret: String @@ -56,20 +56,21 @@ internal sealed class QrCodeData( transactionId, userMasterCrossSigningPublicKey, otherUserMasterCrossSigningPublicKey, - sharedSecret) + sharedSecret + ) /** * self-verifying in which the current device does trust the master key - * QR code verification mode: 0x01 + * QR code verification mode: 0x01. */ data class SelfVerifyingMasterKeyTrusted( override val transactionId: String, /** - * the user's own master cross-signing public key + * the user's own master cross-signing public key. */ val userMasterCrossSigningPublicKey: String, /** - * what the device thinks the other device's device key is + * what the device thinks the other device's device key is. */ val otherDeviceKey: String, override val sharedSecret: String @@ -77,20 +78,21 @@ internal sealed class QrCodeData( transactionId, userMasterCrossSigningPublicKey, otherDeviceKey, - sharedSecret) + sharedSecret + ) /** * self-verifying in which the current device does not yet trust the master key - * QR code verification mode: 0x02 + * QR code verification mode: 0x02. */ data class SelfVerifyingMasterKeyNotTrusted( override val transactionId: String, /** - * the current device's device key + * the current device's device key. */ val deviceKey: String, /** - * what the device thinks the user's master cross-signing key is + * what the device thinks the user's master cross-signing key is. */ val userMasterCrossSigningPublicKey: String, override val sharedSecret: String @@ -98,5 +100,6 @@ internal sealed class QrCodeData( transactionId, deviceKey, userMasterCrossSigningPublicKey, - sharedSecret) + sharedSecret + ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmKeysUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmKeysUtils.kt index 7c622146d34682e41469f77227160ed98b42dd9e..392c1a7185a98df3ac69dc0af04faae422df5570 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmKeysUtils.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmKeysUtils.kt @@ -53,7 +53,7 @@ internal class RealmKeysUtils @Inject constructor(context: Context, } /** - * Check if there is already a key for this alias + * Check if there is already a key for this alias. */ private fun hasKeyForDatabase(alias: String): Boolean { return sharedPreferences.contains("${ENCRYPTED_KEY_PREFIX}_$alias") @@ -77,8 +77,8 @@ internal class RealmKeysUtils @Inject constructor(context: Context, } /** - * Retrieves the key for this database - * throws if something goes wrong + * Retrieves the key for this database. + * Throws if something goes wrong. */ private fun extractKeyForDatabase(alias: String): ByteArray { val encryptedB64 = sharedPreferences.getString("${ENCRYPTED_KEY_PREFIX}_$alias", null) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index 04a6e83ea17723fee7b5a6ff7aa8efaf9f12e31a..55bccfd1ec69775d60c2d951cab7fe37a5dad786 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -54,8 +54,8 @@ internal class RealmSessionStoreMigration @Inject constructor( private val normalizer: Normalizer ) : RealmMigration { /** - * Forces all RealmSessionStoreMigration instances to be equal - * Avoids Realm throwing when multiple instances of the migration are set + * Forces all RealmSessionStoreMigration instances to be equal. + * Avoids Realm throwing when multiple instances of the migration are set. */ override fun equals(other: Any?) = other is RealmSessionStoreMigration override fun hashCode() = 1000 diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt index 4fdedabd705dc5223aef54e91c19c00d0a721a71..caaf6b81100ce609bf37c09213522768f77db7b8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt @@ -166,7 +166,7 @@ private fun ChunkEntity.addTimelineEventFromMerge(realm: Realm, timelineEventEnt } /** - * Upon copy of the timeline events we should update the latestMessage TimelineEventEntity with the new one + * Upon copy of the timeline events we should update the latestMessage TimelineEventEntity with the new one. */ private fun handleThreadSummary(realm: Realm, oldEventId: String, newTimelineEventEntity: TimelineEventEntity) { EventEntity diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadEventsHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadEventsHelper.kt index 04cf5b78af79e8dc4d3994782ac11768d6a55580..db3647c3fae24312b899091329e4a7c4b7aea074 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadEventsHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadEventsHelper.kt @@ -83,7 +83,7 @@ internal fun EventEntity.findRootThreadEvent(): EventEntity? = } /** - * Mark or update the current event a root thread event + * Mark or update the current event a root thread event. */ internal fun EventEntity.markEventAsRoot( inThreadMessages: Int, @@ -94,8 +94,8 @@ internal fun EventEntity.markEventAsRoot( } /** - * Count the number of threads for the provided root thread eventId, and finds the latest event message - * note: Redactions are handled by RedactionEventProcessor + * Count the number of threads for the provided root thread eventId, and finds the latest event message. + * Note: Redactions are handled by RedactionEventProcessor. * @param rootThreadEventId The root eventId that will find the number of threads * @return A ThreadSummary containing the counted threads and the latest event message */ @@ -150,7 +150,7 @@ internal fun countInThreadMessages(realm: Realm, roomId: String, rootThreadEvent }.size /** - * Mapping string to UnsignedData using Moshi + * Mapping string to UnsignedData using Moshi. */ private fun String.toUnsignedData(): UnsignedData? = try { @@ -162,7 +162,7 @@ private fun String.toUnsignedData(): UnsignedData? = /** * Lets compare them in case user is moving forward in the timeline and we cannot know the - * exact chunk sequence while currentChunk is not yet committed in the DB + * exact chunk sequence while currentChunk is not yet committed in the DB. */ private fun findMostRecentEvent(result: TimelineEventEntity, currentChunkLatestEvent: TimelineEventEntity?): TimelineEventEntity { currentChunkLatestEvent ?: return result @@ -175,7 +175,7 @@ private fun findMostRecentEvent(result: TimelineEventEntity, currentChunkLatestE } /** - * Find the latest event of the current chunk + * Find the latest event of the current chunk. */ private fun findLatestSortedChunkEvent(chunk: ChunkEntity, rootThreadEventId: String): TimelineEventEntity? = chunk.timelineEvents.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.DESCENDING)?.firstOrNull { @@ -183,7 +183,7 @@ private fun findLatestSortedChunkEvent(chunk: ChunkEntity, rootThreadEventId: St } /** - * Find all TimelineEventEntity that are root threads for the specified room + * Find all TimelineEventEntity that are root threads for the specified room. * @param roomId The room that all stored root threads will be returned */ internal fun TimelineEventEntity.Companion.findAllThreadsForRoomId(realm: Realm, roomId: String): RealmQuery<TimelineEventEntity> = @@ -194,7 +194,7 @@ internal fun TimelineEventEntity.Companion.findAllThreadsForRoomId(realm: Realm, .sort("${TimelineEventEntityFields.ROOT.THREAD_SUMMARY_LATEST_MESSAGE}.${TimelineEventEntityFields.ROOT.ORIGIN_SERVER_TS}", Sort.DESCENDING) /** - * Map each root thread TimelineEvent with the equivalent decrypted text edition/replacement + * Map each root thread TimelineEvent with the equivalent decrypted text edition/replacement. */ internal fun List<TimelineEvent>.mapEventsWithEdition(realm: Realm, roomId: String): List<TimelineEvent> = this.map { @@ -207,15 +207,17 @@ internal fun List<TimelineEvent>.mapEventsWithEdition(realm: Realm, roomId: Stri ?.eventId ?.let { editedEventId -> TimelineEventEntity.where(realm, roomId, eventId = editedEventId).findFirst()?.let { editedEvent -> - it.root.threadDetails = it.root.threadDetails?.copy(lastRootThreadEdition = editedEvent.root?.asDomain()?.getDecryptedTextSummary() - ?: "(edited)") + it.root.threadDetails = it.root.threadDetails?.copy( + lastRootThreadEdition = editedEvent.root?.asDomain()?.getDecryptedTextSummary() + ?: "(edited)" + ) it } ?: it } ?: it } /** - * Returns a list of all the marked unread threads that exists for the specified room + * Returns a list of all the marked unread threads that exists for the specified room. * @param roomId The roomId that the user is currently in */ internal fun TimelineEventEntity.Companion.findAllLocalThreadNotificationsForRoomId(realm: Realm, roomId: String): RealmQuery<TimelineEventEntity> = @@ -229,7 +231,7 @@ internal fun TimelineEventEntity.Companion.findAllLocalThreadNotificationsForRoo .endGroup() /** - * Returns whether or not the given user is participating in a current thread + * Returns whether or not the given user is participating in a current thread. * @param roomId the room that the thread exists * @param rootThreadEventId the thread that the search will be done * @param senderId the user that will try to find participation @@ -244,7 +246,7 @@ internal fun TimelineEventEntity.Companion.isUserParticipatingInThread(realm: Re ?: false /** - * Returns whether or not the given user is mentioned in a current thread + * Returns whether or not the given user is mentioned in a current thread. * @param roomId the room that the thread exists * @param rootThreadEventId the thread that the search will be done * @param userId the user that will try to find if there is a mention @@ -260,7 +262,7 @@ internal fun TimelineEventEntity.Companion.isUserMentionedInThread(realm: Realm, ?: false /** - * Find the read receipt for the current user + * Find the read receipt for the current user. */ internal fun findMyReadReceipt(realm: Realm, roomId: String, userId: String): String? = ReadReceiptEntity.where(realm, roomId = roomId, userId = userId) @@ -268,7 +270,7 @@ internal fun findMyReadReceipt(realm: Realm, roomId: String, userId: String): St ?.eventId /** - * Returns whether or not the user is mentioned in the event + * Returns whether or not the user is mentioned in the event. */ internal fun isUserMentioned(currentUserId: String, timelineEventEntity: TimelineEventEntity?): Boolean { return timelineEventEntity?.root?.asDomain()?.isUserMentioned(currentUserId) == true @@ -341,7 +343,8 @@ internal fun updateNotificationsNew(roomId: String, realm: Realm, currentUserId: realm = realm, roomId = roomId, rootThreadEventId = eventId, - senderId = currentUserId) + senderId = currentUserId + ) val rootThreadEventEntity = EventEntity.where(realm, eventId).findFirst() if (isUserParticipating) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt index d052a7dea497660a8dd83bb7ff9a530d4bf44351..3bf574c207db20f12d2949e2398426834e39b704 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt @@ -65,7 +65,7 @@ internal fun ThreadSummaryEntity.updateThreadSummary( } /** - * Updates the root thread event properties + * Updates the root thread event properties. */ internal fun ThreadSummaryEntity.updateThreadSummaryRootEvent( rootThreadEventEntity: EventEntity, @@ -84,7 +84,7 @@ internal fun ThreadSummaryEntity.updateThreadSummaryRootEvent( } /** - * Updates the latest thread event properties + * Updates the latest thread event properties. */ internal fun ThreadSummaryEntity.updateThreadSummaryLatestEvent( latestThreadEventEntity: EventEntity?, @@ -241,7 +241,7 @@ private fun decryptIfNeeded(cryptoService: CryptoService?, eventEntity: EventEnt } /** - * Request decryption + * Request decryption. */ private fun requestDecryption(eventDecryptor: TimelineEventDecryptor?, event: Event?) { eventDecryptor ?: return @@ -255,7 +255,7 @@ private fun requestDecryption(eventDecryptor: TimelineEventDecryptor?, event: Ev } /** - * If we don't have any new state on this user, get it from db + * If we don't have any new state on this user, get it from db. */ private fun HashMap<String, RoomMemberContent?>.addSenderState(realm: Realm, roomId: String, senderId: String) { getOrPut(senderId) { @@ -267,7 +267,7 @@ private fun HashMap<String, RoomMemberContent?>.addSenderState(realm: Realm, roo } /** - * Create an EventEntity for the root thread event or get an existing one + * Create an EventEntity for the root thread event or get an existing one. */ private fun createEventEntity(realm: Realm, roomId: String, event: Event, currentTimeMillis: Long): EventEntity { val ageLocalTs = event.unsignedData?.age?.let { currentTimeMillis - it } @@ -294,15 +294,15 @@ private fun createLatestEventEntity( } /** - * Returned the latest event message, if any + * Returned the latest event message, if any. */ private fun getLatestEvent(rootThreadEvent: Event): Event? { return rootThreadEvent.unsignedData?.relations?.latestThread?.event } /** - * Find all ThreadSummaryEntity for the specified roomId, sorted by origin server - * note: Sorting cannot be provided by server, so we have to use that unstable property + * Find all ThreadSummaryEntity for the specified roomId, sorted by origin server. + * note: Sorting cannot be provided by server, so we have to use that unstable property. * @param roomId The id of the room */ internal fun ThreadSummaryEntity.Companion.findAllThreadsForRoomId(realm: Realm, roomId: String): RealmQuery<ThreadSummaryEntity> = @@ -311,7 +311,7 @@ internal fun ThreadSummaryEntity.Companion.findAllThreadsForRoomId(realm: Realm, .sort(ThreadSummaryEntityFields.LATEST_THREAD_EVENT_ENTITY.ORIGIN_SERVER_TS, Sort.DESCENDING) /** - * Enhance each [ThreadSummary] root and latest event with the equivalent decrypted text edition/replacement + * Enhance each [ThreadSummary] root and latest event with the equivalent decrypted text edition/replacement. */ internal fun List<ThreadSummary>.enhanceWithEditions(realm: Realm, roomId: String): List<ThreadSummary> = this.map { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/DraftMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/DraftMapper.kt index 737c4b4608d1f206fc30c6d3fbfc5ede77cbcb5f..a00a2a8ee111d189741323704b23a465d0d2abd7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/DraftMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/DraftMapper.kt @@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.session.room.send.UserDraft import org.matrix.android.sdk.internal.database.model.DraftEntity /** - * DraftEntity <-> UserDraft + * DraftEntity <-> UserDraft. */ internal object DraftMapper { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt index 2e33988a22b853f941add399e3da3464928e2417..20af43530c4821a11892dc1fd8d37c8dbb1a5da3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt @@ -28,7 +28,7 @@ import org.matrix.android.sdk.internal.session.homeserver.RoomVersions import org.matrix.android.sdk.internal.session.room.version.DefaultRoomVersionService /** - * HomeServerCapabilitiesEntity -> HomeSeverCapabilities + * HomeServerCapabilitiesEntity -> HomeSeverCapabilities. */ internal object HomeServerCapabilitiesMapper { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo026.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo026.kt index 35a6135ba203aac3f2f1a7e75543821eb9ea49db..5bab93cb04fee37ac127f93f85ff3b04e3a15866 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo026.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo026.kt @@ -29,7 +29,7 @@ import org.matrix.android.sdk.internal.util.database.RealmMigrator /** * Migrating to: * Live thread list: using enhanced /messages api MSC3440 - * Live thread timeline: using /relations api + * Live thread timeline: using /relations api. */ internal class MigrateSessionTo026(realm: DynamicRealm) : RealmMigrator(realm, 26) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo027.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo027.kt index fdd8c46d027ae4b4f6654e6d5799df1d3c7e115e..40189c0f466aecc10e3d3c9d2476ec01f346ba87 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo027.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo027.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.internal.util.database.RealmMigrator /** * Migrating to: - * Live location sharing aggregated summary + * Live location sharing aggregated summary. */ internal class MigrateSessionTo027(realm: DynamicRealm) : RealmMigrator(realm, 27) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo028.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo028.kt index 1d0c638d7b8fc902a4ea192aebbb6dcc6b8e6b98..ed9b90d28886a7d62e9ad5290a62d1407f36c006 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo028.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo028.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.util.database.RealmMigrator /** * Migrating to: - * Live location sharing aggregated summary + * Live location sharing aggregated summary. */ internal class MigrateSessionTo028(realm: DynamicRealm) : RealmMigrator(realm, 28) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/ChunkEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/ChunkEntity.kt index 822bc1bd8f45c9e5f0326a61371b2e073af4354d..8399d82d5d75821e55d769dd8c8d06baca2be775 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/ChunkEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/ChunkEntity.kt @@ -69,7 +69,7 @@ internal fun ChunkEntity.deleteOnCascade( } /** - * Delete the chunk along with the thread events that were temporarily created + * Delete the chunk along with the thread events that were temporarily created. */ internal fun ChunkEntity.deleteAndClearThreadEvents() { assertIsManaged() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EditAggregatedSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EditAggregatedSummaryEntity.kt index 0ed927a6b8618c64cb9655956e395e5cd2be9eb9..61acd51dd46730a9e45d6a8f1bf8b3180dc7757a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EditAggregatedSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EditAggregatedSummaryEntity.kt @@ -20,7 +20,7 @@ import io.realm.RealmObject import io.realm.annotations.RealmClass /** - * Keep all the editions of a message + * Keep all the editions of a message. */ internal open class EditAggregatedSummaryEntity( // The list of the editions used to build the summary (might be out of sync if chunked received from message chunk) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventAnnotationsSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventAnnotationsSummaryEntity.kt index c3abd8b028b92a211607f5bb116cd15332835c16..645998d0c029ce5b5a0ba58aaa5e95bc67efea4b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventAnnotationsSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventAnnotationsSummaryEntity.kt @@ -33,7 +33,7 @@ internal open class EventAnnotationsSummaryEntity( ) : RealmObject() { /** - * Cleanup undesired editions, done by users different from the originalEventSender + * Cleanup undesired editions, done by users different from the originalEventSender. */ fun cleanUp(originalEventSenderId: String?) { originalEventSenderId ?: return diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/FilterEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/FilterEntity.kt index 96014d29add8c720a7a6b3b98cccbe5b95a08d85..e138e305c7e6a12430b2963e9b7662a66c57f302 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/FilterEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/FilterEntity.kt @@ -19,8 +19,8 @@ package org.matrix.android.sdk.internal.database.model import io.realm.RealmObject /** - * Contain a map between Json filter string and filterId (from Homeserver) - * Currently there is only one object in this table + * Contain a map between Json filter string and filterId (from Homeserver). + * Currently there is only one object in this table. */ internal open class FilterEntity( // The serialized FilterBody diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PendingThreePidEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PendingThreePidEntity.kt index 98c38c8969fa300f94c7553d55b54e69ced8a1fa..bcf64e0da8f89f0bd9841856a73d5aab8944aa8d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PendingThreePidEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PendingThreePidEntity.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.database.model import io.realm.RealmObject /** - * This class is used to store pending threePid data, when user wants to add a threePid to his account + * This class is used to store pending threePid data, when user wants to add a threePid to his account. */ internal open class PendingThreePidEntity( var email: String? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PollResponseAggregatedSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PollResponseAggregatedSummaryEntity.kt index 0000a558ac99349bbe682843f5489b8be273bb8e..d759bd3cd930fe5b2b3b649aba4cb419cd3ec3e4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PollResponseAggregatedSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PollResponseAggregatedSummaryEntity.kt @@ -19,7 +19,7 @@ import io.realm.RealmList import io.realm.RealmObject /** - * Keep the latest state of a poll + * Keep the latest state of a poll. */ internal open class PollResponseAggregatedSummaryEntity( // For now we persist this a JSON for greater flexibility diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt index 9a92b145101f0da1adf7a83c37447dea783b8c64..890c2300f8bd52852e64b439a424caa5353399d9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt @@ -22,9 +22,10 @@ import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntit import org.matrix.android.sdk.internal.database.model.threads.ThreadSummaryEntity /** - * Realm module for Session + * Realm module for Session. */ -@RealmModule(library = true, +@RealmModule( + library = true, classes = [ ChunkEntity::class, EventEntity::class, @@ -71,5 +72,6 @@ import org.matrix.android.sdk.internal.database.model.threads.ThreadSummaryEntit SpaceParentSummaryEntity::class, UserPresenceEntity::class, ThreadSummaryEntity::class - ]) + ] +) internal class SessionRealmModule diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/UserDraftsEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/UserDraftsEntity.kt index 06a6349350454aaf83072cf77f62a624721d10d2..2c778f979762a31ca76788697bf1ff14a9d83d0f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/UserDraftsEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/UserDraftsEntity.kt @@ -22,7 +22,7 @@ import io.realm.RealmResults import io.realm.annotations.LinkingObjects /** - * Create a specific table to be able to do direct query on it and keep the draft ordered + * Create a specific table to be able to do direct query on it and keep the draft ordered. */ internal open class UserDraftsEntity(var userDrafts: RealmList<DraftEntity> = RealmList() ) : RealmObject() { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt index 1376839f9375d0ce7ee5c1507e552492d4fd07f6..4d0d2c5c64303cbbfc676c3ce419b3adcdc9e739 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt @@ -36,7 +36,7 @@ internal open class LiveLocationShareAggregatedSummaryEntity( var endOfLiveTimestampMillis: Long? = null, /** - * For now we persist this as a JSON for greater flexibility + * For now we persist this as a JSON for greater flexibility. * @see [org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent] */ var lastLocationContent: String? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/FilterEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/FilterEntityQueries.kt index 3968169e08323aaeee6aebf867b5cc477eeaed26..903282bac4598c9e1f3269d364ccc772e4f78dc9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/FilterEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/FilterEntityQueries.kt @@ -23,14 +23,14 @@ import org.matrix.android.sdk.internal.database.model.FilterEntity import org.matrix.android.sdk.internal.session.filter.FilterFactory /** - * Get the current filter + * Get the current filter. */ internal fun FilterEntity.Companion.get(realm: Realm): FilterEntity? { return realm.where<FilterEntity>().findFirst() } /** - * Get the current filter, create one if it does not exist + * Get the current filter, create one if it does not exist. */ internal fun FilterEntity.Companion.getOrCreate(realm: Realm): FilterEntity { return get(realm) ?: realm.createObject<FilterEntity>() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/HomeServerCapabilitiesQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/HomeServerCapabilitiesQueries.kt index 4f8ac20e9446b8a057fd70d152c46059c6304a41..2cb6faafb7689f070f41c2a108b0103876edfc22 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/HomeServerCapabilitiesQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/HomeServerCapabilitiesQueries.kt @@ -22,14 +22,14 @@ import io.realm.kotlin.where import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntity /** - * Get the current HomeServerCapabilitiesEntity, return null if it does not exist + * Get the current HomeServerCapabilitiesEntity, return null if it does not exist. */ internal fun HomeServerCapabilitiesEntity.Companion.get(realm: Realm): HomeServerCapabilitiesEntity? { return realm.where<HomeServerCapabilitiesEntity>().findFirst() } /** - * Get the current HomeServerCapabilitiesEntity, create one if it does not exist + * Get the current HomeServerCapabilitiesEntity, create one if it does not exist. */ internal fun HomeServerCapabilitiesEntity.Companion.getOrCreate(realm: Realm): HomeServerCapabilitiesEntity { return get(realm) ?: realm.createObject() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/PreviewUrlCacheEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/PreviewUrlCacheEntityQueries.kt index a139c174394b7e3e430f89443efb7020898e730d..32ea7a1ba6d3ecb648484fa13af6440916cd2a14 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/PreviewUrlCacheEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/PreviewUrlCacheEntityQueries.kt @@ -23,7 +23,7 @@ import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntity import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntityFields /** - * Get the current PreviewUrlCacheEntity, return null if it does not exist + * Get the current PreviewUrlCacheEntity, return null if it does not exist. */ internal fun PreviewUrlCacheEntity.Companion.get(realm: Realm, url: String): PreviewUrlCacheEntity? { return realm.where<PreviewUrlCacheEntity>() @@ -32,7 +32,7 @@ internal fun PreviewUrlCacheEntity.Companion.get(realm: Realm, url: String): Pre } /** - * Get the current PreviewUrlCacheEntity, create one if it does not exist + * Get the current PreviewUrlCacheEntity, create one if it does not exist. */ internal fun PreviewUrlCacheEntity.Companion.getOrCreate(realm: Realm, url: String): PreviewUrlCacheEntity { return get(realm, url) ?: realm.createObject(url) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/RawCacheQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/RawCacheQueries.kt index ac5e29e1de8e170e09712afd105904ab202c8b08..634c3b26f26e572df7e9d8010912f531581979c8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/RawCacheQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/RawCacheQueries.kt @@ -23,7 +23,7 @@ import org.matrix.android.sdk.internal.database.model.RawCacheEntity import org.matrix.android.sdk.internal.database.model.RawCacheEntityFields /** - * Get the current RawCacheEntity, return null if it does not exist + * Get the current RawCacheEntity, return null if it does not exist. */ internal fun RawCacheEntity.Companion.get(realm: Realm, url: String): RawCacheEntity? { return realm.where<RawCacheEntity>() @@ -32,7 +32,7 @@ internal fun RawCacheEntity.Companion.get(realm: Realm, url: String): RawCacheEn } /** - * Get the current RawCacheEntity, create one if it does not exist + * Get the current RawCacheEntity, create one if it does not exist. */ internal fun RawCacheEntity.Companion.getOrCreate(realm: Realm, url: String): RawCacheEntity { return get(realm, url) ?: realm.createObject(url) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt index 6c587dfcae8381743c97383a8b7fefd64ea0115e..1a832a29bbbca135aa680e7b7e3d99a925d27266 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt @@ -61,7 +61,7 @@ private fun TimelineEventEntity.isBeforeLatestReadReceipt(realm: Realm, roomId: /** * Missing events can be caused by the latest timeline chunk no longer contain an older event or - * by fast lane eagerly displaying events before the database has finished updating + * by fast lane eagerly displaying events before the database has finished updating. */ private fun hasReadMissingEvent(realm: Realm, latestChunkEntity: ChunkEntity, roomId: String, userId: String, eventId: String): Boolean { return realm.doesEventExistInChunkHistory(eventId) && realm.hasReadReceiptInLatestChunk(latestChunkEntity, roomId, userId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventEntityQueries.kt index 215ab34f95438a7c697f5b7f48274e4e4920bdb0..1654a33806dee20f2bf1f4bfa8c342f3fdd457b5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventEntityQueries.kt @@ -143,7 +143,7 @@ internal fun RealmQuery<TimelineEventEntity>.filterSendStates(sendStates: List<S } /** - * Find all TimelineEventEntity items where sender is in senderIds collection, excluding state events + * Find all TimelineEventEntity items where sender is in senderIds collection, excluding state events. */ internal fun TimelineEventEntity.Companion.findAllFrom(realm: Realm, senderIds: Collection<String>): RealmResults<TimelineEventEntity> { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventFilter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventFilter.kt index a7317506a0aafbf7e3d05eafb0f2dd1f365d85a0..7a65623b76fad182f58a02385462ff33a008dacc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventFilter.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventFilter.kt @@ -17,11 +17,11 @@ package org.matrix.android.sdk.internal.database.query /** - * Query strings used to filter the timeline events regarding the Json raw string of the Event + * Query strings used to filter the timeline events regarding the Json raw string of the Event. */ internal object TimelineEventFilter { /** - * To apply to Event.content + * To apply to Event.content. */ internal object Content { internal const val EDIT = """{*"m.relates_to"*"rel_type":*"m.replace"*}""" @@ -30,14 +30,14 @@ internal object TimelineEventFilter { } /** - * To apply to Event.decryptionResultJson + * To apply to Event.decryptionResultJson. */ internal object DecryptedContent { internal const val URL = """{*"file":*"url":*}""" } /** - * To apply to Event.unsigned + * To apply to Event.unsigned. */ internal object Unsigned { internal const val REDACTED = """{*"redacted_because":*}""" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt index 103e84dea6c91d7b5ff6cb1ff85093a6d600f44e..dc20549eb3e7da3aed0e8623596ea6a956045614 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt @@ -25,7 +25,7 @@ internal class RealmDebugTools( private val realmConfiguration: RealmConfiguration ) { /** - * Log info about the DB + * Log info about the DB. */ fun logInfo(baseName: String) { buildString { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixComponent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixComponent.kt index 2fad2d8e786153b3c9704fe686b26c91aa9005d8..dbc6aac6b59a329f0685b36880d268217d5a178a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixComponent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixComponent.kt @@ -43,15 +43,17 @@ import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory import org.matrix.olm.OlmManager import java.io.File -@Component(modules = [ - MatrixModule::class, - NetworkModule::class, - AuthModule::class, - RawModule::class, - SettingsModule::class, - SystemModule::class, - NoOpTestModule::class -]) +@Component( + modules = [ + MatrixModule::class, + NetworkModule::class, + AuthModule::class, + RawModule::class, + SettingsModule::class, + SystemModule::class, + NoOpTestModule::class + ] +) @MatrixScope internal interface MatrixComponent { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt index 9cab307c6153638cffcb76e84279b5346cc71a78..49713a1d7f3502f83782f3193e81c8b9c10c7f62 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt @@ -36,7 +36,8 @@ internal object MatrixModule { @Provides @MatrixScope fun providesMatrixCoroutineDispatchers(): MatrixCoroutineDispatchers { - return MatrixCoroutineDispatchers(io = Dispatchers.IO, + return MatrixCoroutineDispatchers( + io = Dispatchers.IO, computation = Dispatchers.Default, main = Dispatchers.Main, crypto = createBackgroundHandler("Crypto_Thread").asCoroutineDispatcher(), diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixScope.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixScope.kt index b027d47144190c1c465b81f56348de422318bb6d..21e324c05f1909cc3eb636091587335a39f731e2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixScope.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixScope.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.di import javax.inject.Scope /** - * Use the annotation @MatrixScope to annotate classes we want the SDK to instantiate only once + * Use the annotation @MatrixScope to annotate classes we want the SDK to instantiate only once. */ @Scope @MustBeDocumented diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MoshiProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MoshiProvider.kt index 10b0d4fb13136029292bf774ce30f6789cdcaa07..8f007f227c27e6232b41e7c125811933a403216c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MoshiProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MoshiProvider.kt @@ -46,17 +46,18 @@ internal object MoshiProvider { .add(TlsVersionMoshiAdapter()) // Use addLast here so we can inject a SplitLazyRoomSyncJsonAdapter later to override the default parsing. .addLast(DefaultLazyRoomSyncEphemeralJsonAdapter()) - .add(RuntimeJsonAdapterFactory.of(MessageContent::class.java, "msgtype", MessageDefaultContent::class.java) - .registerSubtype(MessageTextContent::class.java, MessageType.MSGTYPE_TEXT) - .registerSubtype(MessageNoticeContent::class.java, MessageType.MSGTYPE_NOTICE) - .registerSubtype(MessageEmoteContent::class.java, MessageType.MSGTYPE_EMOTE) - .registerSubtype(MessageAudioContent::class.java, MessageType.MSGTYPE_AUDIO) - .registerSubtype(MessageImageContent::class.java, MessageType.MSGTYPE_IMAGE) - .registerSubtype(MessageVideoContent::class.java, MessageType.MSGTYPE_VIDEO) - .registerSubtype(MessageLocationContent::class.java, MessageType.MSGTYPE_LOCATION) - .registerSubtype(MessageFileContent::class.java, MessageType.MSGTYPE_FILE) - .registerSubtype(MessageVerificationRequestContent::class.java, MessageType.MSGTYPE_VERIFICATION_REQUEST) - .registerSubtype(MessagePollResponseContent::class.java, MessageType.MSGTYPE_POLL_RESPONSE) + .add( + RuntimeJsonAdapterFactory.of(MessageContent::class.java, "msgtype", MessageDefaultContent::class.java) + .registerSubtype(MessageTextContent::class.java, MessageType.MSGTYPE_TEXT) + .registerSubtype(MessageNoticeContent::class.java, MessageType.MSGTYPE_NOTICE) + .registerSubtype(MessageEmoteContent::class.java, MessageType.MSGTYPE_EMOTE) + .registerSubtype(MessageAudioContent::class.java, MessageType.MSGTYPE_AUDIO) + .registerSubtype(MessageImageContent::class.java, MessageType.MSGTYPE_IMAGE) + .registerSubtype(MessageVideoContent::class.java, MessageType.MSGTYPE_VIDEO) + .registerSubtype(MessageLocationContent::class.java, MessageType.MSGTYPE_LOCATION) + .registerSubtype(MessageFileContent::class.java, MessageType.MSGTYPE_FILE) + .registerSubtype(MessageVerificationRequestContent::class.java, MessageType.MSGTYPE_VERIFICATION_REQUEST) + .registerSubtype(MessagePollResponseContent::class.java, MessageType.MSGTYPE_POLL_RESPONSE) ) .add(SerializeNulls.JSON_ADAPTER_FACTORY) .build() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/StringQualifiers.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/StringQualifiers.kt index d74a8dce570ac5c522cdf682565fe6eb921dd10e..05ba6e408c58576ebbb3dbdf097dcda60d466908 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/StringQualifiers.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/StringQualifiers.kt @@ -19,28 +19,28 @@ package org.matrix.android.sdk.internal.di import javax.inject.Qualifier /** - * Used to inject the userId + * Used to inject the userId. */ @Qualifier @Retention(AnnotationRetention.RUNTIME) internal annotation class UserId /** - * Used to inject the deviceId + * Used to inject the deviceId. */ @Qualifier @Retention(AnnotationRetention.RUNTIME) internal annotation class DeviceId /** - * Used to inject the md5 of the userId + * Used to inject the md5 of the userId. */ @Qualifier @Retention(AnnotationRetention.RUNTIME) internal annotation class UserMd5 /** - * Used to inject the sessionId, which is defined as md5(userId|deviceId) + * Used to inject the sessionId, which is defined as md5(userId|deviceId). */ @Qualifier @Retention(AnnotationRetention.RUNTIME) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt index fedd7d05f90117a9a1176c6d9d7a3db7db8f8f9a..c59936af94d314a31dd11708731c0ed2b4038132 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt @@ -50,14 +50,14 @@ internal class WorkManagerProvider @Inject constructor( } /** - * Create a OneTimeWorkRequestBuilder, with the Matrix SDK tag + * Create a OneTimeWorkRequestBuilder, with the Matrix SDK tag. */ inline fun <reified W : ListenableWorker> matrixOneTimeWorkRequestBuilder() = OneTimeWorkRequestBuilder<W>() .addTag(tag) /** - * Create a PeriodicWorkRequestBuilder, with the Matrix SDK tag + * Create a PeriodicWorkRequestBuilder, with the Matrix SDK tag. */ inline fun <reified W : ListenableWorker> matrixPeriodicWorkRequestBuilder(repeatInterval: Long, repeatIntervalTimeUnit: TimeUnit) = @@ -65,7 +65,7 @@ internal class WorkManagerProvider @Inject constructor( .addTag(tag) /** - * Cancel all works instantiated by the Matrix SDK for the current session, and not those from the SDK client, or for other sessions + * Cancel all works instantiated by the Matrix SDK for the current session, and not those from the SDK client, or for other sessions. */ fun cancelAllWorks() { workManager.let { @@ -84,9 +84,11 @@ internal class WorkManagerProvider @Inject constructor( if (workInfo?.state?.isFinished == true) { checkWorkerLiveState.removeObserver(this) if (workInfo.state == WorkInfo.State.FAILED) { - throw RuntimeException("MatrixWorkerFactory is not being set on your worker configuration.\n" + - "Makes sure to add it to a DelegatingWorkerFactory if you have your own factory or use it directly.\n" + - "You can grab the instance through the Matrix class.") + throw RuntimeException( + "MatrixWorkerFactory is not being set on your worker configuration.\n" + + "Makes sure to add it to a DelegatingWorkerFactory if you have your own factory or use it directly.\n" + + "You can grab the instance through the Matrix class." + ) } } } @@ -99,7 +101,7 @@ internal class WorkManagerProvider @Inject constructor( private const val MATRIX_SDK_TAG_PREFIX = "MatrixSDK-" /** - * Default constraints: connected network + * Default constraints: connected network. */ val workConstraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Primitives.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Primitives.kt index 290f06142c6e0f435070bcb8096cb825af900a8c..c08dfa02e8126a9c8a7414282415a30a9877e959 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Primitives.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Primitives.kt @@ -17,6 +17,6 @@ package org.matrix.android.sdk.internal.extensions /** - * Convert a signed byte to a int value + * Convert a signed byte to a int value. */ internal fun Byte.toUnsignedInt() = toInt() and 0xff diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/RealmExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/RealmExtensions.kt index 28b9f6418826886193330fd5e14ef4f5a4c8df52..00cbe0aa85ebb394c02e205be79ad84583557721 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/RealmExtensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/RealmExtensions.kt @@ -26,7 +26,7 @@ internal fun RealmObject.assertIsManaged() { } /** - * Clear a RealmList by deleting all its items calling the provided lambda + * Clear a RealmList by deleting all its items calling the provided lambda. */ internal fun <T> RealmList<T>.clearWith(delete: (T) -> Unit) { while (!isEmpty()) { @@ -35,7 +35,7 @@ internal fun <T> RealmList<T>.clearWith(delete: (T) -> Unit) { } /** - * Schedule a refresh of the HomeServers capabilities + * Schedule a refresh of the HomeServers capabilities. */ internal fun RealmObjectSchema?.forceRefreshOfHomeServerCapabilities(): RealmObjectSchema? { return this?.transform { obj -> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnown.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnown.kt index 3b4bd1b1a3e87986588b9fea0fbfa0646c4184aa..a754a0da967c221111c64c4bbbd2641298a36f99 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnown.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnown.kt @@ -63,7 +63,7 @@ class WellKnown { var integrations: Map<String, *>? = null /** - * Returns the list of integration managers proposed + * Returns the list of integration managers proposed. */ fun getIntegrationManagers(): List<WellKnownManagerConfig> { val managers = ArrayList<WellKnownManagerConfig>() @@ -76,10 +76,12 @@ class WellKnown { if (apiUrl != null && apiUrl.startsWith("https://") && uiUrl!!.startsWith("https://")) { - managers.add(WellKnownManagerConfig( - apiUrl = apiUrl, - uiUrl = uiUrl - )) + managers.add( + WellKnownManagerConfig( + apiUrl = apiUrl, + uiUrl = uiUrl + ) + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt index 3d2b2bfbfb8c19f7e4cad09f8b2949c2eaaad3af..65bf3fcadf926303670501e01b92b54f07fef1e2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt @@ -27,7 +27,7 @@ import javax.inject.Inject internal interface NetworkConnectivityChecker { /** - * Returns true when internet is available + * Returns true when internet is available. */ @WorkerThread fun hasInternetAccess(forcePing: Boolean): Boolean @@ -59,7 +59,7 @@ internal class DefaultNetworkConnectivityChecker @Inject constructor(private val } /** - * Returns true when internet is available + * Returns true when internet is available. */ @WorkerThread override fun hasInternetAccess(forcePing: Boolean): Boolean { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt index 60055be9ec14de6f0b5ed9cb5b0d4c55fe2502f1..5268ea851d5f54d6e67562b4fa52ae4ab5fb045e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitExtensions.kt @@ -53,21 +53,21 @@ internal suspend fun okhttp3.Call.awaitResponse(): okhttp3.Response { } /** - * Convert a retrofit Response to a Failure, and eventually parse errorBody to convert it to a MatrixError + * Convert a retrofit Response to a Failure, and eventually parse errorBody to convert it to a [MatrixError]. */ internal fun <T> Response<T>.toFailure(globalErrorReceiver: GlobalErrorReceiver?): Failure { return toFailure(errorBody(), code(), globalErrorReceiver) } /** - * Convert a HttpException to a Failure, and eventually parse errorBody to convert it to a MatrixError + * Convert a HttpException to a Failure, and eventually parse errorBody to convert it to a [MatrixError]. */ internal fun HttpException.toFailure(globalErrorReceiver: GlobalErrorReceiver?): Failure { return toFailure(response()?.errorBody(), code(), globalErrorReceiver) } /** - * Convert a okhttp3 Response to a Failure, and eventually parse errorBody to convert it to a MatrixError + * Convert a okhttp3 Response to a Failure, and eventually parse errorBody to convert it to a [MatrixError]. */ internal fun okhttp3.Response.toFailure(globalErrorReceiver: GlobalErrorReceiver?): Failure { return toFailure(body, code, globalErrorReceiver) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitFactory.kt index 0a797c8bc00909f9c88b9c5f1caed260c26ebb3a..b2eea84b07e630820b630c0aa806d9726a5b3ba7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitFactory.kt @@ -29,7 +29,7 @@ import javax.inject.Inject internal class RetrofitFactory @Inject constructor(private val moshi: Moshi) { /** - * Use only for authentication service + * Use only for authentication service. */ fun create(okHttpClient: OkHttpClient, baseUrl: String): Retrofit { return Retrofit.Builder() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt index 6efa347d3ac374075f0eaddbc95996a0a8f26330..8b549782795866699e2c023766f24d5b5c605272 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt @@ -33,7 +33,7 @@ internal interface CheckNumberType { companion object { val JSON_ADAPTER_FACTORY = object : JsonAdapter.Factory { @Nullable - override fun create(type: Type, annotations: Set<Annotation?>?, moshi: Moshi): JsonAdapter<*>? { + override fun create(type: Type, annotations: Set<Annotation>, moshi: Moshi): JsonAdapter<*>? { if (type !== Any::class.java) { return null } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/RuntimeJsonAdapterFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/RuntimeJsonAdapterFactory.kt index 0aaa4991cde768ef84d047f25fffe6ac739ee1f2..40d174ee2d5df87d09b22aa8bf6847467ed601f8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/RuntimeJsonAdapterFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/RuntimeJsonAdapterFactory.kt @@ -63,8 +63,10 @@ internal class RuntimeJsonAdapterFactory<T>( } val fallbackAdapter = moshi.adapter<Any>(fallbackType) val objectJsonAdapter = moshi.adapter(Any::class.java) - return RuntimeJsonAdapter(labelKey, labelToAdapter, typeToLabel, - objectJsonAdapter, fallbackAdapter).nullSafe() + return RuntimeJsonAdapter( + labelKey, labelToAdapter, typeToLabel, + objectJsonAdapter, fallbackAdapter + ).nullSafe() } @Suppress("UNCHECKED_CAST") @@ -77,8 +79,10 @@ internal class RuntimeJsonAdapterFactory<T>( override fun fromJson(reader: JsonReader): Any? { val peekedToken = reader.peek() if (peekedToken != JsonReader.Token.BEGIN_OBJECT) { - throw JsonDataException("Expected BEGIN_OBJECT but was " + peekedToken + - " at path " + reader.path) + throw JsonDataException( + "Expected BEGIN_OBJECT but was " + peekedToken + + " at path " + reader.path + ) } val jsonValue = reader.readJsonValue() val jsonObject = jsonValue as Map<String, Any>? @@ -91,13 +95,15 @@ internal class RuntimeJsonAdapterFactory<T>( override fun toJson(writer: JsonWriter, value: Any?) { val type: Class<*> = value!!.javaClass val label = typeToLabel[type] - ?: throw IllegalArgumentException("Expected one of " + - typeToLabel.keys + - " but found " + - value + - ", a " + - value.javaClass + - ". Register this subtype.") + ?: throw IllegalArgumentException( + "Expected one of " + + typeToLabel.keys + + " but found " + + value + + ", a " + + value.javaClass + + ". Register this subtype." + ) val adapter = labelToAdapter[label]!! val jsonValue = adapter.toJsonValue(value) as Map<String, Any>? val valueWithLabel: MutableMap<String, Any> = LinkedHashMap(1 + jsonValue!!.size) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/CertUtil.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/CertUtil.kt index d8bdc5fc2b2b29fa01a707d845af712997d42c1b..2ef40fe2a3fbb162b8ce3ef1800081cdffd18124 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/CertUtil.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/CertUtil.kt @@ -33,7 +33,7 @@ import javax.net.ssl.TrustManagerFactory import javax.net.ssl.X509TrustManager /** - * Various utility classes for dealing with X509Certificates + * Various utility classes for dealing with X509Certificates. */ internal object CertUtil { @@ -43,7 +43,7 @@ internal object CertUtil { private val hexArray = "0123456789ABCDEF".toCharArray() /** - * Generates the SHA-256 fingerprint of the given certificate + * Generates the SHA-256 fingerprint of the given certificate. * * @param cert the certificate. * @return the finger print @@ -55,7 +55,7 @@ internal object CertUtil { } /** - * Generates the SHA-1 fingerprint of the given certificate + * Generates the SHA-1 fingerprint of the given certificate. * * @param cert the certificated * @return the SHA1 fingerprint @@ -109,7 +109,7 @@ internal object CertUtil { /** * Recursively checks the exception to see if it was caused by an - * UnrecognizedCertificateException + * UnrecognizedCertificateException. * * @param root the throwable. * @return The UnrecognizedCertificateException if exists, else null. @@ -250,7 +250,7 @@ internal object CertUtil { builder.supportsTlsExtensions(hsConfig.shouldAcceptTlsExtensions) val list = ArrayList<ConnectionSpec>() list.add(builder.build()) - // TODO: we should display a warning if user enter an http url + // TODO we should display a warning if user enter an http url if (hsConfig.allowHttpExtension || hsConfig.homeServerUriBase.toString().startsWith("http://")) { list.add(ConnectionSpec.CLEARTEXT) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt index 7294ce4abf0fbc80edf572cac5e4cfac634ac2f8..c5ea2d48ad4e517cd8d75cacd2598b46140f6e80 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt @@ -35,8 +35,10 @@ internal fun RealmQuery<RoomSummaryEntity>.process(sortOrder: RoomSortOrder): Re arrayOf( RoomSummaryEntityFields.IS_FAVOURITE, RoomSummaryEntityFields.IS_LOW_PRIORITY, - RoomSummaryEntityFields.LAST_ACTIVITY_TIME), - arrayOf(Sort.DESCENDING, Sort.ASCENDING, Sort.DESCENDING)) + RoomSummaryEntityFields.LAST_ACTIVITY_TIME + ), + arrayOf(Sort.DESCENDING, Sort.ASCENDING, Sort.DESCENDING) + ) } RoomSortOrder.NONE -> { } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/GlobalRealmMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/GlobalRealmMigration.kt index 8dffac5fa074f1705a8c2ef62091af72bcc65641..a9dfd47b5a46a42ff94443d3d6aa00b51904956b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/GlobalRealmMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/GlobalRealmMigration.kt @@ -24,8 +24,8 @@ import javax.inject.Inject internal class GlobalRealmMigration @Inject constructor() : RealmMigration { /** - * Forces all GlobalRealmMigration instances to be equal - * Avoids Realm throwing when multiple instances of the migration are set + * Forces all GlobalRealmMigration instances to be equal. + * Avoids Realm throwing when multiple instances of the migration are set. */ override fun equals(other: Any?) = other is GlobalRealmMigration override fun hashCode() = 2000 diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/GlobalRealmModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/GlobalRealmModule.kt index 770a49c90411574ebc70c800c1b308a90682145a..2d9ec8e820e9f0e1c194c3da1b1245a83d7dc1c5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/GlobalRealmModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/GlobalRealmModule.kt @@ -21,11 +21,13 @@ import org.matrix.android.sdk.internal.database.model.KnownServerUrlEntity import org.matrix.android.sdk.internal.database.model.RawCacheEntity /** - * Realm module for global classes + * Realm module for global classes. */ -@RealmModule(library = true, +@RealmModule( + library = true, classes = [ RawCacheEntity::class, KnownServerUrlEntity::class - ]) + ] +) internal class GlobalRealmModule diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt index 78f1c84f3dd417d99cc4c5620581fda8bc46476b..760aa410817389bce1a762c2917669ebbccc3026 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt @@ -72,12 +72,12 @@ internal class DefaultFileService @Inject constructor( /** * Retain ongoing downloads to avoid re-downloading and already downloading file - * map of mxCurl to callbacks + * map of mxCurl to callbacks. */ private val ongoing = mutableMapOf<String, CompletableDeferred<File>>() /** - * Download file in the cache folder, and eventually decrypt it + * Download file in the cache folder, and eventually decrypt it. * TODO looks like files are copied 3 times */ override suspend fun downloadFile(fileName: String, @@ -88,7 +88,7 @@ internal class DefaultFileService @Inject constructor( Timber.v("## FileService downloadFile $url") - // TODO: Remove use of `synchronized` in suspend function. + // TODO Remove use of `synchronized` in suspend function. val existingDownload = synchronized(ongoing) { val existing = ongoing[url] if (existing != null) { @@ -312,7 +312,7 @@ internal class DefaultFileService @Inject constructor( /** * Use this URI and pass it to intent using flag Intent.FLAG_GRANT_READ_URI_PERMISSION - * (if not other app won't be able to access it) + * (if not other app won't be able to access it). */ override fun getTemporarySharableURI(mxcUrl: String?, fileName: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt index 76e5d84e56622b1753098998f103e7e744699be1..050480e6c955d58a4d4e01ed749c82cd1ba30ed8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt @@ -21,12 +21,8 @@ import dagger.Component import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.auth.data.SessionParams import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.internal.crypto.CancelGossipRequestWorker import org.matrix.android.sdk.internal.crypto.CryptoModule -import org.matrix.android.sdk.internal.crypto.SendGossipRequestWorker -import org.matrix.android.sdk.internal.crypto.SendGossipWorker import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorker -import org.matrix.android.sdk.internal.crypto.verification.SendVerificationMessageWorker import org.matrix.android.sdk.internal.di.MatrixComponent import org.matrix.android.sdk.internal.federation.FederationModule import org.matrix.android.sdk.internal.network.NetworkConnectivityChecker @@ -68,7 +64,8 @@ import org.matrix.android.sdk.internal.session.widgets.WidgetModule import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.util.system.SystemModule -@Component(dependencies = [MatrixComponent::class], +@Component( + dependencies = [MatrixComponent::class], modules = [ SessionModule::class, RoomModule::class, @@ -132,14 +129,6 @@ internal interface SessionComponent { fun inject(worker: AddPusherWorker) - fun inject(worker: SendVerificationMessageWorker) - - fun inject(worker: SendGossipRequestWorker) - - fun inject(worker: CancelGossipRequestWorker) - - fun inject(worker: SendGossipWorker) - fun inject(worker: UpdateTrustWorker) @Component.Factory diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt index 0aae9f31058a253b92d65c3e40e50e42f7c5c7d1..7ceb89e892c24c8a27649b9985746f59633c0fba 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt @@ -49,7 +49,6 @@ import org.matrix.android.sdk.api.util.md5 import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService import org.matrix.android.sdk.internal.crypto.tasks.DefaultRedactEventTask import org.matrix.android.sdk.internal.crypto.tasks.RedactEventTask -import org.matrix.android.sdk.internal.crypto.verification.VerificationMessageProcessor import org.matrix.android.sdk.internal.database.EventInsertLiveObserver import org.matrix.android.sdk.internal.database.RealmSessionProvider import org.matrix.android.sdk.internal.database.SessionRealmConfigurationFactory @@ -318,10 +317,6 @@ internal abstract class SessionModule { @IntoSet abstract fun bindRoomCreateEventProcessor(processor: RoomCreateEventProcessor): EventInsertLiveProcessor - @Binds - @IntoSet - abstract fun bindVerificationMessageProcessor(processor: VerificationMessageProcessor): EventInsertLiveProcessor - @Binds @IntoSet abstract fun bindCallEventProcessor(processor: CallEventProcessor): EventInsertLiveProcessor diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/AccountAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/AccountAPI.kt index a04d0f2686f935de33c0f4f95ded495bbecc98e3..4bd3b6360d91f7e9f54a1e68014309f96f16248b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/AccountAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/AccountAPI.kt @@ -30,7 +30,7 @@ internal interface AccountAPI { suspend fun changePassword(@Body params: ChangePasswordParams) /** - * Deactivate the user account + * Deactivate the user account. * * @param params the deactivate account params */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/GetTurnServerTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/GetTurnServerTask.kt index d53ddb737116385dde615ad9a342bfc5345ad8a0..1313fcaa62484b3d03d5c699c79a06bd53575d19 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/GetTurnServerTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/GetTurnServerTask.kt @@ -22,16 +22,16 @@ import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import javax.inject.Inject -internal abstract class GetTurnServerTask : Task<GetTurnServerTask.Params, TurnServerResponse> { - object Params -} +internal abstract class GetTurnServerTask : Task<Unit, TurnServerResponse> -internal class DefaultGetTurnServerTask @Inject constructor(private val voipAPI: VoipApi, - private val globalErrorReceiver: GlobalErrorReceiver) : GetTurnServerTask() { +internal class DefaultGetTurnServerTask @Inject constructor( + private val voipApi: VoipApi, + private val globalErrorReceiver: GlobalErrorReceiver +) : GetTurnServerTask() { - override suspend fun execute(params: Params): TurnServerResponse { + override suspend fun execute(params: Unit): TurnServerResponse { return executeRequest(globalErrorReceiver) { - voipAPI.getTurnServer() + voipApi.getTurnServer() } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/TurnServerDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/TurnServerDataSource.kt index 8e2ac5e17e7626dc04ef64d1285d08d1d8cbc24c..126a581fa4729e36ac5f65bd6f35bc2b78909646 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/TurnServerDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/TurnServerDataSource.kt @@ -39,7 +39,7 @@ internal class TurnServerDataSource @Inject constructor(private val turnServerTa } suspend fun getTurnServer(): TurnServerResponse { - return cachedTurnServerResponse.data ?: turnServerTask.execute(GetTurnServerTask.Params).also { + return cachedTurnServerResponse.data ?: turnServerTask.execute(Unit).also { cachedTurnServerResponse.data = it } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageExifTagRemover.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageExifTagRemover.kt index 239a768498500f298815e7d1e602163f58d3f919..3fa9ffb0e118371a050196e6158c6ea3527579d6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageExifTagRemover.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageExifTagRemover.kt @@ -31,9 +31,8 @@ import java.io.FileOutputStream import javax.inject.Inject /** - * This class is responsible for removing Exif tags from image files + * This class is responsible for removing Exif tags from image files. */ - internal class ImageExifTagRemover @Inject constructor( private val temporaryFileCreator: TemporaryFileCreator, private val coroutineDispatchers: MatrixCoroutineDispatchers diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt index 75a79abcdbcd2aad7e828ebfe9b0ceb8de796da1..5a00c4b5b477f53bbeffef003063145bc8ca455b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt @@ -62,8 +62,8 @@ private data class NewAttachmentAttributes( ) /** - * Possible previous worker: None - * Possible next worker : Always [MultipleEventSendingDispatcherWorker] + * Possible previous worker: None. + * Possible next worker : Always [MultipleEventSendingDispatcherWorker]. */ internal class UploadContentWorker(val context: Context, params: WorkerParameters, sessionManager: SessionManager) : SessionSafeCoroutineWorker<UploadContentWorker.Params>(context, params, sessionManager, Params::class.java) { @@ -289,12 +289,14 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter val uploadThumbnailResult = dealWithThumbnail(params) - handleSuccess(params, + handleSuccess( + params, contentUploadResponse.contentUri, uploadedFileEncryptedFileInfo, uploadThumbnailResult?.uploadedThumbnailUrl, uploadThumbnailResult?.uploadedThumbnailEncryptedFileInfo, - newAttachmentAttributes) + newAttachmentAttributes + ) } catch (t: Throwable) { Timber.e(t, "## ERROR ${t.localizedMessage}") handleFailure(params, t) @@ -316,7 +318,7 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter ) /** - * If appropriate, it will create and upload a thumbnail + * If appropriate, it will create and upload a thumbnail. */ private suspend fun dealWithThumbnail(params: Params): UploadThumbnailResult? { return thumbnailExtractor.extractThumbnail(params.attachment) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/ContentScannerRealmModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/ContentScannerRealmModule.kt index bb53140ad989bfd2dec97b0f3ddaedd89455277c..1872bb72a9f7173f634487deddd812cb56db5416 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/ContentScannerRealmModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/ContentScannerRealmModule.kt @@ -19,11 +19,13 @@ package org.matrix.android.sdk.internal.session.contentscanner.db import io.realm.annotations.RealmModule /** - * Realm module for content scanner classes + * Realm module for content scanner classes. */ -@RealmModule(library = true, +@RealmModule( + library = true, classes = [ ContentScannerInfoEntity::class, ContentScanResultEntity::class - ]) + ] +) internal class ContentScannerRealmModule diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/model/ScanResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/model/ScanResponse.kt index f783fe0a6c2c384a551af47803c3cfdbc141d2b2..85d7f2e09420da44cdf528de9ca3d6f32102f384 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/model/ScanResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/model/ScanResponse.kt @@ -20,10 +20,14 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** + * Example: + * <pre> * { * "clean": true, * "info": "File clean at 6/7/2018, 6:02:40 PM" * } + * </pre> + * . */ @JsonClass(generateAdapter = true) internal data class ScanResponse( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/directory/DirectoryAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/directory/DirectoryAPI.kt index 16c57baafc59ddd5f76c75889fea5bfe35e5240f..19b9130fc4b6e7f63954c518fcb8d81a3f61d74f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/directory/DirectoryAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/directory/DirectoryAPI.kt @@ -61,7 +61,7 @@ internal interface DirectoryAPI { @Body body: AddRoomAliasBody) /** - * Delete a room alias + * Delete a room alias. * @param roomAlias the room alias. */ @DELETE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterApi.kt index 2809dea23b71b83dd2b584c9359cdc636450b068..dab801360fd99e98aec6095020c76ba6b7437e6f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterApi.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterApi.kt @@ -25,7 +25,7 @@ import retrofit2.http.Path internal interface FilterApi { /** - * Upload FilterBody to get a filter_id which can be used for /sync requests + * Upload FilterBody to get a filter_id which can be used for /sync requests. * * @param userId the user id * @param body the Json representation of a FilterBody object @@ -35,7 +35,7 @@ internal interface FilterApi { @Body body: Filter): FilterResponse /** - * Gets a filter with a given filterId from the homeserver + * Gets a filter with a given filterId from the homeserver. * * @param userId the user id * @param filterId the filterID diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterRepository.kt index df615395478fcaeac1b5feae4af9d0587878bf99..f40231c8cffa93d7f1bf44828143867685b640bf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterRepository.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterRepository.kt @@ -19,22 +19,22 @@ package org.matrix.android.sdk.internal.session.filter internal interface FilterRepository { /** - * Return true if the filterBody has changed, or need to be sent to the server + * Return true if the filterBody has changed, or need to be sent to the server. */ suspend fun storeFilter(filter: Filter, roomEventFilter: RoomEventFilter): Boolean /** - * Set the filterId of this filter + * Set the filterId of this filter. */ suspend fun storeFilterId(filter: Filter, filterId: String) /** - * Return filter json or filter id + * Return filter json or filter id. */ suspend fun getFilter(): String /** - * Return the room filter + * Return the room filter. */ suspend fun getRoomFilter(): String } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterUtil.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterUtil.kt index bd7f0ad402fc9feff402255400e67d51dca5c418..562fea88b66c0b7fc015f98f2fe75b26618900b6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterUtil.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterUtil.kt @@ -81,8 +81,7 @@ internal object FilterUtil { } */ /** - * Compute a new filter to enable or disable the lazy loading - * + * Compute a new filter to enable or disable the lazy loading. * * If lazy loading is on, the filter will looks like * {"room":{"state":{"lazy_load_members":true})} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomFilter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomFilter.kt index 585d013eaef4e3105acb29292948b890dbff0cbc..72b1af52b82a3bd9bc8268007d84697d77ccae19 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomFilter.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomFilter.kt @@ -40,7 +40,7 @@ internal data class RoomFilter( */ @Json(name = "ephemeral") val ephemeral: RoomEventFilter? = null, /** - * Include rooms that the user has left in the sync, default false + * Include rooms that the user has left in the sync, default false. */ @Json(name = "include_leave") val includeLeave: Boolean? = null, /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/SaveFilterTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/SaveFilterTask.kt index 3cac89ce285551228e8d7d8998a2e08449f8814b..e9d5b876a8d14512ec122aa72bdc9ab65589aea9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/SaveFilterTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/SaveFilterTask.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.internal.task.Task import javax.inject.Inject /** - * Save a filter, in db and if any changes, upload to the server + * Save a filter, in db and if any changes, upload to the server. */ internal interface SaveFilterTask : Task<SaveFilterTask.Params, Unit> { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataWorker.kt index 716859f195f75736591bdc8f9192eb7996cbd6ea..21582cb4bed7b2867768c73e768b44b469d08f96 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GetGroupDataWorker.kt @@ -26,8 +26,8 @@ import org.matrix.android.sdk.internal.worker.SessionWorkerParams import javax.inject.Inject /** - * Possible previous worker: None - * Possible next worker : None + * Possible previous worker: None. + * Possible next worker : None. */ internal class GetGroupDataWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : SessionSafeCoroutineWorker<GetGroupDataWorker.Params>(context, params, sessionManager, Params::class.java) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupAPI.kt index 58dcc57dd6ab24e901e58097773890d56ff52467..c9d25b910441388d331af54a81c1da767d16a5b6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/GroupAPI.kt @@ -26,7 +26,7 @@ import retrofit2.http.Path internal interface GroupAPI { /** - * Request a group summary + * Request a group summary. * * @param groupId the group id */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryRoomsSection.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryRoomsSection.kt index 8f9b29ed0a02f5344676181e6ec8365ab16ba971..87d07167ce2aad46469c1cc8bb95a54b1346b182 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryRoomsSection.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryRoomsSection.kt @@ -29,6 +29,6 @@ internal data class GroupSummaryRoomsSection( @Json(name = "rooms") val rooms: List<String> = emptyList() - // @TODO: Check the meaning and the usage of these categories. This dictionary is empty FTM. + // TODO Check the meaning and the usage of these categories. This dictionary is empty FTM. // public Map<Object, Object> categories; ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUsersSection.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUsersSection.kt index 799aa8a5b1010eb4ad6c1c1dbdbf608798682465..63608c582a66db0d2f7a96899999235583e747e3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUsersSection.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/group/model/GroupSummaryUsersSection.kt @@ -30,6 +30,6 @@ internal data class GroupSummaryUsersSection( @Json(name = "users") val users: List<String> = emptyList() - // @TODO: Check the meaning and the usage of these roles. This dictionary is empty FTM. + // TODO Check the meaning and the usage of these roles. This dictionary is empty FTM. // public Map<Object, Object> roles; ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/CapabilitiesAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/CapabilitiesAPI.kt index 7de0cc95928c784b4466b7a0fc371b425486b569..f658cda9739fb42dcd5b57b9bebe4dce11077250 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/CapabilitiesAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/CapabilitiesAPI.kt @@ -22,19 +22,19 @@ import retrofit2.http.GET internal interface CapabilitiesAPI { /** - * Request the homeserver capabilities + * Request the homeserver capabilities. */ @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "capabilities") suspend fun getCapabilities(): GetCapabilitiesResult /** - * Request the versions + * Request the versions. */ @GET(NetworkConstants.URI_API_PREFIX_PATH_ + "versions") suspend fun getVersions(): Versions /** - * Ping the homeserver. We do not care about the returned data, so there is no use to parse them + * Ping the homeserver. We do not care about the returned data, so there is no use to parse them. */ @GET(NetworkConstants.URI_API_PREFIX_PATH_ + "versions") suspend fun ping() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetCapabilitiesResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetCapabilitiesResult.kt index 55526b41db604d0126d0fe69e604bbcccfe3f5f0..95ff44807c85c7c7cf46f35458faf98686593282 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetCapabilitiesResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetCapabilitiesResult.kt @@ -67,8 +67,8 @@ internal data class Capabilities( @Json(name = "m.room_versions") val roomVersions: RoomVersions? = null, /** - * Capability to indicate if the server supports MSC3440 Threading - * True if the user can use m.thread relation, false otherwise + * Capability to indicate if the server supports MSC3440 Threading. + * True if the user can use m.thread relation, false otherwise. */ @Json(name = "m.thread") val threads: BooleanCapability? = null @@ -98,6 +98,8 @@ internal data class RoomVersions( val available: JsonDict? = null, /** + * Example: + * <pre> * "room_capabilities": { * "knock" : { * "preferred": "7", @@ -108,6 +110,7 @@ internal data class RoomVersions( * "support" : ["8", "9"] * } * } + * </pre>. */ @Json(name = "org.matrix.msc3244.room_capabilities") val roomCapabilities: JsonDict? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index 44e13d971a84b3d52a278a1b78783c73e907e75b..e9097e4d033f0721bc0f49d967413e7838be0f7f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -94,10 +94,12 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( }.getOrNull() val wellknownResult = runCatching { - getWellknownTask.execute(GetWellknownTask.Params( - domain = userId.getDomain(), - homeServerConnectionConfig = homeServerConnectionConfig - )) + getWellknownTask.execute( + GetWellknownTask.Params( + domain = userId.getDomain(), + homeServerConnectionConfig = homeServerConnectionConfig + ) + ) }.getOrNull() insertInDb(capabilities, mediaConfig, versions, wellknownResult) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt index 4285f38893cdde2da859a85465d1c65aff6c8bbf..74838afc6587b6eacfd4b58a2550f3c0a9db8dcf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt @@ -218,9 +218,11 @@ internal class DefaultIdentityService @Inject constructor( listeners.toList().forEach { tryOrNull { it.onIdentityServerChange() } } } - updateUserAccountDataTask.execute(UpdateUserAccountDataTask.IdentityParams( - identityContent = IdentityServerContent(baseUrl = url) - )) + updateUserAccountDataTask.execute( + UpdateUserAccountDataTask.IdentityParams( + identityContent = IdentityServerContent(baseUrl = url) + ) + ) } override fun getUserConsent(): Boolean { @@ -297,11 +299,13 @@ internal class DefaultIdentityService @Inject constructor( } override suspend fun sign3pidInvitation(identiyServer: String, token: String, secret: String): SignInvitationResult { - return sign3pidInvitationTask.execute(Sign3pidInvitationTask.Params( - url = identiyServer, - token = token, - privateKey = secret - )) + return sign3pidInvitationTask.execute( + Sign3pidInvitationTask.Params( + url = identiyServer, + token = token, + privateKey = secret + ) + ) } override fun addListener(listener: IdentityServiceListener) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAPI.kt index 7ca875867706eab5030c38d2b5464b595fb75fa8..aef86ed08efaed4a3fe1feee081a4c304ff2e056 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAPI.kt @@ -34,8 +34,8 @@ import retrofit2.http.Path import retrofit2.http.Query /** - * Ref: https://matrix.org/docs/spec/identity_service/latest - * This contain the requests which need an identity server token + * Ref: https://matrix.org/docs/spec/identity_service/latest. + * This contain the requests which need an identity server token. */ internal interface IdentityAPI { /** @@ -69,8 +69,8 @@ internal interface IdentityAPI { suspend fun lookup(@Body body: IdentityLookUpParams): IdentityLookUpResponse /** - * Create a session to change the bind status of an email to an identity server - * The identity server will also send an email + * Create a session to change the bind status of an email to an identity server. + * The identity server will also send an email. * * @param body * @return the sid @@ -79,8 +79,8 @@ internal interface IdentityAPI { suspend fun requestTokenToBindEmail(@Body body: IdentityRequestTokenForEmailBody): IdentityRequestTokenResponse /** - * Create a session to change the bind status of an phone number to an identity server - * The identity server will also send an SMS on the ThreePid provided + * Create a session to change the bind status of an phone number to an identity server. + * The identity server will also send an SMS on the ThreePid provided. * * @param body * @return the sid @@ -99,9 +99,9 @@ internal interface IdentityAPI { @Body body: IdentityRequestOwnershipParams): SuccessResult /** - * https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-sign-ed25519 + * https://matrix.org/docs/spec/identity_service/r0.3.0#post-matrix-identity-v2-sign-ed25519. * - * Have to rely on V1 for now + * Have to rely on V1 for now. */ @POST(NetworkConstants.URI_IDENTITY_PATH_V1 + "sign-ed25519") suspend fun signInvitationDetails( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAuthAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAuthAPI.kt index f77eb296aa9e48438206662fe1dee09d85718e77..85791f59a3755a9d664f8cc8b5e682d237a84c6f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAuthAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAuthAPI.kt @@ -24,14 +24,14 @@ import retrofit2.http.GET import retrofit2.http.POST /** - * Ref: https://matrix.org/docs/spec/identity_service/latest - * This contain the requests which do not need an identity server token + * Ref: https://matrix.org/docs/spec/identity_service/latest. + * This contain the requests which do not need an identity server token. */ internal interface IdentityAuthAPI { /** - * https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery - * Simple ping call to check if server exists and is alive + * https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery. + * Simple ping call to check if server exists and is alive. * * Ref: https://matrix.org/docs/spec/identity_service/unstable#status-check * https://matrix.org/docs/spec/identity_service/latest#get-matrix-identity-v2 @@ -42,7 +42,7 @@ internal interface IdentityAuthAPI { suspend fun ping() /** - * Ping v1 will be used to check outdated identity server + * Ping v1 will be used to check outdated identity server. */ @GET("_matrix/identity/api/v1") suspend fun pingV1() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt index f6ef370f8d3064a7c4561405311b522715ee30bb..f642ed4cf2f936574cf2de6366eac908f2b20396 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt @@ -83,11 +83,13 @@ internal class DefaultIdentityBulkLookupTask @Inject constructor( return try { LookUpData(hashedAddresses, executeRequest(null) { - identityAPI.lookup(IdentityLookUpParams( - hashedAddresses, - IdentityHashDetailResponse.ALGORITHM_SHA256, - hashDetailResponse.pepper - )) + identityAPI.lookup( + IdentityLookUpParams( + hashedAddresses, + IdentityHashDetailResponse.ALGORITHM_SHA256, + hashDetailResponse.pepper + ) + ) }) } catch (failure: Throwable) { // Catch invalid hash pepper and retry @@ -117,8 +119,10 @@ internal class DefaultIdentityBulkLookupTask @Inject constructor( return withOlmUtility { olmUtility -> threePids.map { threePid -> base64ToBase64Url( - olmUtility.sha256(threePid.value.lowercase(Locale.ROOT) + - " " + threePid.toMedium() + " " + pepper) + olmUtility.sha256( + threePid.value.lowercase(Locale.ROOT) + + " " + threePid.toMedium() + " " + pepper + ) ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityRequestTokenForBindingTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityRequestTokenForBindingTask.kt index 9c89048176f6d8d918f324e6bf34845d882524dc..fe123096509fc4246693ec91a5cc3006ac0acbee 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityRequestTokenForBindingTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityRequestTokenForBindingTask.kt @@ -57,18 +57,22 @@ internal class DefaultIdentityRequestTokenForBindingTask @Inject constructor( val tokenResponse = executeRequest(null) { when (params.threePid) { - is ThreePid.Email -> identityAPI.requestTokenToBindEmail(IdentityRequestTokenForEmailBody( - clientSecret = clientSecret, - sendAttempt = sendAttempt, - email = params.threePid.email - )) + is ThreePid.Email -> identityAPI.requestTokenToBindEmail( + IdentityRequestTokenForEmailBody( + clientSecret = clientSecret, + sendAttempt = sendAttempt, + email = params.threePid.email + ) + ) is ThreePid.Msisdn -> { - identityAPI.requestTokenToBindMsisdn(IdentityRequestTokenForMsisdnBody( - clientSecret = clientSecret, - sendAttempt = sendAttempt, - phoneNumber = params.threePid.msisdn, - countryCode = params.threePid.getCountryCode() - )) + identityAPI.requestTokenToBindMsisdn( + IdentityRequestTokenForMsisdnBody( + clientSecret = clientSecret, + sendAttempt = sendAttempt, + phoneNumber = params.threePid.msisdn, + countryCode = params.threePid.getCountryCode() + ) + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentitySubmitTokenForBindingTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentitySubmitTokenForBindingTask.kt index f884e2816dccfb9e3e63b572e1976b3a83f995cb..fcf8ce6317b93e20506ea782cd4bd912a9feb8ac 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentitySubmitTokenForBindingTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentitySubmitTokenForBindingTask.kt @@ -50,7 +50,8 @@ internal class DefaultIdentitySubmitTokenForBindingTask @Inject constructor( clientSecret = identityPendingBinding.clientSecret, sid = identityPendingBinding.sid, token = params.token - )) + ) + ) } if (!tokenResponse.isSuccess()) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/data/IdentityStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/data/IdentityStore.kt index 0e05224be5db88716aa025f39eb99a2345c08679..51d4ed7c6dde0b3a62550fe8c733f3b0f68897b8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/data/IdentityStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/data/IdentityStore.kt @@ -32,7 +32,7 @@ internal interface IdentityStore { fun setHashDetails(hashDetailResponse: IdentityHashDetailResponse) /** - * Store details about a current binding + * Store details about a current binding. */ fun storePendingBinding(threePid: ThreePid, data: IdentityPendingBinding) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/IdentityDataEntityQuery.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/IdentityDataEntityQuery.kt index 5152e33743640057512747a5796be732a65467e5..aecf21678c12576fff363146adc0bb39beb7818a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/IdentityDataEntityQuery.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/IdentityDataEntityQuery.kt @@ -22,7 +22,7 @@ import io.realm.kotlin.createObject import io.realm.kotlin.where /** - * Only one object can be stored at a time + * Only one object can be stored at a time. */ internal fun IdentityDataEntity.Companion.get(realm: Realm): IdentityDataEntity? { return realm.where<IdentityDataEntity>().findFirst() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/IdentityRealmModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/IdentityRealmModule.kt index 1f2cfad33c9b806bbe6fb1050f726a266b0869ed..a5ec6061ba68b2e9d5117c60c20ecb7bb459357b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/IdentityRealmModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/IdentityRealmModule.kt @@ -19,11 +19,13 @@ package org.matrix.android.sdk.internal.session.identity.db import io.realm.annotations.RealmModule /** - * Realm module for identity server classes + * Realm module for identity server classes. */ -@RealmModule(library = true, +@RealmModule( + library = true, classes = [ IdentityDataEntity::class, IdentityPendingBindingEntity::class - ]) + ] +) internal class IdentityRealmModule diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/RealmIdentityStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/RealmIdentityStoreMigration.kt index 0c279d8a7ed80f42e8bc1df22e55f1f82d31eb41..e731f9f3472e473b810bba0c3b9be2bb05d02a30 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/RealmIdentityStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/RealmIdentityStoreMigration.kt @@ -24,8 +24,8 @@ import javax.inject.Inject internal class RealmIdentityStoreMigration @Inject constructor() : RealmMigration { /** - * Forces all RealmIdentityStoreMigration instances to be equal - * Avoids Realm throwing when multiple instances of the migration are set + * Forces all RealmIdentityStoreMigration instances to be equal. + * Avoids Realm throwing when multiple instances of the migration are set. */ override fun equals(other: Any?) = other is RealmIdentityStoreMigration override fun hashCode() = 3000 diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/model/SignInvitationBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/model/SignInvitationBody.kt index 699825726375ae1b5b0084ac953babbb291c0fc6..465d296e94515a902faf70dc859d86b3bd07cc07 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/model/SignInvitationBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/model/SignInvitationBody.kt @@ -16,14 +16,16 @@ package org.matrix.android.sdk.internal.session.identity.model +import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) internal data class SignInvitationBody( - /**The Matrix user ID of the user accepting the invitation.*/ + /** The Matrix user ID of the user accepting the invitation.*/ val mxid: String, - /**The token from the call to store- invite..*/ + /** The token from the call to store- invite..*/ val token: String, /** The private key, encoded as Unpadded base64. */ - val private_key: String + @Json(name = "private_key") + val privateKey: String ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt index c138c1a40e666ee5e4d687b8228bccc028cac72d..2aa0be80c9b4e36473adc2d433e517532b5a09c5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt @@ -41,7 +41,7 @@ internal class DefaultSyncStatusService @Inject constructor() : } /** - * Create a rootTask + * Create a rootTask. */ fun startRoot(initSyncStep: InitSyncStep, totalProgress: Int) { @@ -51,7 +51,7 @@ internal class DefaultSyncStatusService @Inject constructor() : } /** - * Add a child to the leaf + * Add a child to the leaf. */ override fun startTask(initSyncStep: InitSyncStep, totalProgress: Int, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/TaskInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/TaskInfo.kt index 3e4cce2e1fbbc79bbddf8ecebe2c246673ecb655..fef16bf1d773492b7054901a4101c41434bc7482 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/TaskInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/TaskInfo.kt @@ -29,7 +29,7 @@ internal class TaskInfo(val initSyncStep: InitSyncStep, private val offset = parent?.currentProgress ?: 0F /** - * Get the further child + * Get the further child. */ fun leaf(): TaskInfo { var last = this @@ -40,7 +40,7 @@ internal class TaskInfo(val initSyncStep: InitSyncStep, } /** - * Set progress of this task and update the parent progress iteratively + * Set progress of this task and update the parent progress iteratively. */ fun setProgress(progress: Float) { Timber.v("setProgress: $progress / $totalProgress") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/AllowedWidgetsContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/AllowedWidgetsContent.kt index 8d0e8c930dc47acafdcced5bb76d6e9f5b171828..ebf14c602c587c867471eab7a47217c7b30186a1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/AllowedWidgetsContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/AllowedWidgetsContent.kt @@ -22,18 +22,20 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) internal data class AllowedWidgetsContent( /** - * Map of stateEventId to Allowed + * Map of stateEventId to Allowed. */ @Json(name = "widgets") val widgets: Map<String, Boolean> = emptyMap(), /** - * Map of native widgetType to a map of domain to Allowed + * Map of native widgetType to a map of domain to Allowed. + * <pre> * { * "jitsi" : { * "jitsi.domain.org" : true, * "jitsi.other.org" : false * } * } + * </pre> */ @Json(name = "native_widgets") val native: Map<String, Map<String, Boolean>> = emptyMap() ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt index 1b96931c6c8eaeaf3155ed298d6f73fbc076baca..8034e5b9740632b1df5b272fa6fd44588300ef8a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt @@ -124,7 +124,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri } /** - * Returns false if the user as disabled integration manager feature + * Returns false if the user as disabled integration manager feature. */ fun isIntegrationEnabled(): Boolean { val integrationProvisioningData = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_INTEGRATION_PROVISIONING) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/PreviewUrlMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/PreviewUrlMapper.kt index 551dc29b926d085a1f489bf298d01d148d844b97..06fbf802ae54dcd829020d895ea7d4cdcabe3a45 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/PreviewUrlMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/PreviewUrlMapper.kt @@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.session.media.PreviewUrlData import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntity /** - * PreviewUrlCacheEntity -> PreviewUrlData + * PreviewUrlCacheEntity -> PreviewUrlData. */ internal fun PreviewUrlCacheEntity.toDomain() = PreviewUrlData( url = urlFromServer ?: url, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/PermalinkFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/PermalinkFactory.kt index 0aeb0467de8ebf4ad3f7520448da03becb3a1baa..f9da7b66f623ff96a116637bc69697ab0fa5bd9a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/PermalinkFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/PermalinkFactory.kt @@ -126,7 +126,7 @@ internal class PermalinkFactory @Inject constructor( } /** - * Escape '/' in id, because it is used as a separator + * Escape '/' in id, because it is used as a separator. * * @param id the id to escape * @return the escaped id @@ -136,7 +136,7 @@ internal class PermalinkFactory @Inject constructor( } /** - * Unescape '/' in id + * Unescape '/' in id. * * @param id the id to escape * @return the escaped id diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt index d20cf8f140dd9d88594cc860c844d4c3ca16aa5a..0f667c65df7562390eeab67ac24f37c19c56edd3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt @@ -68,7 +68,7 @@ internal class ViaParameterFinder @Inject constructor( } /** - * Get a set of userIds of joined members of a room + * Get a set of userIds of joined members of a room. */ private fun getUserIdsOfJoinedMembers(roomId: String): Set<String> { return roomGetterProvider.get().getRoom(roomId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/PresenceContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/PresenceContent.kt index b1ca5126528f3a66af87f1d30d7a874ab7b254cd..abad91bad2f84900ecf270501fb915b6719ca157 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/PresenceContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/PresenceContent.kt @@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.session.presence.model.PresenceEnum /** - * Class representing the EventType.PRESENCE event content + * Class representing the EventType.PRESENCE event content. */ @JsonClass(generateAdapter = true) internal data class PresenceContent( @@ -38,7 +38,7 @@ internal data class PresenceContent( */ @Json(name = "status_msg") val statusMessage: String? = null, /** - * Whether the user is currently active + * Whether the user is currently active. */ @Json(name = "currently_active") val isCurrentlyActive: Boolean = false, /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AccountThreePidsResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AccountThreePidsResponse.kt index 0a792397f8e3699380953b7dd7dadeb9d73b3497..6d2b3c480d8f2387865beb0be9f0ddba17838ecd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AccountThreePidsResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AccountThreePidsResponse.kt @@ -19,7 +19,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing the ThreePids response + * Class representing the ThreePids response. */ @JsonClass(generateAdapter = true) internal data class AccountThreePidsResponse( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidsTask.kt index 87e51181e636952d757bb71c92607f06ef3b5447..f630c2c225fc355106eb018adb2ddb49d177f798 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidsTask.kt @@ -50,7 +50,8 @@ internal class DefaultBindThreePidsTask @Inject constructor(private val profileA identityServerUrlWithoutProtocol = identityServerUrlWithoutProtocol, identityServerAccessToken = identityServerAccessToken, sid = identityPendingBinding.sid - )) + ) + ) } // Binding is over, cleanup the store diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt index 6f99577ac27c48d7ee8b0eb66b4d6b093ad90499..5e64a6af0e2bc568989b4c75eab6ca892be9afa9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt @@ -135,21 +135,25 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto override suspend fun finalizeAddingThreePid(threePid: ThreePid, userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor) { finalizeAddingThreePidTask - .execute(FinalizeAddingThreePidTask.Params( - threePid = threePid, - userInteractiveAuthInterceptor = userInteractiveAuthInterceptor, - userWantsToCancel = false - )) + .execute( + FinalizeAddingThreePidTask.Params( + threePid = threePid, + userInteractiveAuthInterceptor = userInteractiveAuthInterceptor, + userWantsToCancel = false + ) + ) refreshThreePids() } override suspend fun cancelAddingThreePid(threePid: ThreePid) { finalizeAddingThreePidTask - .execute(FinalizeAddingThreePidTask.Params( - threePid = threePid, - userInteractiveAuthInterceptor = null, - userWantsToCancel = true - )) + .execute( + FinalizeAddingThreePidTask.Params( + threePid = threePid, + userInteractiveAuthInterceptor = null, + userWantsToCancel = true + ) + ) refreshThreePids() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt index 4b56db9f1330cf999d5bcf6715c5bcbb1820d268..4d4506be76785f2d3365cabfd3848ad6c7f51d94 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt @@ -46,7 +46,7 @@ internal interface ProfileAPI { suspend fun getThreePIDs(): AccountThreePidsResponse /** - * Change user display name + * Change user display name. */ @PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "profile/{userId}/displayname") suspend fun setDisplayName(@Path("userId") userId: String, @@ -86,7 +86,7 @@ internal interface ProfileAPI { suspend fun addMsisdn(@Body body: AddMsisdnBody): AddMsisdnResponse /** - * Validate Msisdn code (same model than for identity server API) + * Validate Msisdn code (same model than for identity server API). */ @POST suspend fun validateMsisdn(@Url url: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/UnbindThreePidsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/UnbindThreePidsTask.kt index df8a1c97ffb5a29854d4af2cf9ad229a45e18797..acbecc9fbee766050e12bf6f5815eef7eddd6cc2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/UnbindThreePidsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/UnbindThreePidsTask.kt @@ -45,7 +45,8 @@ internal class DefaultUnbindThreePidsTask @Inject constructor(private val profil identityServerUrlWithoutProtocol, params.threePid.toMedium(), params.threePid.value - )) + ) + ) }.isSuccess() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt index e87c27e601573e5e6a97cba49b238473a58d87bd..13b990a9ff5baeb0135c634d9ed156726535d7a8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt @@ -85,17 +85,19 @@ internal class DefaultPushersService @Inject constructor( deviceDisplayName: String, append: Boolean) { addPusherTask.execute( - AddPusherTask.Params(JsonPusher( - pushKey = email, - kind = Pusher.KIND_EMAIL, - appId = Pusher.APP_ID_EMAIL, - profileTag = "", - lang = lang, - appDisplayName = appDisplayName, - deviceDisplayName = deviceDisplayName, - data = JsonPusherData(brand = emailBranding), - append = append - )) + AddPusherTask.Params( + JsonPusher( + pushKey = email, + kind = Pusher.KIND_EMAIL, + appId = Pusher.APP_ID_EMAIL, + profileTag = "", + lang = lang, + appDisplayName = appDisplayName, + deviceDisplayName = deviceDisplayName, + data = JsonPusherData(brand = emailBranding), + append = append + ) + ) ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesResponse.kt index de038196291efb2aca738291d6486cf9e2e09399..5f35c919fc021caab4e267874cd54ff3d29a6866 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesResponse.kt @@ -26,13 +26,13 @@ import org.matrix.android.sdk.api.session.pushrules.rest.RuleSet @JsonClass(generateAdapter = true) internal data class GetPushRulesResponse( /** - * Global rules, account level applying to all devices + * Global rules, account level applying to all devices. */ @Json(name = "global") val global: RuleSet, /** - * Device specific rules, apply only to current device + * Device specific rules, apply only to current device. */ @Json(name = "device") val device: RuleSet? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesTask.kt index 8cf861d2853c88dc769cc0d76b31916cb4a9463f..8e7078292bd0b46a43f802afe9e555dce26faffa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesTask.kt @@ -25,7 +25,7 @@ internal interface GetPushRulesTask : Task<GetPushRulesTask.Params, Unit> { } /** - * We keep this task, but it should not be used anymore, the push rules comes from the sync response + * We keep this task, but it should not be used anymore, the push rules comes from the sync response. */ internal class DefaultGetPushRulesTask @Inject constructor( private val pushRulesApi: PushRulesApi, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/JsonPusher.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/JsonPusher.kt index 8dc0954694c8e1a3a9bdd59eaa01695cf6f53d15..71a1ea8c6669471d191b44c8c2e068c6c186d8ef 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/JsonPusher.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/JsonPusher.kt @@ -22,7 +22,6 @@ import java.security.InvalidParameterException /** * Example: - * * <code> * { * "pushers": [ @@ -40,6 +39,7 @@ import java.security.InvalidParameterException * }] * } * </code> + * . */ @JsonClass(generateAdapter = true) internal data class JsonPusher( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushRulesApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushRulesApi.kt index dab6d373177b9f26062c70048d5be00c8a710633..40b4ee269ac8b3d82318f5c6c1e52af2438be1b1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushRulesApi.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushRulesApi.kt @@ -25,13 +25,13 @@ import retrofit2.http.Path internal interface PushRulesApi { /** - * Get all push rules + * Get all push rules. */ @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "pushrules/") suspend fun getAllRules(): GetPushRulesResponse /** - * Update the ruleID enable status + * Update the ruleID enable status. * * @param kind the notification kind (sender, room...) * @param ruleId the ruleId @@ -43,7 +43,7 @@ internal interface PushRulesApi { @Body enabledBody: EnabledBody) /** - * Update the ruleID action + * Update the ruleID action. * Ref: https://matrix.org/docs/spec/client_server/latest#put-matrix-client-r0-pushrules-scope-kind-ruleid-actions * * @param kind the notification kind (sender, room...) @@ -56,7 +56,7 @@ internal interface PushRulesApi { @Body actions: Any) /** - * Delete a rule + * Delete a rule. * * @param kind the notification kind (sender, room...) * @param ruleId the ruleId @@ -66,7 +66,7 @@ internal interface PushRulesApi { @Path("ruleId") ruleId: String) /** - * Add the ruleID enable status + * Add the ruleID enable status. * * @param kind the notification kind (sender, room...) * @param ruleId the ruleId. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/SavePushRulesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/SavePushRulesTask.kt index ff685e9281554754fe04128c17bd73e2aeeaaa4a..88c78aa460e335cf8ce115f9bb3769d2131ab881 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/SavePushRulesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/SavePushRulesTask.kt @@ -27,7 +27,7 @@ import org.matrix.android.sdk.internal.util.awaitTransaction import javax.inject.Inject /** - * Save the push rules in DB + * Save the push rules in DB. */ internal interface SavePushRulesTask : Task<SavePushRulesTask.Params, Unit> { data class Params(val pushRules: GetPushRulesResponse) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/ProcessEventForPushTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/ProcessEventForPushTask.kt index 91d092a2b4b552f9b2e1185f01d24a1fb07edbe3..60c1194708307859e2060ae2d42251f8d540d042 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/ProcessEventForPushTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/ProcessEventForPushTask.kt @@ -67,8 +67,10 @@ internal class DefaultProcessEventForPushTask @Inject constructor( }.filter { it.senderId != userId } - Timber.v("[PushRules] Found ${allEvents.size} out of ${(newJoinEvents + inviteEvents).size}" + - " to check for push rules with ${params.rules.size} rules") + Timber.v( + "[PushRules] Found ${allEvents.size} out of ${(newJoinEvents + inviteEvents).size}" + + " to check for push rules with ${params.rules.size} rules" + ) val matchedEvents = allEvents.mapNotNull { event -> pushRuleFinder.fulfilledBingRule(event, params.rules)?.let { Timber.v("[PushRules] Rule $it match for event ${event.eventId}") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt index 7e0b44a3149fd0bce90e99f1f049c8dc016ec5d2..16a63a9a96afb152dee055d4b9e3cb74ae5473dc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt @@ -372,7 +372,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor( } /** - * Check if the edition is on the latest thread event, and update it accordingly + * Check if the edition is on the latest thread event, and update it accordingly. * @param editedEvent The event that will be changed * @param replaceEvent The new event */ @@ -651,7 +651,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor( } /** - * Called when an event is deleted + * Called when an event is deleted. */ private fun handleRedactionOfReplace(realm: Realm, redacted: EventEntity, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt index 65ef94999fc2e79b43aeda24cd56f79d987f0c0f..72f56ddf688524128ec8a77b13b04daa8315f1b4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt @@ -92,7 +92,7 @@ internal interface RoomAPI { ): PaginationResponse /** - * Get all members of a room + * Get all members of a room. * * @param roomId the room id where to get the members * @param syncToken the sync token (optional) @@ -136,7 +136,7 @@ internal interface RoomAPI { @Query("filter") filter: String? = null): EventContextResponse /** - * Retrieve an event from its room id / events id + * Retrieve an event from its room id / events id. * * @param roomId the room id * @param eventId the event Id @@ -156,7 +156,7 @@ internal interface RoomAPI { @Body markers: Map<String, String>) /** - * Send receipt to a room + * Send receipt to a room. */ @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/receipt/{receiptType}/{eventId}") suspend fun sendReceipt(@Path("roomId") roomId: String, @@ -185,7 +185,7 @@ internal interface RoomAPI { @Body body: ThreePidInviteBody) /** - * Send a generic state event + * Send a generic state event. * * @param roomId the room id. * @param stateEventType the state event type @@ -198,7 +198,7 @@ internal interface RoomAPI { ): SendResponse /** - * Send a generic state event + * Send a generic state event. * * @param roomId the room id. * @param stateEventType the state event type @@ -220,7 +220,7 @@ internal interface RoomAPI { suspend fun getRoomState(@Path("roomId") roomId: String): List<Event> /** - * Paginate relations for event based in normal topological order + * Paginate relations for event based in normal topological order. * @param relationType filter for this relation type * @param eventType filter for this event type */ @@ -235,7 +235,7 @@ internal interface RoomAPI { ): RelationsResponse /** - * Paginate relations for thread events based in normal topological order + * Paginate relations for thread events based in normal topological order. * @param relationType filter for this relation type */ @GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "rooms/{roomId}/relations/{eventId}/{relationType}") @@ -337,14 +337,14 @@ internal interface RoomAPI { suspend fun getAliases(@Path("roomId") roomId: String): GetAliasesResponse /** - * Inform that the user is starting to type or has stopped typing + * Inform that the user is starting to type or has stopped typing. */ @PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/typing/{userId}") suspend fun sendTypingState(@Path("roomId") roomId: String, @Path("userId") userId: String, @Body body: TypingBody) - /** + /* * Room tagging */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAvatarResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAvatarResolver.kt index 60ad83ee055ebc668b1e7047138c33c8f4b08b36..29a303475bc17898db0d108dad2498e0de0af3dd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAvatarResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAvatarResolver.kt @@ -34,7 +34,7 @@ import javax.inject.Inject internal class RoomAvatarResolver @Inject constructor(@UserId private val userId: String) { /** - * Compute the room avatar url + * Compute the room avatar url. * @param realm: the current instance of realm * @param roomId the roomId of the room to resolve avatar * @return the room avatar url, can be a fallback to a room member avatar or null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt index 5e90076b8af24fb73116c5d52fc9af1830cd56dc..f3845f1f15c93911224c72b339367387088912a6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt @@ -108,14 +108,14 @@ import retrofit2.Retrofit import javax.inject.Qualifier /** - * Used to inject the simple commonmark Parser + * Used to inject the simple commonmark Parser. */ @Qualifier @Retention(AnnotationRetention.RUNTIME) internal annotation class SimpleCommonmarkParser /** - * Used to inject the advanced commonmark Parser + * Used to inject the advanced commonmark Parser. */ @Qualifier @Retention(AnnotationRetention.RUNTIME) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBody.kt index 69352688e3b74382804011f01d9c49fb745ad8b2..cffa632768ca7f2e3fbc02645fa56c8f721877a8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBody.kt @@ -25,7 +25,7 @@ import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset import org.matrix.android.sdk.internal.session.room.membership.threepid.ThreePidInviteBody /** - * Parameter to create a room + * Parameter to create a room. */ @JsonClass(generateAdapter = true) internal data class CreateRoomBody( @@ -108,7 +108,7 @@ internal data class CreateRoomBody( val isDirect: Boolean?, /** - * The power level content to override in the default power level event + * The power level content to override in the default power level event. */ @Json(name = "power_level_content_override") val powerLevelContentOverride: PowerLevelsContent?, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt index 3b2e9d3d2287515dc5796498b611178cf4d82466..faf68d538fd9d8fd52f650a9e040564dfcad826a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt @@ -116,7 +116,8 @@ internal class CreateRoomBodyBuilder @Inject constructor( fileUploader.uploadFromUri( uri = avatarUri, filename = UUID.randomUUID().toString(), - mimeType = MimeTypes.Jpeg) + mimeType = MimeTypes.Jpeg + ) } }?.let { response -> Event( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt index bd9f2ecc36791a67242de1a5d9d010ee953498e1..59e0f81ece88e81435d1c866b77f492d27782104 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt @@ -38,7 +38,7 @@ import org.matrix.android.sdk.internal.util.Normalizer import javax.inject.Inject /** - * This class computes room display name + * This class computes room display name. */ internal class RoomDisplayNameResolver @Inject constructor( matrixConfiguration: MatrixConfiguration, @@ -50,7 +50,7 @@ internal class RoomDisplayNameResolver @Inject constructor( private val roomDisplayNameFallbackProvider = matrixConfiguration.roomDisplayNameFallbackProvider /** - * Compute the room display name + * Compute the room display name. * * @param realm: the current instance of realm * @param roomId: the roomId to resolve the name of. @@ -157,7 +157,7 @@ internal class RoomDisplayNameResolver @Inject constructor( return (name ?: roomId).toRoomName() } - /** See [org.matrix.android.sdk.api.session.room.sender.SenderInfo.disambiguatedDisplayName] */ + /** See [org.matrix.android.sdk.api.session.room.sender.SenderInfo.disambiguatedDisplayName]. */ private fun resolveRoomMemberName(roomMemberSummary: RoomMemberSummaryEntity, roomMemberHelper: RoomMemberHelper): String { val isUnique = roomMemberHelper.isUniqueDisplayName(roomMemberSummary.displayName) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt index 85300fa3518de924f1e6dbf3b108ecb56b7e0951..a1b30a0be562756ebec3d617f9e3b9119ad02305 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt @@ -83,7 +83,8 @@ internal class RoomMemberEventHandler @Inject constructor( roomMember, // When an update is happening, insertOrUpdate replace existing values with null if they are not provided, // but we want to preserve presence record value and not replace it with null - getExistingPresenceState(realm, roomId, userId)) + getExistingPresenceState(realm, roomId, userId) + ) realm.insertOrUpdate(roomMemberEntity) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberHelper.kt index 9ce8db25a5bec865c4412bc7d7c257b096f94e6d..40228fe8c977a1f4372b6dca04d23ed02cde8a59 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberHelper.kt @@ -104,7 +104,7 @@ internal class RoomMemberHelper(private val realm: Realm, } /** - * Return all the roomMembers ids which are joined or invited to the room + * Return all the roomMembers ids which are joined or invited to the room. * * @return a roomMember id list of joined or invited members. */ @@ -113,7 +113,7 @@ internal class RoomMemberHelper(private val realm: Realm, } /** - * Return all the roomMembers ids which are joined to the room + * Return all the roomMembers ids which are joined to the room. * * @return a roomMember id list of joined members. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt index 6306f3c6fee3b8a126d5e7cea13ae2fabbfc22c2..4c631c2182733ba966a0e211bafab0ff6c142be1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.room.membership.joining import io.realm.RealmConfiguration import kotlinx.coroutines.TimeoutCancellationException +import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult import org.matrix.android.sdk.api.session.room.failure.JoinRoomFailure @@ -53,6 +54,7 @@ internal class DefaultJoinRoomTask @Inject constructor( private val readMarkersTask: SetReadMarkersTask, @SessionDatabase private val realmConfiguration: RealmConfiguration, + private val coroutineDispatcher: MatrixCoroutineDispatchers, private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource, private val globalErrorReceiver: GlobalErrorReceiver, private val clock: Clock, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/prune/RedactionEventProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/prune/RedactionEventProcessor.kt index fe7dc28228eda5f39c0a90885d4234b1734df0f1..e926d6a785ab1b859508f5310fe50091fb5c2722 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/prune/RedactionEventProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/prune/RedactionEventProcessor.kt @@ -148,7 +148,8 @@ internal class RedactionEventProcessor @Inject constructor() : EventInsertLivePr EventType.STATE_ROOM_MEMBER -> listOf("membership") EventType.STATE_ROOM_CREATE -> listOf("creator") EventType.STATE_ROOM_JOIN_RULES -> listOf("join_rule") - EventType.STATE_ROOM_POWER_LEVELS -> listOf("users", + EventType.STATE_ROOM_POWER_LEVELS -> listOf( + "users", "users_default", "events", "events_default", @@ -156,7 +157,8 @@ internal class RedactionEventProcessor @Inject constructor() : EventInsertLivePr "ban", "kick", "redact", - "invite") + "invite" + ) EventType.STATE_ROOM_ALIASES -> listOf("aliases") EventType.STATE_ROOM_CANONICAL_ALIAS -> listOf("alias") EventType.FEEDBACK -> listOf("type", "target_event_id") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt index ab514d31c8480951f7ff567eb803562566aba1e8..7b68e2a74c1b3b1efe728301bb65f4fcdcee05e9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt @@ -131,7 +131,8 @@ internal class DefaultRelationService @AssistedInject constructor( replyText = replyText, autoMarkdown = autoMarkdown, rootThreadEventId = rootThreadEventId, - showInThread = showInThread) + showInThread = showInThread + ) ?.also { saveLocalEcho(it) } ?: return null @@ -186,7 +187,8 @@ internal class DefaultRelationService @AssistedInject constructor( text = replyInThreadText, msgType = msgType, autoMarkdown = autoMarkdown, - formattedText = formattedText) + formattedText = formattedText + ) .also { saveLocalEcho(it) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt index 8d35a8fea4cb4fec267ee82051fa85baa78d9f33..dabdd04f60205d9e3b0c986489817e043d92c036 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt @@ -192,7 +192,7 @@ internal class DefaultFetchThreadTimelineTask @Inject constructor( // TODO Reuse this function to all the app /** - * If we don't have any new state on this user, get it from db + * If we don't have any new state on this user, get it from db. */ private fun HashMap<String, RoomMemberContent?>.addSenderState(realm: Realm, roomId: String, senderId: String) { getOrPut(senderId) { @@ -204,7 +204,7 @@ internal class DefaultFetchThreadTimelineTask @Inject constructor( } /** - * Create an EventEntity to be added in the TimelineEventEntity + * Create an EventEntity to be added in the TimelineEventEntity. */ private fun createEventEntity(roomId: String, event: Event, realm: Realm): EventEntity { val ageLocalTs = event.unsignedData?.age?.let { clock.epochMillis() - it } @@ -212,7 +212,7 @@ internal class DefaultFetchThreadTimelineTask @Inject constructor( } /** - * Invoke the event decryption mechanism for a specific event + * Invoke the event decryption mechanism for a specific event. */ private suspend fun decryptIfNeeded(event: Event, roomId: String) { try { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt index 34e38581d1fc0ccd2710387c46b7b2f598fa43e0..8529365858e6bbaeaf34b4b1070ca18645287cde 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt @@ -275,7 +275,8 @@ internal class DefaultSendService @AssistedInject constructor( attachment = it, compressBeforeSending = compressBeforeSending, roomIds = roomIds, - rootThreadEventId = rootThreadEventId) + rootThreadEventId = rootThreadEventId + ) } } @@ -297,7 +298,8 @@ internal class DefaultSendService @AssistedInject constructor( localEchoEventFactory.createMediaEvent( roomId = it, attachment = attachment, - rootThreadEventId = rootThreadId).also { event -> + rootThreadEventId = rootThreadId + ).also { event -> createLocalEcho(event) } } @@ -305,7 +307,7 @@ internal class DefaultSendService @AssistedInject constructor( } /** - * We use the roomId of the local echo event + * We use the roomId of the local echo event. */ private fun internalSendMedia(allLocalEchoes: List<Event>, attachment: ContentAttachmentData, compressBeforeSending: Boolean): Cancelable { val cancelableBag = CancelableBag() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt index d019ffada62a2a6815b13eb72014314b746fe25a..d39088bd6dc54758b7449d1880b481504b89afbe 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt @@ -506,7 +506,7 @@ internal class LocalEchoEventFactory @Inject constructor( } /** - * Enhance sticker to support threads fallback if needed + * Enhance sticker to support threads fallback if needed. */ private fun enhanceStickerIfNeeded(type: String, content: Content?): Content? { var newContent: Content? = null @@ -526,7 +526,7 @@ internal class LocalEchoEventFactory @Inject constructor( } /** - * Creates a thread event related to the already existing root event + * Creates a thread event related to the already existing root event. */ fun createThreadTextEvent( rootThreadEventId: String, @@ -553,7 +553,7 @@ internal class LocalEchoEventFactory @Inject constructor( } /** - * Creates a reply to a regular timeline Event or a thread Event if needed + * Creates a reply to a regular timeline Event or a thread Event if needed. */ fun createReplyTextEvent(roomId: String, eventReplied: TimelineEvent, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt index 9fd45b917fa28f3a0df38abb6994f57de30c4043..bed590fd09816e683f0ed37738ef205813b04f75 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt @@ -221,7 +221,7 @@ internal class LocalEchoRepository @Inject constructor( } /** - * Returns the latest known thread event message, or the rootThreadEventId if no other event found + * Returns the latest known thread event message, or the rootThreadEventId if no other event found. */ fun getLatestThreadEvent(rootThreadEventId: String): String { return realmSessionProvider.withRealm { realm -> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt index 05585a4cb5c6c138963fa993a65ad10a0a90ac51..6a9f86893f005fad2c1f8996f508b17d27fb5f38 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt @@ -78,7 +78,7 @@ internal class MarkdownParser @Inject constructor( text != htmlText && htmlText != "<p>${text.trim()}</p>\n" /** - * The parser makes some mistakes, so deal with it here + * The parser makes some mistakes, so deal with it here. */ private fun String.postTreatment(): String { return this diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt index ecc81492554838d1fdbebb1757003db4bc65dce3..2afca6e554a76d92be906640db22dc5787e9b7f8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt @@ -33,10 +33,10 @@ import timber.log.Timber import javax.inject.Inject /** - * This worker creates a new work for each events passed in parameter + * This worker creates a new work for each events passed in parameter. * - * Possible previous worker: Always [UploadContentWorker] - * Possible next worker : None, but it will post new work to send events, encrypted or not + * Possible previous worker: Always [UploadContentWorker]. + * Possible next worker : None, but it will post new work to send events, encrypted or not. */ internal class MultipleEventSendingDispatcherWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : SessionSafeCoroutineWorker<MultipleEventSendingDispatcherWorker.Params>(context, params, sessionManager, Params::class.java) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/NoMerger.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/NoMerger.kt index b56b2831714160eff582b877589daa6312a33547..6dbd8682d79dd58011f37e8b943a8316c6be1a40 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/NoMerger.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/NoMerger.kt @@ -19,7 +19,7 @@ import androidx.work.Data import androidx.work.InputMerger /** - * InputMerger which takes only the first input, to ensure an appended work will only have the specified parameters + * InputMerger which takes only the first input, to ensure an appended work will only have the specified parameters. */ internal class NoMerger : InputMerger() { override fun merge(inputs: MutableList<Data>): Data { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt index 83c61d28451b3718b190264df985d659e0c5bda7..1c0da4839ab64b3be55b7309c9f504ad55ad6169 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt @@ -30,8 +30,8 @@ import org.matrix.android.sdk.internal.worker.WorkerParamsFactory import javax.inject.Inject /** - * Possible previous worker: None - * Possible next worker : None + * Possible previous worker: None. + * Possible next worker : None. */ internal class RedactEventWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : SessionSafeCoroutineWorker<RedactEventWorker.Params>(context, params, sessionManager, Params::class.java) { @@ -74,9 +74,13 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters, ses else -> { // TODO mark as failed to send? // always return success, or the chain will be stuck for ever! - Result.success(WorkerParamsFactory.toData(params.copy( - lastFailureMessage = it.localizedMessage - ))) + Result.success( + WorkerParamsFactory.toData( + params.copy( + lastFailureMessage = it.localizedMessage + ) + ) + ) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt index ddbe8a61a0f0ef4a45a52933a2a5c8e9a41f824f..bea6069dd69fae281c1313cd2aca4a732c671293 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt @@ -36,8 +36,8 @@ import javax.inject.Inject // private const val MAX_NUMBER_OF_RETRY_BEFORE_FAILING = 3 /** - * Possible previous worker: [EncryptEventWorker] or first worker - * Possible next worker : None + * Possible previous worker: [EncryptEventWorker] or first worker. + * Possible next worker : None. */ internal class SendEventWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : SessionSafeCoroutineWorker<SendEventWorker.Params>(context, params, sessionManager, Params::class.java) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/TextContentExtension.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/TextContentExtension.kt index 8caa99d90a25798af721958d9d73099f17582215..49bc05f40c92f632b5bd6eff298542f576981b8c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/TextContentExtension.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/TextContentExtension.kt @@ -54,7 +54,8 @@ internal fun TextContent.toThreadTextContent( isFallingBack = true, inReplyTo = ReplyToContent( eventId = latestThreadEventId - )), + ) + ), formattedBody = formattedText ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt index a1d3e2c0ac45ea670c85a38cf2f065e6c464cb24..8ef631ad36a499f148fe0c23f0e8b8d5b4ef1ae0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt @@ -64,12 +64,12 @@ internal class EventSenderProcessorCoroutine @Inject constructor( private val waitForNetworkSequencer = SemaphoreCoroutineSequencer() /** - * sequencers use QueuedTask.queueIdentifier as key + * sequencers use QueuedTask.queueIdentifier as key. */ private val sequencers = ConcurrentHashMap<String, CoroutineSequencer>() /** - * cancelableBag use QueuedTask.taskIdentifier as key + * cancelableBag use QueuedTask.taskIdentifier as key. */ private val cancelableBag = ConcurrentHashMap<String, Cancelable>() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/TaskInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/TaskInfo.kt index a03ab778f68ca6980454402350094244b8dd1e64..e216e5109fc22c397d85d51f16c4fed5a30da265 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/TaskInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/TaskInfo.kt @@ -24,8 +24,8 @@ import org.matrix.android.sdk.internal.di.SerializeNulls import org.matrix.android.sdk.internal.network.parsing.RuntimeJsonAdapterFactory /** - * Info that need to be persisted by the sender thread - * With polymorphic moshi parsing + * Info that need to be persisted by the sender thread. + * With polymorphic moshi parsing. */ internal interface TaskInfo { val type: String @@ -37,9 +37,10 @@ internal interface TaskInfo { const val TYPE_REDACT = "TYPE_REDACT" private val moshi = Moshi.Builder() - .add(RuntimeJsonAdapterFactory.of(TaskInfo::class.java, "type", FallbackTaskInfo::class.java) - .registerSubtype(SendEventTaskInfo::class.java, TYPE_SEND) - .registerSubtype(RedactEventTaskInfo::class.java, TYPE_REDACT) + .add( + RuntimeJsonAdapterFactory.of(TaskInfo::class.java, "type", FallbackTaskInfo::class.java) + .registerSubtype(SendEventTaskInfo::class.java, TYPE_SEND) + .registerSubtype(RedactEventTaskInfo::class.java, TYPE_REDACT) ) .add(SerializeNulls.JSON_ADAPTER_FACTORY) .build() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt index e5c7a75cb6bd19e7ccf66e171344c91bc059972d..60231892e104ddf9ef784d0a5bfd18bba898aeae 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt @@ -136,7 +136,7 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private if (joinRules != null) { val body = if (joinRules == RoomJoinRules.RESTRICTED) { RoomJoinRulesContent( - _joinRules = RoomJoinRules.RESTRICTED.value, + joinRulesStr = RoomJoinRules.RESTRICTED.value, allowList = allowList ).toContent() } else { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt index 1f2ec09367d4c996c70445b6dab0a27bf9ff3181..b0c795950e276fd5ea19ec4aadbd6f7bf062a1f1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt @@ -23,8 +23,11 @@ import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.api.util.JsonDict +/** + * Serializable object. + */ @JsonClass(generateAdapter = true) -internal data class SerializablePowerLevelsContent( +internal data class SafePowerLevelContent( @Json(name = "ban") val ban: Int?, @Json(name = "kick") val kick: Int?, @Json(name = "invite") val invite: Int?, @@ -41,7 +44,7 @@ internal data class SerializablePowerLevelsContent( internal fun JsonDict.toSafePowerLevelsContentDict(): JsonDict { return toModel<PowerLevelsContent>() ?.let { content -> - SerializablePowerLevelsContent( + SafePowerLevelContent( ban = content.ban, kick = content.kick, invite = content.invite, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt index 52879d71219264e422502d08e3dab0f163e54566..496bc7097fe1e6b910e50d47bf9d81778e4320a2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt @@ -71,7 +71,7 @@ internal class Graph { } /** - * Depending on the chosen starting point the background edge might change + * Depending on the chosen starting point the background edge might change. */ fun findBackwardEdges(startFrom: GraphNode? = null): List<GraphEdge> { val backwardEdges = mutableSetOf<GraphEdge>() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index 3af579d0507bed867b1dfb4c448d7d11c604d333..611d6dc65e7a84b70885ab60eb21d92962fb613e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -212,7 +212,7 @@ internal class RoomSummaryUpdater @Inject constructor( } /** - * Should be called at the end of the room sync, to check and validate all parent/child relations + * Should be called at the end of the room sync, to check and validate all parent/child relations. */ fun validateSpaceRelationship(realm: Realm) { measureTimeMillis { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/threads/DefaultThreadsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/threads/DefaultThreadsService.kt index b65991347dd3693edab907d8c211243e3c72c544..6c6d6368d1ab775f8d6d9ac17b0c2b03ef6b717f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/threads/DefaultThreadsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/threads/DefaultThreadsService.kt @@ -72,17 +72,21 @@ internal class DefaultThreadsService @AssistedInject constructor( } override suspend fun fetchThreadTimeline(rootThreadEventId: String, from: String, limit: Int) { - fetchThreadTimelineTask.execute(FetchThreadTimelineTask.Params( - roomId = roomId, - rootThreadEventId = rootThreadEventId, - from = from, - limit = limit - )) + fetchThreadTimelineTask.execute( + FetchThreadTimelineTask.Params( + roomId = roomId, + rootThreadEventId = rootThreadEventId, + from = from, + limit = limit + ) + ) } override suspend fun fetchThreadSummaries() { - fetchThreadSummariesTask.execute(FetchThreadSummariesTask.Params( - roomId = roomId - )) + fetchThreadSummariesTask.execute( + FetchThreadSummariesTask.Params( + roomId = roomId + ) + ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/threads/local/DefaultThreadsLocalService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/threads/local/DefaultThreadsLocalService.kt index 3bc36fb2a804c8b9dfc0452a1f63d5a3e774dfbf..296981dfc8e7097efb3da70ed96928762bad7c6c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/threads/local/DefaultThreadsLocalService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/threads/local/DefaultThreadsLocalService.kt @@ -83,7 +83,8 @@ internal class DefaultThreadsLocalService @AssistedInject constructor( realm = it, roomId = roomId, rootThreadEventId = rootThreadEventId, - senderId = userId) + senderId = userId + ) } } @@ -97,7 +98,8 @@ internal class DefaultThreadsLocalService @AssistedInject constructor( monarchy.awaitTransaction { EventEntity.where( realm = it, - eventId = rootThreadEventId).findFirst()?.threadNotificationState = ThreadNotificationState.NO_NEW_MESSAGE + eventId = rootThreadEventId + ).findFirst()?.threadNotificationState = ThreadNotificationState.NO_NEW_MESSAGE } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt index 18fbe73c098e58b831eed28eb4caacd2df24e9e9..fad21c09180f9a3e8d9c9061f5201368408453e9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt @@ -39,6 +39,7 @@ import org.matrix.android.sdk.api.settings.LightweightSettingsStorage import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask import org.matrix.android.sdk.internal.session.room.relation.threads.FetchThreadTimelineTask +import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource import org.matrix.android.sdk.internal.session.sync.handler.room.ReadReceiptHandler import org.matrix.android.sdk.internal.session.sync.handler.room.ThreadsAwarenessHandler import org.matrix.android.sdk.internal.task.SemaphoreCoroutineSequencer @@ -59,6 +60,7 @@ internal class DefaultTimeline( private val settings: TimelineSettings, private val coroutineDispatchers: MatrixCoroutineDispatchers, private val clock: Clock, + stateEventDataSource: StateEventDataSource, paginationTask: PaginationTask, getEventTask: GetContextOfEventTask, fetchTokenAndPaginateTask: FetchTokenAndPaginateTask, @@ -106,7 +108,9 @@ internal class DefaultTimeline( onEventsUpdated = this::sendSignalToPostSnapshot, onEventsDeleted = this::onEventsDeleted, onLimitedTimeline = this::onLimitedTimeline, - onNewTimelineEvents = this::onNewTimelineEvents + onNewTimelineEvents = this::onNewTimelineEvents, + stateEventDataSource = stateEventDataSource, + matrixCoroutineDispatchers = coroutineDispatchers, ) private var strategy: LoadTimelineStrategy = buildStrategy(LoadTimelineStrategy.Mode.Live) @@ -291,7 +295,6 @@ internal class DefaultTimeline( } } - @Suppress("EXPERIMENTAL_API_USAGE") private fun listenToPostSnapshotSignals() { postSnapshotSignalFlow .sample(150) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt index 849d7bd7ab6b195b244b3173dbec48a4a5757620..53c025387668a2cd3d5fee93e76959dd2969f0b1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt @@ -32,6 +32,7 @@ import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask import org.matrix.android.sdk.internal.session.room.relation.threads.FetchThreadTimelineTask +import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource import org.matrix.android.sdk.internal.session.sync.handler.room.ReadReceiptHandler import org.matrix.android.sdk.internal.session.sync.handler.room.ThreadsAwarenessHandler import org.matrix.android.sdk.internal.util.time.Clock @@ -53,7 +54,8 @@ internal class DefaultTimelineService @AssistedInject constructor( private val coroutineDispatchers: MatrixCoroutineDispatchers, private val timelineEventDataSource: TimelineEventDataSource, private val clock: Clock, - ) : TimelineService { + private val stateEventDataSource: StateEventDataSource, +) : TimelineService { @AssistedFactory interface Factory { @@ -78,7 +80,8 @@ internal class DefaultTimelineService @AssistedInject constructor( getEventTask = contextOfEventTask, threadsAwarenessHandler = threadsAwarenessHandler, lightweightSettingsStorage = lightweightSettingsStorage, - clock = clock + clock = clock, + stateEventDataSource = stateEventDataSource, ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LiveRoomStateListener.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LiveRoomStateListener.kt new file mode 100644 index 0000000000000000000000000000000000000000..b2692bf8051c7924a3c1c6573447c85b4bad48eb --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LiveRoomStateListener.kt @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022 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.session.room.timeline + +import androidx.lifecycle.LiveData +import androidx.lifecycle.Observer +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.withContext +import org.matrix.android.sdk.api.query.QueryStringValue +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.room.model.RoomMemberContent +import org.matrix.android.sdk.internal.session.events.getFixedRoomMemberContent +import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource + +/** + * Helper to observe and query the live room state. + */ +internal class LiveRoomStateListener( + roomId: String, + stateEventDataSource: StateEventDataSource, + private val mainDispatcher: CoroutineDispatcher, +) { + private val roomStateObserver = Observer<List<Event>> { stateEvents -> + stateEvents.map { event -> + val memberContent = event.getFixedRoomMemberContent() ?: return@map + val stateKey = event.stateKey ?: return@map + liveRoomState[stateKey] = memberContent + } + } + private val stateEventsLiveData: LiveData<List<Event>> by lazy { + stateEventDataSource.getStateEventsLive( + roomId = roomId, + eventTypes = setOf(EventType.STATE_ROOM_MEMBER), + stateKey = QueryStringValue.NoCondition, + ) + } + + private val liveRoomState = mutableMapOf<String, RoomMemberContent>() + + suspend fun start() = withContext(mainDispatcher) { + stateEventsLiveData.observeForever(roomStateObserver) + } + + suspend fun stop() = withContext(mainDispatcher) { + if (stateEventsLiveData.hasActiveObservers()) { + stateEventsLiveData.removeObserver(roomStateObserver) + } + } + + fun getLiveState(stateKey: String): RoomMemberContent? = liveRoomState[stateKey] +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt index bcf202962c9399a88c8d51b14948137e555c5e31..4f65f85ce4ac31f4c03578068c5f1a3a013a5d9b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt @@ -23,6 +23,7 @@ import io.realm.RealmConfiguration import io.realm.RealmResults import io.realm.kotlin.createObject import kotlinx.coroutines.CompletableDeferred +import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError @@ -41,6 +42,7 @@ import org.matrix.android.sdk.internal.database.query.findAllIncludingEvents import org.matrix.android.sdk.internal.database.query.findLastForwardChunkOfThread import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.session.room.relation.threads.FetchThreadTimelineTask +import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource import org.matrix.android.sdk.internal.session.sync.handler.room.ThreadsAwarenessHandler import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber @@ -100,7 +102,9 @@ internal class LoadTimelineStrategy constructor( val onEventsUpdated: (Boolean) -> Unit, val onEventsDeleted: () -> Unit, val onLimitedTimeline: () -> Unit, - val onNewTimelineEvents: (List<String>) -> Unit + val onNewTimelineEvents: (List<String>) -> Unit, + val stateEventDataSource: StateEventDataSource, + val matrixCoroutineDispatchers: MatrixCoroutineDispatchers, ) private var getContextLatch: CompletableDeferred<Unit>? = null @@ -165,7 +169,13 @@ internal class LoadTimelineStrategy constructor( onEventsUpdated = dependencies.onEventsUpdated ) - fun onStart() { + private val liveRoomStateListener = LiveRoomStateListener( + roomId, + dependencies.stateEventDataSource, + dependencies.matrixCoroutineDispatchers.main + ) + + suspend fun onStart() { dependencies.eventDecryptor.start() dependencies.timelineInput.listeners.add(timelineInputListener) val realm = dependencies.realm.get() @@ -174,9 +184,13 @@ internal class LoadTimelineStrategy constructor( it.addChangeListener(chunkEntityListener) timelineChunk = it.createTimelineChunk() } + + if (dependencies.timelineSettings.useLiveSenderInfo) { + liveRoomStateListener.start() + } } - fun onStop() { + suspend fun onStop() { dependencies.eventDecryptor.destroy() dependencies.timelineInput.listeners.remove(timelineInputListener) chunkEntity?.removeChangeListener(chunkEntityListener) @@ -188,6 +202,9 @@ internal class LoadTimelineStrategy constructor( if (mode is Mode.Thread) { clearThreadChunkEntity(dependencies.realm.get(), mode.rootThreadEventId) } + if (dependencies.timelineSettings.useLiveSenderInfo) { + liveRoomStateListener.stop() + } } suspend fun loadMore(count: Int, direction: Timeline.Direction, fetchOnServerIfNeeded: Boolean = true): LoadMoreResult { @@ -222,7 +239,22 @@ internal class LoadTimelineStrategy constructor( } fun buildSnapshot(): List<TimelineEvent> { - return buildSendingEvents() + timelineChunk?.builtItems(includesNext = true, includesPrev = true).orEmpty() + val events = buildSendingEvents() + timelineChunk?.builtItems(includesNext = true, includesPrev = true).orEmpty() + return if (dependencies.timelineSettings.useLiveSenderInfo) { + events.map(this::applyLiveRoomState) + } else { + events + } + } + + private fun applyLiveRoomState(event: TimelineEvent): TimelineEvent { + val updatedState = liveRoomStateListener.getLiveState(event.senderInfo.userId) + return if (updatedState != null) { + val updatedSenderInfo = event.senderInfo.copy(avatarUrl = updatedState.avatarUrl, displayName = updatedState.displayName) + event.copy(senderInfo = updatedSenderInfo) + } else { + event + } } private fun buildSendingEvents(): List<TimelineEvent> { @@ -255,7 +287,7 @@ internal class LoadTimelineStrategy constructor( /** * Clear any existing thread chunk entity and create a new one, with the - * rootThreadEventId included + * rootThreadEventId included. */ private fun recreateThreadChunkEntity(realm: Realm, rootThreadEventId: String) { realm.executeTransaction { @@ -275,7 +307,7 @@ internal class LoadTimelineStrategy constructor( } /** - * Clear any existing thread chunk + * Clear any existing thread chunk. */ private fun clearThreadChunkEntity(realm: Realm, rootThreadEventId: String) { realm.executeTransaction { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt index 27f4245b22803d070865454db93e5478247bab35..6a5f9da8a64400255e9873968c870ec393b0095d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt @@ -136,6 +136,7 @@ internal class TimelineChunk( val prevEvents = prevChunk?.builtItems(includesNext = false, includesPrev = true).orEmpty() deepBuiltItems.addAll(prevEvents) } + return deepBuiltItems } @@ -180,12 +181,14 @@ internal class TimelineChunk( val rootThreadEventId = timelineSettings.rootThreadEventId ?: return LoadMoreResult.FAILURE return if (direction == Timeline.Direction.BACKWARDS) { try { - fetchThreadTimelineTask.execute(FetchThreadTimelineTask.Params( - roomId, - rootThreadEventId, - chunkEntity.prevToken, - count - )).toLoadMoreResult() + fetchThreadTimelineTask.execute( + FetchThreadTimelineTask.Params( + roomId, + rootThreadEventId, + chunkEntity.prevToken, + count + ) + ).toLoadMoreResult() } catch (failure: Throwable) { Timber.e(failure, "Failed to fetch thread timeline events from the server") LoadMoreResult.FAILURE @@ -236,13 +239,15 @@ internal class TimelineChunk( } /** - * Simple log that displays the number and timeline of loaded events + * Simple log that displays the number and timeline of loaded events. */ private fun logLoadedFromStorage(loadedFromStorage: LoadedFromStorage, direction: Timeline.Direction) { - Timber.v("[" + - "${if (timelineSettings.isThreadTimeline()) "ThreadTimeLine" else "Timeline"}] Has loaded " + - "${loadedFromStorage.numberOfEvents} items from storage in $direction " + - if (timelineSettings.isThreadTimeline() && loadedFromStorage.threadReachedEnd) "[Reached End]" else "") + Timber.v( + "[" + + "${if (timelineSettings.isThreadTimeline()) "ThreadTimeLine" else "Timeline"}] Has loaded " + + "${loadedFromStorage.numberOfEvents} items from storage in $direction " + + if (timelineSettings.isThreadTimeline() && loadedFromStorage.threadReachedEnd) "[Reached End]" else "" + ) } fun getBuiltEventIndex(eventId: String, searchInNext: Boolean, searchInPrev: Boolean): Int? { @@ -361,7 +366,8 @@ internal class TimelineChunk( } return LoadedFromStorage( threadReachedEnd = threadReachedEnd(timelineEvents), - numberOfEvents = timelineEvents.size) + numberOfEvents = timelineEvents.size + ) } /** @@ -375,7 +381,7 @@ internal class TimelineChunk( /** * This function is responsible to fetch and store the root event of a thread event - * in order to be able to display the event to the user appropriately + * in order to be able to display the event to the user appropriately. */ private suspend fun fetchRootThreadEventsIfNeeded(offsetResults: List<TimelineEventEntity>) { val eventEntityList = offsetResults diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt index e5dd8aab304bd88ce008425b706e5eb9a494f666..96ceb6c6dca21ead391b0a860d527f79daee07df 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt @@ -230,7 +230,8 @@ internal class TokenChunkEventPersistor @Inject constructor( roomId = roomId, eventEntity = eventEntity, direction = direction, - roomMemberContentsByUser = roomMemberContentsByUser) + roomMemberContentsByUser = roomMemberContentsByUser + ) if (lightweightSettingsStorage.areThreadMessagesEnabled()) { eventEntity.rootThreadEventId?.let { // This is a thread event diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/UIEchoManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/UIEchoManager.kt index 828e01955a0ab6cedc2d744f1ac249bf1f30b7ae..66bb04400b320b61294fc3b3f982a5d7b8e2b56a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/UIEchoManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/UIEchoManager.kt @@ -44,7 +44,7 @@ internal class UIEchoManager( } /** - * Due to lag of DB updates, we keep some UI echo of some properties to update timeline faster + * Due to lag of DB updates, we keep some UI echo of some properties to update timeline faster. */ private val inMemorySendingStates = Collections.synchronizedMap<String, SendState>(HashMap()) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt index b76829e8937eda5fce2a22b5a446bab224855cbd..38ccd190204c68dcfa665c863e3574362cabb16d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt @@ -31,7 +31,7 @@ import timber.log.Timber * Rules: * - user is typing: notify the homeserver (true), at least once every 10s * - user stop typing: after 10s delay: notify the homeserver (false) - * - user empty the text composer or quit the timeline screen: notify the homeserver (false) + * - user empty the text composer or quit the timeline screen: notify the homeserver (false). */ internal class DefaultTypingService @AssistedInject constructor( @Assisted private val roomId: String, @@ -53,7 +53,7 @@ internal class DefaultTypingService @AssistedInject constructor( private var lastRequestTimestamp: Long = 0 /** - * Notify to the server that the user is typing and schedule the auto typing off + * Notify to the server that the user is typing and schedule the auto typing off. */ override fun userIsTyping() { val now = SystemClock.elapsedRealtime() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/DefaultSearchService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/DefaultSearchService.kt index 8033b0654da4a2b96f4beb40acec4dfc0cb04a3b..12ca36fa6bb52c31f9ed620cd20145490e050b9f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/DefaultSearchService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/DefaultSearchService.kt @@ -32,15 +32,17 @@ internal class DefaultSearchService @Inject constructor( beforeLimit: Int, afterLimit: Int, includeProfile: Boolean): SearchResult { - return searchTask.execute(SearchTask.Params( - searchTerm = searchTerm, - roomId = roomId, - nextBatch = nextBatch, - orderByRecent = orderByRecent, - limit = limit, - beforeLimit = beforeLimit, - afterLimit = afterLimit, - includeProfile = includeProfile - )) + return searchTask.execute( + SearchTask.Params( + searchTerm = searchTerm, + roomId = roomId, + nextBatch = nextBatch, + orderByRecent = orderByRecent, + limit = limit, + beforeLimit = beforeLimit, + afterLimit = afterLimit, + includeProfile = includeProfile + ) + ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt index fcaf3b60a761a1f156d91fb5c4d2dc06eeaa3432..f785ed42663919975915fe22c3ec88299b7df0f8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt @@ -112,7 +112,7 @@ internal class DefaultSearchTask @Inject constructor( } /** - * Find local events if exists in order to enhance the result with thread summary + * Find local events if exists in order to enhance the result with thread summary. */ private fun findRootThreadEventsFromDB(searchResponseItemList: List<SearchResponseItem>?): List<TimelineEventEntity>? { return realmSessionProvider.withRealm { realm -> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/request/SearchRequestRoomEvents.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/request/SearchRequestRoomEvents.kt index 60643818089d28477bdcf601c86d617525dc9bc9..e78c170a3277d5c69182550253ece049ca857d9e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/request/SearchRequestRoomEvents.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/request/SearchRequestRoomEvents.kt @@ -55,7 +55,7 @@ internal data class SearchRequestRoomEvents( * Requests the server return the current state for each room returned. */ @Json(name = "include_state") - val include_state: Boolean? = null + val includeState: Boolean? = null /** * Requests that the server partitions the result set based on the provided list of keys. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt index 17dc90fdb0e09d32b206f3b2bb886143b9e930d8..07a5cbe5a0249d26f6f26b2c4b07d37dac73e57e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt @@ -129,7 +129,7 @@ internal class SecretStoringUtils @Inject constructor( } /** - * Decrypt a secret that was encrypted by #securelyStoreString() + * Decrypt a secret that was encrypted by #securelyStoreString(). */ @SuppressLint("NewApi") @Throws(Exception::class) @@ -169,8 +169,10 @@ internal class SecretStoringUtils @Inject constructor( if (secretKeyEntry == null) { // we generate it val generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore") - val keyGenSpec = KeyGenParameterSpec.Builder(alias, - KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT) + val keyGenSpec = KeyGenParameterSpec.Builder( + alias, + KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT + ) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setKeySize(128) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/JoinSpaceTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/JoinSpaceTask.kt index 7eeaed4ff62095ec8d7310ffc9c3b2d750672192..a0925cabcce47d3a5ddea3f7c7e67f866b6a5fb5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/JoinSpaceTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/JoinSpaceTask.kt @@ -49,11 +49,13 @@ internal class DefaultJoinSpaceTask @Inject constructor( override suspend fun execute(params: JoinSpaceTask.Params): JoinSpaceResult { Timber.v("## Space: > Joining root space ${params.roomIdOrAlias} ...") try { - joinRoomTask.execute(JoinRoomTask.Params( - params.roomIdOrAlias, - params.reason, - params.viaServers - )) + joinRoomTask.execute( + JoinRoomTask.Params( + params.roomIdOrAlias, + params.reason, + params.viaServers + ) + ) } catch (failure: Throwable) { return JoinSpaceResult.Fail(failure) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceApi.kt index fda9b4b5bc6db6418bb8e54b5d7242cd3452d4bc..d8daa55e150e2bcd64e8be5548de35a0396cabd6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceApi.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceApi.kt @@ -40,7 +40,7 @@ internal interface SpaceApi { @Query("from") from: String?): SpacesResponse /** - * Unstable version of [getSpaceHierarchy] + * Unstable version of [getSpaceHierarchy]. */ @GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "org.matrix.msc2946/rooms/{roomId}/hierarchy") suspend fun getSpaceHierarchyUnstable( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceChildSummaryResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceChildSummaryResponse.kt index b6a9c73d36596323af4f8855b7ac259e4fbad87c..e3f8977ac59bd5dd6ac6547310ee13215fee7b44 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceChildSummaryResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/SpaceChildSummaryResponse.kt @@ -97,7 +97,7 @@ internal data class SpaceChildSummaryResponse( val avatarUrl: String? = null, /** - * Undocumented item + * Undocumented item. */ @Json(name = "m.federate") val isFederated: Boolean = false diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStatusRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStatusRepository.kt index 8e0c3422b933d81806fdfa9126a07f30b19fa6fa..e90df3d39dcd79c20ed084bb3da052aa9c4b03d7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStatusRepository.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStatusRepository.kt @@ -45,7 +45,7 @@ internal interface InitialSyncStatusRepository { } /** - * This class handle the current status of an initial sync and persist it on the disk, to be robust against crash + * This class handle the current status of an initial sync and persist it on the disk, to be robust against crash. */ internal class FileInitialSyncStatusRepository( directory: File, @@ -95,7 +95,7 @@ internal class FileInitialSyncStatusRepository( } /** - * File -> Cache + * File -> Cache. */ private fun readFile() { cache = file @@ -104,7 +104,7 @@ internal class FileInitialSyncStatusRepository( } /** - * Cache -> File + * Cache -> File. */ private fun writeFile() { file.delete() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncEphemeralTemporaryStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncEphemeralTemporaryStore.kt index ef9f468c8645394af7b2e3dd50cc68cd60e0bb22..0e48cddc2d427bbcac6e8ea3eb6fe3f3b666c863 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncEphemeralTemporaryStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncEphemeralTemporaryStore.kt @@ -48,7 +48,7 @@ internal class RoomSyncEphemeralTemporaryStoreFile @Inject constructor( private val roomSyncEphemeralAdapter = moshi.adapter(RoomSyncEphemeral::class.java) /** - * Write RoomSyncEphemeral to a file + * Write RoomSyncEphemeral to a file. */ override fun write(roomId: String, roomSyncEphemeralJson: String) { Timber.w("INIT_SYNC Store ephemeral events for room $roomId") @@ -56,7 +56,7 @@ internal class RoomSyncEphemeralTemporaryStoreFile @Inject constructor( } /** - * Read RoomSyncEphemeral from a file, or null if there is no file to read + * Read RoomSyncEphemeral from a file, or null if there is no file to read. */ override fun read(roomId: String): RoomSyncEphemeral? { return getFile(roomId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncAPI.kt index 73ec0aa7ef1a5891eb7d21f3f6515442bcb1b4f8..6c8a71f35ecd02a6875d2d70fc0e9f5561eb88e6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncAPI.kt @@ -28,7 +28,7 @@ import retrofit2.http.Streaming internal interface SyncAPI { /** - * Set all the timeouts to 1 minute by default + * Set all the timeouts to 1 minute by default. */ @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "sync") suspend fun sync(@QueryMap params: Map<String, String>, @@ -38,7 +38,7 @@ internal interface SyncAPI { ): SyncResponse /** - * Set all the timeouts to 1 minute by default + * Set all the timeouts to 1 minute by default. */ @Streaming @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "sync") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt index 42cd972e0cf93bda572d5ed58d801feba5bfcc20..ce41a4568cdf190c16a47da9739366a8c61a444b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt @@ -29,6 +29,7 @@ import org.matrix.android.sdk.api.session.presence.model.PresenceEnum internal enum class SyncPresence(val value: String) { Offline("offline"), Online("online"), + Busy("busy"), Unavailable("unavailable"); companion object { @@ -36,6 +37,7 @@ internal enum class SyncPresence(val value: String) { return when (presenceEnum) { PresenceEnum.ONLINE -> Online PresenceEnum.OFFLINE -> Offline + PresenceEnum.BUSY -> Busy PresenceEnum.UNAVAILABLE -> Unavailable } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/CryptoSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/CryptoSyncHandler.kt index 429f4985334d77e4f5fefedb72b4a38ecbf32002..dd9576216649bac3d7129c941e64646b05b4d12c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/CryptoSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/CryptoSyncHandler.kt @@ -60,7 +60,7 @@ internal class CryptoSyncHandler @Inject constructor(private val cryptoService: } /** - * Decrypt an encrypted event + * Decrypt an encrypted event. * * @param event the event to decrypt * @param timelineId the timeline identifier diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/PresenceSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/PresenceSyncHandler.kt index 6a7af1dda4a86fa3b005cff30a96cc0fe8c3fabb..0d4c06339b502c295f960a30bb5963d608750f7e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/PresenceSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/PresenceSyncHandler.kt @@ -52,7 +52,7 @@ internal class PresenceSyncHandler @Inject constructor(private val matrixConfigu } /** - * Store user presence to DB and update Direct Rooms and Room Member Summaries accordingly + * Store user presence to DB and update Direct Rooms and Room Member Summaries accordingly. */ private fun storePresenceToDB(realm: Realm, userPresenceEntity: UserPresenceEntity) = realm.copyToRealmOrUpdate(userPresenceEntity)?.apply { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt index 5437a015fdf25d17dfb7bec7796c7c1cbc423d7b..c5d14afac0096ac9afb401b81f2a7e8ca172ead0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt @@ -213,7 +213,7 @@ internal class RoomSyncHandler @Inject constructor( val isInitialSync = insertType == EventInsertType.INITIAL_SYNC val ephemeralResult = (roomSync.ephemeral as? LazyRoomSyncEphemeral.Parsed) - ?._roomSyncEphemeral + ?.roomSyncEphemeral ?.events ?.takeIf { it.isNotEmpty() } ?.let { handleEphemeral(realm, roomId, it, insertType == EventInsertType.INITIAL_SYNC, aggregator) } @@ -382,7 +382,10 @@ internal class RoomSyncHandler @Inject constructor( val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>() val optimizedThreadSummaryMap = hashMapOf<String, EventEntity>() - for (event in eventList) { + for (rawEvent in eventList) { + // It's annoying roomId is not there, but lot of code rely on it. + // And had to do it now as copy would delete all decryption results.. + val event = rawEvent.copy(roomId = roomId) if (event.eventId == null || event.senderId == null || event.type == null) { continue } @@ -454,7 +457,7 @@ internal class RoomSyncHandler @Inject constructor( } } // Give info to crypto module - cryptoService.onLiveEvent(roomEntity.roomId, event) + cryptoService.onLiveEvent(roomEntity.roomId, event, isInitialSync) // Try to remove local echo event.unsignedData?.transactionId?.also { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ThreadsAwarenessHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ThreadsAwarenessHandler.kt index efc8e39a18d8873fab3926a35ea9ef0633aba034..03e076c217726f29c2d0ebffb36b04b55a9c3349 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ThreadsAwarenessHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ThreadsAwarenessHandler.kt @@ -73,7 +73,7 @@ internal class ThreadsAwarenessHandler @Inject constructor( private val cacheEventRootId = hashSetOf<String>() /** - * Fetch root thread events if they are missing from the local storage + * Fetch root thread events if they are missing from the local storage. * @param syncResponse the sync response */ suspend fun fetchRootThreadEventsIfNeeded(syncResponse: SyncResponse) { @@ -92,7 +92,7 @@ internal class ThreadsAwarenessHandler @Inject constructor( } /** - * Fetch root thread events if they are missing from the local storage + * Fetch root thread events if they are missing from the local storage. * @param eventList a list with the events to examine */ suspend fun fetchRootThreadEventsIfNeeded(eventList: List<Event>) { @@ -115,7 +115,7 @@ internal class ThreadsAwarenessHandler @Inject constructor( } /** - * Fetch multiple unique events using the fetchEvent function + * Fetch multiple unique events using the fetchEvent function. */ private suspend fun fetchThreadsEvents(threadsToFetch: Map<String, String>) { val eventEntityList = threadsToFetch.mapNotNull { (eventId, roomId) -> @@ -153,7 +153,7 @@ internal class ThreadsAwarenessHandler @Inject constructor( } /** - * Handle events mainly coming from the RoomSyncHandler + * Handle events mainly coming from the RoomSyncHandler. * @return The content to inject in the roomSyncHandler live events */ fun makeEventThreadAware(realm: Realm, @@ -186,7 +186,8 @@ internal class ThreadsAwarenessHandler @Inject constructor( eventBody = eventBody, eventToInject = eventToInject, eventToInjectBody = eventToInjectBody, - threadRelation = threadRelation) ?: return null + threadRelation = threadRelation + ) ?: return null // update the event contentForNonEncrypted = updateEventEntity(event, eventEntity, eventPayload, messageTextContent) @@ -225,9 +226,9 @@ internal class ThreadsAwarenessHandler @Inject constructor( } /** - * This function is responsible to check if there is any event that relates to our current event + * This function is responsible to check if there is any event that relates to our current event. * This is useful when we receive an event that relates to a missing parent, so when later we receive the parent - * we can update the child as well + * we can update the child as well. * @param event the current event that we examine * @param eventBody the current body of the event * @param isFromCache determines whether or not we already know this is root thread event @@ -253,7 +254,8 @@ internal class ThreadsAwarenessHandler @Inject constructor( eventBody = newEventBody, eventToInject = event, eventToInjectBody = eventBody, - threadRelation = threadRelation) ?: return null + threadRelation = threadRelation + ) ?: return null return updateEventEntity(newEventFound, eventEntityFound, newEventPayload, messageTextContent) } @@ -261,7 +263,7 @@ internal class ThreadsAwarenessHandler @Inject constructor( } /** - * Actual update the eventEntity with the new payload + * Actual update the eventEntity with the new payload. * @return the content to inject when this is executed by RoomSyncHandler */ private fun updateEventEntity(event: Event, @@ -289,7 +291,7 @@ internal class ThreadsAwarenessHandler @Inject constructor( } /** - * Injecting $eventToInject decrypted content as a reply to $event + * Injecting $eventToInject decrypted content as a reply to $event. * @param eventToInject the event that will inject * @param eventBody the actual event body * @return The final content with the injected event @@ -309,7 +311,8 @@ internal class ThreadsAwarenessHandler @Inject constructor( userLink, eventIdToInjectSenderId, eventToInjectBody, - eventBody) + eventBody + ) return MessageTextContent( relatesTo = threadRelation, @@ -321,7 +324,7 @@ internal class ThreadsAwarenessHandler @Inject constructor( } /** - * Integrate fallback Quote reply + * Integrate fallback Quote reply. */ private fun injectFallbackIndicator(event: Event, eventBody: String, @@ -330,7 +333,8 @@ internal class ThreadsAwarenessHandler @Inject constructor( threadRelation: RelationDefaultContent?): String? { val replyFormatted = LocalEchoEventFactory.QUOTE_PATTERN.format( "In reply to a thread", - eventBody) + eventBody + ) val messageTextContent = MessageTextContent( relatesTo = threadRelation, @@ -360,7 +364,7 @@ internal class ThreadsAwarenessHandler @Inject constructor( /** * Try to get the event form the local DB, if the event does not exist null - * will be returned + * will be returned. */ private fun getEventFromDB(realm: Realm, eventId: String): Event? { val eventEntity = EventEntity.where(realm, eventId = eventId).findFirst() ?: return null @@ -368,14 +372,14 @@ internal class ThreadsAwarenessHandler @Inject constructor( } /** - * Returns True if the event is a thread + * Returns True if the event is a thread. * @param event */ private fun isThreadEvent(event: Event): Boolean = event.content.toModel<MessageRelationContent>()?.relatesTo?.type == RelationType.THREAD /** - * Returns the root thread eventId or null otherwise + * Returns the root thread eventId or null otherwise. * @param event */ private fun getRootThreadEventId(event: Event): String? = diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt index f183c4cb28cd5c67f139270255114c817925e6f3..bbb18b664c6bf43a72b9024c7f593a243800cad4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt @@ -38,8 +38,8 @@ private const val DEFAULT_LONG_POOL_TIMEOUT_SECONDS = 6L private const val DEFAULT_DELAY_MILLIS = 30_000L /** - * Possible previous worker: None - * Possible next worker : None + * Possible previous worker: None. + * Possible next worker : None. */ internal class SyncWorker(context: Context, workerParameters: WorkerParameters, sessionManager: SessionManager) : SessionSafeCoroutineWorker<SyncWorker.Params>(context, workerParameters, sessionManager, Params::class.java) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DeviceInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DeviceInfo.kt index fdb9916190bffb60a98db00b3cc8a4b6ac4c5d10..7f6759906f2a4284f4232c6588ca6598064785cd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DeviceInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DeviceInfo.kt @@ -19,24 +19,24 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * This class describes the device information + * This class describes the device information. */ @JsonClass(generateAdapter = true) internal data class DeviceInfo( /** - * The owner user id + * The owner user id. */ @Json(name = "user_id") val userId: String? = null, /** - * The device id + * The device id. */ @Json(name = "device_id") val deviceId: String? = null, /** - * The device display name + * The device display name. */ @Json(name = "display_name") val displayName: String? = null, @@ -48,7 +48,7 @@ internal data class DeviceInfo( val lastSeenTs: Long = 0, /** - * The last ip address + * The last ip address. */ @Json(name = "last_seen_ip") val lastSeenIp: String? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DevicesListResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DevicesListResponse.kt index 3dc71a355dbd0dd07f5b33bf40b21b588deb1ee7..acef22a5429323dcaf84eebb2dac9097cfcee510 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DevicesListResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DevicesListResponse.kt @@ -17,9 +17,6 @@ package org.matrix.android.sdk.internal.session.sync.model import com.squareup.moshi.JsonClass -/** - * This class describes the - */ @JsonClass(generateAdapter = true) internal data class DevicesListResponse( val devices: List<DeviceInfo>? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/DirectMessagesContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/DirectMessagesContent.kt index 7c73f1fed0762f70f5b750553c9e9c8485d34f8e..2e45b2ad985ba52de67934d087d70bd4fb291e95 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/DirectMessagesContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/DirectMessagesContent.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.sync.model.accountdata /** - * Keys are userIds, values are list of roomIds + * Keys are userIds, values are list of roomIds. */ internal typealias DirectMessagesContent = Map<String, List<String>> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/AcceptTermsBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/AcceptTermsBody.kt index ee23c9e6bc4c3b39c0c525e2ac051c857abba0b1..bf954b0aee7fb6ee7cca927b34a99d7160850d90 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/AcceptTermsBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/AcceptTermsBody.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * This class represent a list of urls of terms the user wants to accept + * This class represent a list of urls of terms the user wants to accept. */ @JsonClass(generateAdapter = true) internal data class AcceptTermsBody( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt index 5f62f40ab3f45ace08f439fe87966abd30d723a0..9876643bed1a6c8ca3ff0c3ced398ef91183d11b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt @@ -61,7 +61,7 @@ internal class DefaultTermsService @Inject constructor( } /** - * We use a trick here to get the homeserver T&C, we use the register API + * We use a trick here to get the homeserver T&C, we use the register API. */ override suspend fun getHomeserverTerms(baseUrl: String): TermsResponse { return try { @@ -108,9 +108,11 @@ internal class DefaultTermsService @Inject constructor( val newList = listOfAcceptedTerms.toMutableSet().apply { addAll(agreedUrls) }.toList() - updateUserAccountDataTask.execute(UpdateUserAccountDataTask.AcceptedTermsParams( - acceptedTermsContent = AcceptedTermsContent(newList) - )) + updateUserAccountDataTask.execute( + UpdateUserAccountDataTask.AcceptedTermsParams( + acceptedTermsContent = AcceptedTermsContent(newList) + ) + ) } private suspend fun getToken(url: String): String { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt index 1f117de67e529e7303d66cc83becba4da03be002..f6f57bf0ef0919b0c4fc4dfbc720d9186c6ccf80 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt @@ -28,13 +28,13 @@ import retrofit2.http.Url internal interface TermsAPI { /** - * This request does not require authentication + * This request does not require authentication. */ @GET suspend fun getTerms(@Url url: String): TermsResponse /** - * This request requires authentication + * This request requires authentication. */ @POST suspend fun agreeToTerms(@Url url: String, @@ -43,7 +43,7 @@ internal interface TermsAPI { /** * API to retrieve the terms for a homeserver. The API /terms does not exist yet, so retrieve the terms from the login flow. - * We do not care about the result (Credentials) + * We do not care about the result (Credentials). */ @POST suspend fun register(@Url url: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/typing/DefaultTypingUsersTracker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/typing/DefaultTypingUsersTracker.kt index c5c3fc4b59525920c2679e001b688146de6f4e66..ac4a886aa3567ac7d83ed627b5d6fe423a920ae5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/typing/DefaultTypingUsersTracker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/typing/DefaultTypingUsersTracker.kt @@ -27,7 +27,7 @@ internal class DefaultTypingUsersTracker @Inject constructor() : TypingUsersTrac private val typingUsers = mutableMapOf<String, List<SenderInfo>>() /** - * Set all currently typing users for a room (excluding yourself) + * Set all currently typing users for a room (excluding yourself). */ fun setTypingUsersFromRoom(roomId: String, senderInfoList: List<SenderInfo>) { val hasNewValue = typingUsers[roomId] != senderInfoList diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/AccountDataContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/AccountDataContent.kt index 5f9f0777d8b5915c473772907022ab63f8aa0ca2..c3daa2a0e9820c54353c66bc3e1a874d5c638fc8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/AccountDataContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/AccountDataContent.kt @@ -17,6 +17,6 @@ package org.matrix.android.sdk.internal.session.user.accountdata /** - * Tag class to identify every account data content + * Tag class to identify every account data content. */ internal interface AccountDataContent diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt index 59c4dd671eb25e14ee771a7ca3ffa928773a51a0..df9dcfb903ec533efddbd1b77f93e73e043c7d4b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt @@ -68,7 +68,7 @@ internal class DefaultSessionAccountDataService @Inject constructor( val params = UpdateUserAccountDataTask.AnyParams(type = type, any = content) awaitCallback<Unit> { callback -> updateUserAccountDataTask.configureWith(params) { - this.retryCount = 5 // TODO: Need to refactor retrying out into a helper method. + this.retryCount = 5 // TODO Need to refactor retrying out into a helper method. this.callback = callback } .executeBy(taskExecutor) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveBreadcrumbsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveBreadcrumbsTask.kt index 22af56a169609146b2223aca256dd0feda8be799..148f9d657df46b26884da1fe12707b08b72cd028 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveBreadcrumbsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveBreadcrumbsTask.kt @@ -29,7 +29,7 @@ import org.matrix.android.sdk.internal.util.awaitTransaction import javax.inject.Inject /** - * Save the Breadcrumbs roomId list in DB, either from the sync, or updated locally + * Save the Breadcrumbs roomId list in DB, either from the sync, or updated locally. */ internal interface SaveBreadcrumbsTask : Task<SaveBreadcrumbsTask.Params, Unit> { data class Params( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateBreadcrumbsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateBreadcrumbsTask.kt index 874c2741de807b2d1922a23d8d2aa90db6cf5ba3..c4ea029cbb0f2022b4c47016926b64b2e8ada37a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateBreadcrumbsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateBreadcrumbsTask.kt @@ -60,8 +60,10 @@ internal class DefaultUpdateBreadcrumbsTask @Inject constructor( // FIXME It can remove the previous breadcrumbs, if not synced yet // And update account data - updateUserAccountDataTask.execute(UpdateUserAccountDataTask.BreadcrumbsParams( - breadcrumbsContent = BreadcrumbsContent(newBreadcrumbs) - )) + updateUserAccountDataTask.execute( + UpdateUserAccountDataTask.BreadcrumbsParams( + breadcrumbsContent = BreadcrumbsContent(newBreadcrumbs) + ) + ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/model/SearchUsersParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/model/SearchUsersParams.kt index 46285965b413f9f4441c51abf8f44463c3c366bd..29d957f2bfbe856f7566a5faacdb5f273afd2d30 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/model/SearchUsersParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/model/SearchUsersParams.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing an user search parameters + * Class representing an user search parameters. */ @JsonClass(generateAdapter = true) internal data class SearchUsersParams( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/model/SearchUsersResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/model/SearchUsersResponse.kt index e2a93abde018c563361c2ff2ea7773604cc15f1b..058bf09da698aa2110f2872bf989edceea4ca4e7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/model/SearchUsersResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/model/SearchUsersResponse.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass /** - * Class representing an users search response + * Class representing an users search response. */ @JsonClass(generateAdapter = true) internal data class SearchUsersResponse( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt index 9f42688f7d63ebf732f6328387711dba6c9af310..1da682791618ff56e64b84ec3aafe41878202306 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt @@ -93,7 +93,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(private val mosh */ /** - * Send a boolean response + * Send a boolean response. * * @param response the response * @param eventData the modular data @@ -104,7 +104,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(private val mosh } /** - * Send an integer response + * Send an integer response. * * @param response the response * @param eventData the modular data @@ -114,7 +114,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(private val mosh } /** - * Send an object response + * Send an object response. * * @param response the response * @param eventData the modular data @@ -133,7 +133,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(private val mosh } /** - * Send success + * Send success. * * @param eventData the modular data */ @@ -143,7 +143,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(private val mosh } /** - * Send an error + * Send an error. * * @param message the error message * @param eventData the modular data @@ -151,7 +151,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(private val mosh override fun sendError(message: String, eventData: JsonDict) { Timber.e("## sendError() : eventData $eventData failed $message") - // TODO: JS has an additional optional parameter: nestedError + // TODO JS has an additional optional parameter: nestedError val params = HashMap<String, Map<String, String>>() val subMap = HashMap<String, String>() subMap["message"] = message @@ -160,7 +160,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(private val mosh } /** - * Send the response to the javascript + * Send the response to the javascript. * * @param jsString the response data * @param eventData the modular data diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetsAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetsAPI.kt index bfc243c213a866b942911fd4d48efd6d48bd67d6..b871a317c88c5217afda2c97f385e2918b943d15 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetsAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetsAPI.kt @@ -24,7 +24,7 @@ import retrofit2.http.Query internal interface WidgetsAPI { /** - * register to the server + * Register to the server. * * @param body the body content (Ref: https://github.com/matrix-org/matrix-doc/pull/1961) */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Base64.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Base64.kt index aae8bf19671e66cfd4744278896da24a4019a109..ea7d75a42cef62ef786bb0e1158c8ba20b82c004 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Base64.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Base64.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.util /** - * Base64 URL conversion methods + * Base64 URL conversion methods. */ internal fun base64UrlToBase64(base64Url: String): String { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/MathUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BestChunkSize.kt similarity index 100% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/MathUtils.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BestChunkSize.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CancelableCoroutine.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CancelableCoroutine.kt index f398ee25d8b1831d2e7cdeb1cbd226b0e206e607..74b54943cd9e99573b80f160d441ddc3b8b1f050 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CancelableCoroutine.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CancelableCoroutine.kt @@ -24,7 +24,7 @@ internal fun Job.toCancelable(): Cancelable { } /** - * Private, use the extension above + * Private, use the extension above. */ private class CancelableCoroutine(private val job: Job) : Cancelable { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FailureExt.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FailureExt.kt index 8c78feeac3d883d6d2ab668946a4254e1c86cc49..0d6555570792c6c7568559f1c44a89fad6e1e687 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FailureExt.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FailureExt.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.internal.di.MoshiProvider /** - * Try to extract and serialize a MatrixError, or default to localizedMessage + * Try to extract and serialize a MatrixError, or default to localizedMessage. */ internal fun Throwable.toMatrixErrorStr(): String { return (this as? Failure.ServerError) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt index 3fcf35c127cec270d04dc42c73e592cbf7543d04..1bd704a9e84a4ea2f23c9653d3bebc6cdcdcb82a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt @@ -21,7 +21,7 @@ import java.io.File import java.io.InputStream /** - * Save an input stream to a file with Okio + * Save an input stream to a file with Okio. */ @WorkerThread internal fun writeToFile(inputStream: InputStream, outputFile: File) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/JsonCanonicalizer.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/JsonCanonicalizer.kt index 5994cbcf93fca7ac35a32f0609438f81dbc9de9c..94aa238789fd9dbc8e28bb598a66e2fa744ab3c0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/JsonCanonicalizer.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/JsonCanonicalizer.kt @@ -51,7 +51,7 @@ internal object JsonCanonicalizer { } /** - * Canonicalize a JSON element + * Canonicalize a JSON element. * * @param src the src * @return the canonicalize element diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/SecretKeyAndVersion.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/SecretKeyAndVersion.kt index 40aead5d637f8d6d75462cc781ef67b72ff04a86..79a15546105f4549c86cf395ed507fecdd69a854 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/SecretKeyAndVersion.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/SecretKeyAndVersion.kt @@ -19,14 +19,15 @@ package org.matrix.android.sdk.internal.util import javax.crypto.SecretKey /** - * Tuple which contains the secret key and the version of Android when the key has been generated + * Tuple which contains the secret key and the version of Android when the key has been generated. */ internal data class SecretKeyAndVersion( /** - * the key + * the key. */ val secretKey: SecretKey, /** - * The android version when the key has been generated + * The android version when the key has been generated. */ - val androidVersionWhenTheKeyHasBeenGenerated: Int) + val androidVersionWhenTheKeyHasBeenGenerated: Int +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt index 8a6ec189863849f588054103a06e00a117a44376..d9fd312a6fc1d4a9d2635eff929a219cd88c6a75 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt @@ -20,7 +20,7 @@ import timber.log.Timber import java.util.Locale /** - * Convert a string to an UTF8 String + * Convert a string to an UTF8 String. * * @param s the string to convert * @return the utf-8 string @@ -36,7 +36,7 @@ internal fun convertToUTF8(s: String): String { } /** - * Convert a string from an UTF8 String + * Convert a string from an UTF8 String. * * @param s the string to convert * @return the utf-16 string @@ -76,7 +76,7 @@ internal fun String.caseInsensitiveFind(subString: String): Boolean { internal val spaceChars = "[\u00A0\u2000-\u200B\u2800\u3000]".toRegex() /** - * Strip all the UTF-8 chars which are actually spaces + * Strip all the UTF-8 chars which are actually spaces. */ internal fun String.replaceSpaceChars(replacement: String = "") = replace(spaceChars, replacement) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/UrlUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/UrlUtils.kt index d13753b5ee582e740f22f729c9345d7f203911cd..fbbec1a100985df2227a000d373104c27bae3f35 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/UrlUtils.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/UrlUtils.kt @@ -39,7 +39,7 @@ internal fun String.ensureProtocol(): String { } /** - * Ensure string has trailing / + * Ensure string ends with "/", if not empty. */ internal fun String.ensureTrailingSlash(): String { return when { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/BuildVersionSdkIntProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/BuildVersionSdkIntProvider.kt index b660796ad82d483d993e815171f418bd60d27b0c..515656049a0fe1af25056af5f64aae720a0fd122 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/BuildVersionSdkIntProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/BuildVersionSdkIntProvider.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.util.system internal interface BuildVersionSdkIntProvider { /** - * Return the current version of the Android SDK + * Return the current version of the Android SDK. */ fun get(): Int } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt index 82ff9a321fcc068f35746bd98fc2a9b63099dcc5..0d4a5ac28f25400a56b3c1a39ef498cca8cb6c98 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt @@ -39,16 +39,16 @@ import javax.net.ssl.HttpsURLConnection internal interface GetWellknownTask : Task<GetWellknownTask.Params, WellknownResult> { data class Params( /** - * domain, for instance "matrix.org" + * domain, for instance "matrix.org". * the URL will be https://{domain}/.well-known/matrix/client */ val domain: String, - val homeServerConnectionConfig: HomeServerConnectionConfig? + val homeServerConnectionConfig: HomeServerConnectionConfig ) } /** - * Inspired from AutoDiscovery class from legacy Matrix Android SDK + * Inspired from AutoDiscovery class from legacy Matrix Android SDK. */ internal class DefaultGetWellknownTask @Inject constructor( @Unauthenticated @@ -61,19 +61,15 @@ internal class DefaultGetWellknownTask @Inject constructor( return findClientConfig(params.domain, client) } - private fun buildClient(homeServerConnectionConfig: HomeServerConnectionConfig?): OkHttpClient { - return if (homeServerConnectionConfig != null) { - okHttpClient.get() - .newBuilder() - .addSocketFactory(homeServerConnectionConfig) - .build() - } else { - okHttpClient.get() - } + private fun buildClient(homeServerConnectionConfig: HomeServerConnectionConfig): OkHttpClient { + return okHttpClient.get() + .newBuilder() + .addSocketFactory(homeServerConnectionConfig) + .build() } /** - * Find client config + * Find client config. * * - Do the .well-known request * - validate homeserver url and identity server url if provide in .well-known result @@ -130,7 +126,7 @@ internal class DefaultGetWellknownTask @Inject constructor( } /** - * Return true if homeserver is valid, and (if applicable) if identity server is pingable + * Return true if homeserver is valid, and (if applicable) if identity server is pingable. */ private suspend fun validateHomeServer(homeServerBaseUrl: String, wellKnown: WellKnown, client: OkHttpClient): WellknownResult { val capabilitiesAPI = retrofitFactory.create(client, homeServerBaseUrl) @@ -168,7 +164,7 @@ internal class DefaultGetWellknownTask @Inject constructor( } /** - * Return true if identity server is pingable + * Return true if identity server is pingable. */ private suspend fun validateIdentityServer(identityServerBaseUrl: String, client: OkHttpClient): Boolean { val identityPingApi = retrofitFactory.create(client, identityServerBaseUrl) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/Extensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/Extensions.kt index d36e1647139a89e3568dc51a5b29e85249170506..e822c63b564eac300d59ff41b96a8f03900f18fd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/Extensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/Extensions.kt @@ -20,7 +20,7 @@ import androidx.work.OneTimeWorkRequest import org.matrix.android.sdk.internal.session.room.send.NoMerger /** - * If startChain parameter is true, the builder will have a inputMerger set to [NoMerger] + * If startChain parameter is true, the builder will have a inputMerger set to [NoMerger]. */ internal fun OneTimeWorkRequest.Builder.startChain(startChain: Boolean): OneTimeWorkRequest.Builder { if (startChain) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt index e56b359f7ab08537c58effbf8ce9c1955ed13ed9..95b3662c670c6973e2132ba1cc50f378c196a449 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt @@ -22,11 +22,7 @@ import androidx.work.ListenableWorker import androidx.work.WorkerFactory import androidx.work.WorkerParameters import org.matrix.android.sdk.internal.SessionManager -import org.matrix.android.sdk.internal.crypto.CancelGossipRequestWorker -import org.matrix.android.sdk.internal.crypto.SendGossipRequestWorker -import org.matrix.android.sdk.internal.crypto.SendGossipWorker import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorker -import org.matrix.android.sdk.internal.crypto.verification.SendVerificationMessageWorker import org.matrix.android.sdk.internal.di.MatrixScope import org.matrix.android.sdk.internal.session.content.UploadContentWorker import org.matrix.android.sdk.internal.session.group.GetGroupDataWorker @@ -56,8 +52,6 @@ internal class MatrixWorkerFactory @Inject constructor(private val sessionManage CheckFactoryWorker(appContext, workerParameters, true) AddPusherWorker::class.java.name -> AddPusherWorker(appContext, workerParameters, sessionManager) - CancelGossipRequestWorker::class.java.name -> - CancelGossipRequestWorker(appContext, workerParameters, sessionManager) GetGroupDataWorker::class.java.name -> GetGroupDataWorker(appContext, workerParameters, sessionManager) MultipleEventSendingDispatcherWorker::class.java.name -> @@ -66,12 +60,6 @@ internal class MatrixWorkerFactory @Inject constructor(private val sessionManage RedactEventWorker(appContext, workerParameters, sessionManager) SendEventWorker::class.java.name -> SendEventWorker(appContext, workerParameters, sessionManager) - SendGossipRequestWorker::class.java.name -> - SendGossipRequestWorker(appContext, workerParameters, sessionManager) - SendGossipWorker::class.java.name -> - SendGossipWorker(appContext, workerParameters, sessionManager) - SendVerificationMessageWorker::class.java.name -> - SendVerificationMessageWorker(appContext, workerParameters, sessionManager) SyncWorker::class.java.name -> SyncWorker(appContext, workerParameters, sessionManager) UpdateTrustWorker::class.java.name -> @@ -96,9 +84,11 @@ internal class MatrixWorkerFactory @Inject constructor(private val sessionManage CoroutineWorker(context, workerParameters) { // Called by WorkManager if there is no MatrixWorkerFactory - constructor(context: Context, workerParameters: WorkerParameters) : this(context, + constructor(context: Context, workerParameters: WorkerParameters) : this( + context, workerParameters, - isCreatedByMatrixWorkerFactory = false) + isCreatedByMatrixWorkerFactory = false + ) override suspend fun doWork(): Result { return if (!isCreatedByMatrixWorkerFactory) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt index 334c4580e91dcb254d619a587c18d58fb808a0bd..030f51428ba830fe9d93507d1be67bf9503de9ea 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt @@ -69,7 +69,7 @@ internal abstract class SessionSafeCoroutineWorker<PARAM : SessionWorkerParams>( abstract fun injectWith(injector: SessionComponent) /** - * Should only return Result.Success for workers added to a unique queue + * Should only return Result.Success for workers added to a unique queue. */ abstract suspend fun doSafeWork(params: PARAM): Result diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionWorkerParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionWorkerParams.kt index de36b85660f0d81766280fe335b0c0b3a9eb8489..36d03f7fcfbf03da6fd0224d3b1ac0208eb64bca 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionWorkerParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionWorkerParams.kt @@ -18,14 +18,14 @@ package org.matrix.android.sdk.internal.worker /** * Note about the Worker usage: - * The workers we chain, or when using the append strategy, should never return Result.Failure(), else the chain will be broken forever + * The workers we chain, or when using the append strategy, should never return Result.Failure(), else the chain will be broken forever. */ internal interface SessionWorkerParams { val sessionId: String /** * Null when no error occurs. When chaining Workers, first step is to check that there is no lastFailureMessage from the previous workers - * If it is the case, the worker should just transmit the error and shouldn't do anything else + * If it is the case, the worker should just transmit the error and shouldn't do anything else. */ val lastFailureMessage: String? } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/auth/data/VersionsKtTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/auth/data/VersionsKtTest.kt index 088e16095031cd085e492900a755ae4647fffffe..e1438f47411a4e454601747d5e648f2185af639a 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/auth/data/VersionsKtTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/auth/data/VersionsKtTest.kt @@ -62,12 +62,12 @@ class VersionsKtTest { Versions(supportedVersions = listOf("r0.6.0")).doesServerSupportThreads() shouldBe false Versions(supportedVersions = listOf("r0.9.1")).doesServerSupportThreads() shouldBe false Versions(supportedVersions = listOf("v1.2.0")).doesServerSupportThreads() shouldBe false - Versions(supportedVersions = listOf("v1.3.0")).doesServerSupportThreads() shouldBe true - Versions(supportedVersions = listOf("v1.3.1")).doesServerSupportThreads() shouldBe true - Versions(supportedVersions = listOf("v1.5.1")).doesServerSupportThreads() shouldBe true + Versions(supportedVersions = listOf("v1.3.0")).doesServerSupportThreads() shouldBe false + Versions(supportedVersions = listOf("v1.3.1")).doesServerSupportThreads() shouldBe false + Versions(supportedVersions = listOf("v1.5.1")).doesServerSupportThreads() shouldBe false Versions(supportedVersions = listOf("r0.6.0"), unstableFeatures = mapOf("org.matrix.msc3440.stable" to true)).doesServerSupportThreads() shouldBe true Versions(supportedVersions = listOf("v1.2.1"), unstableFeatures = mapOf("org.matrix.msc3440.stable" to true)).doesServerSupportThreads() shouldBe true Versions(supportedVersions = listOf("r0.6.0"), unstableFeatures = mapOf("org.matrix.msc3440.stable" to false)).doesServerSupportThreads() shouldBe false - Versions(supportedVersions = listOf("v1.4.0"), unstableFeatures = mapOf("org.matrix.msc3440.stable" to false)).doesServerSupportThreads() shouldBe true + Versions(supportedVersions = listOf("v1.4.0"), unstableFeatures = mapOf("org.matrix.msc3440.stable" to false)).doesServerSupportThreads() shouldBe false } } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/pushrules/PushRulesConditionTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/pushrules/PushRulesConditionTest.kt index 95787173da3af05b95f59f40538e82e940a337d8..c4a3404e80d63dc2ba73abf38d6956b855c455dd 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/pushrules/PushRulesConditionTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/pushrules/PushRulesConditionTest.kt @@ -43,7 +43,8 @@ class PushRulesConditionTest : MatrixTest { type = "m.room.message", eventId = "mx0", content = MessageTextContent("m.text", text).toContent(), - originServerTs = 0) + originServerTs = 0 + ) } @Test @@ -62,7 +63,8 @@ class PushRulesConditionTest : MatrixTest { eventId = "mx0", stateKey = "@foo:matrix.org", content = rm.toContent(), - originServerTs = 0) + originServerTs = 0 + ) assert(condition.isSatisfied(simpleTextEvent)) assert(!condition.isSatisfied(simpleRoomMemberEvent)) @@ -131,7 +133,8 @@ class PushRulesConditionTest : MatrixTest { eventId = "mx0", content = MessageTextContent("m.notice", "A").toContent(), originServerTs = 0, - roomId = "2joined").also { + roomId = "2joined" + ).also { assertTrue("Notice", conditionEqual.isSatisfied(it)) } } @@ -175,7 +178,8 @@ class PushRulesConditionTest : MatrixTest { eventId = "mx0", content = MessageTextContent("m.text", "A").toContent(), originServerTs = 0, - roomId = room2JoinedId).also { + roomId = room2JoinedId + ).also { assertFalse("This room does not have 3 members", conditionEqual3.isSatisfied(it, roomGetterStub)) assertFalse("This room does not have 3 members", conditionEqual3Bis.isSatisfied(it, roomGetterStub)) assertTrue("This room has less than 3 members", conditionLessThan3.isSatisfied(it, roomGetterStub)) @@ -186,7 +190,8 @@ class PushRulesConditionTest : MatrixTest { eventId = "mx0", content = MessageTextContent("m.text", "A").toContent(), originServerTs = 0, - roomId = room3JoinedId).also { + roomId = room3JoinedId + ).also { assertTrue("This room has 3 members", conditionEqual3.isSatisfied(it, roomGetterStub)) assertTrue("This room has 3 members", conditionEqual3Bis.isSatisfied(it, roomGetterStub)) assertFalse("This room has more than 3 members", conditionLessThan3.isSatisfied(it, roomGetterStub)) @@ -206,7 +211,8 @@ class PushRulesConditionTest : MatrixTest { eventId = "mx0", content = MessageTextContent("m.text", "How was the cake benoit?").toContent(), originServerTs = 0, - roomId = "2joined") + roomId = "2joined" + ) condition.isSatisfied(event, "how") shouldBe true condition.isSatisfied(event, "How") shouldBe true diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58Test.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58Test.kt index a93883a34401a8d03de1a2e1cce8c0132a3ac7ef..e6fe8fbb00f62f61daf45a736552158e29de2352 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58Test.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58Test.kt @@ -41,13 +41,17 @@ class Base58Test : MatrixTest { @Test fun encode_curve25519() { // Encode a 32 bytes key - assertEquals("4F85ZySpwyY6FuH7mQYyyr5b8nV9zFRBLj92AJa37sMr", - base58encode(("0123456789" + "0123456789" + "0123456789" + "01").toByteArray())) + assertEquals( + "4F85ZySpwyY6FuH7mQYyyr5b8nV9zFRBLj92AJa37sMr", + base58encode(("0123456789" + "0123456789" + "0123456789" + "01").toByteArray()) + ) } @Test fun decode_curve25519() { - assertArrayEquals(("0123456789" + "0123456789" + "0123456789" + "01").toByteArray(), - base58decode("4F85ZySpwyY6FuH7mQYyyr5b8nV9zFRBLj92AJa37sMr")) + assertArrayEquals( + ("0123456789" + "0123456789" + "0123456789" + "01").toByteArray(), + base58decode("4F85ZySpwyY6FuH7mQYyyr5b8nV9zFRBLj92AJa37sMr") + ) } } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKeyTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKeyTest.kt index d4c9da2986e782882e18071a29558cef3657d374..4146e6b3b70c3fa97387c0aaebc8dfd28726400b 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKeyTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKeyTest.kt @@ -32,7 +32,8 @@ class RecoveryKeyTest : MatrixTest { 0x77.toByte(), 0x07.toByte(), 0x6D.toByte(), 0x0A.toByte(), 0x73.toByte(), 0x18.toByte(), 0xA5.toByte(), 0x7D.toByte(), 0x3C.toByte(), 0x16.toByte(), 0xC1.toByte(), 0x72.toByte(), 0x51.toByte(), 0xB2.toByte(), 0x66.toByte(), 0x45.toByte(), 0xDF.toByte(), 0x4C.toByte(), 0x2F.toByte(), 0x87.toByte(), 0xEB.toByte(), 0xC0.toByte(), 0x99.toByte(), 0x2A.toByte(), - 0xB1.toByte(), 0x77.toByte(), 0xFB.toByte(), 0xA5.toByte(), 0x1D.toByte(), 0xB9.toByte(), 0x2C.toByte(), 0x2A.toByte()) + 0xB1.toByte(), 0x77.toByte(), 0xFB.toByte(), 0xA5.toByte(), 0x1D.toByte(), 0xB9.toByte(), 0x2C.toByte(), 0x2A.toByte() + ) @Test fun isValidRecoveryKey_valid_true() { diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/BinaryStringTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/BinaryStringTest.kt index 5a82052d1af3c9ddd359f4e72ea26c525d230233..b7951fcc6eab2225afae26dfd01571577de2aeb8 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/BinaryStringTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/BinaryStringTest.kt @@ -26,7 +26,7 @@ import org.matrix.android.sdk.MatrixTest class BinaryStringTest : MatrixTest { /** - * I want to put bytes to a String, and vice versa + * I want to put bytes to a String, and vice versa. */ @Test fun testNominalCase() { diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/pushers/DefaultAddPusherTaskTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/pushers/DefaultAddPusherTaskTest.kt index 31fd86fe65ecf172a167ac2febfb193973c511ae..32b1d44fb9a5429c25cf1187f358507085b5175e 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/pushers/DefaultAddPusherTaskTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/pushers/DefaultAddPusherTaskTest.kt @@ -81,7 +81,7 @@ class DefaultAddPusherTaskTest { } @Test - fun `given a persisted push entity and SetPush API fails when adding Pusher then mutates persisted result with Failed registration state and rethrows error`() { + fun `given a persisted push entity and SetPush API fails when adding Pusher then mutates persisted result with Failed registration state and rethrows`() { val realmResult = PusherEntity() monarchy.givenWhereReturns(result = realmResult) pushersAPI.givenSetPusherErrors(SocketException()) diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/task/CoroutineSequencersTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/task/CoroutineSequencersTest.kt index 149b964fd25a09f832732887a6f0334ccc2593fa..0cfd9d97a84dcf48ebc0376deacd7c1808a90066 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/task/CoroutineSequencersTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/task/CoroutineSequencersTest.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.internal.task +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.delay @@ -31,8 +33,8 @@ class CoroutineSequencersTest : MatrixTest { private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + @OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class) @Test - @Suppress("EXPERIMENTAL_API_USAGE") fun sequencer_should_run_sequential() { val sequencer = SemaphoreCoroutineSequencer() val results = ArrayList<String>() @@ -60,8 +62,8 @@ class CoroutineSequencersTest : MatrixTest { assertEquals(results[2], "#3") } + @OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class) @Test - @Suppress("EXPERIMENTAL_API_USAGE") fun sequencer_should_run_parallel() { val sequencer1 = SemaphoreCoroutineSequencer() val sequencer2 = SemaphoreCoroutineSequencer() @@ -87,8 +89,8 @@ class CoroutineSequencersTest : MatrixTest { assertEquals(3, results.size) } + @OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class) @Test - @Suppress("EXPERIMENTAL_API_USAGE") fun sequencer_should_jump_to_next_when_current_job_canceled() { val sequencer = SemaphoreCoroutineSequencer() val results = ArrayList<String>()