diff --git a/vector-config/src/main/java/im/vector/app/config/Config.kt b/vector-config/src/main/java/im/vector/app/config/Config.kt index 412e942fd7..70ccc5bd5e 100644 --- a/vector-config/src/main/java/im/vector/app/config/Config.kt +++ b/vector-config/src/main/java/im/vector/app/config/Config.kt @@ -42,6 +42,11 @@ object Config { */ const val VOICE_MESSAGE_LIMIT_MS = 120_000L + /** + * The strategy for sharing device keys + */ + val KEY_SHARING_STRATEGY = KeySharingStrategy.WhenTyping + /** * The onboarding flow */ @@ -111,3 +116,21 @@ enum class OnboardingVariant { LOGIN_2, FTUE_AUTH } + +enum class KeySharingStrategy { + /** + * Keys will be sent for the first time when the first message is sent. + * This is handled by the Matrix SDK so there's no need to do it in Vector. + */ + WhenSendingEvent, + + /** + * Keys will be sent for the first time when the timeline displayed. + */ + WhenEnteringRoom, + + /** + * Keys will be sent for the first time when a typing started. + */ + WhenTyping +} diff --git a/vector/build.gradle b/vector/build.gradle index 3fd6237fc4..3d6f50ed93 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -156,8 +156,6 @@ android { buildConfigField "String", "GIT_BRANCH_NAME", "\"${gitBranchName()}\"" buildConfigField "String", "BUILD_NUMBER", "\"${buildNumber}\"" - buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping" - // If set, MSC3086 asserted identity messages sent on VoIP calls will cause the call to appear in the room corresponding to the asserted identity. // This *must* only be set in trusted environments. buildConfigField "Boolean", "handleCallAssertedIdentityEvents", "false" diff --git a/vector/src/main/java/im/vector/app/core/di/ConfigurationModule.kt b/vector/src/main/java/im/vector/app/core/di/ConfigurationModule.kt new file mode 100644 index 0000000000..dc4f8dac40 --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/di/ConfigurationModule.kt @@ -0,0 +1,66 @@ +/* + * 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.di + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import im.vector.app.BuildConfig +import im.vector.app.config.Analytics +import im.vector.app.config.Config +import im.vector.app.config.KeySharingStrategy +import im.vector.app.features.analytics.AnalyticsConfig +import im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy +import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageConfig +import im.vector.app.features.raw.wellknown.CryptoConfig + +@InstallIn(SingletonComponent::class) +@Module +object ConfigurationModule { + + @Provides + fun providesAnalyticsConfig(): AnalyticsConfig { + val config: Analytics = when (BuildConfig.DEBUG) { + true -> Config.DEBUG_ANALYTICS_CONFIG + false -> Config.RELEASE_ANALYTICS_CONFIG + } + return when (config) { + Analytics.Disabled -> AnalyticsConfig(isEnabled = false, "", "", "") + is Analytics.PostHog -> AnalyticsConfig( + isEnabled = true, + postHogHost = config.postHogHost, + postHogApiKey = config.postHogApiKey, + policyLink = config.policyLink + ) + } + } + + @Provides + fun providesVoiceMessageConfig() = VoiceMessageConfig( + lengthLimitMs = Config.VOICE_MESSAGE_LIMIT_MS + ) + + @Provides + fun providesCryptoConfig() = CryptoConfig( + fallbackKeySharingStrategy = when (Config.KEY_SHARING_STRATEGY) { + KeySharingStrategy.WhenSendingEvent -> OutboundSessionKeySharingStrategy.WhenSendingEvent + KeySharingStrategy.WhenEnteringRoom -> OutboundSessionKeySharingStrategy.WhenSendingEvent + KeySharingStrategy.WhenTyping -> OutboundSessionKeySharingStrategy.WhenSendingEvent + } + ) +} diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt index 64ad9eda6c..bfa37057e2 100644 --- a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt @@ -207,6 +207,9 @@ object VectorStaticModule { return GlobalScope } + @Provides + fun providesPhoneNumberUtil(): PhoneNumberUtil = PhoneNumberUtil.getInstance() + @Provides fun providesAnalyticsConfig(): AnalyticsConfig { val config: Analytics = when (BuildConfig.BUILD_TYPE) { @@ -226,9 +229,6 @@ object VectorStaticModule { } } - @Provides - fun providesPhoneNumberUtil(): PhoneNumberUtil = PhoneNumberUtil.getInstance() - @Provides fun providesVoiceMessageConfig() = VoiceMessageConfig( lengthLimitMs = Config.VOICE_MESSAGE_LIMIT_MS diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index 848bd3aed4..b2a0e52db9 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -56,6 +56,7 @@ import im.vector.app.features.location.LocationSharingServiceConnection import im.vector.app.features.location.live.StopLiveLocationShareUseCase import im.vector.app.features.notifications.NotificationDrawerManager import im.vector.app.features.powerlevel.PowerLevelsFlowFactory +import im.vector.app.features.raw.wellknown.CryptoConfig import im.vector.app.features.raw.wellknown.getOutboundSessionKeySharingStrategyOrDefault import im.vector.app.features.raw.wellknown.withElementWellKnown import im.vector.app.features.session.coroutineScope @@ -137,6 +138,7 @@ class TimelineViewModel @AssistedInject constructor( private val locationSharingServiceConnection: LocationSharingServiceConnection, private val stopLiveLocationShareUseCase: StopLiveLocationShareUseCase, private val redactLiveLocationShareEventUseCase: RedactLiveLocationShareEventUseCase, + private val cryptoConfig: CryptoConfig, timelineFactory: TimelineFactory, spaceStateHandler: SpaceStateHandler, ) : VectorViewModel(initialState), @@ -205,7 +207,7 @@ class TimelineViewModel @AssistedInject constructor( // Ensure to share the outbound session keys with all members if (room.roomCryptoService().isEncrypted()) { rawService.withElementWellKnown(viewModelScope, session.sessionParams) { - val strategy = it.getOutboundSessionKeySharingStrategyOrDefault() + val strategy = it.getOutboundSessionKeySharingStrategyOrDefault(cryptoConfig.fallbackKeySharingStrategy) if (strategy == OutboundSessionKeySharingStrategy.WhenEnteringRoom) { prepareForEncryption() } @@ -688,7 +690,7 @@ class TimelineViewModel @AssistedInject constructor( // Ensure outbound session keys if (room.roomCryptoService().isEncrypted()) { rawService.withElementWellKnown(viewModelScope, session.sessionParams) { - val strategy = it.getOutboundSessionKeySharingStrategyOrDefault() + val strategy = it.getOutboundSessionKeySharingStrategyOrDefault(cryptoConfig.fallbackKeySharingStrategy) if (strategy == OutboundSessionKeySharingStrategy.WhenTyping && action.focused) { // Should we add some rate limit here, or do it only once per model lifecycle? prepareForEncryption() diff --git a/vector/src/main/java/im/vector/app/features/raw/wellknown/CryptoConfig.kt b/vector/src/main/java/im/vector/app/features/raw/wellknown/CryptoConfig.kt new file mode 100644 index 0000000000..130fa0078a --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/raw/wellknown/CryptoConfig.kt @@ -0,0 +1,23 @@ +/* + * 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.features.raw.wellknown + +import im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy + +data class CryptoConfig( + val fallbackKeySharingStrategy: OutboundSessionKeySharingStrategy +) diff --git a/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownExt.kt b/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownExt.kt index 73662613f7..28c7fecf0b 100644 --- a/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownExt.kt +++ b/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownExt.kt @@ -16,7 +16,6 @@ package im.vector.app.features.raw.wellknown -import im.vector.app.BuildConfig import im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -35,12 +34,12 @@ suspend fun RawService.getElementWellknown(sessionParams: SessionParams): Elemen fun ElementWellKnown.isE2EByDefault() = elementE2E?.e2eDefault ?: riotE2E?.e2eDefault ?: true -fun ElementWellKnown?.getOutboundSessionKeySharingStrategyOrDefault(): OutboundSessionKeySharingStrategy { +fun ElementWellKnown?.getOutboundSessionKeySharingStrategyOrDefault(fallback: OutboundSessionKeySharingStrategy): OutboundSessionKeySharingStrategy { return when (this?.elementE2E?.outboundsKeyPreSharingMode) { "on_room_opening" -> OutboundSessionKeySharingStrategy.WhenEnteringRoom "on_typing" -> OutboundSessionKeySharingStrategy.WhenTyping "disabled" -> OutboundSessionKeySharingStrategy.WhenSendingEvent - else -> BuildConfig.outboundSessionKeySharingStrategy + else -> fallback } }