Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions changelog.d/7257.wip
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[Device Management] Save "matrix_client_information" events on login/registration
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ internal class DefaultSessionAccountDataService @Inject constructor(

override suspend fun updateUserAccountData(type: String, content: Content) {
val params = UpdateUserAccountDataTask.AnyParams(type = type, any = content)
awaitCallback<Unit> { callback ->
awaitCallback { callback ->
updateUserAccountDataTask.configureWith(params) {
this.retryCount = 5 // TODO Need to refactor retrying out into a helper method.
this.callback = callback
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ package im.vector.app.core.di
import android.content.Context
import arrow.core.Option
import im.vector.app.ActiveSessionDataSource
import im.vector.app.core.extensions.configureAndStart
import im.vector.app.core.extensions.startSyncing
import im.vector.app.core.pushers.UnifiedPushHelper
import im.vector.app.core.services.GuardServiceStarter
import im.vector.app.core.session.ConfigureAndStartSessionUseCase
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.crypto.keysrequest.KeyRequestHandler
import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler
Expand Down Expand Up @@ -50,6 +50,7 @@ class ActiveSessionHolder @Inject constructor(
private val sessionInitializer: SessionInitializer,
private val applicationContext: Context,
private val authenticationService: AuthenticationService,
private val configureAndStartSessionUseCase: ConfigureAndStartSessionUseCase,
) {

private var activeSessionReference: AtomicReference<Session?> = AtomicReference()
Expand Down Expand Up @@ -109,7 +110,9 @@ class ActiveSessionHolder @Inject constructor(
}
?: sessionInitializer.tryInitialize(readCurrentSession = { activeSessionReference.get() }) { session ->
setActiveSession(session)
session.configureAndStart(applicationContext, startSyncing = startSync)
runBlocking {
configureAndStartSessionUseCase.execute(session, startSyncing = startSync)
}
}
}

Expand Down
12 changes: 0 additions & 12 deletions vector/src/main/java/im/vector/app/core/extensions/Session.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,8 @@ import im.vector.app.core.services.VectorSyncAndroidService
import im.vector.app.features.session.VectorSessionStore
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
import org.matrix.android.sdk.api.session.sync.FilterService
import timber.log.Timber

fun Session.configureAndStart(context: Context, startSyncing: Boolean = true) {
Timber.i("Configure and start session for $myUserId. startSyncing: $startSyncing")
open()
filterService().setFilter(FilterService.FilterPreset.ElementFilter)
if (startSyncing) {
startSyncing(context)
}
pushersService().refreshPushers()
context.singletonEntryPoint().webRtcCallManager().checkForProtocolsSupportIfNeeded()
}

fun Session.startSyncing(context: Context) {
val applicationContext = context.applicationContext
if (!syncService().hasAlreadySynced()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2022 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 im.vector.app.core.session

import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import im.vector.app.core.extensions.startSyncing
import im.vector.app.core.session.clientinfo.UpdateMatrixClientInfoUseCase
import im.vector.app.features.call.webrtc.WebRtcCallManager
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.sync.FilterService
import timber.log.Timber
import javax.inject.Inject

class ConfigureAndStartSessionUseCase @Inject constructor(
@ApplicationContext private val context: Context,
private val webRtcCallManager: WebRtcCallManager,
private val updateMatrixClientInfoUseCase: UpdateMatrixClientInfoUseCase,
) {

suspend fun execute(session: Session, startSyncing: Boolean = true) {
Timber.i("Configure and start session for ${session.myUserId}. startSyncing: $startSyncing")
session.open()
session.filterService().setFilter(FilterService.FilterPreset.ElementFilter)
if (startSyncing) {
session.startSyncing(context)
}
session.pushersService().refreshPushers()
webRtcCallManager.checkForProtocolsSupportIfNeeded()
updateMatrixClientInfoUseCase.execute(session)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2022 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 im.vector.app.core.session.clientinfo

import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.toModel
import javax.inject.Inject

/**
* This use case retrieves the current account data event containing extended client info
* for a given deviceId.
*/
class GetMatrixClientInfoUseCase @Inject constructor() {

fun execute(session: Session, deviceId: String): MatrixClientInfoContent? {
val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId
val content = session.accountDataService().getUserAccountDataEvent(type)?.content
return content.toModel()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2022 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 im.vector.app.core.session.clientinfo

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class MatrixClientInfoContent(
// app name
@Json(name = "name")
val name: String? = null,
// app version
@Json(name = "version")
val version: String? = null,
// app url (optional, applicable only for web)
@Json(name = "url")
val url: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2022 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 im.vector.app.core.session.clientinfo

class NoDeviceIdError : IllegalStateException("device id is empty")
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2022 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 im.vector.app.core.session.clientinfo

/**
* Prefix for the key account data event which holds client info.
*/
const val MATRIX_CLIENT_INFO_KEY_PREFIX = "io.element.matrix_client_information."
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2022 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 im.vector.app.core.session.clientinfo

import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.toContent
import javax.inject.Inject

/**
* This use case sets the account data event containing extended client info.
*/
class SetMatrixClientInfoUseCase @Inject constructor() {

suspend fun execute(session: Session, clientInfo: MatrixClientInfoContent): Result<Unit> = runCatching {
val deviceId = session.sessionParams.deviceId.orEmpty()
if (deviceId.isNotEmpty()) {
val type = MATRIX_CLIENT_INFO_KEY_PREFIX + deviceId
session.accountDataService()
.updateUserAccountData(type, clientInfo.toContent())
} else {
throw NoDeviceIdError()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2022 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 im.vector.app.core.session.clientinfo

import im.vector.app.core.resources.AppNameProvider
import im.vector.app.core.resources.BuildMeta
import org.matrix.android.sdk.api.session.Session
import timber.log.Timber
import javax.inject.Inject

/**
* This use case updates if needed the account data event containing extended client info.
*/
class UpdateMatrixClientInfoUseCase @Inject constructor(
private val appNameProvider: AppNameProvider,
private val buildMeta: BuildMeta,
private val getMatrixClientInfoUseCase: GetMatrixClientInfoUseCase,
private val setMatrixClientInfoUseCase: SetMatrixClientInfoUseCase,
) {

suspend fun execute(session: Session) = runCatching {
val clientInfo = MatrixClientInfoContent(
name = appNameProvider.getAppName(),
version = buildMeta.versionName
)
val deviceId = session.sessionParams.deviceId.orEmpty()
if (deviceId.isNotEmpty()) {
val storedClientInfo = getMatrixClientInfoUseCase.execute(session, deviceId)
Timber.d("storedClientInfo=$storedClientInfo, current client info=$clientInfo")
if (clientInfo != storedClientInfo) {
Timber.d("client info need to be updated")
return setMatrixClientInfoUseCase.execute(session, clientInfo)
}
} else {
throw NoDeviceIdError()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.configureAndStart
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.session.ConfigureAndStartSessionUseCase
import im.vector.app.core.utils.ensureTrailingSlash
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -64,7 +64,8 @@ class LoginViewModel @AssistedInject constructor(
private val homeServerConnectionConfigFactory: HomeServerConnectionConfigFactory,
private val reAuthHelper: ReAuthHelper,
private val stringProvider: StringProvider,
private val homeServerHistoryService: HomeServerHistoryService
private val homeServerHistoryService: HomeServerHistoryService,
private val configureAndStartSessionUseCase: ConfigureAndStartSessionUseCase,
) : VectorViewModel<LoginViewState, LoginAction, LoginViewEvents>(initialState) {

@AssistedFactory
Expand Down Expand Up @@ -732,7 +733,7 @@ class LoginViewModel @AssistedInject constructor(
activeSessionHolder.setActiveSession(session)

authenticationService.reset()
session.configureAndStart(applicationContext)
configureAndStartSessionUseCase.execute(session)
setState {
copy(
asyncLoginAction = Success(Unit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.cancelCurrentOnSet
import im.vector.app.core.extensions.configureAndStart
import im.vector.app.core.extensions.inferNoConnectivity
import im.vector.app.core.extensions.isMatrixId
import im.vector.app.core.extensions.toReducedUrl
import im.vector.app.core.extensions.vectorStore
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.session.ConfigureAndStartSessionUseCase
import im.vector.app.core.utils.ensureProtocol
import im.vector.app.core.utils.ensureTrailingSlash
import im.vector.app.features.VectorFeatures
Expand Down Expand Up @@ -91,6 +91,7 @@ class OnboardingViewModel @AssistedInject constructor(
private val vectorOverrides: VectorOverrides,
private val registrationActionHandler: RegistrationActionHandler,
private val sdkIntProvider: BuildVersionSdkIntProvider,
private val configureAndStartSessionUseCase: ConfigureAndStartSessionUseCase,
) : VectorViewModel<OnboardingViewState, OnboardingAction, OnboardingViewEvents>(initialState) {

@AssistedFactory
Expand Down Expand Up @@ -616,7 +617,7 @@ class OnboardingViewModel @AssistedInject constructor(
activeSessionHolder.setActiveSession(session)

authenticationService.reset()
session.configureAndStart(applicationContext)
configureAndStartSessionUseCase.execute(session)

when (authenticationDescription) {
is AuthenticationDescription.Register -> {
Expand Down
Loading