Skip to content

Commit

Permalink
Add play purchasing android ipc calls
Browse files Browse the repository at this point in the history
  • Loading branch information
albin-mullvad committed Oct 3, 2023
1 parent f57120d commit 0b263c0
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import kotlinx.parcelize.Parcelize
import net.mullvad.mullvadvpn.model.AccountCreationResult
import net.mullvad.mullvadvpn.model.AccountExpiry
import net.mullvad.mullvadvpn.model.AccountHistory
import net.mullvad.mullvadvpn.model.AppVersionInfo
import net.mullvad.mullvadvpn.model.DeviceListEvent
import net.mullvad.mullvadvpn.model.DeviceState
import net.mullvad.mullvadvpn.model.GeoIpLocation
import net.mullvad.mullvadvpn.model.LoginResult
import net.mullvad.mullvadvpn.model.PlayPurchaseInitResult
import net.mullvad.mullvadvpn.model.PlayPurchaseVerifyResult
import net.mullvad.mullvadvpn.model.RelayList
import net.mullvad.mullvadvpn.model.RemoveDeviceResult
import net.mullvad.mullvadvpn.model.Settings
import net.mullvad.mullvadvpn.model.TunnelState
import net.mullvad.mullvadvpn.model.VoucherSubmissionResult

// Events that can be sent from the service
sealed class Event : Message.EventMessage() {
Expand Down Expand Up @@ -61,6 +61,11 @@ sealed class Event : Message.EventMessage() {
val result: net.mullvad.mullvadvpn.model.VoucherSubmissionResult
) : Event()

@Parcelize data class PlayPurchaseInitResultEvent(val result: PlayPurchaseInitResult) : Event()

@Parcelize
data class PlayPurchaseVerifyResultEvent(val result: PlayPurchaseVerifyResult) : Event()

@Parcelize object VpnPermissionRequest : Event()

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import kotlinx.parcelize.Parcelize
import net.mullvad.mullvadvpn.model.DnsOptions
import net.mullvad.mullvadvpn.model.GeographicLocationConstraint
import net.mullvad.mullvadvpn.model.ObfuscationSettings
import net.mullvad.mullvadvpn.model.PlayPurchase
import net.mullvad.mullvadvpn.model.QuantumResistantState
import net.mullvad.mullvadvpn.model.WireguardConstraints

Expand Down Expand Up @@ -80,6 +81,10 @@ sealed class Request : Message.RequestMessage() {

@Parcelize data class SubmitVoucher(val voucher: String) : Request()

@Parcelize data object InitPlayPurchase : Request()

@Parcelize data class VerifyPlayPurchase(val playPurchase: PlayPurchase) : Request()

@Parcelize data class UnregisterListener(val listenerId: Int) : Request()

@Parcelize data class VpnPermissionResponse(val isGranted: Boolean) : Request()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
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.trySendBlocking
import net.mullvad.mullvadvpn.lib.ipc.Event
import net.mullvad.mullvadvpn.lib.ipc.Request
import net.mullvad.mullvadvpn.model.PlayPurchase

// WIP - adapted copy of VoucherRedeemer
class PlayPurchaseHandler(private val endpoint: ServiceEndpoint) {
private val daemon
get() = endpoint.intermittentDaemon

private val playPurchaseChannel = spawnActor()

init {
endpoint.dispatcher.registerHandler(Request.InitPlayPurchase::class) {
playPurchaseChannel.trySendBlocking(Command.InitPlayPurchase)
}
endpoint.dispatcher.registerHandler(Request.VerifyPlayPurchase::class) { request ->
playPurchaseChannel.trySendBlocking(Command.VerifyPlayPurchase(request.playPurchase))
}
}

fun onDestroy() {
playPurchaseChannel.close()
}

private fun spawnActor() =
GlobalScope.actor<Command>(Dispatchers.Default, Channel.UNLIMITED) {
try {
for (command in channel) {
when (command) {
is Command.InitPlayPurchase -> initializePurchase()
is Command.VerifyPlayPurchase -> verifyPlayPurchase(command.playPurchase)
}
}
} catch (exception: ClosedReceiveChannelException) {
// Channel was closed, stop the actor
}
}

private suspend fun initializePurchase() {
val result = daemon.await().initPlayPurchase()
endpoint.sendEvent(Event.PlayPurchaseInitResultEvent(result))
}

private suspend fun verifyPlayPurchase(playPurchase: PlayPurchase) {
val result = daemon.await().verifyPlayPurchase(playPurchase)
endpoint.sendEvent(Event.PlayPurchaseVerifyResultEvent(result))
}

companion object {
private sealed class Command {
data object InitPlayPurchase : Command()

data class VerifyPlayPurchase(val playPurchase: PlayPurchase) : Command()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class ServiceEndpoint(
val splitTunneling = SplitTunneling(SplitTunnelingPersistence(context), this)
val voucherRedeemer = VoucherRedeemer(this)

private val playPurchaseHandler = PlayPurchaseHandler(this)

private val deviceRepositoryBackend = DaemonDeviceDataSource(this)

init {
Expand Down Expand Up @@ -80,6 +82,7 @@ class ServiceEndpoint(
settingsListener.onDestroy()
splitTunneling.onDestroy()
voucherRedeemer.onDestroy()
playPurchaseHandler.onDestroy()
}

internal fun sendEvent(event: Event) {
Expand Down

0 comments on commit 0b263c0

Please sign in to comment.