summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2021-04-22 16:32:48 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2021-04-22 16:32:48 -0300
commit218d6f677eaa1dd0d635158fa69e56df9299e8ad (patch)
treea6e75ebc3dab3d7f09249172866b1ef813d4b816 /android
parentcf6dd6e770c5a4b52908a8595692c9a2a932a490 (diff)
parent4035d890540b69bd8e6671dad4e70b62414f2490 (diff)
downloadmullvadvpn-218d6f677eaa1dd0d635158fa69e56df9299e8ad.tar.xz
mullvadvpn-218d6f677eaa1dd0d635158fa69e56df9299e8ad.zip
Merge branch 'split-voucher-redeemer'
Diffstat (limited to 'android')
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Event.kt7
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt3
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/model/VoucherSubmission.kt6
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/model/VoucherSubmissionResult.kt24
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt2
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/VoucherRedeemer.kt40
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/RedeemVoucherDialogFragment.kt26
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt2
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/VoucherRedeemer.kt43
9 files changed, 128 insertions, 25 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Event.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Event.kt
index ab71cdc133..c48758230d 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Event.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Event.kt
@@ -9,6 +9,7 @@ import net.mullvad.mullvadvpn.model.LoginStatus as LoginStatusData
import net.mullvad.mullvadvpn.model.RelayList
import net.mullvad.mullvadvpn.model.Settings
import net.mullvad.mullvadvpn.model.TunnelState
+import net.mullvad.mullvadvpn.model.VoucherSubmissionResult as VoucherSubmissionResultData
// Events that can be sent from the service
sealed class Event : Message.EventMessage() {
@@ -48,6 +49,12 @@ sealed class Event : Message.EventMessage() {
data class TunnelStateChange(val tunnelState: TunnelState) : Event()
@Parcelize
+ data class VoucherSubmissionResult(
+ val voucher: String,
+ val result: VoucherSubmissionResultData
+ ) : Event()
+
+ @Parcelize
data class WireGuardKeyStatus(val keyStatus: KeygenEvent?) : Event()
companion object {
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt
index 67ae40f187..0f64daece7 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt
@@ -87,6 +87,9 @@ sealed class Request : Message.RequestMessage() {
data class SetWireGuardMtu(val mtu: Int?) : Request()
@Parcelize
+ data class SubmitVoucher(val voucher: String) : Request()
+
+ @Parcelize
data class VpnPermissionResponse(val isGranted: Boolean) : Request()
@Parcelize
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/VoucherSubmission.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/VoucherSubmission.kt
index 9a14c4cf7e..bf96646516 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/VoucherSubmission.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/VoucherSubmission.kt
@@ -1,3 +1,7 @@
package net.mullvad.mullvadvpn.model
-data class VoucherSubmission(val timeAdded: Long, val newExpiry: String)
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class VoucherSubmission(val timeAdded: Long, val newExpiry: String) : Parcelable
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/VoucherSubmissionResult.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/VoucherSubmissionResult.kt
index 6978ebba73..7403d66014 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/VoucherSubmissionResult.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/VoucherSubmissionResult.kt
@@ -1,9 +1,21 @@
package net.mullvad.mullvadvpn.model
-sealed class VoucherSubmissionResult {
- class Ok(val submission: VoucherSubmission) : VoucherSubmissionResult()
- object InvalidVoucher : VoucherSubmissionResult()
- object VoucherAlreadyUsed : VoucherSubmissionResult()
- object RpcError : VoucherSubmissionResult()
- object OtherError : VoucherSubmissionResult()
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+sealed class VoucherSubmissionResult : Parcelable {
+ @Parcelize
+ class Ok(val submission: VoucherSubmission) : VoucherSubmissionResult(), Parcelable
+
+ @Parcelize
+ object InvalidVoucher : VoucherSubmissionResult(), Parcelable
+
+ @Parcelize
+ object VoucherAlreadyUsed : VoucherSubmissionResult(), Parcelable
+
+ @Parcelize
+ object RpcError : VoucherSubmissionResult(), Parcelable
+
+ @Parcelize
+ object OtherError : VoucherSubmissionResult(), Parcelable
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt
index f251f39340..188f75a0ea 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt
@@ -47,6 +47,7 @@ class ServiceEndpoint(
val locationInfoCache = LocationInfoCache(this)
val relayListListener = RelayListListener(this)
val splitTunneling = SplitTunneling(SplitTunnelingPersistence(context), this)
+ val voucherRedeemer = VoucherRedeemer(this)
init {
dispatcher.registerHandler(Request.RegisterListener::class) { request ->
@@ -68,6 +69,7 @@ class ServiceEndpoint(
relayListListener.onDestroy()
settingsListener.onDestroy()
splitTunneling.onDestroy()
+ voucherRedeemer.onDestroy()
}
internal fun sendEvent(event: Event) {
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/VoucherRedeemer.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/VoucherRedeemer.kt
new file mode 100644
index 0000000000..6b83b0d333
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/VoucherRedeemer.kt
@@ -0,0 +1,40 @@
+package net.mullvad.mullvadvpn.service.endpoint
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.ClosedReceiveChannelException
+import kotlinx.coroutines.channels.actor
+import kotlinx.coroutines.channels.sendBlocking
+import net.mullvad.mullvadvpn.ipc.Event
+import net.mullvad.mullvadvpn.ipc.Request
+import net.mullvad.mullvadvpn.model.VoucherSubmissionResult
+
+class VoucherRedeemer(private val endpoint: ServiceEndpoint) {
+ private val daemon
+ get() = endpoint.intermittentDaemon
+
+ private val voucherChannel = spawnActor()
+
+ init {
+ endpoint.dispatcher.registerHandler(Request.SubmitVoucher::class) { request ->
+ voucherChannel.sendBlocking(request.voucher)
+ }
+ }
+
+ fun onDestroy() {
+ voucherChannel.close()
+ }
+
+ private fun spawnActor() = GlobalScope.actor<String>(Dispatchers.Default, Channel.UNLIMITED) {
+ try {
+ for (voucher in channel) {
+ val result = daemon.await().submitVoucher(voucher)
+
+ endpoint.sendEvent(Event.VoucherSubmissionResult(voucher, result))
+ }
+ } catch (exception: ClosedReceiveChannelException) {
+ // Voucher channel was closed, stop the actor
+ }
+ }
+}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/RedeemVoucherDialogFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/RedeemVoucherDialogFragment.kt
index e5936a1ffb..41cb29498b 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/RedeemVoucherDialogFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/RedeemVoucherDialogFragment.kt
@@ -15,8 +15,8 @@ import android.widget.TextView
import androidx.fragment.app.DialogFragment
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.model.VoucherSubmissionResult
-import net.mullvad.mullvadvpn.service.MullvadDaemon
import net.mullvad.mullvadvpn.ui.serviceconnection.AccountCache
+import net.mullvad.mullvadvpn.ui.serviceconnection.VoucherRedeemer
import net.mullvad.mullvadvpn.ui.widget.Button
import net.mullvad.mullvadvpn.util.JobTracker
import net.mullvad.mullvadvpn.util.SegmentedInputFormatter
@@ -33,14 +33,8 @@ class RedeemVoucherDialogFragment : DialogFragment() {
private var accountCache: AccountCache? = null
private var accountExpiry: DateTime? = null
- private var accountExpiryListener: Int? = null
private var redeemButton: Button? = null
-
- private var daemon: MullvadDaemon? = null
- set(value) {
- field = value
- updateRedeemButton()
- }
+ private var voucherRedeemer: VoucherRedeemer? = null
private var voucherInputIsValid = false
set(value) {
@@ -54,8 +48,6 @@ class RedeemVoucherDialogFragment : DialogFragment() {
parentActivity = context as MainActivity
parentActivity.serviceNotifier.subscribe(this) { connection ->
- daemon = connection?.daemon
-
accountCache?.onAccountExpiryChange?.unsubscribe(this@RedeemVoucherDialogFragment)
accountCache = connection?.accountCache?.apply {
@@ -64,6 +56,10 @@ class RedeemVoucherDialogFragment : DialogFragment() {
accountExpiry = newAccountExpiry
}
}
+
+ voucherRedeemer = connection?.voucherRedeemer
+
+ updateRedeemButton()
}
}
@@ -126,25 +122,19 @@ class RedeemVoucherDialogFragment : DialogFragment() {
override fun onDetach() {
parentActivity.serviceNotifier.unsubscribe(this)
- accountExpiryListener?.let { id ->
- accountCache?.onAccountExpiryChange?.unsubscribe(id)
- }
-
super.onDetach()
}
private fun updateRedeemButton() {
redeemButton?.apply {
- setEnabled(voucherInputIsValid && daemon != null)
+ setEnabled(voucherInputIsValid && voucherRedeemer != null)
}
}
private suspend fun submitVoucher() {
errorMessage.visibility = View.INVISIBLE
- val result = jobTracker.runOnBackground {
- daemon?.submitVoucher(voucherInput.text.toString())
- }
+ val result = voucherRedeemer?.submit(voucherInput.text.toString())
when (result) {
is VoucherSubmissionResult.Ok -> handleAddedTime(result.submission.timeAdded)
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt
index 3034b64073..b17db68b34 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt
@@ -43,6 +43,7 @@ class ServiceConnection(
val splitTunneling = get<SplitTunneling>(
parameters = { parametersOf(service.messenger, dispatcher) }
)
+ val voucherRedeemer = VoucherRedeemer(service.messenger, dispatcher)
val vpnPermission = VpnPermission(service.messenger)
val appVersionInfoCache = AppVersionInfoCache(dispatcher, settingsListener)
@@ -67,6 +68,7 @@ class ServiceConnection(
keyStatusListener.onDestroy()
locationInfoCache.onDestroy()
settingsListener.onDestroy()
+ voucherRedeemer.onDestroy()
appVersionInfoCache.onDestroy()
customDns.onDestroy()
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/VoucherRedeemer.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/VoucherRedeemer.kt
new file mode 100644
index 0000000000..d2378100ea
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/VoucherRedeemer.kt
@@ -0,0 +1,43 @@
+package net.mullvad.mullvadvpn.ui.serviceconnection
+
+import android.os.Messenger
+import kotlinx.coroutines.CompletableDeferred
+import net.mullvad.mullvadvpn.ipc.Event
+import net.mullvad.mullvadvpn.ipc.MessageDispatcher
+import net.mullvad.mullvadvpn.ipc.Request
+import net.mullvad.mullvadvpn.model.VoucherSubmissionResult
+
+class VoucherRedeemer(val connection: Messenger, eventDispatcher: MessageDispatcher<Event>) {
+ private val activeSubmissions =
+ mutableMapOf<String, CompletableDeferred<VoucherSubmissionResult>>()
+
+ init {
+ eventDispatcher.registerHandler(Event.VoucherSubmissionResult::class) { event ->
+ synchronized(this@VoucherRedeemer) {
+ activeSubmissions.remove(event.voucher)?.complete(event.result)
+ }
+ }
+ }
+
+ suspend fun submit(voucher: String): VoucherSubmissionResult {
+ val result = CompletableDeferred<VoucherSubmissionResult>()
+
+ synchronized(this) {
+ activeSubmissions.put(voucher, result)
+ }
+
+ connection.send(Request.SubmitVoucher(voucher).message)
+
+ return result.await()
+ }
+
+ fun onDestroy() {
+ synchronized(this) {
+ for ((_, submission) in activeSubmissions) {
+ submission.cancel()
+ }
+
+ activeSubmissions.clear()
+ }
+ }
+}