Use the right base URL for the ESS config/well known endpoints (#7469)

* Rename `UrlContentFetcher` to `ClientUrlContentFetcher` and add missing base URL data (server name, homeserver URL)

* Avoid passing the `homeserverUrl/serverName` around.

Calculate the URL in `DefaultRemoteEnterpriseConfigRetriever` using the newly added `homserver` and `server` values as the possible base URLs, depending on the remote config source

* Make sure we don't perform blocking requests to fetch the remote config when restoring a session

Add a `needsRefresh` parameter to `RemoteEnterpriseConfigResult.NotFound` to handle this, and store a `no-config` value in the store to indicate an endpoint has been checked and no config was found

* Bump enterprise module
This commit is contained in:
Jorge Martin Espinosa
2026-08-19 09:24:22 +02:00
committed by GitHub
parent c31d7e6cce
commit a1e86ad499
23 changed files with 79 additions and 57 deletions
@@ -10,7 +10,7 @@ package io.element.android.features.enterprise.api
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.compound.colors.SemanticColorsLightDark
import io.element.android.libraries.matrix.api.UrlContentFetcher import io.element.android.libraries.matrix.api.ClientUrlContentFetcher
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -31,10 +31,9 @@ interface EnterpriseService {
* Rewrites the authentication server URL when the deployment requires a different one from the one advertised. * Rewrites the authentication server URL when the deployment requires a different one from the one advertised.
* *
* @param url the URL to rewrite. * @param url the URL to rewrite.
* @param homeserver the homeserver the URL belongs to.
* @param urlContentFetcher used to read the deployment configuration; a client that is not authenticated yet also works. * @param urlContentFetcher used to read the deployment configuration; a client that is not authenticated yet also works.
*/ */
suspend fun tweakMasUrl(url: String, homeserver: String, urlContentFetcher: UrlContentFetcher): String suspend fun tweakMasUrl(url: String, urlContentFetcher: ClientUrlContentFetcher): String
/** /**
* Returns the list of homeservers the user is allowed to sign in to. * Returns the list of homeservers the user is allowed to sign in to.
@@ -53,9 +52,9 @@ interface EnterpriseService {
/** /**
* Whether the given homeserver enforces the use of Element Pro or a derived app. * Whether the given homeserver enforces the use of Element Pro or a derived app.
* *
* @param homeserverUrl the homeserver to check. * @param serverName the homeserver to check.
*/ */
suspend fun isElementProEnforced(homeserverUrl: String): Boolean suspend fun isElementProEnforced(serverName: String): Boolean
/** /**
* Override the brand color. * Override the brand color.
@@ -99,14 +98,6 @@ interface EnterpriseService {
*/ */
fun getNoisyNotificationChannelId(sessionId: SessionId): String? fun getNoisyNotificationChannelId(sessionId: SessionId): String?
/**
* Gets the Element Server Suite (ESS) config endpoint URL for the given domain.
* Returns `null` when this build does not read its configuration from an ESS deployment.
*
* @param domain the server whose configuration endpoint is requested.
*/
fun essConfigEndpointUrl(domain: String): String?
companion object { companion object {
const val ANY_ACCOUNT_PROVIDER = "*" const val ANY_ACCOUNT_PROVIDER = "*"
} }
@@ -19,9 +19,11 @@ sealed interface RemoteEnterpriseConfigResult<out T> {
data class Outdated<out T>(val data: T) : RemoteEnterpriseConfigResult<T> data class Outdated<out T>(val data: T) : RemoteEnterpriseConfigResult<T>
/** /**
* Well-known data is not found (file does not exist server side, we got a 404). * Well-known data is not found (file does not exist server side, we got a 404). `needsRefresh` indicates whether a refresh must be done
* to replace this value: if it's `true`, the caller must trigger a refresh to try to fetch the data again;
* if it's `false`, the caller can assume that the data is not available and no refresh is needed before returning the data.
*/ */
data object NotFound : RemoteEnterpriseConfigResult<Nothing> data class NotFound(val needsRefresh: Boolean) : RemoteEnterpriseConfigResult<Nothing>
/** /**
* Any other error. * Any other error.
@@ -32,13 +34,13 @@ sealed interface RemoteEnterpriseConfigResult<out T> {
is Success<T> -> data is Success<T> -> data
is Outdated<T> -> data is Outdated<T> -> data
is Error -> null is Error -> null
NotFound -> null is NotFound -> null
} }
fun upToDateDataOrNull(): T? = when (this) { fun upToDateDataOrNull(): T? = when (this) {
is Success<T> -> data is Success<T> -> data
is Outdated<T> -> null is Outdated<T> -> null
is Error -> null is Error -> null
NotFound -> null is NotFound -> null
} }
} }
@@ -14,7 +14,7 @@ import dev.zacsweers.metro.ContributesBinding
import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.compound.colors.SemanticColorsLightDark
import io.element.android.features.enterprise.api.BugReportUrl import io.element.android.features.enterprise.api.BugReportUrl
import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.features.enterprise.api.EnterpriseService
import io.element.android.libraries.matrix.api.UrlContentFetcher import io.element.android.libraries.matrix.api.ClientUrlContentFetcher
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
@@ -22,10 +22,10 @@ import kotlinx.coroutines.flow.flowOf
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class DefaultEnterpriseService : EnterpriseService { class DefaultEnterpriseService : EnterpriseService {
override suspend fun isEnterpriseUser(sessionId: SessionId) = false override suspend fun isEnterpriseUser(sessionId: SessionId) = false
override suspend fun tweakMasUrl(url: String, homeserver: String, urlContentFetcher: UrlContentFetcher) = url override suspend fun tweakMasUrl(url: String, urlContentFetcher: ClientUrlContentFetcher) = url
override fun homeserverAllowList(): List<String> = emptyList() override fun homeserverAllowList(): List<String> = emptyList()
override suspend fun isAllowedToConnectToHomeserver(homeserverUrl: String) = true override suspend fun isAllowedToConnectToHomeserver(homeserverUrl: String) = true
override suspend fun isElementProEnforced(homeserverUrl: String): Boolean = false override suspend fun isElementProEnforced(serverName: String): Boolean = false
override suspend fun overrideBrandColor(sessionId: SessionId?, brandColor: String?) = Unit override suspend fun overrideBrandColor(sessionId: SessionId?, brandColor: String?) = Unit
@@ -45,6 +45,4 @@ class DefaultEnterpriseService : EnterpriseService {
} }
override fun getNoisyNotificationChannelId(sessionId: SessionId): String? = null override fun getNoisyNotificationChannelId(sessionId: SessionId): String? = null
override fun essConfigEndpointUrl(domain: String): String? = null
} }
@@ -9,7 +9,7 @@ package io.element.android.features.enterprise.impl.scanner
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.matrix.api.UrlContentFetcher import io.element.android.libraries.matrix.api.ClientUrlContentFetcher
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.scanner.ContentScannerUrlProvider import io.element.android.libraries.matrix.api.scanner.ContentScannerUrlProvider
@@ -22,7 +22,7 @@ class DefaultContentScannerUrlProvider : ContentScannerUrlProvider {
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class Factory : ContentScannerUrlProvider.Factory { class Factory : ContentScannerUrlProvider.Factory {
override fun create(urlContentFetcher: UrlContentFetcher): ContentScannerUrlProvider { override fun create(urlContentFetcher: ClientUrlContentFetcher): ContentScannerUrlProvider {
return DefaultContentScannerUrlProvider() return DefaultContentScannerUrlProvider()
} }
} }
@@ -12,7 +12,7 @@ import androidx.compose.ui.graphics.Color
import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.compound.colors.SemanticColorsLightDark
import io.element.android.features.enterprise.api.BugReportUrl import io.element.android.features.enterprise.api.BugReportUrl
import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.features.enterprise.api.EnterpriseService
import io.element.android.libraries.matrix.api.UrlContentFetcher import io.element.android.libraries.matrix.api.ClientUrlContentFetcher
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.simulateLongTask import io.element.android.tests.testutils.simulateLongTask
@@ -30,8 +30,7 @@ class FakeEnterpriseService(
private val firebasePushGatewayResult: () -> String? = { lambdaError() }, private val firebasePushGatewayResult: () -> String? = { lambdaError() },
private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() }, private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() },
private val getNoisyNotificationChannelIdResult: (SessionId?) -> String? = { lambdaError() }, private val getNoisyNotificationChannelIdResult: (SessionId?) -> String? = { lambdaError() },
private val tweakMasUrlResult: (String, String, UrlContentFetcher) -> String = { _, _, _ -> lambdaError() }, private val tweakMasUrlResult: (String, ClientUrlContentFetcher) -> String = { _, _ -> lambdaError() },
private val essConfigEndpointUrlResult: (String) -> String = { lambdaError() },
private val isElementProEnforcedResult: (String) -> Boolean = { lambdaError() }, private val isElementProEnforcedResult: (String) -> Boolean = { lambdaError() },
) : EnterpriseService { ) : EnterpriseService {
private val brandColorState = MutableStateFlow(initialBrandColor) private val brandColorState = MutableStateFlow(initialBrandColor)
@@ -41,8 +40,8 @@ class FakeEnterpriseService(
isEnterpriseUserResult(sessionId) isEnterpriseUserResult(sessionId)
} }
override suspend fun tweakMasUrl(url: String, homeserver: String, urlContentFetcher: UrlContentFetcher): String = simulateLongTask { override suspend fun tweakMasUrl(url: String, urlContentFetcher: ClientUrlContentFetcher): String = simulateLongTask {
tweakMasUrlResult(url, homeserver, urlContentFetcher) tweakMasUrlResult(url, urlContentFetcher)
} }
override fun homeserverAllowList(): List<String> { override fun homeserverAllowList(): List<String> {
@@ -53,8 +52,8 @@ class FakeEnterpriseService(
isAllowedToConnectToHomeserverResult(homeserverUrl) isAllowedToConnectToHomeserverResult(homeserverUrl)
} }
override suspend fun isElementProEnforced(homeserverUrl: String): Boolean = simulateLongTask { override suspend fun isElementProEnforced(serverName: String): Boolean = simulateLongTask {
isElementProEnforcedResult(homeserverUrl) isElementProEnforcedResult(serverName)
} }
override suspend fun overrideBrandColor(sessionId: SessionId?, brandColor: String?) = simulateLongTask { override suspend fun overrideBrandColor(sessionId: SessionId?, brandColor: String?) = simulateLongTask {
@@ -85,8 +84,4 @@ class FakeEnterpriseService(
override fun getNoisyNotificationChannelId(sessionId: SessionId): String? { override fun getNoisyNotificationChannelId(sessionId: SessionId): String? {
return getNoisyNotificationChannelIdResult(sessionId) return getNoisyNotificationChannelIdResult(sessionId)
} }
override fun essConfigEndpointUrl(domain: String): String {
return essConfigEndpointUrlResult(domain)
}
} }
@@ -8,9 +8,19 @@
package io.element.android.libraries.matrix.api package io.element.android.libraries.matrix.api
/** /**
* An interface to fetch content from a URL using a simple GET request. * An interface to fetch content from a URL using a simple GET request launched from a Matrix client.
*/ */
fun interface UrlContentFetcher { interface ClientUrlContentFetcher {
/**
* The domain of the public server for this homeserver.
*/
val server: String?
/**
* The URL of the actual Matrix homeserver.
*/
val homeserverUrl: String
/** /**
* Execute generic GET requests through the SDKs internal HTTP client. * Execute generic GET requests through the SDKs internal HTTP client.
*/ */
@@ -60,16 +60,13 @@ import java.util.Optional
* One instance exists per session, created on login or session restore and torn down by [logout], [clearCache] or account deactivation. * One instance exists per session, created on login or session restore and torn down by [logout], [clearCache] or account deactivation.
* Suspending members here report failures through a [Result] instead of throwing, and run their work off the main thread. * Suspending members here report failures through a [Result] instead of throwing, and run their work off the main thread.
*/ */
interface MatrixClient : UrlContentFetcher { interface MatrixClient : ClientUrlContentFetcher {
/** Identifier of the logged in user; a [SessionId] and a [UserId] are the same value. */ /** Identifier of the logged in user; a [SessionId] and a [UserId] are the same value. */
val sessionId: SessionId val sessionId: SessionId
/** Identifier of this device, as assigned by the homeserver when the session was created. */ /** Identifier of this device, as assigned by the homeserver when the session was created. */
val deviceId: DeviceId val deviceId: DeviceId
/** Base URL of the homeserver this client is connected to. */
val homeserverUrl: String
/** Directories holding this session's databases, caches and downloaded media. */ /** Directories holding this session's databases, caches and downloaded media. */
val sessionPaths: SessionPaths val sessionPaths: SessionPaths
@@ -15,4 +15,4 @@ import java.lang.AutoCloseable
* Note: this client implements an [AutoCloseable] interface, so using [AutoCloseable.close] or [AutoCloseable.use] will clean up any resources associated * Note: this client implements an [AutoCloseable] interface, so using [AutoCloseable.close] or [AutoCloseable.use] will clean up any resources associated
* with it, such as temporary files. * with it, such as temporary files.
*/ */
interface TemporaryMatrixClient : UrlContentFetcher, AutoCloseable interface TemporaryMatrixClient : ClientUrlContentFetcher, AutoCloseable
@@ -12,10 +12,10 @@ package io.element.android.libraries.matrix.api
*/ */
interface TemporaryMatrixClientFactory { interface TemporaryMatrixClientFactory {
/** /**
* Builds an unauthenticated client pointing at [homeServerUrl], backed by a fresh set of temporary session directories. * Builds an unauthenticated client pointing at [serverName], backed by a fresh set of temporary session directories.
* The caller owns the returned client and must close it to delete those directories. * The caller owns the returned client and must close it to delete those directories.
* *
* @param homeServerUrl the URL of the homeserver the client will talk to. * @param serverName the domain of the public-facing server for the actual homeserver
*/ */
suspend fun create(homeServerUrl: String): Result<TemporaryMatrixClient> suspend fun create(serverName: String): Result<TemporaryMatrixClient>
} }
@@ -7,7 +7,7 @@
package io.element.android.libraries.matrix.api.scanner package io.element.android.libraries.matrix.api.scanner
import io.element.android.libraries.matrix.api.UrlContentFetcher import io.element.android.libraries.matrix.api.ClientUrlContentFetcher
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
/** /**
@@ -26,6 +26,6 @@ fun interface ContentScannerUrlProvider {
/** /**
* @param urlContentFetcher used to read the configuration advertised by the homeserver; a client that is not authenticated yet also works. * @param urlContentFetcher used to read the configuration advertised by the homeserver; a client that is not authenticated yet also works.
*/ */
fun create(urlContentFetcher: UrlContentFetcher): ContentScannerUrlProvider fun create(urlContentFetcher: ClientUrlContentFetcher): ContentScannerUrlProvider
} }
} }
@@ -163,6 +163,7 @@ class RustMatrixClient(
) : MatrixClient { ) : MatrixClient {
override val sessionId: UserId = UserId(innerClient.userId()) override val sessionId: UserId = UserId(innerClient.userId())
override val deviceId: DeviceId = DeviceId(innerClient.deviceId()) override val deviceId: DeviceId = DeviceId(innerClient.deviceId())
override val server: String? = innerClient.server()
override val homeserverUrl: String = innerClient.homeserver() override val homeserverUrl: String = innerClient.homeserver()
override val sessionCoroutineScope = appCoroutineScope.childScope(dispatchers.main, "Session-$sessionId") override val sessionCoroutineScope = appCoroutineScope.childScope(dispatchers.main, "Session-$sessionId")
private val sessionDispatcher = dispatchers.io.limitedParallelism(64) private val sessionDispatcher = dispatchers.io.limitedParallelism(64)
@@ -22,6 +22,9 @@ class RustTemporaryMatrixClient(
client.getUrl(url) client.getUrl(url)
}.mapFailure { it.mapClientException() } }.mapFailure { it.mapClientException() }
override val server: String? = client.server()
override val homeserverUrl: String = client.homeserver()
override fun close() { override fun close() {
client.close() client.close()
paths?.let { paths?.let {
@@ -19,7 +19,7 @@ class RustTemporaryMatrixClientFactory(
private val sessionPathsFactory: SessionPathsFactory, private val sessionPathsFactory: SessionPathsFactory,
private val rustMatrixClientFactory: RustMatrixClientFactory, private val rustMatrixClientFactory: RustMatrixClientFactory,
) : TemporaryMatrixClientFactory { ) : TemporaryMatrixClientFactory {
override suspend fun create(homeServerUrl: String): Result<TemporaryMatrixClient> { override suspend fun create(serverName: String): Result<TemporaryMatrixClient> {
return runCatchingExceptions { return runCatchingExceptions {
val sessionPaths = sessionPathsFactory.create() val sessionPaths = sessionPathsFactory.create()
val client = rustMatrixClientFactory.getBaseClientBuilder( val client = rustMatrixClientFactory.getBaseClientBuilder(
@@ -28,7 +28,7 @@ class RustTemporaryMatrixClientFactory(
slidingSyncType = ClientBuilderSlidingSync.Native, slidingSyncType = ClientBuilderSlidingSync.Native,
isMessageSearchAvailable = false, isMessageSearchAvailable = false,
) )
.homeserverUrl(homeServerUrl) .serverName(serverName)
.build() .build()
RustTemporaryMatrixClient(client, sessionPaths) RustTemporaryMatrixClient(client, sessionPaths)
} }
@@ -278,7 +278,6 @@ class RustMatrixAuthenticationService(
.let { .let {
enterpriseService.tweakMasUrl( enterpriseService.tweakMasUrl(
url = it, url = it,
homeserver = client.server() ?: client.homeserver(),
urlContentFetcher = getUrlResolver, urlContentFetcher = getUrlResolver,
) )
} }
@@ -13,9 +13,9 @@ import dev.zacsweers.metro.ContributesTo
import dev.zacsweers.metro.Provides import dev.zacsweers.metro.Provides
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.di.annotations.SessionCoroutineScope
import io.element.android.libraries.matrix.api.ClientUrlContentFetcher
import io.element.android.libraries.matrix.api.HomeserverCapabilitiesProvider import io.element.android.libraries.matrix.api.HomeserverCapabilitiesProvider
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.UrlContentFetcher
import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.DeviceId
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.EncryptionService
@@ -111,7 +111,7 @@ object SessionMatrixModule {
} }
@Provides @Provides
fun providesGetUrlResolverClient(matrixClient: MatrixClient): UrlContentFetcher { fun providesGetUrlResolverClient(matrixClient: MatrixClient): ClientUrlContentFetcher {
return matrixClient return matrixClient
} }
} }
@@ -16,7 +16,6 @@ import io.element.android.tests.testutils.lambda.value
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.Client
import org.matrix.rustcomponents.sdk.NoHandle
import java.io.File import java.io.File
import kotlin.io.path.createTempDirectory import kotlin.io.path.createTempDirectory
import org.matrix.rustcomponents.sdk.ClientException as RustClientException import org.matrix.rustcomponents.sdk.ClientException as RustClientException
@@ -84,7 +83,7 @@ class RustTemporaryMatrixClientTest {
} }
private fun createRustTemporaryMatrixClient( private fun createRustTemporaryMatrixClient(
client: Client = Client(NoHandle), client: Client = FakeFfiClient(),
paths: SessionPaths, paths: SessionPaths,
): RustTemporaryMatrixClient { ): RustTemporaryMatrixClient {
return RustTemporaryMatrixClient(client, paths) return RustTemporaryMatrixClient(client, paths)
@@ -12,6 +12,7 @@ import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSession
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile
import io.element.android.libraries.matrix.test.A_DEVICE_ID import io.element.android.libraries.matrix.test.A_DEVICE_ID
import io.element.android.libraries.matrix.test.A_HOMESERVER_URL import io.element.android.libraries.matrix.test.A_HOMESERVER_URL
import io.element.android.libraries.matrix.test.A_SERVER_NAME
import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.simulateLongTask import io.element.android.tests.testutils.simulateLongTask
@@ -45,6 +46,7 @@ class FakeFfiClient(
private val userId: String = A_USER_ID.value, private val userId: String = A_USER_ID.value,
private val deviceId: String = A_DEVICE_ID.value, private val deviceId: String = A_DEVICE_ID.value,
private val homeserver: String = A_HOMESERVER_URL, private val homeserver: String = A_HOMESERVER_URL,
private val server: String? = A_SERVER_NAME,
private val notificationClient: NotificationClient = FakeFfiNotificationClient(), private val notificationClient: NotificationClient = FakeFfiNotificationClient(),
private val notificationSettings: NotificationSettings = FakeFfiNotificationSettings(), private val notificationSettings: NotificationSettings = FakeFfiNotificationSettings(),
private val encryption: Encryption = FakeFfiEncryption(), private val encryption: Encryption = FakeFfiEncryption(),
@@ -66,6 +68,7 @@ class FakeFfiClient(
override fun userId(): String = userId override fun userId(): String = userId
override fun deviceId(): String = deviceId override fun deviceId(): String = deviceId
override fun homeserver(): String = homeserver override fun homeserver(): String = homeserver
override fun server(): String? = server
override suspend fun notificationClient(processSetup: NotificationProcessSetup) = notificationClient override suspend fun notificationClient(processSetup: NotificationProcessSetup) = notificationClient
override suspend fun getNotificationSettings(): NotificationSettings = notificationSettings override suspend fun getNotificationSettings(): NotificationSettings = notificationSettings
override fun encryption(): Encryption = encryption override fun encryption(): Encryption = encryption
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2026 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.matrix.test
import io.element.android.libraries.matrix.api.ClientUrlContentFetcher
import io.element.android.tests.testutils.lambda.lambdaError
class FakeClientUrlContentFetcher(
override val server: String = A_SERVER_NAME,
override val homeserverUrl: String = A_HOMESERVER_URL,
private val getUrlResult: (String) -> Result<ByteArray> = { lambdaError() },
) : ClientUrlContentFetcher {
override suspend fun getUrl(url: String): Result<ByteArray> {
return getUrlResult(url)
}
}
@@ -79,6 +79,7 @@ class FakeMatrixClient(
override val sessionId: SessionId = A_SESSION_ID, override val sessionId: SessionId = A_SESSION_ID,
override val sessionPaths: SessionPaths = SessionPaths(fileDirectory = File("files"), cacheDirectory = File("cache")), override val sessionPaths: SessionPaths = SessionPaths(fileDirectory = File("files"), cacheDirectory = File("cache")),
override val deviceId: DeviceId = A_DEVICE_ID, override val deviceId: DeviceId = A_DEVICE_ID,
override val server: String = A_SERVER_NAME,
override val homeserverUrl: String = A_HOMESERVER_URL, override val homeserverUrl: String = A_HOMESERVER_URL,
override val sessionCoroutineScope: CoroutineScope = TestScope(), override val sessionCoroutineScope: CoroutineScope = TestScope(),
private val userDisplayName: String? = A_USER_NAME, private val userDisplayName: String? = A_USER_NAME,
@@ -11,10 +11,11 @@ import io.element.android.libraries.matrix.api.TemporaryMatrixClient
import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaError
class FakeTemporaryMatrixClient( class FakeTemporaryMatrixClient(
override val server: String = A_SERVER_NAME,
override val homeserverUrl: String = A_HOMESERVER_URL,
private val getUrlResult: (String) -> Result<ByteArray> = { lambdaError() }, private val getUrlResult: (String) -> Result<ByteArray> = { lambdaError() },
private val closeLambda: () -> Unit = {}, private val closeLambda: () -> Unit = {},
) : TemporaryMatrixClient { ) : TemporaryMatrixClient {
override suspend fun getUrl(url: String): Result<ByteArray> = getUrlResult(url) override suspend fun getUrl(url: String): Result<ByteArray> = getUrlResult(url)
override fun close() = closeLambda() override fun close() = closeLambda()
} }
@@ -13,5 +13,5 @@ import io.element.android.libraries.matrix.api.TemporaryMatrixClientFactory
class FakeTemporaryMatrixClientFactory( class FakeTemporaryMatrixClientFactory(
private val createResult: (String) -> Result<TemporaryMatrixClient> = { Result.success(FakeTemporaryMatrixClient()) }, private val createResult: (String) -> Result<TemporaryMatrixClient> = { Result.success(FakeTemporaryMatrixClient()) },
) : TemporaryMatrixClientFactory { ) : TemporaryMatrixClientFactory {
override suspend fun create(homeServerUrl: String): Result<TemporaryMatrixClient> = createResult(homeServerUrl) override suspend fun create(serverName: String): Result<TemporaryMatrixClient> = createResult(serverName)
} }
@@ -72,6 +72,7 @@ const val A_SPACE_NAME = "A space name"
const val A_REDACTION_REASON = "A redaction reason" const val A_REDACTION_REASON = "A redaction reason"
const val A_SERVER_NAME = "matrix.org"
const val A_HOMESERVER_URL = "matrix.org" const val A_HOMESERVER_URL = "matrix.org"
const val A_HOMESERVER_URL_2 = "matrix-client.org" const val A_HOMESERVER_URL_2 = "matrix-client.org"