Feature/fga/matrix client versions (#1022)

* Extract a RustMatrixClientFactory

* Use serverVersions api on client builder to speed up startup.

* Clean up

* Fix compilation of sample

---------

Co-authored-by: ganfra <francoisg@element.io>
This commit is contained in:
ganfra 2023-08-02 20:56:26 +02:00 committed by GitHub
parent f68b357e54
commit ac7412c2d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 100 additions and 51 deletions

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.matrix.impl
import android.content.Context
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.network.useragent.UserAgentProvider
import io.element.android.libraries.sessionstorage.api.SessionData
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.ClientBuilder
import org.matrix.rustcomponents.sdk.Session
import org.matrix.rustcomponents.sdk.use
import java.io.File
import javax.inject.Inject
class RustMatrixClientFactory @Inject constructor(
@ApplicationContext private val context: Context,
private val baseDirectory: File,
private val appCoroutineScope: CoroutineScope,
private val coroutineDispatchers: CoroutineDispatchers,
private val sessionStore: SessionStore,
private val userAgentProvider: UserAgentProvider,
private val clock: SystemClock,
) {
suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) {
val client = ClientBuilder()
.basePath(baseDirectory.absolutePath)
.homeserverUrl(sessionData.homeserverUrl)
.username(sessionData.userId)
.userAgent(userAgentProvider.provide())
// FIXME Quick and dirty fix for stopping version requests on startup https://github.com/matrix-org/matrix-rust-sdk/pull/1376
.serverVersions(listOf("v1.0", "v1.1", "v1.2", "v1.3", "v1.4", "v1.5"))
.use { it.build() }
client.restoreSession(sessionData.toSession())
val syncService = client.syncService().finish()
RustMatrixClient(
client = client,
syncService = syncService,
sessionStore = sessionStore,
appCoroutineScope = appCoroutineScope,
dispatchers = coroutineDispatchers,
baseDirectory = baseDirectory,
baseCacheDirectory = context.cacheDir,
clock = clock,
)
}
}
private fun SessionData.toSession() = Session(
accessToken = accessToken,
refreshToken = refreshToken,
userId = userId,
deviceId = deviceId,
homeserverUrl = homeserverUrl,
slidingSyncProxy = slidingSyncProxy,
)

View file

@ -16,33 +16,27 @@
package io.element.android.libraries.matrix.impl.auth
import android.content.Context
// TODO Oidc
// import org.matrix.rustcomponents.sdk.OidcAuthenticationUrl
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.extensions.mapFailure
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
import io.element.android.libraries.matrix.api.auth.OidcDetails
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.impl.RustMatrixClient
import io.element.android.libraries.matrix.impl.RustMatrixClientFactory
import io.element.android.libraries.matrix.impl.exception.mapClientException
import io.element.android.libraries.network.useragent.UserAgentProvider
import io.element.android.libraries.sessionstorage.api.SessionData
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.Client
import org.matrix.rustcomponents.sdk.ClientBuilder
// TODO Oidc
// import org.matrix.rustcomponents.sdk.OidcAuthenticationUrl
import org.matrix.rustcomponents.sdk.Session
import org.matrix.rustcomponents.sdk.use
import java.io.File
@ -53,13 +47,11 @@ import org.matrix.rustcomponents.sdk.AuthenticationService as RustAuthentication
@ContributesBinding(AppScope::class)
@SingleIn(AppScope::class)
class RustMatrixAuthenticationService @Inject constructor(
@ApplicationContext private val context: Context,
private val baseDirectory: File,
private val appCoroutineScope: CoroutineScope,
baseDirectory: File,
private val coroutineDispatchers: CoroutineDispatchers,
private val sessionStore: SessionStore,
private val clock: SystemClock,
private val userAgentProvider: UserAgentProvider,
userAgentProvider: UserAgentProvider,
private val rustMatrixClientFactory: RustMatrixClientFactory,
) : MatrixAuthenticationService {
private val authService: RustAuthenticationService = RustAuthenticationService(
@ -84,14 +76,7 @@ class RustMatrixAuthenticationService @Inject constructor(
runCatching {
val sessionData = sessionStore.getSession(sessionId.value)
if (sessionData != null) {
val client = ClientBuilder()
.basePath(baseDirectory.absolutePath)
.homeserverUrl(sessionData.homeserverUrl)
.username(sessionData.userId)
.userAgent(userAgentProvider.provide())
.use { it.build() }
client.restoreSession(sessionData.toSession())
createMatrixClient(client)
rustMatrixClientFactory.create(sessionData)
} else {
error("No session to restore with id $sessionId")
}
@ -181,30 +166,8 @@ class RustMatrixAuthenticationService @Inject constructor(
*/
}
private suspend fun createMatrixClient(client: Client): MatrixClient {
val syncService = client.syncService().finish()
return RustMatrixClient(
client = client,
syncService = syncService,
sessionStore = sessionStore,
appCoroutineScope = appCoroutineScope,
dispatchers = coroutineDispatchers,
baseDirectory = baseDirectory,
baseCacheDirectory = context.cacheDir,
clock = clock,
)
}
}
private fun SessionData.toSession() = Session(
accessToken = accessToken,
refreshToken = refreshToken,
userId = userId,
deviceId = deviceId,
homeserverUrl = homeserverUrl,
slidingSyncProxy = slidingSyncProxy,
)
private fun Session.toSessionData() = SessionData(
userId = userId,
deviceId = deviceId,

View file

@ -26,11 +26,12 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.view.WindowCompat
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.impl.RustMatrixClientFactory
import io.element.android.libraries.matrix.impl.auth.RustMatrixAuthenticationService
import io.element.android.libraries.network.useragent.SimpleUserAgentProvider
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
import io.element.android.libraries.theme.ElementTheme
import io.element.android.services.toolbox.impl.systemclock.DefaultSystemClock
import kotlinx.coroutines.runBlocking
import java.io.File
@ -39,15 +40,22 @@ class MainActivity : ComponentActivity() {
private val matrixAuthenticationService: MatrixAuthenticationService by lazy {
val baseDirectory = File(applicationContext.filesDir, "sessions")
val userAgentProvider = SimpleUserAgentProvider("MinimalSample")
val sessionStore = InMemorySessionStore()
RustMatrixAuthenticationService(
context = applicationContext,
baseDirectory = baseDirectory,
appCoroutineScope = Singleton.appScope,
coroutineDispatchers = Singleton.coroutineDispatchers,
sessionStore = InMemorySessionStore(),
clock = DefaultSystemClock(),
userAgentProvider = SimpleUserAgentProvider("MinimalSample")
sessionStore = sessionStore,
userAgentProvider = userAgentProvider,
rustMatrixClientFactory = RustMatrixClientFactory(
context = applicationContext,
baseDirectory = baseDirectory,
appCoroutineScope = Singleton.appScope,
coroutineDispatchers = Singleton.coroutineDispatchers,
sessionStore = sessionStore,
userAgentProvider = userAgentProvider,
clock = DefaultSystemClock()
)
)
}