diff --git a/CHANGES.md b/CHANGES.md index 537e3aef7b..0f72e04574 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,7 @@ Bugfix 🐛: - When receiving a new pepper from identity server, use it on the next hash lookup (#2708) - Crashes reported by PlayStore (new in 1.0.14) (#2707) - Widgets: Support $matrix_widget_id parameter (#2748) + - Data for Worker overload (#2721) Translations 🗣: - diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt index bcad448eb6..8c640a2719 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt @@ -19,30 +19,30 @@ package org.matrix.android.sdk.internal.crypto.crosssigning import androidx.lifecycle.LiveData import androidx.work.BackoffPolicy import androidx.work.ExistingWorkPolicy +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.internal.crypto.DeviceListManager +import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.UploadSignatureQueryBuilder import org.matrix.android.sdk.internal.crypto.model.rest.UserPasswordAuth import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo import org.matrix.android.sdk.internal.crypto.tasks.InitializeCrossSigningTask import org.matrix.android.sdk.internal.crypto.tasks.UploadSignaturesTask +import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.di.WorkManagerProvider import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.TaskThread import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.util.JsonCanonicalizer import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.di.SessionId -import org.matrix.android.sdk.internal.di.WorkManagerProvider import org.matrix.android.sdk.internal.worker.WorkerParamsFactory import org.matrix.olm.OlmPkSigning import org.matrix.olm.OlmUtility @@ -61,7 +61,10 @@ internal class DefaultCrossSigningService @Inject constructor( private val taskExecutor: TaskExecutor, private val coroutineDispatchers: MatrixCoroutineDispatchers, private val cryptoCoroutineScope: CoroutineScope, - private val workManagerProvider: WorkManagerProvider) : CrossSigningService, DeviceListManager.UserDevicesUpdateListener { + private val workManagerProvider: WorkManagerProvider, + private val updateTrustWorkerDataRepository: UpdateTrustWorkerDataRepository +) : CrossSigningService, + DeviceListManager.UserDevicesUpdateListener { private var olmUtility: OlmUtility? = null @@ -689,7 +692,7 @@ internal class DefaultCrossSigningService @Inject constructor( return DeviceTrustResult.Success(DeviceTrustLevel(crossSigningVerified = true, locallyVerified = locallyTrusted)) } - fun checkDeviceTrust(myKeys: MXCrossSigningInfo?, otherKeys: MXCrossSigningInfo?, otherDevice: CryptoDeviceInfo) : DeviceTrustResult { + fun checkDeviceTrust(myKeys: MXCrossSigningInfo?, otherKeys: MXCrossSigningInfo?, otherDevice: CryptoDeviceInfo): DeviceTrustResult { val locallyTrusted = otherDevice.trustLevel?.isLocallyVerified() myKeys ?: return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.CrossSigningNotConfigured(userId)) @@ -747,8 +750,11 @@ internal class DefaultCrossSigningService @Inject constructor( } override fun onUsersDeviceUpdate(userIds: List) { - Timber.d("## CrossSigning - onUsersDeviceUpdate for $userIds") - val workerParams = UpdateTrustWorker.Params(sessionId = sessionId, updatedUserIds = userIds) + Timber.d("## CrossSigning - onUsersDeviceUpdate for ${userIds.size} users: $userIds") + val workerParams = UpdateTrustWorker.Params( + sessionId = sessionId, + filename = updateTrustWorkerDataRepository.createParam(userIds) + ) val workerData = WorkerParamsFactory.toData(workerParams) val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt index 665d770e7f..1660bae0b7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt @@ -55,7 +55,11 @@ internal class UpdateTrustWorker(context: Context, internal data class Params( override val sessionId: String, override val lastFailureMessage: String? = null, - val updatedUserIds: List + // Kept for compatibility, but not used anymore (can be used for pending Worker) + val updatedUserIds: List? = null, + // Passing a long list of userId can break the Work Manager due to data size limitation. + // so now we use a temporary file to store the data + val filename: String? = null ) : SessionWorkerParams @Inject lateinit var crossSigningService: DefaultCrossSigningService @@ -64,6 +68,7 @@ internal class UpdateTrustWorker(context: Context, @CryptoDatabase @Inject lateinit var realmConfiguration: RealmConfiguration @UserId @Inject lateinit var myUserId: String @Inject lateinit var crossSigningKeysMapper: CrossSigningKeysMapper + @Inject lateinit var updateTrustWorkerDataRepository: UpdateTrustWorkerDataRepository @SessionDatabase @Inject lateinit var sessionRealmConfiguration: RealmConfiguration // @Inject lateinit var roomSummaryUpdater: RoomSummaryUpdater @@ -74,7 +79,17 @@ internal class UpdateTrustWorker(context: Context, } override suspend fun doSafeWork(params: Params): Result { - var userList = params.updatedUserIds + var userList = params.filename + ?.let { updateTrustWorkerDataRepository.getParam(it) } + ?.userIds + ?: params.updatedUserIds.orEmpty() + + if (userList.isEmpty()) { + // This should not happen, but let's avoid go further in case of empty list + cleanup(params) + return Result.success() + } + // Unfortunately we don't have much info on what did exactly changed (is it the cross signing keys of that user, // or a new device?) So we check all again :/ @@ -213,9 +228,15 @@ internal class UpdateTrustWorker(context: Context, } } + cleanup(params) return Result.success() } + private fun cleanup(params: Params) { + params.filename + ?.let { updateTrustWorkerDataRepository.delete(it) } + } + private fun updateCrossSigningKeysTrust(realm: Realm, userId: String, verified: Boolean) { val xInfoEntity = realm.where(CrossSigningInfoEntity::class.java) .equalTo(CrossSigningInfoEntityFields.USER_ID, userId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorkerDataRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorkerDataRepository.kt new file mode 100644 index 0000000000..af5255c605 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorkerDataRepository.kt @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 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 org.matrix.android.sdk.internal.crypto.crosssigning + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.internal.di.SessionFilesDirectory +import java.io.File +import java.util.UUID +import javax.inject.Inject + +@JsonClass(generateAdapter = true) +internal data class UpdateTrustWorkerData( + @Json(name = "userIds") + val userIds: List +) + +internal class UpdateTrustWorkerDataRepository @Inject constructor( + @SessionFilesDirectory parentDir: File +) { + private val workingDirectory = File(parentDir, "tw") + private val jsonAdapter = MoshiProvider.providesMoshi().adapter(UpdateTrustWorkerData::class.java) + + // Return the path of the created file + fun createParam(userIds: List): String { + val filename = "${UUID.randomUUID()}.json" + workingDirectory.mkdirs() + val file = File(workingDirectory, filename) + + UpdateTrustWorkerData(userIds = userIds) + .let { jsonAdapter.toJson(it) } + .let { file.writeText(it) } + + return filename + } + + fun getParam(filename: String): UpdateTrustWorkerData? { + return File(workingDirectory, filename) + .takeIf { it.exists() } + ?.readText() + ?.let { jsonAdapter.fromJson(it) } + } + + fun delete(filename: String) { + tryOrNull("Unable to delete $filename") { + File(workingDirectory, filename).delete() + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index 8c71604183..fff780fb0c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -140,14 +140,13 @@ internal class RoomSummaryUpdater @Inject constructor( .queryActiveRoomMembersEvent() .notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId) .findAll() - .asSequence() .map { it.userId } roomSummaryEntity.otherMemberIds.clear() roomSummaryEntity.otherMemberIds.addAll(otherRoomMembers) if (roomSummaryEntity.isEncrypted) { // mmm maybe we could only refresh shield instead of checking trust also? - crossSigningService.onUsersDeviceUpdate(roomSummaryEntity.otherMemberIds.toList()) + crossSigningService.onUsersDeviceUpdate(otherRoomMembers) } } }