Skip to content

Commit 07925cc

Browse files
authored
Merge pull request #4400 from element-hq/feature/bma/customPushGateway
Let EnterpriseService provides push gateways
2 parents 54ab4d2 + 5d881e8 commit 07925cc

File tree

16 files changed

+130
-15
lines changed

16 files changed

+130
-15
lines changed

enterprise

features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,7 @@ interface EnterpriseService {
1717

1818
fun semanticColorsLight(): SemanticColors
1919
fun semanticColorsDark(): SemanticColors
20+
21+
fun firebasePushGateway(): String?
22+
fun unifiedPushDefaultPushGateway(): String?
2023
}

features/enterprise/impl/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,7 @@ class DefaultEnterpriseService @Inject constructor() : EnterpriseService {
2727
override fun semanticColorsLight(): SemanticColors = compoundColorsLight
2828

2929
override fun semanticColorsDark(): SemanticColors = compoundColorsDark
30+
31+
override fun firebasePushGateway(): String? = null
32+
override fun unifiedPushDefaultPushGateway(): String? = null
3033
}

features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class FakeEnterpriseService(
1919
private val defaultHomeserverResult: () -> String? = { A_FAKE_HOMESERVER },
2020
private val semanticColorsLightResult: () -> SemanticColors = { lambdaError() },
2121
private val semanticColorsDarkResult: () -> SemanticColors = { lambdaError() },
22+
private val firebasePushGatewayResult: () -> String? = { lambdaError() },
23+
private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() },
2224
) : EnterpriseService {
2325
override suspend fun isEnterpriseUser(sessionId: SessionId): Boolean = simulateLongTask {
2426
isEnterpriseUserResult(sessionId)
@@ -36,6 +38,14 @@ class FakeEnterpriseService(
3638
return semanticColorsDarkResult()
3739
}
3840

41+
override fun firebasePushGateway(): String? {
42+
return firebasePushGatewayResult()
43+
}
44+
45+
override fun unifiedPushDefaultPushGateway(): String? {
46+
return unifiedPushDefaultPushGatewayResult()
47+
}
48+
3949
companion object {
4050
const val A_FAKE_HOMESERVER = "a_fake_homeserver"
4151
}

libraries/pushproviders/firebase/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ setupAnvil()
5050
dependencies {
5151
implementation(libs.dagger)
5252
implementation(libs.androidx.corektx)
53+
implementation(projects.features.enterprise.api)
5354
implementation(projects.libraries.architecture)
5455
implementation(projects.libraries.core)
5556
implementation(projects.libraries.di)
@@ -74,6 +75,7 @@ dependencies {
7475
testImplementation(libs.test.turbine)
7576
testImplementation(libs.test.robolectric)
7677
testImplementation(libs.kotlinx.collections.immutable)
78+
testImplementation(projects.features.enterprise.test)
7779
testImplementation(projects.libraries.matrix.test)
7880
testImplementation(projects.libraries.push.test)
7981
testImplementation(projects.libraries.pushstore.test)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.libraries.pushproviders.firebase
9+
10+
import com.squareup.anvil.annotations.ContributesBinding
11+
import io.element.android.features.enterprise.api.EnterpriseService
12+
import io.element.android.libraries.di.AppScope
13+
import javax.inject.Inject
14+
15+
interface FirebaseGatewayProvider {
16+
fun getFirebaseGateway(): String
17+
}
18+
19+
@ContributesBinding(AppScope::class)
20+
class DefaultFirebaseGatewayProvider @Inject constructor(
21+
private val enterpriseService: EnterpriseService,
22+
) : FirebaseGatewayProvider {
23+
override fun getFirebaseGateway(): String {
24+
return enterpriseService.firebasePushGateway() ?: FirebaseConfig.PUSHER_HTTP_URL
25+
}
26+
}

libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseNewTokenHandler.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class DefaultFirebaseNewTokenHandler @Inject constructor(
3636
private val userPushStoreFactory: UserPushStoreFactory,
3737
private val matrixClientProvider: MatrixClientProvider,
3838
private val firebaseStore: FirebaseStore,
39+
private val firebaseGatewayProvider: FirebaseGatewayProvider,
3940
) : FirebaseNewTokenHandler {
4041
override suspend fun handle(firebaseToken: String) {
4142
firebaseStore.storeFcmToken(firebaseToken)
@@ -55,7 +56,7 @@ class DefaultFirebaseNewTokenHandler @Inject constructor(
5556
.registerPusher(
5657
matrixClient = client,
5758
pushKey = firebaseToken,
58-
gateway = FirebaseConfig.PUSHER_HTTP_URL,
59+
gateway = firebaseGatewayProvider.getFirebaseGateway(),
5960
)
6061
.onFailure {
6162
Timber.tag(loggerTag.value).e(it, "Failed to register pusher for session $sessionId")

libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebasePushProvider.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class FirebasePushProvider @Inject constructor(
2727
private val pusherSubscriber: PusherSubscriber,
2828
private val isPlayServiceAvailable: IsPlayServiceAvailable,
2929
private val firebaseTokenRotator: FirebaseTokenRotator,
30+
private val firebaseGatewayProvider: FirebaseGatewayProvider,
3031
) : PushProvider {
3132
override val index = FirebaseConfig.INDEX
3233
override val name = FirebaseConfig.NAME
@@ -48,7 +49,7 @@ class FirebasePushProvider @Inject constructor(
4849
return pusherSubscriber.registerPusher(
4950
matrixClient = matrixClient,
5051
pushKey = pushKey,
51-
gateway = FirebaseConfig.PUSHER_HTTP_URL,
52+
gateway = firebaseGatewayProvider.getFirebaseGateway(),
5253
)
5354
}
5455

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

@@ -72,7 +73,7 @@ class FirebasePushProvider @Inject constructor(
7273
override suspend fun getCurrentUserPushConfig(): CurrentUserPushConfig? {
7374
return firebaseStore.getFcmToken()?.let { fcmToken ->
7475
CurrentUserPushConfig(
75-
url = FirebaseConfig.PUSHER_HTTP_URL,
76+
url = firebaseGatewayProvider.getFirebaseGateway(),
7677
pushKey = fcmToken
7778
)
7879
}

libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/DefaultFirebaseNewTokenHandlerTest.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ class DefaultFirebaseNewTokenHandlerTest {
7979
registerPusherResult.assertions()
8080
.isCalledExactly(2)
8181
.withSequence(
82-
listOf(value(aMatrixClient1), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL)),
83-
listOf(value(aMatrixClient3), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL)),
82+
listOf(value(aMatrixClient1), value("aToken"), value(A_FIREBASE_GATEWAY)),
83+
listOf(value(aMatrixClient3), value("aToken"), value(A_FIREBASE_GATEWAY)),
8484
)
8585
}
8686

@@ -130,7 +130,7 @@ class DefaultFirebaseNewTokenHandlerTest {
130130
registerPusherResult.assertions()
131131
registerPusherResult.assertions()
132132
.isCalledOnce()
133-
.with(value(aMatrixClient1), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL))
133+
.with(value(aMatrixClient1), value("aToken"), value(A_FIREBASE_GATEWAY))
134134
}
135135

136136
private fun createDefaultFirebaseNewTokenHandler(
@@ -139,13 +139,15 @@ class DefaultFirebaseNewTokenHandlerTest {
139139
userPushStoreFactory: UserPushStoreFactory = FakeUserPushStoreFactory(),
140140
matrixClientProvider: MatrixClientProvider = FakeMatrixClientProvider(),
141141
firebaseStore: FirebaseStore = InMemoryFirebaseStore(),
142+
firebaseGatewayProvider: FirebaseGatewayProvider = FakeFirebaseGatewayProvider(),
142143
): FirebaseNewTokenHandler {
143144
return DefaultFirebaseNewTokenHandler(
144145
pusherSubscriber = pusherSubscriber,
145146
sessionStore = sessionStore,
146147
userPushStoreFactory = userPushStoreFactory,
147148
matrixClientProvider = matrixClientProvider,
148-
firebaseStore = firebaseStore
149+
firebaseStore = firebaseStore,
150+
firebaseGatewayProvider = firebaseGatewayProvider,
149151
)
150152
}
151153
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.libraries.pushproviders.firebase
9+
10+
const val A_FIREBASE_GATEWAY = "aGateway"
11+
12+
class FakeFirebaseGatewayProvider(
13+
private val firebaseGatewayResult: () -> String = { A_FIREBASE_GATEWAY }
14+
) : FirebaseGatewayProvider {
15+
override fun getFirebaseGateway() = firebaseGatewayResult()
16+
}

libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/FirebasePushProviderTest.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class FirebasePushProviderTest {
7070
assertThat(result).isEqualTo(Result.success(Unit))
7171
registerPusherResultLambda.assertions()
7272
.isCalledOnce()
73-
.with(value(matrixClient), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL))
73+
.with(value(matrixClient), value("aToken"), value(A_FIREBASE_GATEWAY))
7474
}
7575

7676
@Test
@@ -117,7 +117,7 @@ class FirebasePushProviderTest {
117117
assertThat(result).isEqualTo(Result.success(Unit))
118118
unregisterPusherResultLambda.assertions()
119119
.isCalledOnce()
120-
.with(value(matrixClient), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL))
120+
.with(value(matrixClient), value("aToken"), value(A_FIREBASE_GATEWAY))
121121
}
122122

123123
@Test
@@ -164,7 +164,7 @@ class FirebasePushProviderTest {
164164
),
165165
)
166166
val result = firebasePushProvider.getCurrentUserPushConfig()
167-
assertThat(result).isEqualTo(CurrentUserPushConfig(FirebaseConfig.PUSHER_HTTP_URL, "aToken"))
167+
assertThat(result).isEqualTo(CurrentUserPushConfig(A_FIREBASE_GATEWAY, "aToken"))
168168
}
169169

170170
@Test
@@ -194,12 +194,14 @@ class FirebasePushProviderTest {
194194
pusherSubscriber: PusherSubscriber = FakePusherSubscriber(),
195195
isPlayServiceAvailable: IsPlayServiceAvailable = FakeIsPlayServiceAvailable(false),
196196
firebaseTokenRotator: FirebaseTokenRotator = FakeFirebaseTokenRotator(),
197+
firebaseGatewayProvider: FirebaseGatewayProvider = FakeFirebaseGatewayProvider()
197198
): FirebasePushProvider {
198199
return FirebasePushProvider(
199200
firebaseStore = firebaseStore,
200201
pusherSubscriber = pusherSubscriber,
201202
isPlayServiceAvailable = isPlayServiceAvailable,
202203
firebaseTokenRotator = firebaseTokenRotator,
204+
firebaseGatewayProvider = firebaseGatewayProvider,
203205
)
204206
}
205207
}

libraries/pushproviders/unifiedpush/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ setupAnvil()
1919

2020
dependencies {
2121
implementation(libs.dagger)
22+
implementation(projects.features.enterprise.api)
2223
implementation(projects.libraries.androidutils)
2324
implementation(projects.libraries.core)
2425
implementation(projects.libraries.matrix.api)
@@ -49,6 +50,7 @@ dependencies {
4950
testImplementation(libs.test.truth)
5051
testImplementation(libs.test.turbine)
5152
testImplementation(libs.kotlinx.collections.immutable)
53+
testImplementation(projects.features.enterprise.test)
5254
testImplementation(projects.libraries.matrix.test)
5355
testImplementation(projects.libraries.push.test)
5456
testImplementation(projects.libraries.pushproviders.test)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.libraries.pushproviders.unifiedpush
9+
10+
import com.squareup.anvil.annotations.ContributesBinding
11+
import io.element.android.features.enterprise.api.EnterpriseService
12+
import io.element.android.libraries.di.AppScope
13+
import javax.inject.Inject
14+
15+
interface DefaultPushGatewayHttpUrlProvider {
16+
fun provide(): String
17+
}
18+
19+
@ContributesBinding(AppScope::class)
20+
class DefaultDefaultPushGatewayHttpUrlProvider @Inject constructor(
21+
private val enterpriseService: EnterpriseService,
22+
) : DefaultPushGatewayHttpUrlProvider {
23+
override fun provide(): String {
24+
return enterpriseService.unifiedPushDefaultPushGateway() ?: UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL
25+
}
26+
}

libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushGatewayUrlResolver.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ interface UnifiedPushGatewayUrlResolver {
2121
@ContributesBinding(AppScope::class)
2222
class DefaultUnifiedPushGatewayUrlResolver @Inject constructor(
2323
private val unifiedPushStore: UnifiedPushStore,
24+
private val defaultPushGatewayHttpUrlProvider: DefaultPushGatewayHttpUrlProvider,
2425
) : UnifiedPushGatewayUrlResolver {
2526
override fun resolve(
2627
gatewayResult: UnifiedPushGatewayResolverResult,
@@ -33,7 +34,7 @@ class DefaultUnifiedPushGatewayUrlResolver @Inject constructor(
3334
}
3435
UnifiedPushGatewayResolverResult.ErrorInvalidUrl,
3536
UnifiedPushGatewayResolverResult.NoMatrixGateway -> {
36-
UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL
37+
defaultPushGatewayHttpUrlProvider.provide()
3738
}
3839
is UnifiedPushGatewayResolverResult.Success -> {
3940
gatewayResult.gateway

libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/DefaultUnifiedPushGatewayUrlResolverTest.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class DefaultUnifiedPushGatewayUrlResolverTest {
1818
gatewayResult = UnifiedPushGatewayResolverResult.ErrorInvalidUrl,
1919
instance = "",
2020
)
21-
assertThat(result).isEqualTo(UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL)
21+
assertThat(result).isEqualTo(A_UNIFIED_PUSH_GATEWAY)
2222
}
2323

2424
@Test
@@ -28,7 +28,7 @@ class DefaultUnifiedPushGatewayUrlResolverTest {
2828
gatewayResult = UnifiedPushGatewayResolverResult.NoMatrixGateway,
2929
instance = "",
3030
)
31-
assertThat(result).isEqualTo(UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL)
31+
assertThat(result).isEqualTo(A_UNIFIED_PUSH_GATEWAY)
3232
}
3333

3434
@Test
@@ -77,7 +77,9 @@ class DefaultUnifiedPushGatewayUrlResolverTest {
7777

7878
private fun createDefaultUnifiedPushGatewayUrlResolver(
7979
unifiedPushStore: UnifiedPushStore = FakeUnifiedPushStore(),
80+
defaultPushGatewayHttpUrlProvider: DefaultPushGatewayHttpUrlProvider = FakeDefaultPushGatewayHttpUrlProvider(),
8081
) = DefaultUnifiedPushGatewayUrlResolver(
8182
unifiedPushStore = unifiedPushStore,
83+
defaultPushGatewayHttpUrlProvider = defaultPushGatewayHttpUrlProvider,
8284
)
8385
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.libraries.pushproviders.unifiedpush
9+
10+
const val A_UNIFIED_PUSH_GATEWAY = "aGateway"
11+
12+
class FakeDefaultPushGatewayHttpUrlProvider(
13+
private val provideResult: () -> String = { A_UNIFIED_PUSH_GATEWAY }
14+
) : DefaultPushGatewayHttpUrlProvider {
15+
override fun provide(): String {
16+
return provideResult()
17+
}
18+
}

0 commit comments

Comments
 (0)