diff --git a/CHANGES.md b/CHANGES.md
index 905f178526..39ea3f1477 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,76 @@
+Changes in Element v1.6.2 (2023-06-02)
+======================================
+
+Features ✨
+----------
+ - **Element Android is now using the Crypto Rust SDK**. Migration of user's data should be done at first launch after application upgrade. ([#8390](https://github.com/vector-im/element-android/issues/8390))
+ - Marks WebP files as Animated and allows them to play ([#8120](https://github.com/vector-im/element-android/issues/8120))
+ - Updates to protocol used for Sign in with QR code ([#8299](https://github.com/vector-im/element-android/issues/8299))
+ - Updated rust crypto SDK to version 0.3.9 ([#8488](https://github.com/vector-im/element-android/issues/8488))
+
+Bugfixes 🐛
+----------
+ - Fix: Allow users to sign out even if the sign out request fails. ([#4855](https://github.com/vector-im/element-android/issues/4855))
+ - fix: Make some crypto calls suspendable to avoid reported ANR ([#8482](https://github.com/vector-im/element-android/issues/8482))
+
+Other changes
+-------------
+ - Refactoring: Extract a new interface for common access to crypto store between kotlin and rust crypto ([#8470](https://github.com/vector-im/element-android/issues/8470))
+
+
+Changes in Element v1.6.1 (2023-05-25)
+======================================
+
+Corrective release for 1.6.0
+
+Bugfixes 🐛
+----------
+ - Allow stateloss on verification dialogfragment ([#8439](https://github.com/vector-im/element-android/issues/8439))
+ - Fix: Update verification popup text when a re-verification is needed after rust migration (read only sessions) ([#8445](https://github.com/vector-im/element-android/issues/8445))
+ - Fix several performance issues causing app non responsive issues. ([#8454](https://github.com/vector-im/element-android/issues/8454))
+ - Fix: The device list screen from the member profile page was always showing the current user devices (rust crypto). ([#8457](https://github.com/vector-im/element-android/issues/8457))
+
+Other changes
+-------------
+ - Remove UI option to manually verify a specific device of another user (deprecated behaviour) ([#8458](https://github.com/vector-im/element-android/issues/8458))
+
+
+Changes in Element v1.6.0 (2023-05-17)
+======================================
+
+Features ✨
+----------
+ - **Element Android is now using the Crypto Rust SDK**. Migration of user's data should be done at first launch after application upgrade. ([#8390](https://github.com/vector-im/element-android/issues/8390))
+ - Enable free style cropping for camera and gallery images ([#8325](https://github.com/vector-im/element-android/issues/8325))
+
+Bugfixes 🐛
+----------
+ - User pills get lost at message editing ([#748](https://github.com/vector-im/element-android/issues/748))
+ - Upgrade Jitsi SDK from 6.2.2 to 8.1.1. This fixes video call on some Android devices. ([#7619](https://github.com/vector-im/element-android/issues/7619))
+ - Fix duplicate reactions when using full emoji picker. Contributed by @tulir @ Beeper. ([#8327](https://github.com/vector-im/element-android/issues/8327))
+ - Fix: RustCrossSigning service API confusion (identity trusted vs own device trusted by identity) ([#8352](https://github.com/vector-im/element-android/issues/8352))
+ - Allow custom push gateway to use non-default port ([#8376](https://github.com/vector-im/element-android/issues/8376))
+ - Fix crash when opening "Protect access" screen, and various other issue with `repeatOnLifecycle` ([#8410](https://github.com/vector-im/element-android/issues/8410))
+ - RustCrypto: Verification UX not refreshed after scanning a QR code ([#8418](https://github.com/vector-im/element-android/issues/8418))
+
+SDK API changes ⚠️
+------------------
+ - First integration of rust crypto module. See documentation for details `docs/rust_crypto_integration.md` ([#7628](https://github.com/vector-im/element-android/issues/7628))
+ - Add crypto database migration 22, that extract account and olm session to the new rust DB format ([#8405](https://github.com/vector-im/element-android/issues/8405))
+
+Other changes
+-------------
+ - Add an audio alert when the voice broadcast recording is automatically paused ([#8339](https://github.com/vector-im/element-android/issues/8339))
+ - Analytics: add crypto module to E2E events ([#8340](https://github.com/vector-im/element-android/issues/8340))
+ - Bump rust crypto crate to 0.3.5 ([#8354](https://github.com/vector-im/element-android/issues/8354))
+ - Expose Rust SDK Version in Help & About page and in Bug Reports ([#8364](https://github.com/vector-im/element-android/issues/8364))
+ - Matrix-Ids are sometimes shown in notice events instead of display names ([#8365](https://github.com/vector-im/element-android/issues/8365))
+ - CI: Add workflow to run test with crypto flavor ([#8366](https://github.com/vector-im/element-android/issues/8366))
+ - Remove ability to migrate session from Riot to Element. ([#8402](https://github.com/vector-im/element-android/issues/8402))
+ - Improve keyboard navigation and accessibility when using a screen reader. ([#8426](https://github.com/vector-im/element-android/issues/8426))
+ - Updated posthog url (cosmetic, target same server) and added a new sentry env. ([#8436](https://github.com/vector-im/element-android/issues/8436))
+
+
Changes in Element v1.5.32 (2023-04-19)
=======================================
diff --git a/build.gradle b/build.gradle
index 3060747977..a70b54a833 100644
--- a/build.gradle
+++ b/build.gradle
@@ -28,7 +28,7 @@ buildscript {
classpath 'com.google.gms:google-services:4.3.15'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:4.0.0.2929'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6'
- classpath "com.likethesalad.android:stem-plugin:2.4.0"
+ classpath "com.likethesalad.android:stem-plugin:2.4.1"
classpath 'org.owasp:dependency-check-gradle:8.2.1'
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.8.10"
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
diff --git a/changelog.d/748.bugfix b/changelog.d/748.bugfix
deleted file mode 100644
index cc33be0033..0000000000
--- a/changelog.d/748.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-User pills get lost at message editing
\ No newline at end of file
diff --git a/changelog.d/7619.bugfix b/changelog.d/7619.bugfix
deleted file mode 100644
index a41cf5321f..0000000000
--- a/changelog.d/7619.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Upgrade Jitsi SDK from 6.2.2 to 8.1.1. This fixes video call on some Android devices.
diff --git a/changelog.d/7628.sdk b/changelog.d/7628.sdk
deleted file mode 100644
index d9886730fd..0000000000
--- a/changelog.d/7628.sdk
+++ /dev/null
@@ -1 +0,0 @@
-First integration of rust crypto module. See documentation for details `docs/rust_crypto_integration.md`
diff --git a/changelog.d/8325.feature b/changelog.d/8325.feature
deleted file mode 100644
index 59e57838f8..0000000000
--- a/changelog.d/8325.feature
+++ /dev/null
@@ -1 +0,0 @@
-Enable free style cropping for camera and gallery images
diff --git a/changelog.d/8327.bugfix b/changelog.d/8327.bugfix
deleted file mode 100644
index d1e57f4c16..0000000000
--- a/changelog.d/8327.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Fix duplicate reactions when using full emoji picker. Contributed by @tulir @ Beeper.
diff --git a/changelog.d/8339.misc b/changelog.d/8339.misc
deleted file mode 100644
index 2fed9c438b..0000000000
--- a/changelog.d/8339.misc
+++ /dev/null
@@ -1 +0,0 @@
-Add an audio alert when the voice broadcast recording is automatically paused
diff --git a/changelog.d/8340.misc b/changelog.d/8340.misc
deleted file mode 100644
index 52556b5b42..0000000000
--- a/changelog.d/8340.misc
+++ /dev/null
@@ -1 +0,0 @@
-Analytics: add crypto module to E2E events
diff --git a/changelog.d/8352.bugfix b/changelog.d/8352.bugfix
deleted file mode 100644
index 695c02715e..0000000000
--- a/changelog.d/8352.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Fix: RustCrossSigning service API confusion (identity trusted vs own device trusted by identity)
diff --git a/changelog.d/8354.misc b/changelog.d/8354.misc
deleted file mode 100644
index f26be92ed6..0000000000
--- a/changelog.d/8354.misc
+++ /dev/null
@@ -1 +0,0 @@
-Bump rust crypto crate to 0.3.5
diff --git a/changelog.d/8364.misc b/changelog.d/8364.misc
deleted file mode 100644
index 27bf6b975a..0000000000
--- a/changelog.d/8364.misc
+++ /dev/null
@@ -1 +0,0 @@
-Expose Rust SDK Version in Help & About page and in Bug Reports
diff --git a/changelog.d/8365.misc b/changelog.d/8365.misc
deleted file mode 100644
index ef9bbdca04..0000000000
--- a/changelog.d/8365.misc
+++ /dev/null
@@ -1 +0,0 @@
-Matrix-Ids are sometimes shown in notice events instead of display names
diff --git a/changelog.d/8366.misc b/changelog.d/8366.misc
deleted file mode 100644
index 87c5271688..0000000000
--- a/changelog.d/8366.misc
+++ /dev/null
@@ -1 +0,0 @@
-CI: Add workflow to run test with crypto flavor
diff --git a/changelog.d/8376.bugfix b/changelog.d/8376.bugfix
deleted file mode 100644
index 2c30a1e540..0000000000
--- a/changelog.d/8376.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Allow custom push gateway to use non-default port
\ No newline at end of file
diff --git a/changelog.d/8390.feature b/changelog.d/8390.feature
deleted file mode 100644
index cc430a5a42..0000000000
--- a/changelog.d/8390.feature
+++ /dev/null
@@ -1 +0,0 @@
-Element Android is now using the Crypto Rust SDK. Migration of user's data should be done at first launch after application upgrade.
diff --git a/changelog.d/8402.misc b/changelog.d/8402.misc
deleted file mode 100644
index c493b6bf92..0000000000
--- a/changelog.d/8402.misc
+++ /dev/null
@@ -1 +0,0 @@
-Remove ability to migrate session from Riot to Element.
diff --git a/changelog.d/8405.sdk b/changelog.d/8405.sdk
deleted file mode 100644
index c8d165fcdc..0000000000
--- a/changelog.d/8405.sdk
+++ /dev/null
@@ -1 +0,0 @@
-Add crypto database migration 22, that extract account and olm session to the new rust DB format
diff --git a/changelog.d/8410.bugfix b/changelog.d/8410.bugfix
deleted file mode 100644
index f72d02e0b4..0000000000
--- a/changelog.d/8410.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Fix crash when opening "Protect access" screen, and various other issue with `repeatOnLifecycle`
diff --git a/changelog.d/8418.bugfix b/changelog.d/8418.bugfix
deleted file mode 100644
index 9b5a2e2fa4..0000000000
--- a/changelog.d/8418.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-RustCrypto: Verification UX not refreshed after scanning a QR code
diff --git a/changelog.d/8426.misc b/changelog.d/8426.misc
deleted file mode 100644
index 6e3b5013c8..0000000000
--- a/changelog.d/8426.misc
+++ /dev/null
@@ -1 +0,0 @@
-Improve keyboard navigation and accessibility when using a screen reader.
diff --git a/changelog.d/8436.misc b/changelog.d/8436.misc
deleted file mode 100644
index ab174eca5b..0000000000
--- a/changelog.d/8436.misc
+++ /dev/null
@@ -1 +0,0 @@
-Updated posthog url (cosmetic, target same server) and added a new sentry env.
diff --git a/dependencies.gradle b/dependencies.gradle
index 9fbaf5608d..ccf675321d 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -47,7 +47,7 @@ ext.libs = [
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
],
androidx : [
- 'activity' : "androidx.activity:activity-ktx:1.7.1",
+ 'activity' : "androidx.activity:activity-ktx:1.7.2",
'appCompat' : "androidx.appcompat:appcompat:1.6.1",
'biometric' : "androidx.biometric:biometric:1.1.0",
'core' : "androidx.core:core-ktx:1.10.1",
@@ -101,7 +101,7 @@ ext.libs = [
],
element : [
'opusencoder' : "io.element.android:opusencoder:1.1.0",
- 'wysiwyg' : "io.element.android:wysiwyg:2.2.0"
+ 'wysiwyg' : "io.element.android:wysiwyg:2.2.1"
],
squareup : [
'moshi' : "com.squareup.moshi:moshi:$moshi",
diff --git a/fastlane/metadata/android/en-US/changelogs/40106000.txt b/fastlane/metadata/android/en-US/changelogs/40106000.txt
new file mode 100644
index 0000000000..badf979955
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40106000.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Element Android is now using the Crypto Rust SDK.
+Full changelog: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40106010.txt b/fastlane/metadata/android/en-US/changelogs/40106010.txt
new file mode 100644
index 0000000000..badf979955
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40106010.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Element Android is now using the Crypto Rust SDK.
+Full changelog: https://github.com/vector-im/element-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40106020.txt b/fastlane/metadata/android/en-US/changelogs/40106020.txt
new file mode 100644
index 0000000000..badf979955
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40106020.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Element Android is now using the Crypto Rust SDK.
+Full changelog: https://github.com/vector-im/element-android/releases
diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index 3d1a36d4c3..ee7d2fea12 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -328,6 +328,9 @@
Back up
You’ll lose access to your encrypted messages unless you back up your keys before signing out.
+ Cannot reach the homeserver. If you sign out anyway, this device will not be erased from your device list, you may want to remove it using another client.
+ Sign out anyway
+
Loading…
@@ -2446,6 +2449,7 @@
Verify this device
+ App updated
Unable to verify this device
You won’t be able to access encrypted message history. Reset your Secure Message Backup and verification keys to start fresh.
@@ -2465,7 +2469,9 @@
This session is trusted for secure messaging because %1$s (%2$s) verified it:
%1$s (%2$s) signed in using a new session:
- Until this user trusts this session, messages sent to and from it are labeled with warnings. Alternatively, you can manually verify it.
+
+ Until this user trusts this session, messages sent to and from it are labeled with warnings. Alternatively, you can manually verify it.
+ Until this user trusts this session, messages sent to and from it are labeled with warnings.
Initialize CrossSigning
@@ -2707,6 +2713,7 @@
Verify login
Interactively Verify by Emoji
Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.
+ Secure messaging has been improved with the latest update. Please re-verify your device.
Confirm your identity by verifying this login, granting it access to encrypted messages.
Failed to set up Cross Signing
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index 9c230bb400..420b24ab5a 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -63,7 +63,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
- buildConfigField "String", "SDK_VERSION", "\"1.5.34\""
+ buildConfigField "String", "SDK_VERSION", "\"1.6.2\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
@@ -216,8 +216,8 @@ dependencies {
implementation libs.google.phonenumber
- rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.7")
- // rustCryptoApi project(":library:rustCrypto")
+ rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.9")
+// rustCryptoApi project(":library:rustCrypto")
testImplementation libs.tests.junit
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt b/matrix-sdk-android/src/androidTestKotlinCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt
similarity index 100%
rename from matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt
rename to matrix-sdk-android/src/androidTestKotlinCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt b/matrix-sdk-android/src/androidTestKotlinCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt
similarity index 100%
rename from matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt
rename to matrix-sdk-android/src/androidTestKotlinCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt
diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt
index 6ae12aaf3d..719c45a113 100644
--- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt
+++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt
@@ -59,6 +59,7 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionD
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.store.IMXCommonCryptoStore
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreMigration
@@ -254,6 +255,9 @@ internal abstract class CryptoModule {
@Binds
abstract fun bindCryptoStore(store: RealmCryptoStore): IMXCryptoStore
+ @Binds
+ abstract fun bindCommonCryptoStore(store: RealmCryptoStore): IMXCommonCryptoStore
+
@Binds
abstract fun bindSendEventTask(task: DefaultSendEventTask): SendEventTask
diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt
index 1dd02543cb..b25c04aa9b 100755
--- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt
+++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt
@@ -256,7 +256,7 @@ internal class DefaultCryptoService @Inject constructor(
return if (longFormat) olmManager.getDetailedVersion(context) else olmManager.version
}
- override fun getMyCryptoDevice(): CryptoDeviceInfo {
+ override suspend fun getMyCryptoDevice(): CryptoDeviceInfo {
return myDeviceInfoHolder.get().myDevice
}
@@ -506,10 +506,7 @@ internal class DefaultCryptoService @Inject constructor(
null
} else {
withContext(coroutineDispatchers.io) {
- cryptoStore.deviceWithIdentityKey(senderKey).takeIf {
- // check that the claimed user id matches
- it?.userId == userId
- }
+ cryptoStore.deviceWithIdentityKey(userId, senderKey)
}
}
}
@@ -539,7 +536,7 @@ internal class DefaultCryptoService @Inject constructor(
// .executeBy(taskExecutor)
// }
- override fun getCryptoDeviceInfo(userId: String): List {
+ override suspend fun getCryptoDeviceInfo(userId: String): List {
return cryptoStore.getUserDeviceList(userId).orEmpty()
}
//
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt
similarity index 100%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt
rename to matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt
similarity index 100%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt
rename to matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
similarity index 81%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
rename to matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
index a13c15bd1a..fc882e5c1d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
+++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
@@ -28,20 +28,16 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.UserIdentity
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.CryptoRoomInfo
-import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
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.TrailType
import org.matrix.android.sdk.api.session.events.model.Event
-import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
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.model.MXInboundMegolmSessionWrapper
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.db.CryptoStoreAggregator
import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntity
import org.matrix.olm.OlmAccount
import org.matrix.olm.OlmOutboundGroupSession
@@ -49,7 +45,7 @@ import org.matrix.olm.OlmOutboundGroupSession
/**
* The crypto data store.
*/
-internal interface IMXCryptoStore {
+internal interface IMXCryptoStore : IMXCommonCryptoStore {
/**
* @return the device id
@@ -78,21 +74,6 @@ internal interface IMXCryptoStore {
*/
fun getInboundGroupSessions(roomId: String): List
- /**
- * @return true to unilaterally blacklist all unverified devices.
- */
- fun getGlobalBlacklistUnverifiedDevices(): Boolean
-
- /**
- * Set the global override for whether the client should ever send encrypted
- * messages to unverified devices.
- * If false, it can still be overridden per-room.
- * If true, it overrides the per-room settings.
- *
- * @param block true to unilaterally blacklist all
- */
- fun setGlobalBlacklistUnverifiedDevices(block: Boolean)
-
/**
* Enable or disable key gossiping.
* Default is true.
@@ -123,28 +104,6 @@ internal interface IMXCryptoStore {
*/
fun getRoomsListBlacklistUnverifiedDevices(): List
- /**
- * A live status regarding sharing keys for unverified devices in this room.
- *
- * @return Live status
- */
- fun getLiveBlockUnverifiedDevices(roomId: String): LiveData
-
- /**
- * Tell if unverified devices should be blacklisted when sending keys.
- *
- * @return true if should not send keys to unverified devices
- */
- fun getBlockUnverifiedDevices(roomId: String): Boolean
-
- /**
- * Define if encryption keys should be sent to unverified devices in this room.
- *
- * @param roomId the roomId
- * @param block if true will not send keys to unverified devices
- */
- fun blockUnverifiedDevicesInRoom(roomId: String, block: Boolean)
-
/**
* Get the current keys backup version.
*/
@@ -186,16 +145,6 @@ internal interface IMXCryptoStore {
*/
fun deleteStore()
- /**
- * open any existing crypto store.
- */
- fun open()
-
- /**
- * Close the store.
- */
- fun close()
-
/**
* Store the device id.
*
@@ -262,14 +211,6 @@ internal interface IMXCryptoStore {
fun getLiveDeviceWithId(deviceId: String): LiveData>
- fun getMyDevicesInfo(): List
-
- fun getLiveMyDevicesInfo(): LiveData>
-
- fun getLiveMyDevicesInfo(deviceId: String): LiveData>
-
- fun saveMyDevicesInfo(info: List)
-
/**
* Store the crypto algorithm for a room.
*
@@ -278,47 +219,8 @@ internal interface IMXCryptoStore {
*/
fun storeRoomAlgorithm(roomId: String, algorithm: String?)
- /**
- * Provides the algorithm used in a dedicated room.
- *
- * @param roomId the room id
- * @return the algorithm, null is the room is not encrypted
- */
- fun getRoomAlgorithm(roomId: String): String?
-
- fun getRoomCryptoInfo(roomId: String): CryptoRoomInfo?
- fun setAlgorithmInfo(roomId: String, encryption: EncryptionEventContent?)
-
- /**
- * 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
-
- fun shouldEncryptForInvitedMembers(roomId: String): Boolean
-
- /**
- * Sets a boolean flag that will determine whether or not this device should encrypt Events for
- * invited members.
- *
- * @param roomId the room id
- * @param shouldEncryptForInvitedMembers The boolean flag
- */
- fun setShouldEncryptForInvitedMembers(roomId: String, shouldEncryptForInvitedMembers: Boolean)
-
fun shouldShareHistory(roomId: String): Boolean
- /**
- * Sets a boolean flag that will determine whether or not room history (existing inbound sessions)
- * will be shared to new user invites.
- *
- * @param roomId the room id
- * @param shouldShareHistory The boolean flag
- */
- fun setShouldShareHistory(roomId: String, shouldShareHistory: Boolean)
-
/**
* Store a session between the logged-in user and another device.
*
@@ -361,15 +263,6 @@ internal interface IMXCryptoStore {
*/
fun storeInboundGroupSessions(sessions: List)
- /**
- * Retrieve an inbound group session.
- *
- * @param sessionId the session identifier.
- * @param senderKey the base64-encoded curve25519 key of the sender.
- * @return an inbound group session.
- */
- fun getInboundGroupSession(sessionId: String, senderKey: String): MXInboundMegolmSessionWrapper?
-
/**
* Retrieve an inbound group session, filtering shared history.
*
@@ -552,7 +445,6 @@ internal interface IMXCryptoStore {
// fun getCrossSigningPrivateKeysFlow(): Flow>
fun getGlobalCryptoConfig(): GlobalCryptoConfig
- fun getLiveGlobalCryptoConfig(): LiveData
fun saveBackupRecoveryKey(recoveryKey: String?, version: String?)
fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo?
@@ -597,14 +489,8 @@ internal interface IMXCryptoStore {
fun setDeviceKeysUploaded(uploaded: Boolean)
fun areDeviceKeysUploaded(): Boolean
- fun tidyUpDataBase()
fun getOutgoingRoomKeyRequests(inStates: Set): List
- /**
- * Store a bunch of data collected during a sync response treatment. @See [CryptoStoreAggregator].
- */
- fun storeData(cryptoStoreAggregator: CryptoStoreAggregator)
-
/**
* Store a bunch of data related to the users. @See [UserDataToStore].
*/
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
similarity index 99%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
rename to matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
index 2d82f67b9e..e3595f6618 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
+++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
@@ -280,6 +280,19 @@ internal class RealmCryptoStore @Inject constructor(
}
}
+ override fun deviceWithIdentityKey(userId: String, identityKey: String): CryptoDeviceInfo? {
+ return doWithRealm(realmConfiguration) { realm ->
+ realm.where()
+ .equalTo(DeviceInfoEntityFields.USER_ID, userId)
+ .contains(DeviceInfoEntityFields.KEYS_MAP_JSON, identityKey)
+ .findAll()
+ .mapNotNull { CryptoMapper.mapToModel(it) }
+ .firstOrNull {
+ it.identityKey() == identityKey
+ }
+ }
+ }
+
override fun storeUserDevices(userId: String, devices: Map?) {
doRealmTransaction("storeUserDevices", realmConfiguration) { realm ->
storeUserDevices(realm, userId, devices)
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 043d0a29f5..31d11f6730 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
@@ -73,7 +73,7 @@ interface CryptoService {
suspend fun getUserDevices(userId: String): List
- fun getMyCryptoDevice(): CryptoDeviceInfo
+ suspend fun getMyCryptoDevice(): CryptoDeviceInfo
fun getGlobalBlacklistUnverifiedDevices(): Boolean
@@ -130,7 +130,7 @@ interface CryptoService {
suspend fun getCryptoDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo?
- fun getCryptoDeviceInfo(userId: String): List
+ suspend fun getCryptoDeviceInfo(userId: String): List
// fun getCryptoDeviceInfoFlow(userId: String): Flow>
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 d64b2e6e92..fade51600a 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
@@ -37,6 +37,7 @@ interface SignOutService {
/**
* 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
+ * @param ignoreServerRequestError true to ignore server error if any
*/
- suspend fun signOut(signOutFromHomeserver: Boolean)
+ suspend fun signOut(signOutFromHomeserver: Boolean, ignoreServerRequestError: Boolean = false)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt
index 5ec0dedadf..af8ab71a87 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt
@@ -30,6 +30,7 @@ object MimeTypes {
const val BadJpg = "image/jpg"
const val Jpeg = "image/jpeg"
const val Gif = "image/gif"
+ const val Webp = "image/webp"
const val Ogg = "audio/ogg"
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 d1dd0238ba..bbef75a21d 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
@@ -301,6 +301,9 @@ internal class DefaultAuthenticationService @Inject constructor(
val oidcCompatibilityFlow = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == "m.login.sso" && it.delegatedOidcCompatibilty == true }
val flows = if (oidcCompatibilityFlow != null) listOf(oidcCompatibilityFlow) else loginFlowResponse.flows
+ val supportsGetLoginTokenFlow = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == "m.login.token" && it.getLoginToken == true } != null
+
+ @Suppress("DEPRECATION")
return LoginFlowResult(
supportedLoginTypes = flows.orEmpty().mapNotNull { it.type },
ssoIdentityProviders = flows.orEmpty().firstOrNull { it.type == LoginFlowTypes.SSO }?.ssoIdentityProvider,
@@ -309,7 +312,7 @@ internal class DefaultAuthenticationService @Inject constructor(
isOutdatedHomeserver = !versions.isSupportedBySdk(),
hasOidcCompatibilityFlow = oidcCompatibilityFlow != null,
isLogoutDevicesSupported = versions.doesServerSupportLogoutDevices(),
- isLoginWithQrSupported = versions.doesServerSupportQrCodeLogin(),
+ isLoginWithQrSupported = supportsGetLoginTokenFlow || versions.doesServerSupportQrCodeLogin(),
)
}
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 971407388c..ea749a56b8 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
@@ -51,5 +51,13 @@ internal data class LoginFlow(
* See [MSC3824](https://github.com/matrix-org/matrix-spec-proposals/pull/3824)
*/
@Json(name = "org.matrix.msc3824.delegated_oidc_compatibility")
- val delegatedOidcCompatibilty: Boolean? = null
+ val delegatedOidcCompatibilty: Boolean? = null,
+
+ /**
+ * Whether a login flow of type m.login.token could accept a token issued using /login/get_token.
+ *
+ * See https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv1loginget_token
+ */
+ @Json(name = "get_login_token")
+ val getLoginToken: Boolean? = null
)
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 4d8e90cf35..3fe5541b68 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
@@ -54,6 +54,7 @@ private const val FEATURE_ID_ACCESS_TOKEN = "m.id_access_token"
private const val FEATURE_SEPARATE_ADD_AND_BIND = "m.separate_add_and_bind"
private const val FEATURE_THREADS_MSC3440 = "org.matrix.msc3440"
private const val FEATURE_THREADS_MSC3440_STABLE = "org.matrix.msc3440.stable"
+@Deprecated("The availability of stable get_login_token is now exposed as a capability and part of login flow")
private const val FEATURE_QR_CODE_LOGIN = "org.matrix.msc3882"
private const val FEATURE_THREADS_MSC3771 = "org.matrix.msc3771"
private const val FEATURE_THREADS_MSC3773 = "org.matrix.msc3773"
@@ -94,7 +95,9 @@ internal fun Versions.doesServerSupportThreadUnreadNotifications(): Boolean {
return getMaxVersion() >= HomeServerVersion.v1_4_0 || (msc3771 && msc3773)
}
+@Deprecated("The availability of stable get_login_token is now exposed as a capability and part of login flow")
internal fun Versions.doesServerSupportQrCodeLogin(): Boolean {
+ @Suppress("DEPRECATION")
return unstableFeatures?.get(FEATURE_QR_CODE_LOGIN) ?: false
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ShouldEncryptForInvitedMembersUseCase.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ShouldEncryptForInvitedMembersUseCase.kt
index 29a550aad3..7c7c8ce901 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ShouldEncryptForInvitedMembersUseCase.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/ShouldEncryptForInvitedMembersUseCase.kt
@@ -17,11 +17,11 @@
package org.matrix.android.sdk.internal.crypto
import org.matrix.android.sdk.api.crypto.MXCryptoConfig
-import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
+import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
import javax.inject.Inject
internal class ShouldEncryptForInvitedMembersUseCase @Inject constructor(private val cryptoConfig: MXCryptoConfig,
- private val cryptoStore: IMXCryptoStore) {
+ private val cryptoStore: IMXCommonCryptoStore) {
operator fun invoke(roomId: String): Boolean {
return cryptoConfig.enableEncryptionForInvitedMembers && cryptoStore.shouldEncryptForInvitedMembers(roomId)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCommonCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCommonCryptoStore.kt
new file mode 100644
index 0000000000..68b002c087
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCommonCryptoStore.kt
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2023 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
+
+import androidx.lifecycle.LiveData
+import org.matrix.android.sdk.api.session.crypto.GlobalCryptoConfig
+import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
+import org.matrix.android.sdk.api.session.crypto.model.CryptoRoomInfo
+import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
+import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
+import org.matrix.android.sdk.api.util.Optional
+import org.matrix.android.sdk.internal.crypto.model.MXInboundMegolmSessionWrapper
+import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
+
+/**
+ * As a temporary measure rust and kotlin flavor are still using realm to store some crypto
+ * related information. In the near future rust flavor will complitly stop using realm, as soon
+ * as the missing bits are store in rust side (like room encryption settings, ..)
+ * This interface defines what's now used by both flavors.
+ * The actual implementation are moved in each flavors
+ */
+interface IMXCommonCryptoStore {
+
+ /**
+ * Provides the algorithm used in a dedicated room.
+ *
+ * @param roomId the room id
+ * @return the algorithm, null is the room is not encrypted
+ */
+ fun getRoomAlgorithm(roomId: String): String?
+
+ fun getRoomCryptoInfo(roomId: String): CryptoRoomInfo?
+
+ fun setAlgorithmInfo(roomId: String, encryption: EncryptionEventContent?)
+
+ fun roomWasOnceEncrypted(roomId: String): Boolean
+
+ fun saveMyDevicesInfo(info: List)
+
+ // questionable that it's stored in crypto store
+ fun getMyDevicesInfo(): List
+
+ // questionable that it's stored in crypto store
+ fun getLiveMyDevicesInfo(): LiveData>
+
+ // questionable that it's stored in crypto store
+ fun getLiveMyDevicesInfo(deviceId: String): LiveData>
+
+ /**
+ * open any existing crypto store.
+ */
+ fun open()
+ fun tidyUpDataBase()
+
+ /**
+ * Close the store.
+ */
+ fun close()
+
+ /*
+ * Store a bunch of data collected during a sync response treatment. @See [CryptoStoreAggregator].
+ */
+ fun storeData(cryptoStoreAggregator: CryptoStoreAggregator)
+
+ fun shouldEncryptForInvitedMembers(roomId: String): Boolean
+
+ /**
+ * Sets a boolean flag that will determine whether or not room history (existing inbound sessions)
+ * will be shared to new user invites.
+ *
+ * @param roomId the room id
+ * @param shouldShareHistory The boolean flag
+ */
+ fun setShouldShareHistory(roomId: String, shouldShareHistory: Boolean)
+
+ /**
+ * Sets a boolean flag that will determine whether or not this device should encrypt Events for
+ * invited members.
+ *
+ * @param roomId the room id
+ * @param shouldEncryptForInvitedMembers The boolean flag
+ */
+ fun setShouldEncryptForInvitedMembers(roomId: String, shouldEncryptForInvitedMembers: Boolean)
+
+ /**
+ * Define if encryption keys should be sent to unverified devices in this room.
+ *
+ * @param roomId the roomId
+ * @param block if true will not send keys to unverified devices
+ */
+ fun blockUnverifiedDevicesInRoom(roomId: String, block: Boolean)
+
+ /**
+ * Set the global override for whether the client should ever send encrypted
+ * messages to unverified devices.
+ * If false, it can still be overridden per-room.
+ * If true, it overrides the per-room settings.
+ *
+ * @param block true to unilaterally blacklist all
+ */
+ fun setGlobalBlacklistUnverifiedDevices(block: Boolean)
+
+ fun getLiveGlobalCryptoConfig(): LiveData
+
+ /**
+ * @return true to unilaterally blacklist all unverified devices.
+ */
+ fun getGlobalBlacklistUnverifiedDevices(): Boolean
+
+ /**
+ * A live status regarding sharing keys for unverified devices in this room.
+ *
+ * @return Live status
+ */
+ fun getLiveBlockUnverifiedDevices(roomId: String): LiveData
+
+ /**
+ * Tell if unverified devices should be blacklisted when sending keys.
+ *
+ * @return true if should not send keys to unverified devices
+ */
+ fun getBlockUnverifiedDevices(roomId: String): Boolean
+
+ /**
+ * Retrieve a device by its identity key.
+ *
+ * @param userId the device owner
+ * @param identityKey the device identity key (`MXDeviceInfo.identityKey`)
+ * @return the device or null if not found
+ */
+ fun deviceWithIdentityKey(userId: String, identityKey: String): CryptoDeviceInfo?
+
+ /**
+ * Retrieve an inbound group session.
+ * Used in rust for lazy migration
+ *
+ * @param sessionId the session identifier.
+ * @param senderKey the base64-encoded curve25519 key of the sender.
+ * @return an inbound group session.
+ */
+ fun getInboundGroupSession(sessionId: String, senderKey: String): MXInboundMegolmSessionWrapper?
+}
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 95ff44807c..7c60eab08f 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
@@ -71,7 +71,14 @@ internal data class Capabilities(
* True if the user can use m.thread relation, false otherwise.
*/
@Json(name = "m.thread")
- val threads: BooleanCapability? = null
+ val threads: BooleanCapability? = null,
+
+ /**
+ * Capability to indicate if the server supports login token issuance for signing in another device.
+ * True if the user can use /login/get_token, false otherwise.
+ */
+ @Json(name = "m.get_login_token")
+ val getLoginToken: BooleanCapability? = null
)
@JsonClass(generateAdapter = true)
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 ec12695ecd..a368325793 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
@@ -151,8 +151,6 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor(
getVersionResult.doesServerSupportThreads()
homeServerCapabilitiesEntity.canUseThreadReadReceiptsAndNotifications =
getVersionResult.doesServerSupportThreadUnreadNotifications()
- homeServerCapabilitiesEntity.canLoginWithQrCode =
- getVersionResult.doesServerSupportQrCodeLogin()
homeServerCapabilitiesEntity.canRemotelyTogglePushNotificationsOfDevices =
getVersionResult.doesServerSupportRemoteToggleOfPushNotifications()
homeServerCapabilitiesEntity.canRedactEventWithRelations =
@@ -169,10 +167,25 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor(
}
homeServerCapabilitiesEntity.externalAccountManagementUrl = getWellknownResult.wellKnown.unstableDelegatedAuthConfig?.accountManagementUrl
}
+
+ homeServerCapabilitiesEntity.canLoginWithQrCode = canLoginWithQrCode(getCapabilitiesResult, getVersionResult)
+
homeServerCapabilitiesEntity.lastUpdatedTimestamp = Date().time
}
}
+ private fun canLoginWithQrCode(getCapabilitiesResult: GetCapabilitiesResult?, getVersionResult: Versions?): Boolean {
+ // in r0 of MSC3882 an unstable feature was exposed. In stable it is done via /capabilities and /login
+
+ // in stable 1.7 a capability is exposed for the authenticated user
+ if (getCapabilitiesResult?.capabilities?.getLoginToken != null) {
+ return getCapabilitiesResult.capabilities.getLoginToken.enabled == true
+ }
+
+ @Suppress("DEPRECATION")
+ return getVersionResult?.doesServerSupportQrCodeLogin() == true
+ }
+
companion object {
// 8 hours like on Element Web
private const val MIN_DELAY_BETWEEN_TWO_REQUEST_MILLIS = 8 * 60 * 60 * 1000
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventEditValidator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventEditValidator.kt
index 5a66e7e62d..fbf1dc532c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventEditValidator.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventEditValidator.kt
@@ -26,11 +26,10 @@ import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.events.model.toValidDecryptedEvent
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
-import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
-import timber.log.Timber
+import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
import javax.inject.Inject
-internal class EventEditValidator @Inject constructor(val cryptoStore: IMXCryptoStore) {
+internal class EventEditValidator @Inject constructor(val cryptoStore: IMXCommonCryptoStore) {
sealed class EditValidity {
object Valid : EditValidity()
@@ -53,7 +52,6 @@ internal class EventEditValidator @Inject constructor(val cryptoStore: IMXCrypto
* If the original event was encrypted, the replacement should be too.
*/
fun validateEdit(originalEvent: Event?, replaceEvent: Event): EditValidity {
- Timber.v("###REPLACE valide event $originalEvent replaced $replaceEvent")
// we might not know the original event at that time. In this case we can't perform the validation
// Edits should be revalidated when the original event is received
if (originalEvent == null) {
@@ -80,25 +78,21 @@ internal class EventEditValidator @Inject constructor(val cryptoStore: IMXCrypto
val replaceDecrypted = replaceEvent.toValidDecryptedEvent()
?: return EditValidity.Unknown // UTD can't decide
- val originalCryptoSenderId = cryptoStore.deviceWithIdentityKey(originalDecrypted.cryptoSenderKey)?.userId
- val editCryptoSenderId = cryptoStore.deviceWithIdentityKey(replaceDecrypted.cryptoSenderKey)?.userId
+ if (originalEvent.senderId != replaceEvent.senderId) {
+ return EditValidity.Invalid("original event and replacement event must have the same sender")
+ }
+
+ val originalSendingDevice = originalEvent.senderId?.let { cryptoStore.deviceWithIdentityKey(it, originalDecrypted.cryptoSenderKey) }
+ val editSendingDevice = originalEvent.senderId?.let { cryptoStore.deviceWithIdentityKey(it, replaceDecrypted.cryptoSenderKey) }
if (originalDecrypted.getRelationContent()?.type == RelationType.REPLACE) {
return EditValidity.Invalid("The original event must not, itself, have a rel_type of m.replace ")
}
- if (originalCryptoSenderId == null || editCryptoSenderId == null) {
+ if (originalSendingDevice == null || editSendingDevice == null) {
// mm what can we do? we don't know if it's cryptographically from same user?
- // let valid and UI should display send by deleted device warning?
- val bestEffortOriginal = originalCryptoSenderId ?: originalEvent.senderId
- val bestEffortEdit = editCryptoSenderId ?: replaceEvent.senderId
- if (bestEffortOriginal != bestEffortEdit) {
- return EditValidity.Invalid("original event and replacement event must have the same sender")
- }
- } else {
- if (originalCryptoSenderId != editCryptoSenderId) {
- return EditValidity.Invalid("Crypto: original event and replacement event must have the same sender")
- }
+ // maybe it's a deleted device or a not yet downloaded one?
+ return EditValidity.Unknown
}
if (originalDecrypted.type != replaceDecrypted.type) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt
index 36ec5e8dac..73b7ae05fe 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt
@@ -22,6 +22,8 @@ import com.zhuinden.monarchy.Monarchy
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
+import kotlinx.coroutines.withContext
+import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.session.room.model.ReadReceipt
import org.matrix.android.sdk.api.session.room.read.ReadService
import org.matrix.android.sdk.api.util.Optional
@@ -43,7 +45,8 @@ internal class DefaultReadService @AssistedInject constructor(
private val setReadMarkersTask: SetReadMarkersTask,
private val readReceiptsSummaryMapper: ReadReceiptsSummaryMapper,
@UserId private val userId: String,
- private val homeServerCapabilitiesDataSource: HomeServerCapabilitiesDataSource
+ private val homeServerCapabilitiesDataSource: HomeServerCapabilitiesDataSource,
+ private val matrixCoroutineDispatchers: MatrixCoroutineDispatchers,
) : ReadService {
@AssistedFactory
@@ -66,7 +69,7 @@ internal class DefaultReadService @AssistedInject constructor(
setReadMarkersTask.execute(taskParams)
}
- override suspend fun setReadReceipt(eventId: String, threadId: String) {
+ override suspend fun setReadReceipt(eventId: String, threadId: String) = withContext(matrixCoroutineDispatchers.io) {
val readReceiptThreadId = if (homeServerCapabilitiesDataSource.getHomeServerCapabilities()?.canUseThreadReadReceiptsAndNotifications == true) {
threadId
} else {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt
index 8e7592a8b4..5c44931009 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt
@@ -18,6 +18,8 @@ package org.matrix.android.sdk.internal.session.room.read
import com.zhuinden.monarchy.Monarchy
import io.realm.Realm
+import kotlinx.coroutines.withContext
+import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.session.events.model.LocalEcho
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
@@ -64,9 +66,10 @@ internal class DefaultSetReadMarkersTask @Inject constructor(
private val globalErrorReceiver: GlobalErrorReceiver,
private val clock: Clock,
private val homeServerCapabilitiesService: HomeServerCapabilitiesService,
+ private val coroutineDispatchers: MatrixCoroutineDispatchers,
) : SetReadMarkersTask {
- override suspend fun execute(params: SetReadMarkersTask.Params) {
+ override suspend fun execute(params: SetReadMarkersTask.Params) = withContext(coroutineDispatchers.io) {
val markers = mutableMapOf()
Timber.v("Execute set read marker with params: $params")
val latestSyncedEventId = latestSyncedEventId(params.roomId)
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 d29e7d8f36..7176e36e0c 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
@@ -49,7 +49,7 @@ import org.matrix.android.sdk.api.util.CancelableBag
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.api.util.NoOpCancellable
import org.matrix.android.sdk.api.util.TextContent
-import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
+import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
import org.matrix.android.sdk.internal.di.SessionId
import org.matrix.android.sdk.internal.di.WorkManagerProvider
import org.matrix.android.sdk.internal.session.content.UploadContentWorker
@@ -69,7 +69,7 @@ internal class DefaultSendService @AssistedInject constructor(
private val workManagerProvider: WorkManagerProvider,
@SessionId private val sessionId: String,
private val localEchoEventFactory: LocalEchoEventFactory,
- private val cryptoStore: IMXCryptoStore,
+ private val cryptoStore: IMXCommonCryptoStore,
private val taskExecutor: TaskExecutor,
private val localEchoRepository: LocalEchoRepository,
private val eventSenderProcessor: EventSenderProcessor,
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 929fe7b9a6..9ce29c3c08 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
@@ -28,7 +28,7 @@ import org.matrix.android.sdk.api.failure.isLimitExceededError
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.util.Cancelable
-import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
+import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.internal.task.CoroutineSequencer
import org.matrix.android.sdk.internal.task.SemaphoreCoroutineSequencer
@@ -54,7 +54,7 @@ private const val MAX_RETRY_COUNT = 3
*/
@SessionScope
internal class EventSenderProcessorCoroutine @Inject constructor(
- private val cryptoStore: IMXCryptoStore,
+ private val cryptoStore: IMXCommonCryptoStore,
private val sessionParams: SessionParams,
private val queuedTaskFactory: QueuedTaskFactory,
private val taskExecutor: TaskExecutor,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/DefaultSignOutService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/DefaultSignOutService.kt
index 1bb86ecb4b..2c34f1e2d9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/DefaultSignOutService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/DefaultSignOutService.kt
@@ -35,7 +35,12 @@ internal class DefaultSignOutService @Inject constructor(
sessionParamsStore.updateCredentials(credentials)
}
- override suspend fun signOut(signOutFromHomeserver: Boolean) {
- return signOutTask.execute(SignOutTask.Params(signOutFromHomeserver))
+ override suspend fun signOut(signOutFromHomeserver: Boolean, ignoreServerRequestError: Boolean) {
+ return signOutTask.execute(
+ SignOutTask.Params(
+ signOutFromHomeserver = signOutFromHomeserver,
+ ignoreServerRequestError = ignoreServerRequestError
+ )
+ )
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt
index e5213c4696..f8ec23b24d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/signout/SignOutTask.kt
@@ -30,7 +30,8 @@ import javax.inject.Inject
internal interface SignOutTask : Task {
data class Params(
- val signOutFromHomeserver: Boolean
+ val signOutFromHomeserver: Boolean,
+ val ignoreServerRequestError: Boolean,
)
}
@@ -59,7 +60,9 @@ internal class DefaultSignOutTask @Inject constructor(
// Ignore
Timber.w("Ignore error due to https://github.com/matrix-org/synapse/issues/5755")
} else {
- throw throwable
+ if (!params.ignoreServerRequestError) {
+ throw throwable
+ }
}
}
}
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt
index 876109a2a3..cdc5973fa1 100644
--- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt
@@ -58,8 +58,8 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionD
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.store.IMXCryptoStore
-import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore
+import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
+import org.matrix.android.sdk.internal.crypto.store.RustCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreMigration
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreModule
import org.matrix.android.sdk.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
@@ -246,7 +246,7 @@ internal abstract class CryptoModule {
abstract fun bindVerificationService(service: RustVerificationService): VerificationService
@Binds
- abstract fun bindCryptoStore(store: RealmCryptoStore): IMXCryptoStore
+ abstract fun bindCryptoStore(store: RustCryptoStore): IMXCommonCryptoStore
@Binds
abstract fun bindSendEventTask(task: DefaultSendEventTask): SendEventTask
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt
index 2ff4d2d119..3686ab445d 100644
--- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt
@@ -54,6 +54,7 @@ import org.matrix.android.sdk.api.util.toOptional
import org.matrix.android.sdk.internal.coroutines.builder.safeInvokeOnClose
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.DefaultKeysAlgorithmAndData
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysAlgorithmAndData
+import org.matrix.android.sdk.internal.crypto.model.MXInboundMegolmSessionWrapper
import org.matrix.android.sdk.internal.crypto.network.RequestSender
import org.matrix.android.sdk.internal.crypto.verification.SasVerification
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequest
@@ -312,10 +313,10 @@ internal class OlmMachine @Inject constructor(
/**
* Used for lazy migration of inboundGroupSession from EA to ER
*/
- suspend fun importRoomKey(inbound: InboundGroupSessionHolder): Result {
+ suspend fun importRoomKey(inbound: MXInboundMegolmSessionWrapper): Result {
Timber.v("Migration:: Tentative lazy migration")
return withContext(coroutineDispatchers.io) {
- val export = inbound.wrapper.exportKeys()
+ val export = inbound.exportKeys()
?: return@withContext Result.failure(Exception("Failed to export key"))
val result = importDecryptedKeys(listOf(export), null).also {
Timber.v("Migration:: Tentative lazy migration result: ${it.totalNumberOfKeys}")
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/PrepareToEncryptUseCase.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/PrepareToEncryptUseCase.kt
index cce457f6a7..891e1fe3c0 100644
--- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/PrepareToEncryptUseCase.kt
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/PrepareToEncryptUseCase.kt
@@ -28,7 +28,7 @@ import org.matrix.android.sdk.api.logger.LoggerTag
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.internal.crypto.keysbackup.RustKeyBackupService
import org.matrix.android.sdk.internal.crypto.network.RequestSender
-import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
+import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
import org.matrix.rustcomponents.sdk.crypto.EncryptionSettings
@@ -47,7 +47,7 @@ private val loggerTag = LoggerTag("PrepareToEncryptUseCase", LoggerTag.CRYPTO)
internal class PrepareToEncryptUseCase @Inject constructor(
private val olmMachine: OlmMachine,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
- private val cryptoStore: IMXCryptoStore,
+ private val cryptoStore: IMXCommonCryptoStore,
private val getRoomUserIds: GetRoomUserIdsUseCase,
private val requestSender: RequestSender,
private val loadRoomMembersTask: LoadRoomMembersTask,
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt
index 4769d57dc9..57f81ef592 100755
--- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt
@@ -17,7 +17,6 @@
package org.matrix.android.sdk.internal.crypto
import android.content.Context
-import androidx.annotation.VisibleForTesting
import androidx.lifecycle.LiveData
import androidx.lifecycle.map
import androidx.paging.PagedList
@@ -26,7 +25,6 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
@@ -76,7 +74,7 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.RustKeyBackupService
import org.matrix.android.sdk.internal.crypto.model.SessionInfo
import org.matrix.android.sdk.internal.crypto.network.OutgoingRequestsProcessor
import org.matrix.android.sdk.internal.crypto.repository.WarnOnUnknownDeviceRepository
-import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
+import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
import org.matrix.android.sdk.internal.crypto.tasks.DeleteDeviceTask
import org.matrix.android.sdk.internal.crypto.tasks.GetDeviceInfoTask
@@ -111,7 +109,7 @@ internal class RustCryptoService @Inject constructor(
@UserId private val myUserId: String,
@DeviceId private val deviceId: String,
// the crypto store
- private val cryptoStore: IMXCryptoStore,
+ private val cryptoStore: IMXCommonCryptoStore,
// Set of parameters used to configure/customize the end-to-end crypto.
private val mxCryptoConfig: MXCryptoConfig,
// Actions
@@ -185,12 +183,13 @@ internal class RustCryptoService @Inject constructor(
override fun getCryptoVersion(context: Context, longFormat: Boolean): String {
val version = org.matrix.rustcomponents.sdk.crypto.version()
+ val gitHash = org.matrix.rustcomponents.sdk.crypto.versionInfo().gitSha
val vodozemac = org.matrix.rustcomponents.sdk.crypto.vodozemacVersion()
- return if (longFormat) "Rust SDK $version, Vodozemac $vodozemac" else version
+ return if (longFormat) "Rust SDK $version ($gitHash), Vodozemac $vodozemac" else version
}
- override fun getMyCryptoDevice(): CryptoDeviceInfo {
- return runBlocking { olmMachine.ownDevice() }
+ override suspend fun getMyCryptoDevice(): CryptoDeviceInfo = withContext(coroutineDispatchers.io) {
+ olmMachine.ownDevice()
}
override suspend fun fetchDevicesList(): List {
@@ -342,11 +341,11 @@ internal class RustCryptoService @Inject constructor(
*/
override suspend fun getCryptoDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo? {
if (userId.isEmpty() || deviceId.isNullOrEmpty()) return null
- return olmMachine.getCryptoDeviceInfo(userId, deviceId)
+ return withContext(coroutineDispatchers.io) { olmMachine.getCryptoDeviceInfo(userId, deviceId) }
}
- override fun getCryptoDeviceInfo(userId: String): List {
- return runBlocking {
+ override suspend fun getCryptoDeviceInfo(userId: String): List {
+ return withContext(coroutineDispatchers.io) {
olmMachine.getCryptoDeviceInfo(userId)
}
}
@@ -360,9 +359,7 @@ internal class RustCryptoService @Inject constructor(
}
override fun getLiveCryptoDeviceInfo(userIds: List): LiveData> {
- return olmMachine.getLiveDevices(listOf(myUserId)).map {
- it.filter { it.userId == myUserId }
- }
+ return olmMachine.getLiveDevices(userIds)
}
override fun getLiveCryptoDeviceInfoWithId(deviceId: String): LiveData> {
@@ -905,13 +902,6 @@ internal class RustCryptoService @Inject constructor(
// TODO("Not yet implemented")
}
- /* ==========================================================================================
- * For test only
- * ========================================================================================== */
-
- @VisibleForTesting
- val cryptoStoreForTesting = cryptoStore
-
companion object {
const val CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS = 3_600_000 // one hour
}
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/network/RequestSender.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/network/RequestSender.kt
index df041bbf19..b5212ee45a 100644
--- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/network/RequestSender.kt
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/network/RequestSender.kt
@@ -24,6 +24,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
+import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult
@@ -36,7 +37,6 @@ 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.uia.UiaResult
import org.matrix.android.sdk.internal.auth.registration.handleUIA
-import org.matrix.android.sdk.internal.crypto.InboundGroupSessionStore
import org.matrix.android.sdk.internal.crypto.OlmMachine
import org.matrix.android.sdk.internal.crypto.PerSessionBackupQueryRateLimiter
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.BackupKeysResult
@@ -59,6 +59,7 @@ import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadBody
import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadResponse
import org.matrix.android.sdk.internal.crypto.model.rest.RestKeyInfo
import org.matrix.android.sdk.internal.crypto.model.rest.SignatureUploadResponse
+import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
import org.matrix.android.sdk.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
import org.matrix.android.sdk.internal.crypto.tasks.DefaultSendVerificationMessageTask
import org.matrix.android.sdk.internal.crypto.tasks.DownloadKeysForUsersTask
@@ -102,7 +103,7 @@ internal class RequestSender @Inject constructor(
private val moshi: Moshi,
cryptoCoroutineScope: CoroutineScope,
private val rateLimiter: PerSessionBackupQueryRateLimiter,
- private val inboundGroupSessionStore: InboundGroupSessionStore,
+ private val cryptoStore: IMXCommonCryptoStore,
private val localEchoRepository: LocalEchoRepository,
private val olmMachine: Lazy,
) {
@@ -266,7 +267,9 @@ internal class RequestSender @Inject constructor(
val senderKey = requestBody?.get("sender_key") as? String
if (roomId != null && sessionId != null) {
// try to perform a lazy migration from legacy store
- val legacy = inboundGroupSessionStore.getInboundGroupSession(sessionId, senderKey.orEmpty())
+ val legacy = tryOrNull("Failed to access legacy crypto store") {
+ cryptoStore.getInboundGroupSession(sessionId, senderKey.orEmpty())
+ }
if (legacy == null || olmMachine.get().importRoomKey(legacy).isFailure) {
rateLimiter.tryFromBackupIfPossible(sessionId, roomId)
}
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/RustCryptoStore.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/RustCryptoStore.kt
new file mode 100644
index 0000000000..b242a3ed34
--- /dev/null
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/RustCryptoStore.kt
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2023 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
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.Transformations
+import com.zhuinden.monarchy.Monarchy
+import io.realm.Realm
+import io.realm.RealmConfiguration
+import io.realm.kotlin.where
+import kotlinx.coroutines.runBlocking
+import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
+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.GlobalCryptoConfig
+import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
+import org.matrix.android.sdk.api.session.crypto.model.CryptoRoomInfo
+import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
+import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
+import org.matrix.android.sdk.api.util.Optional
+import org.matrix.android.sdk.api.util.toOptional
+import org.matrix.android.sdk.internal.crypto.OlmMachine
+import org.matrix.android.sdk.internal.crypto.model.MXInboundMegolmSessionWrapper
+import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
+import org.matrix.android.sdk.internal.crypto.store.db.doRealmTransaction
+import org.matrix.android.sdk.internal.crypto.store.db.doRealmTransactionAsync
+import org.matrix.android.sdk.internal.crypto.store.db.doWithRealm
+import org.matrix.android.sdk.internal.crypto.store.db.mapper.CryptoRoomInfoMapper
+import org.matrix.android.sdk.internal.crypto.store.db.mapper.MyDeviceLastSeenInfoEntityMapper
+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.CryptoMetadataEntity
+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.MyDeviceLastSeenInfoEntity
+import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntityFields
+import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSessionEntity
+import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSessionEntityFields
+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.createPrimaryKey
+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.di.CryptoDatabase
+import org.matrix.android.sdk.internal.di.DeviceId
+import org.matrix.android.sdk.internal.di.UserId
+import org.matrix.android.sdk.internal.session.SessionScope
+import org.matrix.android.sdk.internal.util.time.Clock
+import timber.log.Timber
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+import javax.inject.Inject
+
+private val loggerTag = LoggerTag("RealmCryptoStore", LoggerTag.CRYPTO)
+
+/**
+ * In the transition phase, the rust SDK is still using parts to the realm crypto store,
+ * this should be removed after full migration
+ */
+@SessionScope
+internal class RustCryptoStore @Inject constructor(
+ @CryptoDatabase private val realmConfiguration: RealmConfiguration,
+ private val clock: Clock,
+ @UserId private val userId: String,
+ @DeviceId private val deviceId: String,
+ private val myDeviceLastSeenInfoEntityMapper: MyDeviceLastSeenInfoEntityMapper,
+ private val olmMachine: dagger.Lazy,
+ private val matrixCoroutineDispatchers: MatrixCoroutineDispatchers,
+) : IMXCommonCryptoStore {
+
+ // still needed on rust due to the global crypto settings
+ init {
+ // Ensure CryptoMetadataEntity is inserted in DB
+ doRealmTransaction("init", realmConfiguration) { realm ->
+ var currentMetadata = realm.where().findFirst()
+
+ var deleteAll = false
+
+ if (currentMetadata != null) {
+ // Check credentials
+ // The device id may not have been provided in credentials.
+ // Check it only if provided, else trust the stored one.
+ if (currentMetadata.userId != userId || deviceId != currentMetadata.deviceId) {
+ Timber.w("## open() : Credentials do not match, close this store and delete data")
+ deleteAll = true
+ currentMetadata = null
+ }
+ }
+
+ if (currentMetadata == null) {
+ if (deleteAll) {
+ realm.deleteAll()
+ }
+
+ // Metadata not found, or database cleaned, create it
+ realm.createObject(CryptoMetadataEntity::class.java, userId).apply {
+ deviceId = this@RustCryptoStore.deviceId
+ }
+ }
+ }
+ }
+
+ /**
+ * Retrieve a device by its identity key.
+ *
+ * @param identityKey the device identity key (`MXDeviceInfo.identityKey`)
+ * @return the device or null if not found
+ */
+ override fun deviceWithIdentityKey(userId: String, identityKey: String): CryptoDeviceInfo? {
+ // XXX make this suspendable?
+ val knownDevices = runBlocking(matrixCoroutineDispatchers.io) {
+ olmMachine.get().getUserDevices(userId)
+ }
+ return knownDevices
+ .map { it.toCryptoDeviceInfo() }
+ .firstOrNull {
+ it.identityKey() == identityKey
+ }
+ }
+
+ /**
+ * Needed for lazy migration of sessions from the legacy store
+ */
+ override fun getInboundGroupSession(sessionId: String, senderKey: String): MXInboundMegolmSessionWrapper? {
+ val key = OlmInboundGroupSessionEntity.createPrimaryKey(sessionId, senderKey)
+
+ return doWithRealm(realmConfiguration) { realm ->
+ realm.where()
+ .equalTo(OlmInboundGroupSessionEntityFields.PRIMARY_KEY, key)
+ .findFirst()
+ ?.toModel()
+ }
+ }
+
+ // ================================================
+ // Things that should be migrated to another store than realm
+ // ================================================
+
+ private val monarchyWriteAsyncExecutor = Executors.newSingleThreadExecutor()
+
+ private val monarchy = Monarchy.Builder()
+ .setRealmConfiguration(realmConfiguration)
+ .setWriteAsyncExecutor(monarchyWriteAsyncExecutor)
+ .build()
+
+ override fun open() {
+ // nop
+ }
+
+ override fun tidyUpDataBase() {
+ // These entities are not used in rust actually, but as they are not yet cleaned up, this will do it with time
+ val prevWeekTs = clock.epochMillis() - 7 * 24 * 60 * 60 * 1_000
+ doRealmTransaction("tidyUpDataBase", realmConfiguration) { realm ->
+
+ // Clean the old ones?
+ realm.where()
+ .lessThan(OutgoingKeyRequestEntityFields.CREATION_TIME_STAMP, prevWeekTs)
+ .findAll()
+ .also { Timber.i("## Crypto Clean up ${it.size} OutgoingKeyRequestEntity") }
+ .deleteAllFromRealm()
+
+ // Only keep one month history
+
+ val prevMonthTs = clock.epochMillis() - 4 * 7 * 24 * 60 * 60 * 1_000L
+ realm.where()
+ .lessThan(AuditTrailEntityFields.AGE_LOCAL_TS, prevMonthTs)
+ .findAll()
+ .also { Timber.i("## Crypto Clean up ${it.size} AuditTrailEntity") }
+ .deleteAllFromRealm()
+
+ // Can we do something for WithHeldSessionEntity?
+ }
+ }
+
+ override fun close() {
+ val tasks = monarchyWriteAsyncExecutor.shutdownNow()
+ Timber.w("Closing RealmCryptoStore, ${tasks.size} async task(s) cancelled")
+ tryOrNull("Interrupted") {
+ // Wait 1 minute max
+ monarchyWriteAsyncExecutor.awaitTermination(1, TimeUnit.MINUTES)
+ }
+ }
+
+ override fun getRoomAlgorithm(roomId: String): String? {
+ return doWithRealm(realmConfiguration) {
+ CryptoRoomEntity.getById(it, roomId)?.algorithm
+ }
+ }
+
+ override fun getRoomCryptoInfo(roomId: String): CryptoRoomInfo? {
+ return doWithRealm(realmConfiguration) { realm ->
+ CryptoRoomEntity.getById(realm, roomId)?.let {
+ CryptoRoomInfoMapper.map(it)
+ }
+ }
+ }
+
+ /**
+ * 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).
+ */
+ override fun roomWasOnceEncrypted(roomId: String): Boolean {
+ return doWithRealm(realmConfiguration) {
+ CryptoRoomEntity.getById(it, roomId)?.wasEncryptedOnce ?: false
+ }
+ }
+
+ override fun setAlgorithmInfo(roomId: String, encryption: EncryptionEventContent?) {
+ doRealmTransaction("setAlgorithmInfo", realmConfiguration) {
+ CryptoRoomEntity.getOrCreate(it, roomId).let { entity ->
+ entity.algorithm = encryption?.algorithm
+ // store anyway the new algorithm, but mark the room
+ // as having been encrypted once whatever, this can never
+ // go back to false
+ if (encryption?.algorithm == MXCRYPTO_ALGORITHM_MEGOLM) {
+ entity.wasEncryptedOnce = true
+ entity.rotationPeriodMs = encryption.rotationPeriodMs
+ entity.rotationPeriodMsgs = encryption.rotationPeriodMsgs
+ }
+ }
+ }
+ }
+
+ override fun saveMyDevicesInfo(info: List) {
+ val entities = info.map { myDeviceLastSeenInfoEntityMapper.map(it) }
+ doRealmTransactionAsync(realmConfiguration) { realm ->
+ realm.where().findAll().deleteAllFromRealm()
+ entities.forEach {
+ realm.insertOrUpdate(it)
+ }
+ }
+ }
+
+ override fun getMyDevicesInfo(): List {
+ return monarchy.fetchAllCopiedSync {
+ it.where()
+ }.map {
+ DeviceInfo(
+ deviceId = it.deviceId,
+ lastSeenIp = it.lastSeenIp,
+ lastSeenTs = it.lastSeenTs,
+ displayName = it.displayName
+ )
+ }
+ }
+
+ override fun getLiveMyDevicesInfo(): LiveData> {
+ return monarchy.findAllMappedWithChanges(
+ { realm: Realm ->
+ realm.where()
+ },
+ { entity -> myDeviceLastSeenInfoEntityMapper.map(entity) }
+ )
+ }
+
+ override fun getLiveMyDevicesInfo(deviceId: String): LiveData> {
+ val liveData = monarchy.findAllMappedWithChanges(
+ { realm: Realm ->
+ realm.where()
+ .equalTo(MyDeviceLastSeenInfoEntityFields.DEVICE_ID, deviceId)
+ },
+ { entity -> myDeviceLastSeenInfoEntityMapper.map(entity) }
+ )
+
+ return Transformations.map(liveData) {
+ it.firstOrNull().toOptional()
+ }
+ }
+
+ override fun storeData(cryptoStoreAggregator: CryptoStoreAggregator) {
+ if (cryptoStoreAggregator.isEmpty()) {
+ return
+ }
+ doRealmTransaction("storeData - CryptoStoreAggregator", realmConfiguration) { realm ->
+ // setShouldShareHistory
+ cryptoStoreAggregator.setShouldShareHistoryData.forEach {
+ Timber.tag(loggerTag.value)
+ .v("setShouldShareHistory for room ${it.key} is ${it.value}")
+ CryptoRoomEntity.getOrCreate(realm, it.key).shouldShareHistory = it.value
+ }
+ // setShouldEncryptForInvitedMembers
+ cryptoStoreAggregator.setShouldEncryptForInvitedMembersData.forEach {
+ CryptoRoomEntity.getOrCreate(realm, it.key).shouldEncryptForInvitedMembers = it.value
+ }
+ }
+ }
+
+ override fun shouldEncryptForInvitedMembers(roomId: String): Boolean {
+ return doWithRealm(realmConfiguration) {
+ CryptoRoomEntity.getById(it, roomId)?.shouldEncryptForInvitedMembers
+ }
+ ?: false
+ }
+
+ override fun setShouldShareHistory(roomId: String, shouldShareHistory: Boolean) {
+ Timber.tag(loggerTag.value)
+ .v("setShouldShareHistory for room $roomId is $shouldShareHistory")
+ doRealmTransaction("setShouldShareHistory", realmConfiguration) {
+ CryptoRoomEntity.getOrCreate(it, roomId).shouldShareHistory = shouldShareHistory
+ }
+ }
+
+ override fun setShouldEncryptForInvitedMembers(roomId: String, shouldEncryptForInvitedMembers: Boolean) {
+ doRealmTransaction("setShouldEncryptForInvitedMembers", realmConfiguration) {
+ CryptoRoomEntity.getOrCreate(it, roomId).shouldEncryptForInvitedMembers = shouldEncryptForInvitedMembers
+ }
+ }
+
+ override fun blockUnverifiedDevicesInRoom(roomId: String, block: Boolean) {
+ doRealmTransaction("blockUnverifiedDevicesInRoom", realmConfiguration) { realm ->
+ CryptoRoomEntity.getById(realm, roomId)
+ ?.blacklistUnverifiedDevices = block
+ }
+ }
+
+ override fun setGlobalBlacklistUnverifiedDevices(block: Boolean) {
+ doRealmTransaction("setGlobalBlacklistUnverifiedDevices", realmConfiguration) {
+ it.where().findFirst()?.globalBlacklistUnverifiedDevices = block
+ }
+ }
+
+ override fun getLiveGlobalCryptoConfig(): LiveData {
+ val liveData = monarchy.findAllMappedWithChanges(
+ { realm: Realm ->
+ realm
+ .where()
+ },
+ {
+ GlobalCryptoConfig(
+ globalBlockUnverifiedDevices = it.globalBlacklistUnverifiedDevices,
+ globalEnableKeyGossiping = it.globalEnableKeyGossiping,
+ enableKeyForwardingOnInvite = it.enableKeyForwardingOnInvite
+ )
+ }
+ )
+ return Transformations.map(liveData) {
+ it.firstOrNull() ?: GlobalCryptoConfig(false, false, false)
+ }
+ }
+
+ override fun getGlobalBlacklistUnverifiedDevices(): Boolean {
+ return doWithRealm(realmConfiguration) {
+ it.where().findFirst()?.globalBlacklistUnverifiedDevices
+ } ?: false
+ }
+
+ override fun getLiveBlockUnverifiedDevices(roomId: String): LiveData {
+ val liveData = monarchy.findAllMappedWithChanges(
+ { realm: Realm ->
+ realm.where()
+ .equalTo(CryptoRoomEntityFields.ROOM_ID, roomId)
+ },
+ {
+ it.blacklistUnverifiedDevices
+ }
+ )
+ return Transformations.map(liveData) {
+ it.firstOrNull() ?: false
+ }
+ }
+
+ override fun getBlockUnverifiedDevices(roomId: String): Boolean {
+ return doWithRealm(realmConfiguration) { realm ->
+ realm.where()
+ .equalTo(CryptoRoomEntityFields.ROOM_ID, roomId)
+ .findFirst()
+ ?.blacklistUnverifiedDevices ?: false
+ }
+ }
+}
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/migration/rust/ExtractUtils.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/migration/rust/ExtractUtils.kt
index 608f68fc3d..d99403fe19 100644
--- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/migration/rust/ExtractUtils.kt
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/migration/rust/ExtractUtils.kt
@@ -71,6 +71,10 @@ fun RealmToMigrate.getPickledAccount(pickleKey: ByteArray): MigrationData {
val userKey = metadataEntity.xSignUserPrivateKey
val selfSignedKey = metadataEntity.xSignSelfSignedPrivateKey
+ Timber.i("## Migration: has private MSK ${masterKey.isNullOrBlank().not()}")
+ Timber.i("## Migration: has private USK ${userKey.isNullOrBlank().not()}")
+ Timber.i("## Migration: has private SSK ${selfSignedKey.isNullOrBlank().not()}")
+
val userId = metadataEntity.userId
?: throw java.lang.IllegalArgumentException("Rust db migration: userId is null")
val deviceId = metadataEntity.deviceId
@@ -79,6 +83,8 @@ fun RealmToMigrate.getPickledAccount(pickleKey: ByteArray): MigrationData {
val backupVersion = metadataEntity.backupVersion
val backupRecoveryKey = metadataEntity.keyBackupRecoveryKey
+ Timber.i("## Migration: has private backup key ${backupRecoveryKey != null} for version $backupVersion")
+
val isOlmAccountShared = metadataEntity.deviceKeysSentToServer
val olmAccount = metadataEntity.getOlmAccount()
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt
index 8cb6618a18..35965d6f2e 100644
--- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt
@@ -36,6 +36,7 @@ import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_RECIPROCATE
import org.matrix.android.sdk.internal.crypto.model.rest.toValue
import org.matrix.android.sdk.internal.session.SessionScope
+import org.matrix.rustcomponents.sdk.crypto.VerificationRequestState
import timber.log.Timber
import javax.inject.Inject
@@ -165,7 +166,7 @@ internal class RustVerificationService @Inject constructor(
// If this is a SAS verification originating from a `m.key.verification.request`
// event, we auto-accept here considering that we either initiated the request or
// accepted the request. If it's a QR code verification, just dispatch an update.
- if (request.isReady() && transaction is SasVerification) {
+ if (request.innerState() is VerificationRequestState.Ready && transaction is SasVerification) {
// accept() will dispatch an update, no need to do it twice.
Timber.d("## Verification: Auto accepting SAS verification with $sender")
transaction.accept()
@@ -308,7 +309,7 @@ internal class RustVerificationService @Inject constructor(
return if (request != null) {
request.acceptWithMethods(methods)
request.startQrCode()
- request.isReady()
+ request.innerState() is VerificationRequestState.Ready
} else {
false
}
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationRequest.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationRequest.kt
index 8d1b3392aa..641bf66c12 100644
--- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationRequest.kt
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationRequest.kt
@@ -136,9 +136,9 @@ internal class VerificationRequest @AssistedInject constructor(
* concrete verification flow, i.e. we can show/scan a QR code or start emoji
* verification.
*/
- internal fun isReady(): Boolean {
- return innerVerificationRequest.isReady()
- }
+// internal fun isReady(): Boolean {
+// return innerVerificationRequest.isReady()
+// }
/** Did we advertise that we're able to scan QR codes */
internal fun canScanQrCodes(): Boolean {
diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/EventEditValidatorTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/EventEditValidatorTest.kt
index 0ae712bff1..113dc4ce83 100644
--- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/EventEditValidatorTest.kt
+++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/EventEditValidatorTest.kt
@@ -24,7 +24,7 @@ import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
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.events.model.EventType
-import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
+import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
class EventEditValidatorTest {
@@ -62,7 +62,7 @@ class EventEditValidatorTest {
@Test
fun `edit should be valid`() {
- val mockCryptoStore = mockk()
+ val mockCryptoStore = mockk()
val validator = EventEditValidator(mockCryptoStore)
validator
@@ -71,7 +71,7 @@ class EventEditValidatorTest {
@Test
fun `original event and replacement event must have the same sender`() {
- val mockCryptoStore = mockk()
+ val mockCryptoStore = mockk()
val validator = EventEditValidator(mockCryptoStore)
validator
@@ -83,7 +83,7 @@ class EventEditValidatorTest {
@Test
fun `original event and replacement event must have the same room_id`() {
- val mockCryptoStore = mockk()
+ val mockCryptoStore = mockk()
val validator = EventEditValidator(mockCryptoStore)
validator
@@ -101,7 +101,7 @@ class EventEditValidatorTest {
@Test
fun `replacement and original events must not have a state_key property`() {
- val mockCryptoStore = mockk()
+ val mockCryptoStore = mockk()
val validator = EventEditValidator(mockCryptoStore)
validator
@@ -119,8 +119,8 @@ class EventEditValidatorTest {
@Test
fun `replacement event must have an new_content property`() {
- val mockCryptoStore = mockk {
- every { deviceWithIdentityKey("R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
+ val mockCryptoStore = mockk {
+ every { deviceWithIdentityKey("@alice:example.com", "R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
mockk {
every { userId } returns "@alice:example.com"
}
@@ -157,8 +157,8 @@ class EventEditValidatorTest {
@Test
fun `The original event must not itself have a rel_type of m_replace`() {
- val mockCryptoStore = mockk {
- every { deviceWithIdentityKey("R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
+ val mockCryptoStore = mockk {
+ every { deviceWithIdentityKey("@alice:example.com", "R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
mockk {
every { userId } returns "@alice:example.com"
}
@@ -207,8 +207,8 @@ class EventEditValidatorTest {
@Test
fun `valid e2ee edit`() {
- val mockCryptoStore = mockk {
- every { deviceWithIdentityKey("R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
+ val mockCryptoStore = mockk {
+ every { deviceWithIdentityKey("@alice:example.com", "R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
mockk {
every { userId } returns "@alice:example.com"
}
@@ -224,8 +224,8 @@ class EventEditValidatorTest {
@Test
fun `If the original event was encrypted, the replacement should be too`() {
- val mockCryptoStore = mockk {
- every { deviceWithIdentityKey("R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
+ val mockCryptoStore = mockk {
+ every { deviceWithIdentityKey("@alice:example.com", "R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
mockk {
every { userId } returns "@alice:example.com"
}
@@ -241,12 +241,12 @@ class EventEditValidatorTest {
@Test
fun `encrypted, original event and replacement event must have the same sender`() {
- val mockCryptoStore = mockk {
- every { deviceWithIdentityKey("R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
+ val mockCryptoStore = mockk {
+ every { deviceWithIdentityKey("@alice:example.com", "R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
mockk {
every { userId } returns "@alice:example.com"
}
- every { deviceWithIdentityKey("7V5e/2O93mf4GeW7Mtq4YWcRNpYS9NhQbdJMgdnIPUI") } returns
+ every { deviceWithIdentityKey("@bob:example.com", "7V5e/2O93mf4GeW7Mtq4YWcRNpYS9NhQbdJMgdnIPUI") } returns
mockk {
every { userId } returns "@bob:example.com"
}
@@ -256,7 +256,9 @@ class EventEditValidatorTest {
validator
.validateEdit(
encryptedEvent,
- encryptedEditEvent.copy().apply {
+ encryptedEditEvent.copy(
+ senderId = "@bob:example.com"
+ ).apply {
mxDecryptionResult = encryptedEditEvent.mxDecryptionResult!!.copy(
senderKey = "7V5e/2O93mf4GeW7Mtq4YWcRNpYS9NhQbdJMgdnIPUI"
)
@@ -269,12 +271,12 @@ class EventEditValidatorTest {
@Test
fun `encrypted, sent fom a deleted device, original event and replacement event must have the same sender`() {
- val mockCryptoStore = mockk {
- every { deviceWithIdentityKey("R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
+ val mockCryptoStore = mockk {
+ every { deviceWithIdentityKey("@alice:example.com", "R0s/7Aindgg/RNWqUGJyJOXtCz5H7Gx7fInFuroq1xo") } returns
mockk {
every { userId } returns "@alice:example.com"
}
- every { deviceWithIdentityKey("7V5e/2O93mf4GeW7Mtq4YWcRNpYS9NhQbdJMgdnIPUI") } returns
+ every { deviceWithIdentityKey(any(), "7V5e/2O93mf4GeW7Mtq4YWcRNpYS9NhQbdJMgdnIPUI") } returns
null
}
val validator = EventEditValidator(mockCryptoStore)
@@ -288,7 +290,7 @@ class EventEditValidatorTest {
)
}
- ) shouldBeInstanceOf EventEditValidator.EditValidity.Valid::class
+ ) shouldBeInstanceOf EventEditValidator.EditValidity.Unknown::class
validator
.validateEdit(
diff --git a/tools/release/releaseScript.sh b/tools/release/releaseScript.sh
index cf9671c1dc..f198670eae 100755
--- a/tools/release/releaseScript.sh
+++ b/tools/release/releaseScript.sh
@@ -160,11 +160,11 @@ adb -e uninstall im.vector.app.debug.test
printf "\n================================================================================\n"
printf "Running the integration test UiAllScreensSanityTest.allScreensTest()...\n"
-./gradlew connectedGplayDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest
+./gradlew connectedGplayRustCryptoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest
printf "\n================================================================================\n"
printf "Building the app...\n"
-./gradlew assembleGplayDebug
+./gradlew assembleGplayRustCryptoDebug
printf "\n================================================================================\n"
printf "Uninstalling previous debug app if any...\n"
@@ -172,7 +172,7 @@ adb -e uninstall im.vector.app.debug
printf "\n================================================================================\n"
printf "Installing the app...\n"
-adb -e install ./vector-app/build/outputs/apk/gplay/debug/vector-gplay-arm64-v8a-debug.apk
+adb -e install ./vector-app/build/outputs/apk/gplayRustCrypto/debug/vector-gplay-rustCrypto-arm64-v8a-debug.apk
printf "\n================================================================================\n"
printf "Running the app...\n"
@@ -293,67 +293,67 @@ printf "Unzipping the artifact...\n"
unzip ${targetPath}/vector-gplay-release-unsigned.zip -d ${targetPath}
# Flatten folder hierarchy
-mv ${targetPath}/gplay/release/* ${targetPath}
+mv ${targetPath}/gplayRustCrypto/release/* ${targetPath}
rm -rf ${targetPath}/gplay
printf "\n================================================================================\n"
printf "Signing the APKs...\n"
-cp ${targetPath}/vector-gplay-arm64-v8a-release-unsigned.apk \
- ${targetPath}/vector-gplay-arm64-v8a-release-signed.apk
+cp ${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-unsigned.apk \
+ ${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-signed.apk
./tools/release/sign_apk_unsafe.sh \
${keyStorePath} \
- ${targetPath}/vector-gplay-arm64-v8a-release-signed.apk \
+ ${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-signed.apk \
${keyStorePassword} \
${keyPassword}
-cp ${targetPath}/vector-gplay-armeabi-v7a-release-unsigned.apk \
- ${targetPath}/vector-gplay-armeabi-v7a-release-signed.apk
+cp ${targetPath}/vector-gplay-rustCrypto-armeabi-v7a-release-unsigned.apk \
+ ${targetPath}/vector-gplay-rustCrypto-armeabi-v7a-release-signed.apk
./tools/release/sign_apk_unsafe.sh \
${keyStorePath} \
- ${targetPath}/vector-gplay-armeabi-v7a-release-signed.apk \
+ ${targetPath}/vector-gplay-rustCrypto-armeabi-v7a-release-signed.apk \
${keyStorePassword} \
${keyPassword}
-cp ${targetPath}/vector-gplay-x86-release-unsigned.apk \
- ${targetPath}/vector-gplay-x86-release-signed.apk
+cp ${targetPath}/vector-gplay-rustCrypto-x86-release-unsigned.apk \
+ ${targetPath}/vector-gplay-rustCrypto-x86-release-signed.apk
./tools/release/sign_apk_unsafe.sh \
${keyStorePath} \
- ${targetPath}/vector-gplay-x86-release-signed.apk \
+ ${targetPath}/vector-gplay-rustCrypto-x86-release-signed.apk \
${keyStorePassword} \
${keyPassword}
-cp ${targetPath}/vector-gplay-x86_64-release-unsigned.apk \
- ${targetPath}/vector-gplay-x86_64-release-signed.apk
+cp ${targetPath}/vector-gplay-rustCrypto-x86_64-release-unsigned.apk \
+ ${targetPath}/vector-gplay-rustCrypto-x86_64-release-signed.apk
./tools/release/sign_apk_unsafe.sh \
${keyStorePath} \
- ${targetPath}/vector-gplay-x86_64-release-signed.apk \
+ ${targetPath}/vector-gplay-rustCrypto-x86_64-release-signed.apk \
${keyStorePassword} \
${keyPassword}
# Ref: https://docs.fastlane.tools/getting-started/android/beta-deployment/#uploading-your-app
-# set SUPPLY_APK_PATHS="${targetPath}/vector-gplay-arm64-v8a-release-unsigned.apk,${targetPath}/vector-gplay-armeabi-v7a-release-unsigned.apk,${targetPath}/vector-gplay-x86-release-unsigned.apk,${targetPath}/vector-gplay-x86_64-release-unsigned.apk"
+# set SUPPLY_APK_PATHS="${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-unsigned.apk,${targetPath}/vector-gplay-rustCrypto-armeabi-v7a-release-unsigned.apk,${targetPath}/vector-gplay-rustCrypto-x86-release-unsigned.apk,${targetPath}/vector-gplay-rustCrypto-x86_64-release-unsigned.apk"
#
# ./fastlane beta
printf "\n================================================================================\n"
printf "Please check the information below:\n"
-printf "File vector-gplay-arm64-v8a-release-signed.apk:\n"
-${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-arm64-v8a-release-signed.apk | grep package
-printf "File vector-gplay-armeabi-v7a-release-signed.apk:\n"
-${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-armeabi-v7a-release-signed.apk | grep package
-printf "File vector-gplay-x86-release-signed.apk:\n"
-${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-x86-release-signed.apk | grep package
-printf "File vector-gplay-x86_64-release-signed.apk:\n"
-${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-x86_64-release-signed.apk | grep package
+printf "File vector-gplay-rustCrypto-arm64-v8a-release-signed.apk:\n"
+${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-signed.apk | grep package
+printf "File vector-gplay-rustCrypto-armeabi-v7a-release-signed.apk:\n"
+${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-rustCrypto-armeabi-v7a-release-signed.apk | grep package
+printf "File vector-gplay-rustCrypto-x86-release-signed.apk:\n"
+${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-rustCrypto-x86-release-signed.apk | grep package
+printf "File vector-gplay-rustCrypto-x86_64-release-signed.apk:\n"
+${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-rustCrypto-x86_64-release-signed.apk | grep package
printf "\n"
read -p "Does it look correct? Press enter when it's done."
printf "\n================================================================================\n"
read -p "Installing apk on a real device, press enter when a real device is connected. "
-apkPath="${targetPath}/vector-gplay-arm64-v8a-release-signed.apk"
+apkPath="${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-signed.apk"
adb -d install ${apkPath}
read -p "Please run the APK on your phone to check that the upgrade went well (no init sync, etc.). Press enter when it's done."
diff --git a/vector-app/build.gradle b/vector-app/build.gradle
index 2abf6526d2..9a2506391e 100644
--- a/vector-app/build.gradle
+++ b/vector-app/build.gradle
@@ -33,11 +33,11 @@ knit {
// Note: 2 digits max for each value
ext.versionMajor = 1
-ext.versionMinor = 5
+ext.versionMinor = 6
// Note: even values are reserved for regular release, odd values for hotfix release.
// When creating a hotfix, you should decrease the value, since the current value
// is the value for the next regular release.
-ext.versionPatch = 34
+ext.versionPatch = 2
static def getGitTimestamp() {
def cmd = 'git show -s --format=%ct'
diff --git a/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt b/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt
index cafc2d65e6..313073da4d 100644
--- a/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt
+++ b/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt
@@ -17,6 +17,7 @@ package im.vector.app.gplay.features.settings.troubleshoot
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Observer
+import androidx.lifecycle.lifecycleScope
import androidx.work.WorkInfo
import androidx.work.WorkManager
import im.vector.app.R
@@ -25,6 +26,8 @@ import im.vector.app.core.pushers.FcmHelper
import im.vector.app.core.pushers.PushersManager
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.settings.troubleshoot.TroubleshootTest
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.pushers.PusherState
import javax.inject.Inject
@@ -60,16 +63,18 @@ class TestTokenRegistration @Inject constructor(
)
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_token_registration_quick_fix) {
override fun doFix() {
- val workId = pushersManager.enqueueRegisterPusherWithFcmKey(fcmToken)
- WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo ->
- if (workInfo != null) {
- if (workInfo.state == WorkInfo.State.SUCCEEDED) {
- manager?.retry(testParameters)
- } else if (workInfo.state == WorkInfo.State.FAILED) {
- manager?.retry(testParameters)
+ context.lifecycleScope.launch(Dispatchers.IO) {
+ val workId = pushersManager.enqueueRegisterPusherWithFcmKey(fcmToken)
+ WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo ->
+ if (workInfo != null) {
+ if (workInfo.state == WorkInfo.State.SUCCEEDED) {
+ manager?.retry(testParameters)
+ } else if (workInfo.state == WorkInfo.State.FAILED) {
+ manager?.retry(testParameters)
+ }
}
- }
- })
+ })
+ }
}
}
diff --git a/vector-app/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt b/vector-app/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt
index 53e65f88b4..676cd0258f 100755
--- a/vector-app/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt
+++ b/vector-app/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt
@@ -26,8 +26,11 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.DefaultPreferences
+import im.vector.app.core.dispatchers.CoroutineDispatchers
import im.vector.app.core.pushers.FcmHelper
import im.vector.app.core.pushers.PushersManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@@ -38,7 +41,12 @@ import javax.inject.Inject
class GoogleFcmHelper @Inject constructor(
@ApplicationContext private val context: Context,
@DefaultPreferences private val sharedPrefs: SharedPreferences,
+ appScope: CoroutineScope,
+ private val coroutineDispatchers: CoroutineDispatchers
) : FcmHelper {
+
+ private val scope = CoroutineScope(appScope.coroutineContext + coroutineDispatchers.io)
+
companion object {
private const val PREFS_KEY_FCM_TOKEN = "FCM_TOKEN"
}
@@ -64,7 +72,9 @@ class GoogleFcmHelper @Inject constructor(
.addOnSuccessListener { token ->
storeFcmToken(token)
if (registerPusher) {
- pushersManager.enqueueRegisterPusherWithFcmKey(token)
+ scope.launch {
+ pushersManager.enqueueRegisterPusherWithFcmKey(token)
+ }
}
}
.addOnFailureListener { e ->
diff --git a/vector-app/src/gplay/java/im/vector/app/push/fcm/VectorFirebaseMessagingService.kt b/vector-app/src/gplay/java/im/vector/app/push/fcm/VectorFirebaseMessagingService.kt
index 7fd55bd165..6ab9b90a84 100644
--- a/vector-app/src/gplay/java/im/vector/app/push/fcm/VectorFirebaseMessagingService.kt
+++ b/vector-app/src/gplay/java/im/vector/app/push/fcm/VectorFirebaseMessagingService.kt
@@ -27,6 +27,10 @@ import im.vector.app.core.pushers.PushersManager
import im.vector.app.core.pushers.UnifiedPushHelper
import im.vector.app.core.pushers.VectorPushHandler
import im.vector.app.features.settings.VectorPreferences
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.logger.LoggerTag
import timber.log.Timber
import javax.inject.Inject
@@ -43,6 +47,12 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
@Inject lateinit var vectorPushHandler: VectorPushHandler
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
+ private val scope = CoroutineScope(SupervisorJob())
+
+ override fun onDestroy() {
+ scope.cancel()
+ super.onDestroy()
+ }
override fun onNewToken(token: String) {
Timber.tag(loggerTag.value).d("New Firebase token")
fcmHelper.storeFcmToken(token)
@@ -51,7 +61,9 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
activeSessionHolder.hasActiveSession() &&
unifiedPushHelper.isEmbeddedDistributor()
) {
- pushersManager.enqueueRegisterPusher(token, getString(R.string.pusher_http_url))
+ scope.launch {
+ pushersManager.enqueueRegisterPusher(token, getString(R.string.pusher_http_url))
+ }
}
}
diff --git a/vector/build.gradle b/vector/build.gradle
index a5f368ff9d..dab8b8bdeb 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -311,7 +311,7 @@ dependencies {
// Fix issue with Jitsi. Inspired from https://github.com/android/android-test/issues/861#issuecomment-872067868
// Error was lots of `Duplicate class org.checkerframework.common.reflection.qual.MethodVal found in modules jetified-checker-3.1 (org.checkerframework:checker:3.1.1) and jetified-checker-qual-3.12.0 (org.checkerframework:checker-qual:3.12.0)
//noinspection GradleDependency Cannot use latest 3.15.0 since it required min API 26.
- implementation "org.checkerframework:checker:3.34.0"
+ implementation "org.checkerframework:checker:3.35.0"
androidTestImplementation libs.androidx.testCore
androidTestImplementation libs.androidx.testRunner
diff --git a/vector/src/main/java/im/vector/app/core/device/GetDeviceInfoUseCase.kt b/vector/src/main/java/im/vector/app/core/device/GetDeviceInfoUseCase.kt
index 4a66988b46..a97fa32a61 100644
--- a/vector/src/main/java/im/vector/app/core/device/GetDeviceInfoUseCase.kt
+++ b/vector/src/main/java/im/vector/app/core/device/GetDeviceInfoUseCase.kt
@@ -22,14 +22,14 @@ import javax.inject.Inject
interface GetDeviceInfoUseCase {
- fun execute(): CryptoDeviceInfo
+ suspend fun execute(): CryptoDeviceInfo
}
class DefaultGetDeviceInfoUseCase @Inject constructor(
private val activeSessionHolder: ActiveSessionHolder
) : GetDeviceInfoUseCase {
- override fun execute(): CryptoDeviceInfo {
+ override suspend fun execute(): CryptoDeviceInfo {
return activeSessionHolder.getActiveSession().cryptoService().getMyCryptoDevice()
}
}
diff --git a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt
index fb78feaef1..402471ecef 100644
--- a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt
+++ b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt
@@ -49,11 +49,11 @@ class PushersManager @Inject constructor(
)
}
- fun enqueueRegisterPusherWithFcmKey(pushKey: String): UUID {
+ suspend fun enqueueRegisterPusherWithFcmKey(pushKey: String): UUID {
return enqueueRegisterPusher(pushKey, stringProvider.getString(R.string.pusher_http_url))
}
- fun enqueueRegisterPusher(
+ suspend fun enqueueRegisterPusher(
pushKey: String,
gateway: String
): UUID {
@@ -62,7 +62,7 @@ class PushersManager @Inject constructor(
return currentSession.pushersService().enqueueAddHttpPusher(pusher)
}
- private fun createHttpPusher(
+ private suspend fun createHttpPusher(
pushKey: String,
gateway: String
) = HttpPusher(
diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorUnifiedPushMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorUnifiedPushMessagingReceiver.kt
index 838cbd5935..f0e5cd2c2c 100644
--- a/vector/src/main/java/im/vector/app/core/pushers/VectorUnifiedPushMessagingReceiver.kt
+++ b/vector/src/main/java/im/vector/app/core/pushers/VectorUnifiedPushMessagingReceiver.kt
@@ -76,7 +76,9 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
coroutineScope.launch {
unifiedPushHelper.storeCustomOrDefaultGateway(endpoint) {
unifiedPushHelper.getPushGateway()?.let {
- pushersManager.enqueueRegisterPusher(endpoint, it)
+ coroutineScope.launch {
+ pushersManager.enqueueRegisterPusher(endpoint, it)
+ }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteUnusedClientInformationUseCase.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteUnusedClientInformationUseCase.kt
index dcd5c58480..cc5dc6725d 100644
--- a/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteUnusedClientInformationUseCase.kt
+++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteUnusedClientInformationUseCase.kt
@@ -17,6 +17,7 @@
package im.vector.app.core.session.clientinfo
import im.vector.app.core.di.ActiveSessionHolder
+import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
import javax.inject.Inject
@@ -27,16 +28,19 @@ class DeleteUnusedClientInformationUseCase @Inject constructor(
suspend fun execute(deviceInfoList: List): Result = runCatching {
// A defensive approach against local storage reports an empty device list (although it is not a seen situation).
if (deviceInfoList.isEmpty()) return Result.success(Unit)
-
- val expectedClientInfoKeyList = deviceInfoList.map { MATRIX_CLIENT_INFO_KEY_PREFIX + it.deviceId }
- activeSessionHolder
- .getSafeActiveSession()
- ?.accountDataService()
- ?.getUserAccountDataEventsStartWith(MATRIX_CLIENT_INFO_KEY_PREFIX)
- ?.map { it.type }
- ?.subtract(expectedClientInfoKeyList.toSet())
- ?.forEach { userAccountDataKeyToDelete ->
- activeSessionHolder.getSafeActiveSession()?.accountDataService()?.deleteUserAccountData(userAccountDataKeyToDelete)
- }
+ val dispatcher = activeSessionHolder.getSafeActiveSession()?.coroutineDispatchers?.io
+ ?: return@runCatching
+ withContext(dispatcher) {
+ val expectedClientInfoKeyList = deviceInfoList.map { MATRIX_CLIENT_INFO_KEY_PREFIX + it.deviceId }
+ activeSessionHolder
+ .getSafeActiveSession()
+ ?.accountDataService()
+ ?.getUserAccountDataEventsStartWith(MATRIX_CLIENT_INFO_KEY_PREFIX)
+ ?.map { it.type }
+ ?.subtract(expectedClientInfoKeyList.toSet())
+ ?.forEach { userAccountDataKeyToDelete ->
+ activeSessionHolder.getSafeActiveSession()?.accountDataService()?.deleteUserAccountData(userAccountDataKeyToDelete)
+ }
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/MainActivity.kt b/vector/src/main/java/im/vector/app/features/MainActivity.kt
index cffb1577cf..48fe092524 100644
--- a/vector/src/main/java/im/vector/app/features/MainActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/MainActivity.kt
@@ -29,6 +29,7 @@ import com.airbnb.mvrx.viewModel
import com.bumptech.glide.Glide
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
+import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.extensions.startSyncing
import im.vector.app.core.extensions.vectorStore
@@ -59,6 +60,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.failure.GlobalError
+import org.matrix.android.sdk.api.session.Session
import timber.log.Timber
import javax.inject.Inject
@@ -170,6 +172,19 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
}
private fun handleAppStarted() {
+ // On the first run with rust crypto this would be false
+ if (!vectorPreferences.isOnRustCrypto()) {
+ if (activeSessionHolder.hasActiveSession()) {
+ vectorPreferences.setHadExistingLegacyData(activeSessionHolder.getActiveSession().isOpenable)
+ } else {
+ vectorPreferences.setHadExistingLegacyData(false)
+ }
+ }
+
+ if (BuildConfig.FLAVOR == "rustCrypto") {
+ vectorPreferences.setIsOnRustCrypto(true)
+ }
+
if (intent.hasExtra(EXTRA_NEXT_INTENT)) {
// Start the next Activity
startSyncing()
@@ -248,18 +263,7 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
}
}
args.clearCredentials -> {
- lifecycleScope.launch {
- try {
- session.signOutService().signOut(!args.isUserLoggedOut)
- } catch (failure: Throwable) {
- displayError(failure)
- return@launch
- }
- Timber.w("SIGN_OUT: success, start app")
- activeSessionHolder.clearActiveSession()
- doLocalCleanup(clearPreferences = true, onboardingStore)
- startNextActivityAndFinish()
- }
+ signout(session, onboardingStore, ignoreServerError = false)
}
args.clearCache -> {
lifecycleScope.launch {
@@ -272,6 +276,26 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
}
}
+ private fun signout(
+ session: Session,
+ onboardingStore: VectorSessionStore,
+ ignoreServerError: Boolean,
+ ) {
+ lifecycleScope.launch {
+ try {
+ session.signOutService().signOut(!args.isUserLoggedOut, ignoreServerError)
+ } catch (failure: Throwable) {
+ Timber.e(failure, "SIGN_OUT: error, propose to sign out anyway")
+ displaySignOutFailedDialog(session, onboardingStore)
+ return@launch
+ }
+ Timber.w("SIGN_OUT: success, start app")
+ activeSessionHolder.clearActiveSession()
+ doLocalCleanup(clearPreferences = true, onboardingStore)
+ startNextActivityAndFinish()
+ }
+ }
+
override fun handleInvalidToken(globalError: GlobalError.InvalidToken) {
// No op here
Timber.w("Ignoring invalid token global error")
@@ -299,12 +323,20 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
}
}
- private fun displayError(failure: Throwable) {
+ private fun displaySignOutFailedDialog(
+ session: Session,
+ onboardingStore: VectorSessionStore,
+ ) {
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_title_error)
- .setMessage(errorFormatter.toHumanReadable(failure))
- .setPositiveButton(R.string.global_retry) { _, _ -> doCleanUp() }
+ .setMessage(R.string.sign_out_failed_dialog_message)
+ .setPositiveButton(R.string.sign_out_anyway) { _, _ ->
+ signout(session, onboardingStore, ignoreServerError = true)
+ }
+ .setNeutralButton(R.string.global_retry) { _, _ ->
+ signout(session, onboardingStore, ignoreServerError = false)
+ }
.setNegativeButton(R.string.action_cancel) { _, _ -> startNextActivityAndFinish(ignoreClearCredentials = true) }
.setCancelable(false)
.show()
diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt
index 66344107a4..d060e3996d 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt
@@ -52,7 +52,7 @@ class SharedSecuredStorageResetAllFragment :
views.ssssResetOtherDevices.debouncedClicks {
withState(sharedViewModel) {
- DeviceListBottomSheet.newInstance(it.userId, false).show(childFragmentManager, "DEV_LIST")
+ DeviceListBottomSheet.newInstance(it.userId).show(childFragmentManager, "DEV_LIST")
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationController.kt
index 4097cf957b..9871d21601 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationController.kt
@@ -275,7 +275,7 @@ class SelfVerificationController @Inject constructor(
id("notice_div")
}
// Option to verify with another device
- if (state.hasAnyOtherSession) {
+ if (state.hasAnyOtherSession.invoke() == true) {
bottomSheetVerificationActionItem {
id("start")
title(host.stringProvider.getString(R.string.verification_verify_with_another_device))
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationViewModel.kt
index e92616f7df..55d84a2446 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationViewModel.kt
@@ -83,7 +83,7 @@ data class SelfVerificationViewState(
val transactionId: String? = null,
val currentDeviceCanCrossSign: Boolean = false,
val userWantsToCancel: Boolean = false,
- val hasAnyOtherSession: Boolean = false,
+ val hasAnyOtherSession: Async = Uninitialized,
val quadSContainsSecrets: Boolean = false,
val isVerificationRequired: Boolean = false,
val isThisSessionVerified: Boolean = false,
@@ -146,21 +146,28 @@ class SelfVerificationViewModel @AssistedInject constructor(
}
}
- val hasAnyOtherSession = session.cryptoService()
- .getCryptoDeviceInfo(session.myUserId)
- .any {
- it.deviceId != session.sessionParams.deviceId
- }
+ setState { copy(hasAnyOtherSession = Loading()) }
+ viewModelScope.launch {
+ val hasAnyOtherSession = session.cryptoService()
+ .getCryptoDeviceInfo(session.myUserId)
+ .any {
+ it.deviceId != session.sessionParams.deviceId
+ }
+ setState {
+ copy(
+ hasAnyOtherSession = Success(hasAnyOtherSession)
+ )
+ }
+ }
setState {
copy(
currentDeviceCanCrossSign = session.cryptoService().crossSigningService().canCrossSign(),
quadSContainsSecrets = session.sharedSecretStorageService().isRecoverySetup(),
- hasAnyOtherSession = hasAnyOtherSession
)
}
- viewModelScope.launch {
+ viewModelScope.launch(Dispatchers.IO) {
val isThisSessionVerified = session.cryptoService().crossSigningService().isCrossSigningVerified()
setState {
copy(
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
index 42eb200887..428e62724b 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
@@ -469,11 +469,21 @@ class HomeActivity :
private fun handleOnNewSession(event: HomeActivityViewEvents.CurrentSessionNotVerified) {
// We need to ask
+ val titleRes = if (event.afterMigration) {
+ R.string.crosssigning_verify_after_update
+ } else {
+ R.string.crosssigning_verify_this_session
+ }
+ val descRes = if (event.afterMigration) {
+ R.string.confirm_your_identity_after_update
+ } else {
+ R.string.confirm_your_identity
+ }
promptSecurityEvent(
uid = PopupAlertManager.VERIFY_SESSION_UID,
userItem = event.userItem,
- titleRes = R.string.crosssigning_verify_this_session,
- descRes = R.string.confirm_your_identity,
+ titleRes = titleRes,
+ descRes = descRes,
) {
it.navigator.requestSelfSessionVerification(it)
}
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt
index 5f8d9cdc51..c57f32694b 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt
@@ -23,7 +23,7 @@ sealed interface HomeActivityViewEvents : VectorViewEvents {
data class AskPasswordToInitCrossSigning(val userItem: MatrixItem.UserItem) : HomeActivityViewEvents
data class CurrentSessionNotVerified(
val userItem: MatrixItem.UserItem,
-// val waitForIncomingRequest: Boolean = true,
+ val afterMigration: Boolean
) : HomeActivityViewEvents
data class CurrentSessionCannotBeVerified(
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
index 73bbcac070..eb4a796a49 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
@@ -453,6 +453,7 @@ class HomeActivityViewModel @AssistedInject constructor(
_viewEvents.post(
HomeActivityViewEvents.CurrentSessionNotVerified(
session.getUserOrDefault(session.myUserId).toMatrixItem(),
+ vectorPreferences.isOnRustCrypto() && vectorPreferences.hadExistingLegacyData()
)
)
} else {
diff --git a/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt
index 28016f109f..6ba5976eb8 100644
--- a/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt
@@ -92,11 +92,6 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor(
}
init {
- val currentSessionTs = session.cryptoService().getCryptoDeviceInfo(session.myUserId)
- .firstOrNull { it.deviceId == session.sessionParams.deviceId }
- ?.firstTimeSeenLocalTs
- ?: clock.epochMillis()
- Timber.v("## Detector - Current Session first time seen $currentSessionTs")
combine(
session.flow().liveUserCryptoDevices(session.myUserId),
@@ -108,6 +103,12 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor(
deleteUnusedClientInformation(infoList)
+ val currentSessionTs = session.cryptoService().getCryptoDeviceInfo(session.myUserId)
+ .firstOrNull { it.deviceId == session.sessionParams.deviceId }
+ ?.firstTimeSeenLocalTs
+ ?: clock.epochMillis()
+ Timber.v("## Detector - Current Session first time seen $currentSessionTs")
+
infoList
.asSequence()
.filter {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
index 09b91cc4f1..5f8883fdfe 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
@@ -528,6 +528,8 @@ class MessageItemFactory @Inject constructor(
)
val playable = messageContent.mimeType == MimeTypes.Gif
+ // don't show play button because detecting animated webp isn't possible via mimetype
+ val playableIfAutoplay = playable || messageContent.mimeType == MimeTypes.Webp
return MessageImageVideoItem_()
.attributes(attributes)
@@ -549,7 +551,7 @@ class MessageItemFactory @Inject constructor(
}
}
}.apply {
- if (playable && vectorPreferences.autoplayAnimatedImages()) {
+ if (playableIfAutoplay && vectorPreferences.autoplayAnimatedImages()) {
mode(ImageContentRenderer.Mode.ANIMATED_THUMBNAIL)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt
index 74b55d435d..fad1ad613d 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt
@@ -322,11 +322,10 @@ class RoomListViewModel @AssistedInject constructor(
}
private fun handleDeleteLocalRooms() {
- val localRoomIds = session.roomService()
- .getRoomSummaries(roomSummaryQueryParams { roomId = QueryStringValue.Contains(RoomLocalEcho.PREFIX) })
- .map { it.roomId }
-
- viewModelScope.launch {
+ viewModelScope.launch(session.coroutineDispatchers.io) {
+ val localRoomIds = session.roomService()
+ .getRoomSummaries(roomSummaryQueryParams { roomId = QueryStringValue.Contains(RoomLocalEcho.PREFIX) })
+ .map { it.roomId }
localRoomIds.forEach {
session.roomService().deleteLocalRoom(it)
}
diff --git a/vector/src/main/java/im/vector/app/features/media/DataAttachmentRoomProvider.kt b/vector/src/main/java/im/vector/app/features/media/DataAttachmentRoomProvider.kt
index 0924532bc2..a0354f3d60 100644
--- a/vector/src/main/java/im/vector/app/features/media/DataAttachmentRoomProvider.kt
+++ b/vector/src/main/java/im/vector/app/features/media/DataAttachmentRoomProvider.kt
@@ -49,7 +49,7 @@ class DataAttachmentRoomProvider(
return getItem(position).let {
when (it) {
is ImageContentRenderer.Data -> {
- if (it.mimeType == MimeTypes.Gif) {
+ if (it.mimeType == MimeTypes.Gif || it.mimeType == MimeTypes.Webp) {
AttachmentInfo.AnimatedImage(
uid = it.eventId,
url = it.url ?: "",
diff --git a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt
index baad815df2..876812cea0 100644
--- a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt
+++ b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt
@@ -135,7 +135,7 @@ class ImageContentRenderer @Inject constructor(
if (mode == Mode.ANIMATED_THUMBNAIL) it
else it.dontAnimate()
}
- .transform(cornerTransformation)
+ .optionalTransform(cornerTransformation)
.into(imageView)
}
@@ -167,7 +167,7 @@ class ImageContentRenderer @Inject constructor(
}
req
- .fitCenter()
+ .optionalFitCenter()
.into(target)
}
@@ -211,7 +211,7 @@ class ImageContentRenderer @Inject constructor(
return false
}
})
- .fitCenter()
+ .optionalFitCenter()
.into(imageView)
}
diff --git a/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt b/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt
index e18a13a3e6..f833a33b87 100644
--- a/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt
+++ b/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt
@@ -71,7 +71,7 @@ class RoomEventsAttachmentProvider(
allowNonMxcUrls = it.root.sendState.isSending()
)
- if (content.mimeType == MimeTypes.Gif) {
+ if (content.mimeType == MimeTypes.Gif || content.mimeType == MimeTypes.Webp) {
AttachmentInfo.AnimatedImage(
uid = it.eventId,
url = content.url ?: "",
diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt
index d2628fcf0f..b38805f05a 100644
--- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt
+++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt
@@ -38,6 +38,7 @@ import im.vector.app.config.OnboardingVariant
import im.vector.app.core.debug.DebugNavigator
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.error.fatalError
+import im.vector.app.core.extensions.commitTransaction
import im.vector.app.features.VectorFeatures
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsViewRoom
@@ -256,8 +257,9 @@ class DefaultNavigator @Inject constructor(
otherSessionId
)
if (context is AppCompatActivity) {
- SelfVerificationBottomSheet.forTransaction(request.transactionId)
- .show(context.supportFragmentManager, "VERIF")
+ context.supportFragmentManager.commitTransaction(allowStateLoss = true) {
+ add(SelfVerificationBottomSheet.forTransaction(request.transactionId), "VERIF")
+ }
}
}
}
@@ -271,8 +273,9 @@ class DefaultNavigator @Inject constructor(
// .filter { it.deviceId != session.sessionParams.deviceId }
// .map { it.deviceId }
if (context is AppCompatActivity) {
- SelfVerificationBottomSheet.verifyOwnUntrustedDevice()
- .show(context.supportFragmentManager, "VERIF")
+ context.supportFragmentManager.commitTransaction(allowStateLoss = true) {
+ add(SelfVerificationBottomSheet.verifyOwnUntrustedDevice(), "VERIF")
+ }
// if (otherSessions.isNotEmpty()) {
// val pr = session.cryptoService().verificationService().requestSelfKeyVerification(
// supportedVerificationMethodsProvider.provide())
diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt
index 2d799034d9..61cb14a70f 100644
--- a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt
+++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt
@@ -24,7 +24,9 @@ import im.vector.app.R
import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.utils.FirstThrottler
import im.vector.app.features.displayname.getBestName
+import im.vector.app.features.session.coroutineScope
import im.vector.app.features.settings.VectorPreferences
+import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.content.ContentUrlResolver
import org.matrix.android.sdk.api.session.getUserOrDefault
@@ -121,11 +123,15 @@ class NotificationDrawerManager @Inject constructor(
* Used to ignore events related to that room (no need to display notification) and clean any existing notification on this room.
*/
fun setCurrentRoom(roomId: String?) {
- updateEvents {
- val hasChanged = roomId != currentRoomId
- currentRoomId = roomId
- if (hasChanged && roomId != null) {
- it.clearMessagesForRoom(roomId)
+ val dispatcher = currentSession?.coroutineDispatchers?.io ?: return
+ val scope = currentSession?.coroutineScope ?: return
+ scope.launch(dispatcher) {
+ updateEvents {
+ val hasChanged = roomId != currentRoomId
+ currentRoomId = roomId
+ if (hasChanged && roomId != null) {
+ it.clearMessagesForRoom(roomId)
+ }
}
}
}
@@ -135,12 +141,16 @@ class NotificationDrawerManager @Inject constructor(
* Used to ignore events related to that thread (no need to display notification) and clean any existing notification on this room.
*/
fun setCurrentThread(threadId: String?) {
- updateEvents {
- val hasChanged = threadId != currentThreadId
- currentThreadId = threadId
- currentRoomId?.let { roomId ->
- if (hasChanged && threadId != null) {
- it.clearMessagesForThread(roomId, threadId)
+ val dispatcher = currentSession?.coroutineDispatchers?.io ?: return
+ val scope = currentSession?.coroutineScope ?: return
+ scope.launch(dispatcher) {
+ updateEvents {
+ val hasChanged = threadId != currentThreadId
+ currentThreadId = threadId
+ currentRoomId?.let { roomId ->
+ if (hasChanged && threadId != null) {
+ it.clearMessagesForThread(roomId, threadId)
+ }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt
index c269a4166a..09ae73a55c 100644
--- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt
+++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt
@@ -22,6 +22,4 @@ import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
sealed class DeviceListAction : VectorViewModelAction {
data class SelectDevice(val device: CryptoDeviceInfo) : DeviceListAction()
object DeselectDevice : DeviceListAction()
-
- data class ManuallyVerify(val deviceId: String) : DeviceListAction()
}
diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt
index 2a0ca4850e..63c44b4000 100644
--- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt
@@ -47,16 +47,7 @@ class DeviceListBottomSheet :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.observeViewEvents {
- when (it) {
- is DeviceListBottomSheetViewEvents.Verify -> {
- // TODO selfverif
-// VerificationBottomSheet.withArgs(
-// // roomId = null,
-// otherUserId = it.userId,
-// transactionId = it.txID
-// ).show(requireActivity().supportFragmentManager, "REQPOP")
- }
- }
+ // nop
}
}
@@ -109,13 +100,12 @@ class DeviceListBottomSheet :
@Parcelize
data class Args(
val userId: String,
- val allowDeviceAction: Boolean
) : Parcelable
companion object {
- fun newInstance(userId: String, allowDeviceAction: Boolean = true): DeviceListBottomSheet {
+ fun newInstance(userId: String): DeviceListBottomSheet {
return DeviceListBottomSheet().apply {
- setArguments(Args(userId, allowDeviceAction))
+ setArguments(Args(userId))
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewEvents.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewEvents.kt
index 8c6cba6cd9..159f505e16 100644
--- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewEvents.kt
@@ -21,6 +21,4 @@ import im.vector.app.core.platform.VectorViewEvents
/**
* Transient events for device list screen.
*/
-sealed class DeviceListBottomSheetViewEvents : VectorViewEvents {
- data class Verify(val userId: String, val txID: String) : DeviceListBottomSheetViewEvents()
-}
+sealed class DeviceListBottomSheetViewEvents : VectorViewEvents
diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt
index c3281858f0..435c44aa11 100644
--- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt
@@ -34,7 +34,6 @@ import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
-import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.getUserOrDefault
import org.matrix.android.sdk.api.util.MatrixItem
import org.matrix.android.sdk.api.util.toMatrixItem
@@ -42,7 +41,7 @@ import org.matrix.android.sdk.flow.flow
data class DeviceListViewState(
val userId: String,
- val allowDeviceAction: Boolean,
+ val myUserId: String,
val userItem: MatrixItem? = null,
val memberCrossSigningKey: MXCrossSigningInfo? = null,
val myDeviceId: String = "",
@@ -69,7 +68,7 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(
val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession()
return DeviceListViewState(
userId = userId,
- allowDeviceAction = args.allowDeviceAction,
+ myUserId = session.myUserId,
userItem = session.getUserOrDefault(userId).toMatrixItem(),
myDeviceId = session.sessionParams.deviceId,
)
@@ -104,7 +103,6 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(
when (action) {
is DeviceListAction.SelectDevice -> selectDevice(action)
is DeviceListAction.DeselectDevice -> deselectDevice()
- is DeviceListAction.ManuallyVerify -> manuallyVerify(action)
}
}
@@ -121,7 +119,6 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(
}
private fun selectDevice(action: DeviceListAction.SelectDevice) {
- if (!initialState.allowDeviceAction) return
setState {
copy(selectedDevice = action.device)
}
@@ -132,18 +129,4 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(
copy(selectedDevice = null)
}
}
-
- private fun manuallyVerify(action: DeviceListAction.ManuallyVerify) {
- if (!initialState.allowDeviceAction) return
- viewModelScope.launch {
- session.cryptoService().verificationService().requestDeviceVerification(
- methods = listOf(VerificationMethod.SAS),
- otherUserId = initialState.userId,
- otherDeviceId = action.deviceId,
- ).transactionId
- .let { txID ->
- _viewEvents.post(DeviceListBottomSheetViewEvents.Verify(initialState.userId, txID))
- }
- }
- }
}
diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt
index d8abd91091..d3b5a25913 100644
--- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt
@@ -28,7 +28,6 @@ import im.vector.app.core.extensions.configureWith
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.databinding.BottomSheetGenericListBinding
-import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
import javax.inject.Inject
@AndroidEntryPoint
@@ -63,8 +62,4 @@ class DeviceTrustInfoActionFragment :
override fun invalidate() = withState(viewModel) {
epoxyController.setData(it)
}
-
- override fun onVerifyManually(device: CryptoDeviceInfo) {
- viewModel.handle(DeviceListAction.ManuallyVerify(device.deviceId))
- }
}
diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt
index 20c388dd95..0f39fc889c 100644
--- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt
+++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt
@@ -25,13 +25,10 @@ import im.vector.app.core.ui.list.genericFooterItem
import im.vector.app.core.ui.list.genericItem
import im.vector.app.core.ui.list.genericWithValueItem
import im.vector.app.core.utils.DimensionConverter
-import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem
-import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.settings.devices.TrustUtils
import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
import me.gujun.android.span.span
import org.matrix.android.sdk.api.extensions.orFalse
-import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
import javax.inject.Inject
@@ -39,13 +36,10 @@ class DeviceTrustInfoEpoxyController @Inject constructor(
private val stringProvider: StringProvider,
private val colorProvider: ColorProvider,
private val dimensionConverter: DimensionConverter,
- private val vectorPreferences: VectorPreferences
) :
TypedEpoxyController() {
- interface InteractionListener {
- fun onVerifyManually(device: CryptoDeviceInfo)
- }
+ interface InteractionListener
var interactionListener: InteractionListener? = null
@@ -54,7 +48,7 @@ class DeviceTrustInfoEpoxyController @Inject constructor(
data?.selectedDevice?.let { cryptoDeviceInfo ->
val trustMSK = data.memberCrossSigningKey?.isTrusted().orFalse()
val legacyMode = data.memberCrossSigningKey == null
- val isMyDevice = data.myDeviceId == cryptoDeviceInfo.deviceId
+ val isMyDevice = data.userId == data.myUserId && data.myDeviceId == cryptoDeviceInfo.deviceId
val trustLevel = TrustUtils.shieldForTrust(
isMyDevice,
trustMSK,
@@ -126,18 +120,7 @@ class DeviceTrustInfoEpoxyController @Inject constructor(
id("warn")
centered(false)
textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
- text(host.stringProvider.getString(R.string.verification_profile_device_untrust_info).toEpoxyCharSequence())
- }
-
- bottomSheetVerificationActionItem {
- id("verify")
- title(host.stringProvider.getString(R.string.cross_signing_verify_by_emoji))
- titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
- iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
- listener {
- host.interactionListener?.onVerifyManually(cryptoDeviceInfo)
- }
+ text(host.stringProvider.getString(R.string.verification_profile_other_device_untrust_info).toEpoxyCharSequence())
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
index f915395a42..0dd8d14460 100755
--- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
@@ -254,6 +254,8 @@ class VectorPreferences @Inject constructor(
const val TAKE_PHOTO_VIDEO_MODE_PHOTO = 1
const val TAKE_PHOTO_VIDEO_MODE_VIDEO = 2
+ const val HAD_EXISTING_LEGACY_DATA = "HAD_EXISTING_LEGACY_DATA"
+ const val IS_ON_RUST_CRYPTO = "IS_ON_RUST_CRYPTO"
// Background sync modes
// some preferences keys must be kept after a logout
@@ -1278,4 +1280,24 @@ class VectorPreferences @Inject constructor(
putBoolean(SETTINGS_NEW_LOGIN_ALERT_SHOWN_FOR_DEVICE + deviceId, true)
}
}
+
+ fun hadExistingLegacyData(): Boolean {
+ return defaultPrefs.getBoolean(HAD_EXISTING_LEGACY_DATA, false)
+ }
+
+ fun setHadExistingLegacyData(had: Boolean) {
+ defaultPrefs.edit {
+ putBoolean(HAD_EXISTING_LEGACY_DATA, had)
+ }
+ }
+
+ fun isOnRustCrypto(): Boolean {
+ return defaultPrefs.getBoolean(IS_ON_RUST_CRYPTO, false)
+ }
+
+ fun setIsOnRustCrypto(boolean: Boolean) {
+ defaultPrefs.edit {
+ putBoolean(IS_ON_RUST_CRYPTO, boolean)
+ }
+ }
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt
index 268ae86601..762a636494 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt
@@ -25,6 +25,8 @@ class GetEncryptionTrustLevelForDeviceUseCase @Inject constructor(
private val getEncryptionTrustLevelForOtherDeviceUseCase: GetEncryptionTrustLevelForOtherDeviceUseCase,
) {
+ // XXX why is this using the RoomEncryptionTrustLevel?
+ // should be using a new DeviceTrustShield enum
fun execute(currentSessionCrossSigningInfo: CurrentSessionCrossSigningInfo, cryptoDeviceInfo: CryptoDeviceInfo?): RoomEncryptionTrustLevel? {
if (cryptoDeviceInfo == null) {
return null
diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt
index b355b55903..6489fe537d 100644
--- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt
@@ -17,6 +17,7 @@
package im.vector.app.features.settings.troubleshoot
import androidx.fragment.app.FragmentActivity
+import androidx.lifecycle.lifecycleScope
import androidx.work.WorkInfo
import androidx.work.WorkManager
import im.vector.app.R
@@ -72,13 +73,15 @@ class TestEndpointAsTokenRegistration @Inject constructor(
}
private fun unregisterThenRegister(testParameters: TestParameters, pushKey: String) {
- activeSessionHolder.getSafeActiveSession()?.coroutineScope?.launch {
+ val scope = activeSessionHolder.getSafeActiveSession()?.coroutineScope ?: return
+ val io = activeSessionHolder.getActiveSession().coroutineDispatchers.io
+ scope.launch(io) {
unregisterUnifiedPushUseCase.execute(pushersManager)
registerUnifiedPush(distributor = "", testParameters, pushKey)
}
}
- private fun registerUnifiedPush(
+ private suspend fun registerUnifiedPush(
distributor: String,
testParameters: TestParameters,
pushKey: String,
@@ -106,7 +109,9 @@ class TestEndpointAsTokenRegistration @Inject constructor(
pushKey: String,
) {
unifiedPushHelper.showSelectDistributorDialog(context) { selection ->
- registerUnifiedPush(distributor = selection, testParameters, pushKey)
+ context.lifecycleScope.launch {
+ registerUnifiedPush(distributor = selection, testParameters, pushKey)
+ }
}
}
}
diff --git a/vector/src/test/java/im/vector/app/core/device/DefaultGetDeviceInfoUseCaseTest.kt b/vector/src/test/java/im/vector/app/core/device/DefaultGetDeviceInfoUseCaseTest.kt
index 0673fbadb5..01e5c88809 100644
--- a/vector/src/test/java/im/vector/app/core/device/DefaultGetDeviceInfoUseCaseTest.kt
+++ b/vector/src/test/java/im/vector/app/core/device/DefaultGetDeviceInfoUseCaseTest.kt
@@ -19,6 +19,7 @@ package im.vector.app.core.device
import im.vector.app.test.fakes.FakeActiveSessionHolder
import im.vector.app.test.fakes.FakeCryptoService
import im.vector.app.test.fakes.FakeSession
+import kotlinx.coroutines.test.runTest
import org.amshove.kluent.shouldBeEqualTo
import org.junit.Test
@@ -31,7 +32,7 @@ class DefaultGetDeviceInfoUseCaseTest {
private val getDeviceInfoUseCase = DefaultGetDeviceInfoUseCase(activeSessionHolder.instance)
@Test
- fun `when execute, then get crypto device info`() {
+ fun `when execute, then get crypto device info`() = runTest {
val result = getDeviceInfoUseCase.execute()
result shouldBeEqualTo cryptoService.cryptoDeviceInfo
diff --git a/vector/src/test/java/im/vector/app/core/pushers/PushersManagerTest.kt b/vector/src/test/java/im/vector/app/core/pushers/PushersManagerTest.kt
index 1e228353f5..4b6063fb93 100644
--- a/vector/src/test/java/im/vector/app/core/pushers/PushersManagerTest.kt
+++ b/vector/src/test/java/im/vector/app/core/pushers/PushersManagerTest.kt
@@ -29,6 +29,7 @@ import im.vector.app.test.fixtures.CryptoDeviceInfoFixture.aCryptoDeviceInfo
import im.vector.app.test.fixtures.PusherFixture
import im.vector.app.test.fixtures.SessionParamsFixture
import io.mockk.mockk
+import kotlinx.coroutines.test.runTest
import org.amshove.kluent.shouldBeEqualTo
import org.junit.Test
import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo
@@ -56,7 +57,7 @@ class PushersManagerTest {
)
@Test
- fun `when enqueueRegisterPusher, then HttpPusher created and enqueued`() {
+ fun `when enqueueRegisterPusher, then HttpPusher created and enqueued`() = runTest {
val pushKey = "abc"
val gateway = "123"
val pusherAppId = "app-id"
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeCryptoService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeCryptoService.kt
index e8bb15ac58..b5e503dd98 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeCryptoService.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeCryptoService.kt
@@ -84,5 +84,5 @@ class FakeCryptoService(
}
}
- override fun getMyCryptoDevice() = cryptoDeviceInfo
+ override suspend fun getMyCryptoDevice() = cryptoDeviceInfo
}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeGetDeviceInfoUseCase.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeGetDeviceInfoUseCase.kt
index c284263d28..34853d1776 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeGetDeviceInfoUseCase.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeGetDeviceInfoUseCase.kt
@@ -17,13 +17,13 @@
package im.vector.app.test.fakes
import im.vector.app.core.device.GetDeviceInfoUseCase
-import io.mockk.every
+import io.mockk.coEvery
import io.mockk.mockk
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
class FakeGetDeviceInfoUseCase : GetDeviceInfoUseCase by mockk() {
fun givenDeviceInfo(cryptoDeviceInfo: CryptoDeviceInfo) {
- every { execute() } returns cryptoDeviceInfo
+ coEvery { execute() } returns cryptoDeviceInfo
}
}