Skip to content

Let EnterpriseService provides push gateways #4400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 13, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ interface EnterpriseService {

fun semanticColorsLight(): SemanticColors
fun semanticColorsDark(): SemanticColors

fun firebasePushGateway(): String?
fun unifiedPushDefaultPushGateway(): String?
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ class DefaultEnterpriseService @Inject constructor() : EnterpriseService {
override fun semanticColorsLight(): SemanticColors = compoundColorsLight

override fun semanticColorsDark(): SemanticColors = compoundColorsDark

override fun firebasePushGateway(): String? = null
override fun unifiedPushDefaultPushGateway(): String? = null
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class FakeEnterpriseService(
private val defaultHomeserverResult: () -> String? = { A_FAKE_HOMESERVER },
private val semanticColorsLightResult: () -> SemanticColors = { lambdaError() },
private val semanticColorsDarkResult: () -> SemanticColors = { lambdaError() },
private val firebasePushGatewayResult: () -> String? = { lambdaError() },
private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() },
) : EnterpriseService {
override suspend fun isEnterpriseUser(sessionId: SessionId): Boolean = simulateLongTask {
isEnterpriseUserResult(sessionId)
Expand All @@ -36,6 +38,14 @@ class FakeEnterpriseService(
return semanticColorsDarkResult()
}

override fun firebasePushGateway(): String? {
return firebasePushGatewayResult()
}

override fun unifiedPushDefaultPushGateway(): String? {
return unifiedPushDefaultPushGatewayResult()
}

companion object {
const val A_FAKE_HOMESERVER = "a_fake_homeserver"
}
Expand Down
2 changes: 2 additions & 0 deletions libraries/pushproviders/firebase/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ setupAnvil()
dependencies {
implementation(libs.dagger)
implementation(libs.androidx.corektx)
implementation(projects.features.enterprise.api)
implementation(projects.libraries.architecture)
implementation(projects.libraries.core)
implementation(projects.libraries.di)
Expand All @@ -73,6 +74,7 @@ dependencies {
testImplementation(libs.test.truth)
testImplementation(libs.test.turbine)
testImplementation(libs.test.robolectric)
testImplementation(projects.features.enterprise.test)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.push.test)
testImplementation(projects.libraries.pushstore.test)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2025 New Vector 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.firebase

import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.enterprise.api.EnterpriseService
import io.element.android.libraries.di.AppScope
import javax.inject.Inject

interface FirebaseGatewayProvider {
fun getFirebaseGateway(): String
}

@ContributesBinding(AppScope::class)
class DefaultFirebaseGatewayProvider @Inject constructor(
private val enterpriseService: EnterpriseService,
) : FirebaseGatewayProvider {
override fun getFirebaseGateway(): String {
return enterpriseService.firebasePushGateway() ?: FirebaseConfig.PUSHER_HTTP_URL
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class DefaultFirebaseNewTokenHandler @Inject constructor(
private val userPushStoreFactory: UserPushStoreFactory,
private val matrixClientProvider: MatrixClientProvider,
private val firebaseStore: FirebaseStore,
private val firebaseGatewayProvider: FirebaseGatewayProvider,
) : FirebaseNewTokenHandler {
override suspend fun handle(firebaseToken: String) {
firebaseStore.storeFcmToken(firebaseToken)
Expand All @@ -55,7 +56,7 @@ class DefaultFirebaseNewTokenHandler @Inject constructor(
.registerPusher(
matrixClient = client,
pushKey = firebaseToken,
gateway = FirebaseConfig.PUSHER_HTTP_URL,
gateway = firebaseGatewayProvider.getFirebaseGateway(),
)
.onFailure {
Timber.tag(loggerTag.value).e(it, "Failed to register pusher for session $sessionId")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class FirebasePushProvider @Inject constructor(
private val pusherSubscriber: PusherSubscriber,
private val isPlayServiceAvailable: IsPlayServiceAvailable,
private val firebaseTokenRotator: FirebaseTokenRotator,
private val firebaseGatewayProvider: FirebaseGatewayProvider,
) : PushProvider {
override val index = FirebaseConfig.INDEX
override val name = FirebaseConfig.NAME
Expand All @@ -48,7 +49,7 @@ class FirebasePushProvider @Inject constructor(
return pusherSubscriber.registerPusher(
matrixClient = matrixClient,
pushKey = pushKey,
gateway = FirebaseConfig.PUSHER_HTTP_URL,
gateway = firebaseGatewayProvider.getFirebaseGateway(),
)
}

Expand All @@ -60,7 +61,7 @@ class FirebasePushProvider @Inject constructor(
Timber.tag(loggerTag.value).w("Unable to unregister pusher, Firebase token is not known.")
Result.success(Unit)
} else {
pusherSubscriber.unregisterPusher(matrixClient, pushKey, FirebaseConfig.PUSHER_HTTP_URL)
pusherSubscriber.unregisterPusher(matrixClient, pushKey, firebaseGatewayProvider.getFirebaseGateway())
}
}

Expand All @@ -72,7 +73,7 @@ class FirebasePushProvider @Inject constructor(
override suspend fun getCurrentUserPushConfig(): CurrentUserPushConfig? {
return firebaseStore.getFcmToken()?.let { fcmToken ->
CurrentUserPushConfig(
url = FirebaseConfig.PUSHER_HTTP_URL,
url = firebaseGatewayProvider.getFirebaseGateway(),
pushKey = fcmToken
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ class DefaultFirebaseNewTokenHandlerTest {
registerPusherResult.assertions()
.isCalledExactly(2)
.withSequence(
listOf(value(aMatrixClient1), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL)),
listOf(value(aMatrixClient3), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL)),
listOf(value(aMatrixClient1), value("aToken"), value(A_FIREBASE_GATEWAY)),
listOf(value(aMatrixClient3), value("aToken"), value(A_FIREBASE_GATEWAY)),
)
}

Expand Down Expand Up @@ -130,7 +130,7 @@ class DefaultFirebaseNewTokenHandlerTest {
registerPusherResult.assertions()
registerPusherResult.assertions()
.isCalledOnce()
.with(value(aMatrixClient1), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL))
.with(value(aMatrixClient1), value("aToken"), value(A_FIREBASE_GATEWAY))
}

private fun createDefaultFirebaseNewTokenHandler(
Expand All @@ -139,13 +139,15 @@ class DefaultFirebaseNewTokenHandlerTest {
userPushStoreFactory: UserPushStoreFactory = FakeUserPushStoreFactory(),
matrixClientProvider: MatrixClientProvider = FakeMatrixClientProvider(),
firebaseStore: FirebaseStore = InMemoryFirebaseStore(),
firebaseGatewayProvider: FirebaseGatewayProvider = FakeFirebaseGatewayProvider(),
): FirebaseNewTokenHandler {
return DefaultFirebaseNewTokenHandler(
pusherSubscriber = pusherSubscriber,
sessionStore = sessionStore,
userPushStoreFactory = userPushStoreFactory,
matrixClientProvider = matrixClientProvider,
firebaseStore = firebaseStore
firebaseStore = firebaseStore,
firebaseGatewayProvider = firebaseGatewayProvider,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright 2025 New Vector 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.firebase

const val A_FIREBASE_GATEWAY = "aGateway"

class FakeFirebaseGatewayProvider(
private val firebaseGatewayResult: () -> String = { A_FIREBASE_GATEWAY }
) : FirebaseGatewayProvider {
override fun getFirebaseGateway() = firebaseGatewayResult()
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class FirebasePushProviderTest {
assertThat(result).isEqualTo(Result.success(Unit))
registerPusherResultLambda.assertions()
.isCalledOnce()
.with(value(matrixClient), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL))
.with(value(matrixClient), value("aToken"), value(A_FIREBASE_GATEWAY))
}

@Test
Expand Down Expand Up @@ -117,7 +117,7 @@ class FirebasePushProviderTest {
assertThat(result).isEqualTo(Result.success(Unit))
unregisterPusherResultLambda.assertions()
.isCalledOnce()
.with(value(matrixClient), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL))
.with(value(matrixClient), value("aToken"), value(A_FIREBASE_GATEWAY))
}

@Test
Expand Down Expand Up @@ -164,7 +164,7 @@ class FirebasePushProviderTest {
),
)
val result = firebasePushProvider.getCurrentUserPushConfig()
assertThat(result).isEqualTo(CurrentUserPushConfig(FirebaseConfig.PUSHER_HTTP_URL, "aToken"))
assertThat(result).isEqualTo(CurrentUserPushConfig(A_FIREBASE_GATEWAY, "aToken"))
}

@Test
Expand Down Expand Up @@ -194,12 +194,14 @@ class FirebasePushProviderTest {
pusherSubscriber: PusherSubscriber = FakePusherSubscriber(),
isPlayServiceAvailable: IsPlayServiceAvailable = FakeIsPlayServiceAvailable(false),
firebaseTokenRotator: FirebaseTokenRotator = FakeFirebaseTokenRotator(),
firebaseGatewayProvider: FirebaseGatewayProvider = FakeFirebaseGatewayProvider()
): FirebasePushProvider {
return FirebasePushProvider(
firebaseStore = firebaseStore,
pusherSubscriber = pusherSubscriber,
isPlayServiceAvailable = isPlayServiceAvailable,
firebaseTokenRotator = firebaseTokenRotator,
firebaseGatewayProvider = firebaseGatewayProvider,
)
}
}
2 changes: 2 additions & 0 deletions libraries/pushproviders/unifiedpush/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ setupAnvil()

dependencies {
implementation(libs.dagger)
implementation(projects.features.enterprise.api)
implementation(projects.libraries.androidutils)
implementation(projects.libraries.core)
implementation(projects.libraries.matrix.api)
Expand Down Expand Up @@ -48,6 +49,7 @@ dependencies {
testImplementation(libs.test.robolectric)
testImplementation(libs.test.truth)
testImplementation(libs.test.turbine)
testImplementation(projects.features.enterprise.test)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.push.test)
testImplementation(projects.libraries.pushproviders.test)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2025 New Vector 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 com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.enterprise.api.EnterpriseService
import io.element.android.libraries.di.AppScope
import javax.inject.Inject

interface DefaultPushGatewayHttpUrlProvider {
fun provide(): String
}

@ContributesBinding(AppScope::class)
class DefaultDefaultPushGatewayHttpUrlProvider @Inject constructor(
private val enterpriseService: EnterpriseService,
) : DefaultPushGatewayHttpUrlProvider {
override fun provide(): String {
return enterpriseService.unifiedPushDefaultPushGateway() ?: UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface UnifiedPushGatewayUrlResolver {
@ContributesBinding(AppScope::class)
class DefaultUnifiedPushGatewayUrlResolver @Inject constructor(
private val unifiedPushStore: UnifiedPushStore,
private val defaultPushGatewayHttpUrlProvider: DefaultPushGatewayHttpUrlProvider,
) : UnifiedPushGatewayUrlResolver {
override fun resolve(
gatewayResult: UnifiedPushGatewayResolverResult,
Expand All @@ -33,7 +34,7 @@ class DefaultUnifiedPushGatewayUrlResolver @Inject constructor(
}
UnifiedPushGatewayResolverResult.ErrorInvalidUrl,
UnifiedPushGatewayResolverResult.NoMatrixGateway -> {
UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL
defaultPushGatewayHttpUrlProvider.provide()
}
is UnifiedPushGatewayResolverResult.Success -> {
gatewayResult.gateway
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class DefaultUnifiedPushGatewayUrlResolverTest {
gatewayResult = UnifiedPushGatewayResolverResult.ErrorInvalidUrl,
instance = "",
)
assertThat(result).isEqualTo(UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL)
assertThat(result).isEqualTo(A_UNIFIED_PUSH_GATEWAY)
}

@Test
Expand All @@ -28,7 +28,7 @@ class DefaultUnifiedPushGatewayUrlResolverTest {
gatewayResult = UnifiedPushGatewayResolverResult.NoMatrixGateway,
instance = "",
)
assertThat(result).isEqualTo(UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL)
assertThat(result).isEqualTo(A_UNIFIED_PUSH_GATEWAY)
}

@Test
Expand Down Expand Up @@ -77,7 +77,9 @@ class DefaultUnifiedPushGatewayUrlResolverTest {

private fun createDefaultUnifiedPushGatewayUrlResolver(
unifiedPushStore: UnifiedPushStore = FakeUnifiedPushStore(),
defaultPushGatewayHttpUrlProvider: DefaultPushGatewayHttpUrlProvider = FakeDefaultPushGatewayHttpUrlProvider(),
) = DefaultUnifiedPushGatewayUrlResolver(
unifiedPushStore = unifiedPushStore,
defaultPushGatewayHttpUrlProvider = defaultPushGatewayHttpUrlProvider,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright 2025 New Vector 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

const val A_UNIFIED_PUSH_GATEWAY = "aGateway"

class FakeDefaultPushGatewayHttpUrlProvider(
private val provideResult: () -> String = { A_UNIFIED_PUSH_GATEWAY }
) : DefaultPushGatewayHttpUrlProvider {
override fun provide(): String {
return provideResult()
}
}
Loading