summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2022-03-15 16:01:44 +0100
committerAlbin <albin@mullvad.net>2022-03-24 13:24:42 +0100
commit3067fe485b6c894ecd55b3b2ce615064ee49a2dc (patch)
tree3c9fcfc5dbcb72cf1caa5a54dc05d3d61484ceff /android
parenta4e1c265840ae6d254f26f70f5ea316b46a25074 (diff)
downloadmullvadvpn-3067fe485b6c894ecd55b3b2ce615064ee49a2dc.tar.xz
mullvadvpn-3067fe485b6c894ecd55b3b2ce615064ee49a2dc.zip
Initial adaption of Android login to device flow
Adapts the Android app to use the device login/logout functionality. Limitations: * State will not always be correctly propagated to all components of the app (i.e. Settings). This will be fixed in later device commits. * Some temporary error messages will be used in the Login view. These will change in later commits and/or be replaced with new views (i.e. when a user has too many devices registered).
Diffstat (limited to 'android')
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/LoginStatus.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/AccountCache.kt57
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt27
-rw-r--r--android/app/src/main/kotlin/net/mullvad/talpid/util/EventNotifier.kt6
4 files changed, 47 insertions, 46 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/LoginStatus.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/LoginStatus.kt
index e143cc630c..8e3b8f841d 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/LoginStatus.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/LoginStatus.kt
@@ -8,7 +8,8 @@ import org.joda.time.DateTime
data class LoginStatus(
val account: String,
val expiry: DateTime?,
- val isNewAccount: Boolean
+ val isNewAccount: Boolean,
+ val loginResult: LoginResult?
) : Parcelable {
val isExpired: Boolean
get() = expiry != null && expiry.isAfterNow()
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/AccountCache.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/AccountCache.kt
index 830860a45d..40fc8d7bd1 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/AccountCache.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/AccountCache.kt
@@ -10,6 +10,7 @@ import kotlinx.coroutines.delay
import net.mullvad.mullvadvpn.ipc.Event
import net.mullvad.mullvadvpn.ipc.Request
import net.mullvad.mullvadvpn.model.GetAccountDataResult
+import net.mullvad.mullvadvpn.model.LoginResult
import net.mullvad.mullvadvpn.model.LoginStatus
import net.mullvad.mullvadvpn.util.ExponentialBackoff
import net.mullvad.mullvadvpn.util.JobTracker
@@ -57,15 +58,6 @@ class AccountCache(private val endpoint: ServiceEndpoint) {
private var createdAccountExpiry: DateTime? = null
private var oldAccountExpiry: DateTime? = null
- var account: String?
- get() = endpoint.settingsListener.accountNumberNotifier.latestEvent
- set(value) {
- jobTracker.newBackgroundJob("setAccount") {
- // TODO: Skip until device integration is ready.
- // daemon.await().setAccount(value)
- }
- }
-
var loginStatus by onLoginStatusChange.notifiable()
private set
@@ -190,39 +182,31 @@ class AccountCache(private val endpoint: ServiceEndpoint) {
}
private suspend fun doLogin(account: String) {
- val result = daemon.await().getAccountData(account)
+ val loginResult = daemon.await().loginAccount(account)
- when (result) {
- is GetAccountDataResult.Ok -> {
- val expiry = DateTime.parse(result.accountData.expiry, EXPIRY_FORMAT)
-
- finishLogin(account, expiry)
- }
- is GetAccountDataResult.RpcError -> finishLogin(account, null)
- else -> finishLogin(null, null)
- }
- }
+ val accountExpiryDate = loginResult
+ .takeIf { it == LoginResult.Ok }
+ .let { daemon.await().getAccountData(account) as? GetAccountDataResult.Ok }
+ ?.let { DateTime.parse(it.accountData.expiry, EXPIRY_FORMAT) }
- private suspend fun finishLogin(maybeAccount: String?, expiry: DateTime?) {
synchronized(this) {
markAccountAsNotNew()
+ accountNumber = account
+ accountExpiry = accountExpiryDate
- accountNumber = maybeAccount
- accountExpiry = expiry
-
- loginStatus = maybeAccount?.let { account ->
- LoginStatus(account, expiry, false)
- }
+ loginStatus = LoginStatus(
+ account = account,
+ expiry = accountExpiryDate,
+ isNewAccount = newlyCreatedAccount,
+ loginResult
+ )
}
-
- // TODO: Skip until device integration is ready.
- // daemon.await().setAccount(maybeAccount)
}
private suspend fun doLogout() {
if (accountNumber != null) {
- // TODO: Skip until device integration is ready.
- // daemon.await().setAccount(null)
+ daemon.await().logoutAccount()
+ loginStatus = null
}
}
@@ -245,7 +229,7 @@ class AccountCache(private val endpoint: ServiceEndpoint) {
accountNumber = newAccountNumber
loginStatus = newAccountNumber?.let { account ->
- LoginStatus(account, null, newlyCreatedAccount)
+ LoginStatus(account, null, newlyCreatedAccount, null)
}
fetchAccountExpiry()
@@ -270,7 +254,12 @@ class AccountCache(private val endpoint: ServiceEndpoint) {
oldAccountExpiry = null
loginStatus = loginStatus?.let { currentStatus ->
- LoginStatus(currentStatus.account, newAccountExpiry, currentStatus.isNewAccount)
+ LoginStatus(
+ currentStatus.account,
+ newAccountExpiry,
+ currentStatus.isNewAccount,
+ null
+ )
}
if (accountExpiry != null && newlyCreatedAccount) {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt
index 399490f04b..4444812179 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt
@@ -10,6 +10,7 @@ import android.widget.TextView
import androidx.core.content.ContextCompat
import kotlinx.coroutines.delay
import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.model.LoginResult
import net.mullvad.mullvadvpn.model.LoginStatus
import net.mullvad.mullvadvpn.ui.widget.AccountLogin
import net.mullvad.mullvadvpn.ui.widget.Button
@@ -77,14 +78,14 @@ class LoginFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen), Na
}
}
- accountCache.onLoginStatusChange.subscribe(this) { status ->
+ accountCache.onLoginStatusChange.subscribe(this, false) { status ->
jobTracker.newUiJob("updateLoginStatus") {
loginStatus = status
- if (status == null) {
- if (state == State.LoggingIn || state == State.CreatingAccount) {
- loginFailure()
- }
+ if (status == null && state == State.CreatingAccount) {
+ loginFailure(null)
+ } else if (status?.loginResult != LoginResult.Ok) {
+ loginFailure(status?.loginResult)
} else {
if (state == State.Starting) {
openNextScreen()
@@ -201,11 +202,17 @@ class LoginFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen), Na
}
}
- private fun loginFailure() {
- val description = when (state) {
- State.LoggingIn -> R.string.login_fail_description
- State.CreatingAccount -> R.string.failed_to_create_account
- State.Idle, State.Starting -> return
+ // TODO: This error handling and its messages will change once a VM is introduced in a later
+ // commit related to the ongoing device adaption.
+ private fun loginFailure(loginResult: LoginResult?) {
+ val description = when {
+ loginResult == LoginResult.MaxDevicesReached -> "Too many devices"
+ loginResult == LoginResult.RpcError -> "An error occurred"
+ loginResult == LoginResult.OtherError -> "An error occurred"
+ loginResult == LoginResult.InvalidAccount ->
+ resources.getText(R.string.login_fail_description)
+ state == State.CreatingAccount -> resources.getText(R.string.failed_to_create_account)
+ else -> return
}
state = State.Idle
diff --git a/android/app/src/main/kotlin/net/mullvad/talpid/util/EventNotifier.kt b/android/app/src/main/kotlin/net/mullvad/talpid/util/EventNotifier.kt
index 444dd54f42..fb038f1243 100644
--- a/android/app/src/main/kotlin/net/mullvad/talpid/util/EventNotifier.kt
+++ b/android/app/src/main/kotlin/net/mullvad/talpid/util/EventNotifier.kt
@@ -35,9 +35,13 @@ class EventNotifier<T>(private val initialValue: T) {
}
fun subscribe(id: Any, listener: (T) -> Unit) {
+ subscribe(id, true, listener)
+ }
+
+ fun subscribe(id: Any, startWithLatestEvent: Boolean, listener: (T) -> Unit) {
synchronized(this) {
listeners.put(id, listener)
- listener(latestEvent)
+ if (startWithLatestEvent) listener(latestEvent)
}
}