diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushRemovedGatewayHandler.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushRemovedGatewayHandler.kt new file mode 100644 index 0000000000..7f494c3f52 --- /dev/null +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushRemovedGatewayHandler.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.pushproviders.unifiedpush + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.core.extensions.flatMap +import io.element.android.libraries.core.log.logger.LoggerTag +import io.element.android.libraries.matrix.api.MatrixClientProvider +import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret +import timber.log.Timber + +private val loggerTag = LoggerTag("UnifiedPushRemovedGatewayHandler", LoggerTag.PushLoggerTag) + +/** + * Handle new endpoint received from UnifiedPush. Will update the session matching the client secret. + */ +interface UnifiedPushRemovedGatewayHandler { + suspend fun handle(clientSecret: String): Result +} + +@ContributesBinding(AppScope::class) +class DefaultUnifiedPushRemovedGatewayHandler( + private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase, + private val pushClientSecret: PushClientSecret, + private val matrixClientProvider: MatrixClientProvider, +) : UnifiedPushRemovedGatewayHandler { + override suspend fun handle(clientSecret: String): Result { + // Unregister the pusher for the session with this client secret, if is it using UnifiedPush. + val userId = pushClientSecret.getUserIdFromSecret(clientSecret) ?: return Result.failure( + IllegalStateException("Unable to retrieve session") + ).also { + Timber.tag(loggerTag.value).w("Unable to retrieve session") + } + return matrixClientProvider + .getOrRestore(userId) + .flatMap { client -> + unregisterUnifiedPushUseCase.unregister( + matrixClient = client, + clientSecret = clientSecret, + unregisterUnifiedPush = false, + ) + } + .onFailure { + Timber.tag(loggerTag.value).w(it, "Unable to unregister pusher") + } + } +} diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnregisterUnifiedPushUseCase.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnregisterUnifiedPushUseCase.kt index 4340344b14..3157f1492f 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnregisterUnifiedPushUseCase.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnregisterUnifiedPushUseCase.kt @@ -21,12 +21,19 @@ interface UnregisterUnifiedPushUseCase { /** * Unregister the app from the homeserver, then from UnifiedPush. */ - suspend fun unregister(matrixClient: MatrixClient, clientSecret: String): Result + suspend fun unregister( + matrixClient: MatrixClient, + clientSecret: String, + unregisterUnifiedPush: Boolean = true, + ): Result /** * Cleanup any remaining data for the given client secret and unregister the app from UnifiedPush. */ - fun cleanup(clientSecret: String) + fun cleanup( + clientSecret: String, + unregisterUnifiedPush: Boolean = true, + ) } @ContributesBinding(AppScope::class) @@ -35,7 +42,11 @@ class DefaultUnregisterUnifiedPushUseCase( private val unifiedPushStore: UnifiedPushStore, private val pusherSubscriber: PusherSubscriber, ) : UnregisterUnifiedPushUseCase { - override suspend fun unregister(matrixClient: MatrixClient, clientSecret: String): Result { + override suspend fun unregister( + matrixClient: MatrixClient, + clientSecret: String, + unregisterUnifiedPush: Boolean, + ): Result { val endpoint = unifiedPushStore.getEndpoint(clientSecret) val gateway = unifiedPushStore.getPushGateway(clientSecret) if (endpoint == null || gateway == null) { @@ -46,13 +57,15 @@ class DefaultUnregisterUnifiedPushUseCase( } return pusherSubscriber.unregisterPusher(matrixClient, endpoint, gateway) .onSuccess { - cleanup(clientSecret) + cleanup(clientSecret, unregisterUnifiedPush) } } - override fun cleanup(clientSecret: String) { + override fun cleanup(clientSecret: String, unregisterUnifiedPush: Boolean) { unifiedPushStore.storeUpEndpoint(clientSecret, null) unifiedPushStore.storePushGateway(clientSecret, null) - UnifiedPush.unregister(context, clientSecret) + if (unregisterUnifiedPush) { + UnifiedPush.unregister(context, clientSecret) + } } } diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt index 8180ac436b..a7484585fe 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt @@ -35,7 +35,9 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() { @Inject lateinit var unifiedPushGatewayResolver: UnifiedPushGatewayResolver @Inject lateinit var unifiedPushGatewayUrlResolver: UnifiedPushGatewayUrlResolver @Inject lateinit var newGatewayHandler: UnifiedPushNewGatewayHandler + @Inject lateinit var removedGatewayHandler: UnifiedPushRemovedGatewayHandler @Inject lateinit var endpointRegistrationHandler: EndpointRegistrationHandler + @AppCoroutineScope @Inject lateinit var coroutineScope: CoroutineScope @@ -116,18 +118,9 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() { * Called when this application is unregistered from receiving push messages. */ override fun onUnregistered(context: Context, instance: String) { - Timber.tag(loggerTag.value).w("UnifiedPush: Unregistered") - /* - val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME - pushDataStore.setFdroidSyncBackgroundMode(mode) - guardServiceStarter.start() - runBlocking { - try { - pushersManager.unregisterPusher(unifiedPushHelper.getEndpointOrToken().orEmpty()) - } catch (e: Exception) { - Timber.tag(loggerTag.value).d("Probably unregistering a non existing pusher") - } + Timber.tag(loggerTag.value).w("onUnregistered $instance") + coroutineScope.launch { + removedGatewayHandler.handle(instance) } - */ } }