summaryrefslogtreecommitdiffhomepage
path: root/android/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'android/app/src')
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt6
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/MtuComposeCell.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/QuantumResistanceInfoDialog.kt14
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt42
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt37
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt4
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/SettingsListener.kt6
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectionStatus.kt30
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/VpnSettingsFragment.kt18
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/SettingsListener.kt6
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt15
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelState.kt43
-rw-r--r--android/app/src/main/res/values/strings.xml6
15 files changed, 186 insertions, 47 deletions
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt
index f18ba6a801..046e773bc7 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt
@@ -44,6 +44,9 @@ class VpnSettingsScreenTest {
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
}
+ composeTestRule
+ .onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
// Assert
composeTestRule.apply {
@@ -348,6 +351,9 @@ class VpnSettingsScreenTest {
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
}
+ composeTestRule
+ .onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
// Assert
composeTestRule.apply {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt
index ff8771452d..58ab44daaa 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt
@@ -27,7 +27,7 @@ import net.mullvad.mullvadvpn.compose.theme.Dimens
@Preview
@Composable
-fun PreviewBaseCell() {
+private fun PreviewBaseCell() {
AppTheme {
SpacedColumn {
BaseCell(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/MtuComposeCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/MtuComposeCell.kt
index 6cc8eccdc3..b7fe9ee7a1 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/MtuComposeCell.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/MtuComposeCell.kt
@@ -20,7 +20,7 @@ import net.mullvad.mullvadvpn.constant.MTU_MIN_VALUE
@Preview
@Composable
-fun MtuComposeCellPreview() {
+private fun PreviewMtuComposeCell() {
AppTheme { MtuComposeCell(mtuValue = "1300", onEditMtu = {}) }
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/QuantumResistanceInfoDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/QuantumResistanceInfoDialog.kt
new file mode 100644
index 0000000000..faae3fd9f7
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/QuantumResistanceInfoDialog.kt
@@ -0,0 +1,14 @@
+package net.mullvad.mullvadvpn.compose.dialog
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.stringResource
+import net.mullvad.mullvadvpn.R
+
+@Composable
+fun QuantumResistanceInfoDialog(onDismiss: () -> Unit) {
+ InfoDialog(
+ message = stringResource(id = R.string.quantum_resistant_info_first_paragaph),
+ additionalInfo = stringResource(id = R.string.quantum_resistant_info_second_paragaph),
+ onDismiss = onDismiss
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt
index 1414a32899..9ac2a761ff 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt
@@ -64,12 +64,14 @@ import net.mullvad.mullvadvpn.compose.dialog.LocalNetworkSharingInfoDialog
import net.mullvad.mullvadvpn.compose.dialog.MalwareInfoDialog
import net.mullvad.mullvadvpn.compose.dialog.MtuDialog
import net.mullvad.mullvadvpn.compose.dialog.ObfuscationInfoDialog
+import net.mullvad.mullvadvpn.compose.dialog.QuantumResistanceInfoDialog
import net.mullvad.mullvadvpn.compose.extensions.itemWithDivider
import net.mullvad.mullvadvpn.compose.state.VpnSettingsUiState
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_LAST_ITEM_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_TEST_TAG
import net.mullvad.mullvadvpn.compose.theme.AppTheme
import net.mullvad.mullvadvpn.compose.theme.Dimens
+import net.mullvad.mullvadvpn.model.QuantumResistantState
import net.mullvad.mullvadvpn.model.SelectedObfuscation
import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem
@@ -113,7 +115,9 @@ private fun PreviewVpnSettings() {
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow(),
onStopEvent = {},
onSelectObfuscationSetting = {},
- onObfuscationInfoClick = {}
+ onObfuscationInfoClick = {},
+ onSelectQuantumResistanceSetting = {},
+ onQuantumResistanceInfoClicked = {}
)
}
}
@@ -151,7 +155,9 @@ fun VpnSettingsScreen(
onStopEvent: () -> Unit = {},
toastMessagesSharedFlow: SharedFlow<String>,
onSelectObfuscationSetting: (selectedObfuscation: SelectedObfuscation) -> Unit = {},
- onObfuscationInfoClick: () -> Unit = {}
+ onObfuscationInfoClick: () -> Unit = {},
+ onSelectQuantumResistanceSetting: (quantumResistant: Boolean?) -> Unit = {},
+ onQuantumResistanceInfoClicked: () -> Unit = {}
) {
val cellVerticalSpacing = dimensionResource(id = R.dimen.cell_label_vertical_padding)
val cellHorizontalSpacing = dimensionResource(id = R.dimen.cell_left_padding)
@@ -191,6 +197,9 @@ fun VpnSettingsScreen(
is VpnSettingsUiState.ObfuscationInfoDialogUiState -> {
ObfuscationInfoDialog(onDismissInfoClick)
}
+ is VpnSettingsUiState.QuantumResistanceInfoDialogUiState -> {
+ QuantumResistanceInfoDialog(onDismissInfoClick)
+ }
else -> {
// NOOP
}
@@ -381,6 +390,35 @@ fun VpnSettingsScreen(
)
}
+ itemWithDivider {
+ Spacer(modifier = Modifier.height(cellVerticalSpacing))
+ InformationComposeCell(
+ title = stringResource(R.string.quantum_resistant_title),
+ onInfoClicked = { onQuantumResistanceInfoClicked() }
+ )
+ }
+ itemWithDivider {
+ SelectableCell(
+ title = stringResource(id = R.string.automatic),
+ isSelected = uiState.quantumResistant == QuantumResistantState.Auto,
+ onCellClicked = { onSelectQuantumResistanceSetting(QuantumResistantState.Auto) }
+ )
+ }
+ itemWithDivider {
+ SelectableCell(
+ title = stringResource(id = R.string.on),
+ isSelected = uiState.quantumResistant == QuantumResistantState.On,
+ onCellClicked = { onSelectQuantumResistanceSetting(QuantumResistantState.On) }
+ )
+ }
+ itemWithDivider {
+ SelectableCell(
+ title = stringResource(id = R.string.off),
+ isSelected = uiState.quantumResistant == QuantumResistantState.Off,
+ onCellClicked = { onSelectQuantumResistanceSetting(QuantumResistantState.Off) }
+ )
+ }
+
item {
Spacer(modifier = Modifier.height(cellVerticalSpacing))
HeaderSwitchComposeCell(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt
index f5315278ab..c2c7d074fd 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt
@@ -14,6 +14,7 @@ sealed interface VpnSettingsUiState {
val contentBlockersOptions: DefaultDnsOptions
val isAllowLanEnabled: Boolean
val selectedObfuscation: SelectedObfuscation
+ val quantumResistant: Boolean?
data class DefaultUiState(
override val mtu: String = "",
@@ -23,7 +24,8 @@ sealed interface VpnSettingsUiState {
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val quantumResistant: Boolean? = null
) : VpnSettingsUiState
data class MtuDialogUiState(
@@ -35,7 +37,8 @@ sealed interface VpnSettingsUiState {
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
val mtuEditValue: String,
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val quantumResistant: Boolean? = null
) : VpnSettingsUiState
data class DnsDialogUiState(
@@ -47,7 +50,8 @@ sealed interface VpnSettingsUiState {
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
val stagedDns: StagedDns,
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val quantumResistant: Boolean? = null
) : VpnSettingsUiState
data class LocalNetworkSharingInfoDialogUiState(
@@ -58,7 +62,8 @@ sealed interface VpnSettingsUiState {
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val quantumResistant: Boolean? = null
) : VpnSettingsUiState
data class ContentBlockersInfoDialogUiState(
@@ -69,7 +74,8 @@ sealed interface VpnSettingsUiState {
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val quantumResistant: Boolean? = null
) : VpnSettingsUiState
data class CustomDnsInfoDialogUiState(
@@ -80,7 +86,8 @@ sealed interface VpnSettingsUiState {
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val quantumResistant: Boolean? = null
) : VpnSettingsUiState
data class MalwareInfoDialogUiState(
@@ -91,7 +98,8 @@ sealed interface VpnSettingsUiState {
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val quantumResistant: Boolean? = null
) : VpnSettingsUiState
data class ObfuscationInfoDialogUiState(
@@ -102,6 +110,19 @@ sealed interface VpnSettingsUiState {
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val quantumResistant: Boolean? = null
+ ) : VpnSettingsUiState
+
+ data class QuantumResistanceInfoDialogUiState(
+ override val mtu: String = "",
+ override val isAutoConnectEnabled: Boolean = false,
+ override val isLocalNetworkSharingEnabled: Boolean = false,
+ override val isCustomDnsEnabled: Boolean = false,
+ override val isAllowLanEnabled: Boolean = false,
+ override val customDnsItems: List<CustomDnsItem> = listOf(),
+ override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val quantumResistant: Boolean? = null
) : VpnSettingsUiState
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt
index b46bfbf64b..c9bd699c12 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt
@@ -85,6 +85,8 @@ sealed class Request : Message.RequestMessage() {
@Parcelize data class SetObfuscationSettings(val settings: ObfuscationSettings?) : Request()
+ @Parcelize data class SetWireGuardQuantumResistant(val quantumResistant: Boolean?) : Request()
+
companion object {
private const val MESSAGE_KEY = "request"
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt
index c0b9215d37..cde1c698ca 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt
@@ -54,6 +54,10 @@ class SettingsRepository(
serviceConnectionManager.settingsListener()?.wireguardMtu = value
}
+ fun setWireguardQuantumResistant(value: Boolean?) {
+ serviceConnectionManager.settingsListener()?.wireguardQuantumResistant = value
+ }
+
fun setObfuscationOptions(value: ObfuscationSettings) {
serviceConnectionManager.settingsListener()?.obfuscationSettings = value
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/SettingsListener.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/SettingsListener.kt
index 7606e7709c..cd0da7a3fc 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/SettingsListener.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/SettingsListener.kt
@@ -1,5 +1,6 @@
package net.mullvad.mullvadvpn.service.endpoint
+import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.Channel
@@ -59,6 +60,11 @@ class SettingsListener(endpoint: ServiceEndpoint) {
registerHandler(Request.SetObfuscationSettings::class) { request ->
commandChannel.trySendBlocking(Command.SetObfuscationSettings(request.settings))
}
+
+ registerHandler(Request.SetWireGuardQuantumResistant::class) { request ->
+ // TODO
+ Log.d("Remove this", "Set quantum resistant ${request.quantumResistant}")
+ }
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectionStatus.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectionStatus.kt
index d2b413f1d0..c59b603547 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectionStatus.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectionStatus.kt
@@ -7,7 +7,7 @@ import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.model.TunnelState
import net.mullvad.talpid.tunnel.ActionAfterDisconnect
-class ConnectionStatus(val parentView: View, context: Context) {
+class ConnectionStatus(parentView: View, context: Context) {
private val spinner: View = parentView.findViewById(R.id.connecting_spinner)
private val text: TextView = parentView.findViewById(R.id.connection_status)
@@ -20,13 +20,13 @@ class ConnectionStatus(val parentView: View, context: Context) {
is TunnelState.Disconnecting -> {
when (state.actionAfterDisconnect) {
ActionAfterDisconnect.Nothing -> disconnected()
- ActionAfterDisconnect.Block -> connected()
- ActionAfterDisconnect.Reconnect -> connecting()
+ ActionAfterDisconnect.Block -> connected(false)
+ ActionAfterDisconnect.Reconnect -> connecting(state.isSecured())
}
}
is TunnelState.Disconnected -> disconnected()
- is TunnelState.Connecting -> connecting()
- is TunnelState.Connected -> connected()
+ is TunnelState.Connecting -> connecting(state.endpoint?.quantumResistant == true)
+ is TunnelState.Connected -> connected(state.endpoint.quantumResistant)
is TunnelState.Error -> errorState(state.errorState.isBlocking)
}
}
@@ -38,18 +38,30 @@ class ConnectionStatus(val parentView: View, context: Context) {
text.setText(R.string.unsecured_connection)
}
- private fun connecting() {
+ private fun connecting(isQuantumResistant: Boolean) {
spinner.visibility = View.VISIBLE
text.setTextColor(connectingTextColor)
- text.setText(R.string.creating_secure_connection)
+ text.setText(
+ if (isQuantumResistant) {
+ R.string.quantum_creating_secure_connection
+ } else {
+ R.string.creating_secure_connection
+ }
+ )
}
- private fun connected() {
+ private fun connected(isQuantumResistant: Boolean) {
spinner.visibility = View.GONE
text.setTextColor(securedTextColor)
- text.setText(R.string.secure_connection)
+ text.setText(
+ if (isQuantumResistant) {
+ R.string.quantum_secure_connection
+ } else {
+ R.string.secure_connection
+ }
+ )
}
private fun errorState(isBlocking: Boolean) {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/VpnSettingsFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/VpnSettingsFragment.kt
index a299ce357a..6f689ff2c4 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/VpnSettingsFragment.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/VpnSettingsFragment.kt
@@ -55,24 +55,12 @@ class VpnSettingsFragment : BaseFragment() {
onStopEvent = vm::onStopEvent,
toastMessagesSharedFlow = vm.toastMessages,
onSelectObfuscationSetting = vm::onSelectObfuscationSetting,
- onObfuscationInfoClick = vm::onObfuscationInfoClick
+ onObfuscationInfoClick = vm::onObfuscationInfoClick,
+ onSelectQuantumResistanceSetting = vm::onSelectQuantumResistanceSetting,
+ onQuantumResistanceInfoClicked = vm::onQuantumResistanceInfoClicked
)
}
}
}
}
-
- private fun openSplitTunnelingFragment() {
- parentFragmentManager.beginTransaction().apply {
- setCustomAnimations(
- R.anim.fragment_enter_from_right,
- R.anim.fragment_exit_to_left,
- R.anim.fragment_half_enter_from_left,
- R.anim.fragment_exit_to_right
- )
- replace(R.id.main_fragment, SplitTunnelingFragment())
- addToBackStack(null)
- commitAllowingStateLoss()
- }
- }
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/SettingsListener.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/SettingsListener.kt
index 70e9721afc..5cfb4f1f0b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/SettingsListener.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/SettingsListener.kt
@@ -35,6 +35,12 @@ class SettingsListener(private val connection: Messenger, eventDispatcher: Event
connection.send(Request.SetWireGuardMtu(value).message)
}
+ var wireguardQuantumResistant: Boolean?
+ get() = settingsNotifier.latestEvent?.tunnelOptions?.wireguard?.quantumResistant
+ set(value) {
+ connection.send(Request.SetWireGuardQuantumResistant(value).message)
+ }
+
var obfuscationSettings: ObfuscationSettings?
get() = settingsNotifier.latestEvent?.obfuscationSettings
set(value) {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt
index 77d95823a6..b8ff734287 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt
@@ -55,7 +55,8 @@ class VpnSettingsViewModel(
isAllowLanEnabled = settings?.allowLan ?: false,
selectedObfuscation = settings?.selectedObfuscationSettings()
?: SelectedObfuscation.Off,
- dialogState = dialogState
+ dialogState = dialogState,
+ quantumResistant = settings?.quantumResistant()
)
}
.stateIn(
@@ -305,6 +306,16 @@ class VpnSettingsViewModel(
dialogState.update { VpnSettingsDialogState.ObfuscationInfoDialog }
}
+ fun onSelectQuantumResistanceSetting(quantumResistant: Boolean?) {
+ viewModelScope.launch(dispatcher) {
+ repository.setWireguardQuantumResistant(quantumResistant)
+ }
+ }
+
+ fun onQuantumResistanceInfoClicked() {
+ dialogState.update { VpnSettingsDialogState.QuantumResistanceInfoDialog }
+ }
+
private fun updateDefaultDnsOptionsViaRepository(contentBlockersOption: DefaultDnsOptions) =
viewModelScope.launch(dispatcher) {
repository.setDnsOptions(
@@ -341,6 +352,8 @@ class VpnSettingsViewModel(
private fun Settings.mtuString() = tunnelOptions.wireguard.mtu?.toString() ?: EMPTY_STRING
+ private fun Settings.quantumResistant() = tunnelOptions.wireguard.quantumResistant
+
private fun Settings.isCustomDnsEnabled() = tunnelOptions.dnsOptions.state == DnsState.Custom
private fun Settings.addresses() = tunnelOptions.dnsOptions.customOptions.addresses
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelState.kt
index 05ca44feb7..86f0c980eb 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelState.kt
@@ -13,7 +13,8 @@ data class VpnSettingsViewModelState(
val customDnsList: List<CustomDnsItem>,
val contentBlockersOptions: DefaultDnsOptions,
val selectedObfuscation: SelectedObfuscation,
- val dialogState: VpnSettingsDialogState
+ val dialogState: VpnSettingsDialogState,
+ val quantumResistant: Boolean?
) {
fun toUiState(): VpnSettingsUiState {
return when (dialogState) {
@@ -27,7 +28,8 @@ data class VpnSettingsViewModelState(
customDnsItems = customDnsList,
contentBlockersOptions = contentBlockersOptions,
mtuEditValue = dialogState.mtuEditValue,
- selectedObfuscation = selectedObfuscation
+ selectedObfuscation = selectedObfuscation,
+ quantumResistant = quantumResistant
)
is VpnSettingsDialogState.DnsDialog ->
VpnSettingsUiState.DnsDialogUiState(
@@ -39,7 +41,8 @@ data class VpnSettingsViewModelState(
customDnsItems = customDnsList,
contentBlockersOptions = contentBlockersOptions,
stagedDns = dialogState.stagedDns,
- selectedObfuscation = selectedObfuscation
+ selectedObfuscation = selectedObfuscation,
+ quantumResistant = quantumResistant
)
is VpnSettingsDialogState.LocalNetworkSharingInfoDialog ->
VpnSettingsUiState.LocalNetworkSharingInfoDialogUiState(
@@ -49,7 +52,8 @@ data class VpnSettingsViewModelState(
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
- contentBlockersOptions = contentBlockersOptions
+ contentBlockersOptions = contentBlockersOptions,
+ quantumResistant = quantumResistant
)
is VpnSettingsDialogState.ContentBlockersInfoDialog ->
VpnSettingsUiState.ContentBlockersInfoDialogUiState(
@@ -60,7 +64,8 @@ data class VpnSettingsViewModelState(
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
contentBlockersOptions = contentBlockersOptions,
- selectedObfuscation = selectedObfuscation
+ selectedObfuscation = selectedObfuscation,
+ quantumResistant = quantumResistant
)
is VpnSettingsDialogState.CustomDnsInfoDialog ->
VpnSettingsUiState.CustomDnsInfoDialogUiState(
@@ -70,7 +75,8 @@ data class VpnSettingsViewModelState(
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
- contentBlockersOptions = contentBlockersOptions
+ contentBlockersOptions = contentBlockersOptions,
+ quantumResistant = quantumResistant
)
is VpnSettingsDialogState.MalwareInfoDialog ->
VpnSettingsUiState.MalwareInfoDialogUiState(
@@ -81,7 +87,8 @@ data class VpnSettingsViewModelState(
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
contentBlockersOptions = contentBlockersOptions,
- selectedObfuscation = selectedObfuscation
+ selectedObfuscation = selectedObfuscation,
+ quantumResistant = quantumResistant
)
is VpnSettingsDialogState.ObfuscationInfoDialog ->
VpnSettingsUiState.ObfuscationInfoDialogUiState(
@@ -90,8 +97,20 @@ data class VpnSettingsViewModelState(
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
contentBlockersOptions = contentBlockersOptions,
- selectedObfuscation = selectedObfuscation
+ selectedObfuscation = selectedObfuscation,
+ quantumResistant = quantumResistant
)
+ is VpnSettingsDialogState.QuantumResistanceInfoDialog -> {
+ VpnSettingsUiState.QuantumResistanceInfoDialogUiState(
+ mtu = mtuValue,
+ isCustomDnsEnabled = isCustomDnsEnabled,
+ isAllowLanEnabled = isAllowLanEnabled,
+ customDnsItems = customDnsList,
+ contentBlockersOptions = contentBlockersOptions,
+ selectedObfuscation = selectedObfuscation,
+ quantumResistant = quantumResistant
+ )
+ }
else ->
VpnSettingsUiState.DefaultUiState(
mtu = mtuValue,
@@ -101,7 +120,8 @@ data class VpnSettingsViewModelState(
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
contentBlockersOptions = contentBlockersOptions,
- selectedObfuscation = selectedObfuscation
+ selectedObfuscation = selectedObfuscation,
+ quantumResistant = quantumResistant
)
}
}
@@ -119,7 +139,8 @@ data class VpnSettingsViewModelState(
contentBlockersOptions = DefaultDnsOptions(),
isAllowLanEnabled = false,
dialogState = VpnSettingsDialogState.NoDialog,
- selectedObfuscation = SelectedObfuscation.Auto
+ selectedObfuscation = SelectedObfuscation.Auto,
+ quantumResistant = null
)
}
}
@@ -140,6 +161,8 @@ sealed class VpnSettingsDialogState {
object MalwareInfoDialog : VpnSettingsDialogState()
object ObfuscationInfoDialog : VpnSettingsDialogState()
+
+ object QuantumResistanceInfoDialog : VpnSettingsDialogState()
}
sealed interface StagedDns {
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 7354d40a11..e6cb2f84ce 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -196,4 +196,10 @@
<string name="created_x">Created: %s</string>
<string name="local_network_sharing_info">This feature allows access to other devices on the local network, such as for sharing, printing, streaming, etc.</string>
<string name="local_network_sharing_additional_info">It does this by allowing network communication outside the tunnel to local multicast and broadcast ranges as well as to and from these private IP ranges:</string>
+ <string name="quantum_resistant_title">Quantum-resistant tunnel</string>
+ <string name="quantum_resistant_info_first_paragaph">This feature makes the WireGuard tunnel resistant to potential attacks from quantum computers.</string>
+ <string name="quantum_resistant_info_second_paragaph">It does this by performing an extra key exchange using a quantum safe algorithm and mixing the result into WireGuard’s regular encryption. This extra step uses approximately 500 kiB of traffic every time a new tunnel is established.</string>
+ <string name="on">On</string>
+ <string name="quantum_creating_secure_connection">CREATING QUANTUM SECURE CONNECTION</string>
+ <string name="quantum_secure_connection">QUANTUM SECURE CONNECTION</string>
</resources>