diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 8a991771a5..9c0d0c17ac 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -19,6 +19,7 @@ package io.element.android.libraries.matrix.api import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.media.MediaResolver +import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource @@ -33,6 +34,7 @@ interface MatrixClient : Closeable { fun stopSync() fun mediaResolver(): MediaResolver fun sessionVerificationService(): SessionVerificationService + fun pushersService(): PushersService suspend fun logout() suspend fun loadUserDisplayName(): Result suspend fun loadUserAvatarURLString(): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/pusher/PushersService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/pusher/PushersService.kt new file mode 100644 index 0000000000..a868aeab85 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/pusher/PushersService.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 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 io.element.android.libraries.matrix.api.pusher + +interface PushersService { + fun setHttpPusher(setHttpPusherData: SetHttpPusherData) +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/pusher/SetHttpPusherData.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/pusher/SetHttpPusherData.kt new file mode 100644 index 0000000000..43a90f5be2 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/pusher/SetHttpPusherData.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 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 io.element.android.libraries.matrix.api.pusher + +data class SetHttpPusherData( + val pushKey: String, + val appId: String, + val url: String, + val appDisplayName: String, + val deviceDisplayName: String, + val profileTag: String?, + val lang: String, + val defaultPayload: String, +) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 2fe34bfa55..4acafa321e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -21,11 +21,13 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.MediaResolver +import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.impl.media.RustMediaResolver -import io.element.android.libraries.matrix.api.room.RoomMembershipObserver +import io.element.android.libraries.matrix.impl.pushers.RustPushersService import io.element.android.libraries.matrix.impl.room.RustMatrixRoom import io.element.android.libraries.matrix.impl.room.RustRoomSummaryDataSource import io.element.android.libraries.matrix.impl.sync.SlidingSyncObserverProxy @@ -60,6 +62,7 @@ class RustMatrixClient constructor( override val sessionId: UserId = UserId(client.userId()) private val verificationService = RustSessionVerificationService() + private val pushersService = RustPushersService(client) private var slidingSyncUpdateJob: Job? = null private val clientDelegate = object : ClientDelegate { @@ -162,6 +165,8 @@ class RustMatrixClient constructor( override fun sessionVerificationService(): SessionVerificationService = verificationService + override fun pushersService(): PushersService = pushersService + override fun startSync() { if (isSyncing.compareAndSet(false, true)) { slidingSyncObserverToken = slidingSync.sync() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt new file mode 100644 index 0000000000..39dd5c1d11 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 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 io.element.android.libraries.matrix.impl.pushers + +import io.element.android.libraries.matrix.api.pusher.PushersService +import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData +import org.matrix.rustcomponents.sdk.Client +import org.matrix.rustcomponents.sdk.HttpPusherData +import org.matrix.rustcomponents.sdk.PushFormat +import org.matrix.rustcomponents.sdk.PusherIdentifiers +import org.matrix.rustcomponents.sdk.PusherKind + +class RustPushersService( + private val client: Client, +) : PushersService { + override fun setHttpPusher(setHttpPusherData: SetHttpPusherData) { + client.setPusher( + identifiers = PusherIdentifiers( + pushkey = setHttpPusherData.pushKey, + appId = setHttpPusherData.appId + ), + kind = PusherKind.Http( + data = HttpPusherData( + url = setHttpPusherData.url, + format = PushFormat.EVENT_ID_ONLY, + defaultPayload = setHttpPusherData.defaultPayload + ) + ), + appDisplayName = setHttpPusherData.appDisplayName, + deviceDisplayName = setHttpPusherData.deviceDisplayName, + profileTag = setHttpPusherData.profileTag, + lang = setHttpPusherData.lang + ) + } +} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/GoogleFcmHelper.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/GoogleFcmHelper.kt index 16ce8d73ab..b8dc1ad384 100755 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/GoogleFcmHelper.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/GoogleFcmHelper.kt @@ -26,6 +26,7 @@ import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.ApplicationContext import io.element.android.libraries.di.DefaultPreferences +import kotlinx.coroutines.runBlocking import timber.log.Timber import javax.inject.Inject @@ -58,7 +59,9 @@ class GoogleFcmHelper @Inject constructor( .addOnSuccessListener { token -> storeFcmToken(token) if (registerPusher) { - pushersManager.enqueueRegisterPusherWithFcmKey(token) + runBlocking {// TODO + pushersManager.enqueueRegisterPusherWithFcmKey(token) + } } } .addOnFailureListener { e -> diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt index 5525b04d4c..20cbd078e2 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt @@ -16,8 +16,13 @@ package io.element.android.libraries.push.impl +import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData +import io.element.android.libraries.push.impl.clientsecret.PushClientSecret import io.element.android.libraries.push.impl.config.PushConfig import io.element.android.libraries.push.impl.pushgateway.PushGatewayNotifyRequest +import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.services.toolbox.api.appname.AppNameProvider import javax.inject.Inject @@ -31,6 +36,9 @@ class PushersManager @Inject constructor( private val appNameProvider: AppNameProvider, // private val getDeviceInfoUseCase: GetDeviceInfoUseCase, private val pushGatewayNotifyRequest: PushGatewayNotifyRequest, + private val pushClientSecret: PushClientSecret, + private val sessionStore: SessionStore, + private val matrixAuthenticationService: MatrixAuthenticationService, ) { suspend fun testPush() { pushGatewayNotifyRequest.execute( @@ -43,47 +51,45 @@ class PushersManager @Inject constructor( ) } - fun enqueueRegisterPusherWithFcmKey(pushKey: String)/*: UUID*/ { + suspend fun enqueueRegisterPusherWithFcmKey(pushKey: String) { return enqueueRegisterPusher(pushKey, PushConfig.pusher_http_url) } - fun enqueueRegisterPusher( + suspend fun enqueueRegisterPusher( pushKey: String, gateway: String - ) /*: UUID*/ { - /* - val currentSession = activeSessionHolder.getActiveSession() - val pusher = createHttpPusher(pushKey, gateway) - return currentSession.pushersService().enqueueAddHttpPusher(pusher) - - */ - // TODO EAx - // TODO() - // Get all sessions - // Register pusher - // Close sessions + ) { + // Register the pusher for all the sessions + sessionStore.getAllSessions().forEach { sessionData -> + val client = matrixAuthenticationService.restoreSession(SessionId(sessionData.userId)).getOrNull() + client ?: return@forEach + client.pushersService().setHttpPusher(createHttpPusher(pushKey, gateway, sessionData.userId)) + // Close sessions? + } } - private fun createHttpPusher( + private suspend fun createHttpPusher( pushKey: String, - gateway: String - ): Any = TODO() - /* - HttpPusher( - pushkey = pushKey, - appId = PushConfig.pusher_app_id, - profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(activeSessionHolder.getActiveSession().myUserId.hashCode()), - lang = localeProvider.current().language, - appDisplayName = appNameProvider.getAppName(), - deviceDisplayName = getDeviceInfoUseCase.execute().displayName().orEmpty(), - url = gateway, - enabled = true, - deviceId = activeSessionHolder.getActiveSession().sessionParams.deviceId ?: "MOBILE", - append = false, - withEventIdOnly = true, - ) + gateway: String, + userId: String, + ): SetHttpPusherData = + SetHttpPusherData( + pushKey = pushKey, + appId = PushConfig.pusher_app_id, + profileTag = DEFAULT_PUSHER_FILE_TAG + "_" /* TODO + abs(activeSessionHolder.getActiveSession().myUserId.hashCode())*/, + lang = "en", // TODO localeProvider.current().language, + appDisplayName = appNameProvider.getAppName(), + deviceDisplayName = "MyDevice", // TODO getDeviceInfoUseCase.execute().displayName().orEmpty(), + url = gateway, + defaultPayload = createDefaultPayload(pushClientSecret.getSecretForUser(userId)) + ) + /** + * Ex: {"cs":"sfvsdv"} */ + private fun createDefaultPayload(secretForUser: String): String { + return "{\"cs\":\"$secretForUser\"}" + } suspend fun registerEmailForPush(email: String) { TODO() diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorFirebaseMessagingService.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorFirebaseMessagingService.kt index e9bccf7cdd..81afe726f2 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorFirebaseMessagingService.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorFirebaseMessagingService.kt @@ -24,6 +24,9 @@ import io.element.android.libraries.push.api.store.PushDataStore import io.element.android.libraries.push.impl.config.PushConfig import io.element.android.libraries.push.impl.di.FirebaseMessagingServiceBindings import io.element.android.libraries.push.impl.parser.PushParser +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -38,6 +41,8 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { @Inject lateinit var vectorPushHandler: VectorPushHandler @Inject lateinit var unifiedPushHelper: UnifiedPushHelper + private val coroutineScope = CoroutineScope(SupervisorJob()) + override fun onCreate() { super.onCreate() applicationContext.bindings().inject(this) @@ -51,7 +56,9 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { // TODO EAx activeSessionHolder.hasActiveSession() && unifiedPushHelper.isEmbeddedDistributor() ) { - pushersManager.enqueueRegisterPusher(token, PushConfig.pusher_http_url) + coroutineScope.launch { + pushersManager.enqueueRegisterPusher(token, PushConfig.pusher_http_url) + } } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorUnifiedPushMessagingReceiver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorUnifiedPushMessagingReceiver.kt index 0fcdbafb69..49a63ba4aa 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorUnifiedPushMessagingReceiver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorUnifiedPushMessagingReceiver.kt @@ -81,7 +81,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/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/clientsecret/PushClientSecretFactoryImpl.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/clientsecret/PushClientSecretFactoryImpl.kt index 8a23409558..1d7a1e6247 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/clientsecret/PushClientSecretFactoryImpl.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/clientsecret/PushClientSecretFactoryImpl.kt @@ -19,9 +19,10 @@ package io.element.android.libraries.push.impl.clientsecret import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.di.AppScope import java.util.UUID +import javax.inject.Inject @ContributesBinding(AppScope::class) -class PushClientSecretFactoryImpl : PushClientSecretFactory { +class PushClientSecretFactoryImpl @Inject constructor() : PushClientSecretFactory { override fun create(): String { return UUID.randomUUID().toString() }