Benoit Marty
2 days ago
committed by
Benoit Marty
12 changed files with 243 additions and 33 deletions
@ -0,0 +1,54 @@
@@ -0,0 +1,54 @@
|
||||
/* |
||||
* Copyright 2023, 2024 New Vector Ltd. |
||||
* |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
* Please see LICENSE in the repository root for full details. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.pushproviders.firebase |
||||
|
||||
import com.google.firebase.messaging.FirebaseMessaging |
||||
import com.squareup.anvil.annotations.ContributesBinding |
||||
import io.element.android.libraries.di.AppScope |
||||
import timber.log.Timber |
||||
import javax.inject.Inject |
||||
import kotlin.coroutines.resume |
||||
import kotlin.coroutines.resumeWithException |
||||
import kotlin.coroutines.suspendCoroutine |
||||
|
||||
interface FirebaseTokenDeleter { |
||||
suspend fun delete() |
||||
} |
||||
|
||||
/** |
||||
* This class deletes the current Firebase token. |
||||
*/ |
||||
@ContributesBinding(AppScope::class) |
||||
class DefaultFirebaseTokenDeleter @Inject constructor( |
||||
private val isPlayServiceAvailable: IsPlayServiceAvailable, |
||||
) : FirebaseTokenDeleter { |
||||
override suspend fun delete() { |
||||
suspendCoroutine { continuation -> |
||||
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features' |
||||
if (isPlayServiceAvailable.isAvailable()) { |
||||
try { |
||||
FirebaseMessaging.getInstance().deleteToken() |
||||
.addOnSuccessListener { |
||||
continuation.resume(Unit) |
||||
} |
||||
.addOnFailureListener { e -> |
||||
Timber.e(e, "## deleteFirebaseToken() : failed") |
||||
continuation.resumeWithException(e) |
||||
} |
||||
} catch (e: Throwable) { |
||||
Timber.e(e, "## deleteFirebaseToken() : failed") |
||||
continuation.resumeWithException(e) |
||||
} |
||||
} else { |
||||
val e = Exception("No valid Google Play Services found. Cannot use FCM.") |
||||
Timber.e(e) |
||||
throw e |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
/* |
||||
* Copyright 2023, 2024 New Vector Ltd. |
||||
* |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
* Please see LICENSE in the repository root for full details. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.pushproviders.firebase |
||||
|
||||
import com.google.firebase.messaging.FirebaseMessaging |
||||
import com.squareup.anvil.annotations.ContributesBinding |
||||
import io.element.android.libraries.di.AppScope |
||||
import timber.log.Timber |
||||
import javax.inject.Inject |
||||
import kotlin.coroutines.resume |
||||
import kotlin.coroutines.resumeWithException |
||||
import kotlin.coroutines.suspendCoroutine |
||||
|
||||
interface FirebaseTokenGetter { |
||||
suspend fun get(): String |
||||
} |
||||
|
||||
/** |
||||
* This class read the current Firebase token. |
||||
* If the token does not exist, it will be generated. |
||||
*/ |
||||
@ContributesBinding(AppScope::class) |
||||
class DefaultFirebaseTokenGetter @Inject constructor( |
||||
private val isPlayServiceAvailable: IsPlayServiceAvailable, |
||||
) : FirebaseTokenGetter { |
||||
override suspend fun get(): String { |
||||
return suspendCoroutine { continuation -> |
||||
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features' |
||||
if (isPlayServiceAvailable.isAvailable()) { |
||||
try { |
||||
FirebaseMessaging.getInstance().token |
||||
.addOnSuccessListener { token -> |
||||
continuation.resume(token) |
||||
} |
||||
.addOnFailureListener { e -> |
||||
Timber.e(e, "## retrievedFirebaseToken() : failed") |
||||
continuation.resumeWithException(e) |
||||
} |
||||
} catch (e: Throwable) { |
||||
Timber.e(e, "## retrievedFirebaseToken() : failed") |
||||
continuation.resumeWithException(e) |
||||
} |
||||
} else { |
||||
val e = Exception("No valid Google Play Services found. Cannot use FCM.") |
||||
Timber.e(e) |
||||
continuation.resumeWithException(e) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
/* |
||||
* Copyright 2024 New Vector Ltd. |
||||
* |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
* Please see LICENSE in the repository root for full details. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.pushproviders.firebase |
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding |
||||
import io.element.android.libraries.di.AppScope |
||||
import javax.inject.Inject |
||||
|
||||
interface FirebaseTokenRotator { |
||||
suspend fun rotate(): Result<Unit> |
||||
} |
||||
|
||||
/** |
||||
* This class delete the Firebase token and generate a new one. |
||||
*/ |
||||
@ContributesBinding(AppScope::class) |
||||
class DefaultFirebaseTokenRotator @Inject constructor( |
||||
private val firebaseTokenDeleter: FirebaseTokenDeleter, |
||||
private val firebaseTokenGetter: FirebaseTokenGetter, |
||||
) : FirebaseTokenRotator { |
||||
override suspend fun rotate(): Result<Unit> { |
||||
return runCatching { |
||||
firebaseTokenDeleter.delete() |
||||
firebaseTokenGetter.get() |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
/* |
||||
* Copyright 2024 New Vector Ltd. |
||||
* |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
* Please see LICENSE in the repository root for full details. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.pushproviders.firebase |
||||
|
||||
import io.element.android.tests.testutils.lambda.lambdaError |
||||
|
||||
class FakeFirebaseTokenRotator( |
||||
private val rotateWithResult: () -> Result<Unit> = { lambdaError() } |
||||
) : FirebaseTokenRotator { |
||||
override suspend fun rotate(): Result<Unit> { |
||||
return rotateWithResult() |
||||
} |
||||
} |
Loading…
Reference in new issue