diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 4bb3e510..2066c5ef 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -33,6 +33,8 @@ android { targetSdkVersion 28 versionCode 1 versionName "0.0.1" + // Multidex is useful for tests + multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" @@ -66,6 +68,11 @@ android { lintOptions { lintConfig file("lint.xml") } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } static def gitRevision() { diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/util/JsonCanonicalizerTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/util/JsonCanonicalizerTest.kt index 14ee6518..1ea6105d 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/util/JsonCanonicalizerTest.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/util/JsonCanonicalizerTest.kt @@ -52,7 +52,7 @@ internal class JsonCanonicalizerTest : InstrumentedTest { @Test fun realSampleTest() { - assertEquals("""{"algorithms":["m.megolm.v1.aes-sha2","m.olm.v1.curve25519-aes-sha2"],"device_id":"VSCUNFSOUI","keys":{"curve25519:VSCUNFSOUI":"utyOjnhiQ73qNhi9HlN0OgWIowe5gthTS8r0r9TcJ3o","ed25519:VSCUNFSOUI":"qNhEt+Yggaajet0hX/FjTRLfySgs65ldYyomm7PIx6U"},"user_id":"@benoitx:matrix.org"}""", + assertEquals("""{"algorithms":["m.megolm.v1.aes-sha2","m.olm.v1.curve25519-aes-sha2"],"device_id":"VSCUNFSOUI","keys":{"curve25519:VSCUNFSOUI":"utyOjnhiQ73qNhi9HlN0OgWIowe5gthTS8r0r9TcJ3o","ed25519:VSCUNFSOUI":"qNhEt+Yggaajet0hX\/FjTRLfySgs65ldYyomm7PIx6U"},"user_id":"@benoitx:matrix.org"}""", JsonCanonicalizer.canonicalize("""{"algorithms":["m.megolm.v1.aes-sha2","m.olm.v1.curve25519-aes-sha2"],"device_id":"VSCUNFSOUI","user_id":"@benoitx:matrix.org","keys":{"curve25519:VSCUNFSOUI":"utyOjnhiQ73qNhi9HlN0OgWIowe5gthTS8r0r9TcJ3o","ed25519:VSCUNFSOUI":"qNhEt+Yggaajet0hX/FjTRLfySgs65ldYyomm7PIx6U"}}""")) } diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/ChunkEntityTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/ChunkEntityTest.kt index b76014d1..be351fb0 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/ChunkEntityTest.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/ChunkEntityTest.kt @@ -59,7 +59,7 @@ internal class ChunkEntityTest : InstrumentedTest { val chunk: ChunkEntity = realm.createObject() val fakeEvent = createFakeMessageEvent() chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS) - chunk.events.size shouldEqual 1 + chunk.timelineEvents.size shouldEqual 1 } } @@ -70,7 +70,7 @@ internal class ChunkEntityTest : InstrumentedTest { val fakeEvent = createFakeMessageEvent() chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS) chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS) - chunk.events.size shouldEqual 1 + chunk.timelineEvents.size shouldEqual 1 } } @@ -126,7 +126,7 @@ internal class ChunkEntityTest : InstrumentedTest { chunk1.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS) chunk2.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS) chunk1.merge("roomId", chunk2, PaginationDirection.BACKWARDS) - chunk1.events.size shouldEqual 60 + chunk1.timelineEvents.size shouldEqual 60 } } @@ -142,7 +142,7 @@ internal class ChunkEntityTest : InstrumentedTest { chunk1.addAll("roomId", eventsForChunk1, PaginationDirection.FORWARDS) chunk2.addAll("roomId", eventsForChunk2, PaginationDirection.BACKWARDS) chunk1.merge("roomId", chunk2, PaginationDirection.BACKWARDS) - chunk1.events.size shouldEqual 40 + chunk1.timelineEvents.size shouldEqual 40 chunk1.isLastForward.shouldBeTrue() } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt index 342c7ee5..5993548e 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt @@ -48,7 +48,6 @@ import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAct import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting import im.vector.matrix.android.internal.crypto.algorithms.megolm.MXMegolmEncryptionFactory import im.vector.matrix.android.internal.crypto.algorithms.olm.MXOlmEncryptionFactory -import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo @@ -74,12 +73,12 @@ import im.vector.matrix.android.internal.session.room.membership.RoomMembers import im.vector.matrix.android.internal.session.sync.model.SyncResponse import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith +import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.fetchCopied import kotlinx.coroutines.* import org.matrix.olm.OlmManager import timber.log.Timber -import java.io.File import java.util.* import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject @@ -766,7 +765,7 @@ internal class CryptoManager @Inject constructor( private suspend fun uploadDeviceKeys(): Try { // Prepare the device keys data to send // Sign it - val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, getMyDevice().signalableJSONDictionary()) + val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, getMyDevice().signalableJSONDictionary()) getMyDevice().signatures = objectSigner.signObject(canonicalJson) // For now, we set the device id explicitly, as we may not be using the diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt index 519a850f..8f0bfcd4 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt @@ -28,6 +28,7 @@ import im.vector.matrix.android.internal.crypto.model.OlmSessionWrapper import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.session.SessionScope +import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.convertFromUTF8 import im.vector.matrix.android.internal.util.convertToUTF8 import org.matrix.olm.* @@ -728,7 +729,7 @@ internal class MXOlmDevice @Inject constructor( @Throws(Exception::class) fun verifySignature(key: String, jsonDictionary: Map, signature: String) { // Check signature on the canonical version of the JSON - olmUtility!!.verifyEd25519Signature(signature, key, MoshiProvider.getCanonicalJson>(Map::class.java, jsonDictionary)) + olmUtility!!.verifyEd25519Signature(signature, key, JsonCanonicalizer.getCanonicalJson(Map::class.java, jsonDictionary)) } /** diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt index 9cf981b5..a81cbfcf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt @@ -22,8 +22,8 @@ import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.internal.crypto.model.MXKey import im.vector.matrix.android.internal.crypto.model.rest.KeysUploadResponse import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask -import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.session.SessionScope +import im.vector.matrix.android.internal.util.JsonCanonicalizer import org.matrix.olm.OlmAccount import timber.log.Timber import java.util.* @@ -158,7 +158,7 @@ internal class OneTimeKeysUploader @Inject constructor( k["key"] = curve25519Map.getValue(key_id) // the key is also signed - val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, k) + val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, k) k["signatures"] = objectSigner.signObject(canonicalJson) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt index 336a5a0f..3328de0e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt @@ -22,8 +22,7 @@ import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_OLM import im.vector.matrix.android.internal.crypto.MXOlmDevice import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.model.rest.EncryptedMessage -import im.vector.matrix.android.internal.di.MoshiProvider -import im.vector.matrix.android.internal.session.SessionScope +import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.convertToUTF8 import timber.log.Timber import java.util.* @@ -81,7 +80,7 @@ internal class MessageEncrypter @Inject constructor(private val credentials: Cre recipientsKeysMap["ed25519"] = deviceInfo.fingerprint()!! payloadJson["recipient_keys"] = recipientsKeysMap - val payloadString = convertToUTF8(MoshiProvider.getCanonicalJson(Map::class.java, payloadJson)) + val payloadString = convertToUTF8(JsonCanonicalizer.getCanonicalJson(Map::class.java, payloadJson)) ciphertext[deviceKey] = olmDevice.encryptMessage(deviceKey, sessionId!!, payloadString!!)!! } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt index ca9a105e..165fc736 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt @@ -36,7 +36,7 @@ import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.repository.WarnOnUnknownDeviceRepository import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask -import im.vector.matrix.android.internal.di.MoshiProvider +import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.convertToUTF8 import timber.log.Timber import java.util.* @@ -263,7 +263,7 @@ internal class MXMegolmEncryption( // Get canonical Json from - val payloadString = convertToUTF8(MoshiProvider.getCanonicalJson(Map::class.java, payloadJson)) + val payloadString = convertToUTF8(JsonCanonicalizer.getCanonicalJson(Map::class.java, payloadJson)) val ciphertext = olmDevice.encryptGroupMessage(session.sessionId, payloadString!!) val map = HashMap() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt index 5d4a9504..9350fd44 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt @@ -55,6 +55,7 @@ import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskThread import im.vector.matrix.android.internal.task.configureWith +import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -176,7 +177,7 @@ internal class KeysBackup @Inject constructor( megolmBackupAuthData.publicKey = publicKey } - val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, megolmBackupAuthData.signalableJSONDictionary()) + val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, megolmBackupAuthData.signalableJSONDictionary()) megolmBackupAuthData.signatures = objectSigner.signObject(canonicalJson) @@ -456,7 +457,7 @@ internal class KeysBackup @Inject constructor( if (trust) { // Add current device signature - val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, authData.signalableJSONDictionary()) + val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, authData.signalableJSONDictionary()) val deviceSignatures = objectSigner.signObject(canonicalJson) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/IncomingSASVerificationTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/IncomingSASVerificationTransaction.kt index 2a4f0a1d..641062d7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/IncomingSASVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/IncomingSASVerificationTransaction.kt @@ -29,8 +29,8 @@ import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationMac import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask -import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.task.TaskExecutor +import im.vector.matrix.android.internal.util.JsonCanonicalizer import timber.log.Timber internal class IncomingSASVerificationTransaction( @@ -147,7 +147,7 @@ internal class IncomingSASVerificationTransaction( //The hash commitment is the hash (using the selected hash algorithm) of the unpadded base64 representation of QB, // concatenated with the canonical JSON representation of the content of the m.key.verification.start message - val concat = getSAS().publicKey + MoshiProvider.getCanonicalJson(KeyVerificationStart::class.java, startReq!!) + val concat = getSAS().publicKey + JsonCanonicalizer.getCanonicalJson(KeyVerificationStart::class.java, startReq!!) accept.commitment = hashUsingAgreedHashMethod(concat) ?: "" //we need to send this to other device now state = SasVerificationTxState.SendingAccept diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/OutgoingSASVerificationRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/OutgoingSASVerificationRequest.kt index a33f8878..0500be54 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/OutgoingSASVerificationRequest.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/OutgoingSASVerificationRequest.kt @@ -27,8 +27,8 @@ import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationMac import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask -import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.task.TaskExecutor +import im.vector.matrix.android.internal.util.JsonCanonicalizer import timber.log.Timber internal class OutgoingSASVerificationRequest( @@ -164,7 +164,7 @@ internal class OutgoingSASVerificationRequest( // in Bob’s m.key.verification.key and the content of Alice’s m.key.verification.start message. //check commitment - val concat = vKey.key + MoshiProvider.getCanonicalJson(KeyVerificationStart::class.java, startReq!!) + val concat = vKey.key + JsonCanonicalizer.getCanonicalJson(KeyVerificationStart::class.java, startReq!!) val otherCommitment = hashUsingAgreedHashMethod(concat) ?: "" if (accepted!!.commitment.equals(otherCommitment)) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt index 8e877f89..af8317aa 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt @@ -16,6 +16,7 @@ package im.vector.matrix.android.internal.database.helper +import androidx.annotation.VisibleForTesting import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.room.send.SendState @@ -102,11 +103,12 @@ internal fun ChunkEntity.updateSenderDataFor(eventIds: List) { } } -private fun ChunkEntity.add(roomId: String, - event: Event, - direction: PaginationDirection, - stateIndexOffset: Int = 0, - isUnlinked: Boolean = false) { +@VisibleForTesting +internal fun ChunkEntity.add(roomId: String, + event: Event, + direction: PaginationDirection, + stateIndexOffset: Int = 0, + isUnlinked: Boolean = false) { assertIsManaged() if (event.eventId != null && timelineEvents.find(event.eventId) != null) { @@ -149,14 +151,14 @@ private fun ChunkEntity.add(roomId: String, internal fun ChunkEntity.lastDisplayIndex(direction: PaginationDirection, defaultValue: Int = 0): Int { return when (direction) { - PaginationDirection.FORWARDS -> forwardsDisplayIndex - PaginationDirection.BACKWARDS -> backwardsDisplayIndex - } ?: defaultValue + PaginationDirection.FORWARDS -> forwardsDisplayIndex + PaginationDirection.BACKWARDS -> backwardsDisplayIndex + } ?: defaultValue } internal fun ChunkEntity.lastStateIndex(direction: PaginationDirection, defaultValue: Int = 0): Int { return when (direction) { - PaginationDirection.FORWARDS -> forwardsStateIndex - PaginationDirection.BACKWARDS -> backwardsStateIndex - } ?: defaultValue + PaginationDirection.FORWARDS -> forwardsStateIndex + PaginationDirection.BACKWARDS -> backwardsStateIndex + } ?: defaultValue } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt index 3849a2f7..e4303298 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt @@ -23,7 +23,6 @@ import im.vector.matrix.android.internal.network.parsing.UriMoshiAdapter import im.vector.matrix.android.internal.session.sync.model.UserAccountData import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages import im.vector.matrix.android.internal.session.sync.model.UserAccountDataFallback -import im.vector.matrix.android.internal.util.JsonCanonicalizer object MoshiProvider { @@ -50,19 +49,6 @@ object MoshiProvider { return moshi } - // TODO Move - fun getCanonicalJson(type: Class, o: T): String { - val adapter = moshi.adapter(type) - - val json = adapter.toJson(o) - - // Canonicalize manually - val can = JsonCanonicalizer.canonicalize(json) - - val jsonSafe = can.replace("\\/", "/") - - return jsonSafe - } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt index 1e2aec84..ed7e5021 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt @@ -20,7 +20,6 @@ import android.content.Context import android.os.Looper import androidx.annotation.MainThread import androidx.lifecycle.LiveData -import androidx.work.WorkManager import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.api.pushrules.PushRuleService @@ -44,6 +43,7 @@ import im.vector.matrix.android.internal.crypto.CryptoManager import im.vector.matrix.android.internal.database.LiveEntityObserver import im.vector.matrix.android.internal.session.sync.job.SyncThread import im.vector.matrix.android.internal.session.sync.job.SyncWorker +import im.vector.matrix.android.internal.worker.WorkManagerUtil import timber.log.Timber import javax.inject.Inject @@ -150,10 +150,7 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se Timber.w("SIGN_OUT: clear cache -> SUCCESS: clear crypto cache") cryptoService.clearCryptoCache(MatrixCallbackDelegate(callback)) - WorkManager.getInstance(context).also { - it.cancelAllWork() - it.pruneWork() - } + WorkManagerUtil.cancelAllWorks(context) } override fun onFailure(failure: Throwable) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt index 46578272..54184480 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt @@ -17,10 +17,7 @@ package im.vector.matrix.android.internal.session.group import android.content.Context -import androidx.work.Constraints import androidx.work.ExistingWorkPolicy -import androidx.work.NetworkType -import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.auth.data.Credentials @@ -28,6 +25,8 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver import im.vector.matrix.android.internal.database.model.GroupEntity import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.SessionDatabase +import im.vector.matrix.android.internal.worker.WorkManagerUtil +import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkerParamsFactory import io.realm.RealmConfiguration import javax.inject.Inject @@ -41,18 +40,14 @@ internal class GroupSummaryUpdater @Inject constructor(private val context: Cont override val query = Monarchy.Query { GroupEntity.where(it) } - private val workConstraints = Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build() - override fun processChanges(inserted: List, updated: List, deleted: List) { val newGroupIds = inserted.map { it.groupId } val getGroupDataWorkerParams = GetGroupDataWorker.Params(credentials.userId, newGroupIds) val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams) - val sendWork = OneTimeWorkRequestBuilder() + val sendWork = matrixOneTimeWorkRequestBuilder() .setInputData(workData) - .setConstraints(workConstraints) + .setConstraints(WorkManagerUtil.workConstraints) .build() WorkManager.getInstance(context) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt index 8401f3e6..24706841 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt @@ -18,23 +18,19 @@ package im.vector.matrix.android.internal.session.pushers import android.content.Context import androidx.lifecycle.LiveData import androidx.work.BackoffPolicy -import androidx.work.Constraints -import androidx.work.NetworkType -import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.api.session.pushers.Pusher -import im.vector.matrix.android.api.session.pushers.PusherState import im.vector.matrix.android.api.session.pushers.PushersService import im.vector.matrix.android.internal.database.mapper.asDomain -import im.vector.matrix.android.internal.database.mapper.toEntity import im.vector.matrix.android.internal.database.model.PusherEntity -import im.vector.matrix.android.internal.database.model.PusherEntityFields import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith +import im.vector.matrix.android.internal.worker.WorkManagerUtil +import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkerParamsFactory import java.util.* import java.util.concurrent.TimeUnit @@ -76,10 +72,8 @@ internal class DefaultPusherService @Inject constructor( val params = AddHttpPusherWorker.Params(pusher, sessionParam.credentials.userId) - val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build() - - val request = OneTimeWorkRequestBuilder() - .setConstraints(constraints) + val request = matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerUtil.workConstraints) .setInputData(WorkerParamsFactory.toData(params)) .setBackoffCriteria(BackoffPolicy.LINEAR, 10_000L, TimeUnit.MILLISECONDS) .build() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index 162b9d3a..71a2c4bb 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -17,7 +17,10 @@ package im.vector.matrix.android.internal.session.room.send import android.content.Context -import androidx.work.* +import androidx.work.BackoffPolicy +import androidx.work.ExistingWorkPolicy +import androidx.work.OneTimeWorkRequest +import androidx.work.WorkManager import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.session.content.ContentAttachmentData @@ -29,6 +32,8 @@ import im.vector.matrix.android.api.util.CancelableBag import im.vector.matrix.android.internal.session.content.UploadContentWorker import im.vector.matrix.android.internal.session.room.timeline.TimelineSendEventWorkCommon import im.vector.matrix.android.internal.util.CancelableWork +import im.vector.matrix.android.internal.worker.WorkManagerUtil +import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkerParamsFactory import timber.log.Timber import java.util.concurrent.TimeUnit @@ -37,10 +42,6 @@ import javax.inject.Inject private const val UPLOAD_WORK = "UPLOAD_WORK" private const val BACKOFF_DELAY = 10_000L -private val WORK_CONSTRAINTS = Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build() - internal class DefaultSendService @Inject constructor(private val context: Context, private val credentials: Credentials, private val roomId: String, @@ -135,8 +136,8 @@ internal class DefaultSendService @Inject constructor(private val context: Conte val params = EncryptEventWorker.Params(credentials.userId, roomId, event) val sendWorkData = WorkerParamsFactory.toData(params) - return OneTimeWorkRequestBuilder() - .setConstraints(WORK_CONSTRAINTS) + return matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerUtil.workConstraints) .setInputData(sendWorkData) .setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS) .build() @@ -162,8 +163,8 @@ internal class DefaultSendService @Inject constructor(private val context: Conte val uploadMediaWorkerParams = UploadContentWorker.Params(credentials.userId, roomId, event, attachment, isRoomEncrypted) val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams) - return OneTimeWorkRequestBuilder() - .setConstraints(WORK_CONSTRAINTS) + return matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerUtil.workConstraints) .setInputData(uploadWorkData) .setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS) .build() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt index ca2007a1..53906fdd 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt @@ -17,16 +17,14 @@ package im.vector.matrix.android.internal.session.room.timeline import android.content.Context import androidx.work.* +import im.vector.matrix.android.internal.worker.WorkManagerUtil +import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import java.util.concurrent.TimeUnit private const val SEND_WORK = "SEND_WORK" private const val BACKOFF_DELAY = 10_000L -private val WORK_CONSTRAINTS = Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build() - /** * Helper class for sending event related works. * All send event from a room are using the same workchain, in order to ensure order. @@ -60,8 +58,8 @@ internal object TimelineSendEventWorkCommon { } inline fun createWork(data: Data): OneTimeWorkRequest { - return OneTimeWorkRequestBuilder() - .setConstraints(WORK_CONSTRAINTS) + return matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerUtil.workConstraints) .setInputData(data) .setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS) .build() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncWorker.kt index 8a741eb0..ff30dbbc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncWorker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncWorker.kt @@ -24,6 +24,8 @@ import im.vector.matrix.android.internal.session.sync.SyncTask import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskThread import im.vector.matrix.android.internal.task.configureWith +import im.vector.matrix.android.internal.worker.WorkManagerUtil +import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkerParamsFactory import im.vector.matrix.android.internal.worker.getSessionComponent import timber.log.Timber @@ -86,11 +88,9 @@ internal class SyncWorker(context: Context, fun requireBackgroundSync(context: Context, userId: String, serverTimeout: Long = 0) { val data = WorkerParamsFactory.toData(Params(userId, serverTimeout, false)) - val workRequest = OneTimeWorkRequestBuilder() + val workRequest = matrixOneTimeWorkRequestBuilder() .setInputData(data) - .setConstraints(Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build()) + .setConstraints(WorkManagerUtil.workConstraints) .setBackoffCriteria(BackoffPolicy.LINEAR, 1_000, TimeUnit.MILLISECONDS) .build() WorkManager.getInstance(context).enqueueUniqueWork("BG_SYNCP", ExistingWorkPolicy.REPLACE, workRequest) @@ -98,11 +98,9 @@ internal class SyncWorker(context: Context, fun automaticallyBackgroundSync(context: Context, userId: String, serverTimeout: Long = 0, delay: Long = 30_000) { val data = WorkerParamsFactory.toData(Params(userId, serverTimeout, true)) - val workRequest = OneTimeWorkRequestBuilder() + val workRequest = matrixOneTimeWorkRequestBuilder() .setInputData(data) - .setConstraints(Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build()) + .setConstraints(WorkManagerUtil.workConstraints) .setBackoffCriteria(BackoffPolicy.LINEAR, delay, TimeUnit.MILLISECONDS) .build() WorkManager.getInstance(context).enqueueUniqueWork("BG_SYNCP", ExistingWorkPolicy.REPLACE, workRequest) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/JsonCanonicalizer.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/JsonCanonicalizer.kt index f7fd3cf4..36c1ba15 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/JsonCanonicalizer.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/JsonCanonicalizer.kt @@ -16,6 +16,8 @@ package im.vector.matrix.android.internal.util +import androidx.annotation.VisibleForTesting +import im.vector.matrix.android.internal.di.MoshiProvider import org.json.JSONArray import org.json.JSONException import org.json.JSONObject @@ -28,45 +30,41 @@ import java.util.* */ object JsonCanonicalizer { - fun canonicalize(json: String): String { - var can: String? = null - try { - val _json = JSONObject(json) + fun getCanonicalJson(type: Class, o: T): String { + val adapter = MoshiProvider.providesMoshi().adapter(type) - can = _canonicalize(_json) + // Canonicalize manually + return canonicalize(adapter.toJson(o)) + .replace("\\/", "/") + } + + @VisibleForTesting + fun canonicalize(jsonString: String): String { + return try { + val jsonObject = JSONObject(jsonString) + + canonicalizeRecursive(jsonObject) } catch (e: JSONException) { Timber.e(e, "Unable to canonicalize") + jsonString } - - if (can == null) { - Timber.e("Error") - return json - } - - return can } /** - * Canonicalize a JsonElement element + * Canonicalize a JSON element * * @param src the src * @return the canonicalize element */ - private fun _canonicalize(src: Any?): String? { - // sanity check - if (null == src) { - return null - } - - when (src) { + private fun canonicalizeRecursive(any: Any): String { + when (any) { is JSONArray -> { // Canonicalize each element of the array - val srcArray = src as JSONArray? val result = StringBuilder("[") - for (i in 0 until srcArray!!.length()) { - result.append(_canonicalize(srcArray.get(i))) - if (i < srcArray.length() - 1) { + for (i in 0 until any.length()) { + result.append(canonicalizeRecursive(any.get(i))) + if (i < any.length() - 1) { result.append(",") } } @@ -76,11 +74,11 @@ object JsonCanonicalizer { return result.toString() } is JSONObject -> { - // Sort the attributes by name, and the canonicalize each element of the object + // Sort the attributes by name, and the canonicalize each element of the JSONObject val result = StringBuilder("{") val attributes = TreeSet() - for (entry in src.keys()) { + for (entry in any.keys()) { attributes.add(entry) } @@ -89,7 +87,7 @@ object JsonCanonicalizer { .append(attribute.value) .append("\"") .append(":") - .append(_canonicalize(src[attribute.value])) + .append(canonicalizeRecursive(any[attribute.value])) if (attribute.index < attributes.size - 1) { result.append(",") @@ -100,8 +98,8 @@ object JsonCanonicalizer { return result.toString() } - is String -> return JSONObject.quote(src) - else -> return src.toString() + is String -> return JSONObject.quote(any) + else -> return any.toString() } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkManagerUtil.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkManagerUtil.kt new file mode 100644 index 00000000..ea0ff282 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkManagerUtil.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.matrix.android.internal.worker + +import android.content.Context +import androidx.work.* + +internal object WorkManagerUtil { + private const val MATRIX_SDK_TAG = "MatrixSDK" + + /** + * Default constraints: connected network + */ + val workConstraints = Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() + + /** + * Create a OneTimeWorkRequestBuilder, with the Matrix SDK tag + */ + inline fun matrixOneTimeWorkRequestBuilder() = + OneTimeWorkRequestBuilder() + .addTag(MATRIX_SDK_TAG) + + /** + * Cancel all works instantiated by the Matrix SDK and not those from the SDK client + */ + fun cancelAllWorks(context: Context) { + WorkManager.getInstance(context).also { + it.cancelAllWorkByTag(MATRIX_SDK_TAG) + it.pruneWork() + } + } +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerKey.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerKey.kt deleted file mode 100644 index c5b0f45a..00000000 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkerKey.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2019 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.matrix.android.internal.worker - -import androidx.work.ListenableWorker -import dagger.MapKey -import kotlin.reflect.KClass - -@MapKey -@Target(AnnotationTarget.FUNCTION) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class WorkerKey(val value: KClass) \ No newline at end of file diff --git a/tools/check/forbidden_strings_in_code.txt b/tools/check/forbidden_strings_in_code.txt index 7361e5f8..7686cb0b 100644 --- a/tools/check/forbidden_strings_in_code.txt +++ b/tools/check/forbidden_strings_in_code.txt @@ -147,3 +147,6 @@ android\.app\.AlertDialog ### Use JsonUtils.getBasicGson() new Gson\(\) + +### Use matrixOneTimeWorkRequestBuilder +import androidx.work.OneTimeWorkRequestBuilder===1 \ No newline at end of file