Fix message backup checkout e2e tests.

This commit is contained in:
Alex Hart
2025-03-13 11:11:24 -03:00
committed by Cody Henthorne
parent fff74256b5
commit 8d53c1b384
7 changed files with 529 additions and 158 deletions

View File

@@ -10,8 +10,6 @@ import android.os.Environment
import android.os.StatFs
import androidx.annotation.Discouraged
import androidx.annotation.WorkerThread
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okio.ByteString
import okio.ByteString.Companion.toByteString
import org.greenrobot.eventbus.EventBus
@@ -305,9 +303,7 @@ object BackupRepository {
}
val paidType = try {
withContext(Dispatchers.IO) {
getPaidType()
}
getPaidType()
} catch (e: IOException) {
Log.w(TAG, "Failed to retrieve paid type.", e)
return false
@@ -1415,7 +1411,8 @@ object BackupRepository {
}
}
private suspend fun getFreeType(): MessageBackupsType.Free {
@WorkerThread
private fun getFreeType(): MessageBackupsType.Free {
val config = getSubscriptionsConfiguration()
return MessageBackupsType.Free(
@@ -1426,6 +1423,7 @@ object BackupRepository {
private suspend fun getPaidType(): MessageBackupsType.Paid? {
val config = getSubscriptionsConfiguration()
val product = AppDependencies.billingApi.queryProduct() ?: return null
val backupLevelConfiguration = config.backupConfiguration.backupLevelConfigurationMap[SubscriptionsConfiguration.BACKUPS_LEVEL] ?: return null
return MessageBackupsType.Paid(
@@ -1435,12 +1433,11 @@ object BackupRepository {
)
}
private suspend fun getSubscriptionsConfiguration(): SubscriptionsConfiguration {
val serviceResponse = withContext(Dispatchers.IO) {
AppDependencies
.donationsService
.getDonationsConfiguration(Locale.getDefault())
}
@WorkerThread
private fun getSubscriptionsConfiguration(): SubscriptionsConfiguration {
val serviceResponse = AppDependencies
.donationsService
.getDonationsConfiguration(Locale.getDefault())
if (serviceResponse.result.isEmpty) {
if (serviceResponse.applicationError.isPresent) {

View File

@@ -9,7 +9,9 @@ import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.thoughtcrime.securesms.backup.v2.BackupRepository
import org.thoughtcrime.securesms.keyvalue.SignalStore
@@ -25,7 +27,7 @@ object BackupAlertDelegate {
BackupAlertBottomSheet.create(BackupAlert.BackupFailed).show(fragmentManager, null)
} else if (BackupRepository.shouldDisplayCouldNotCompleteBackupSheet()) {
BackupAlertBottomSheet.create(BackupAlert.CouldNotCompleteBackup(daysSinceLastBackup = SignalStore.backup.daysSinceLastBackup)).show(fragmentManager, null)
} else if (BackupRepository.shouldDisplayYourMediaWillBeDeletedTodaySheet()) {
} else if (withContext(Dispatchers.IO) { BackupRepository.shouldDisplayYourMediaWillBeDeletedTodaySheet() }) {
BackupAlertBottomSheet.create(BackupAlert.MediaWillBeDeletedToday).show(fragmentManager, null)
}
}

View File

@@ -8,7 +8,6 @@ package org.thoughtcrime.securesms.backup.v2.ui.subscription
import androidx.annotation.WorkerThread
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.flow.MutableStateFlow
@@ -23,6 +22,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.reactive.asFlow
import kotlinx.coroutines.withContext
import org.signal.core.util.billing.BillingPurchaseResult
import org.signal.core.util.concurrent.SignalDispatchers
import org.signal.core.util.logging.Log
import org.signal.donations.InAppPaymentType
import org.signal.donations.PaymentSourceType
@@ -70,7 +70,7 @@ class MessageBackupsFlowViewModel(
check(SignalStore.backup.backupTier != MessageBackupTier.PAID) { "This screen does not support cancellation or downgrades." }
viewModelScope.launch {
val result = withContext(Dispatchers.IO) {
val result = withContext(SignalDispatchers.IO) {
BackupRepository.triggerBackupIdReservation()
}
@@ -79,20 +79,22 @@ class MessageBackupsFlowViewModel(
internalStateFlow.update { it.copy(paymentReadyState = MessageBackupsFlowState.PaymentReadyState.READY) }
}
result.runOnStatusCodeError {
Log.d(TAG, "Failed to trigger backup id reservation. ($it)")
result.runOnStatusCodeError { code ->
Log.d(TAG, "Failed to trigger backup id reservation. ($code)")
internalStateFlow.update { it.copy(paymentReadyState = MessageBackupsFlowState.PaymentReadyState.FAILED) }
}
}
viewModelScope.launch {
internalStateFlow.update {
it.copy(
availableBackupTypes = BackupRepository.getAvailableBackupsTypes(
if (!RemoteConfig.messageBackups) emptyList() else listOf(MessageBackupTier.FREE, MessageBackupTier.PAID)
)
val availableBackupTypes = withContext(SignalDispatchers.IO) {
BackupRepository.getAvailableBackupsTypes(
if (!RemoteConfig.messageBackups) emptyList() else listOf(MessageBackupTier.FREE, MessageBackupTier.PAID)
)
}
internalStateFlow.update {
it.copy(availableBackupTypes = availableBackupTypes)
}
}
viewModelScope.launch {
@@ -218,7 +220,7 @@ class MessageBackupsFlowViewModel(
check(state.selectedMessageBackupTier == MessageBackupTier.PAID)
check(state.availableBackupTypes.any { it.tier == state.selectedMessageBackupTier })
viewModelScope.launch(Dispatchers.IO) {
viewModelScope.launch(SignalDispatchers.IO) {
internalStateFlow.update { it.copy(inAppPayment = null) }
val paidFiat = AppDependencies.billingApi.queryProduct()!!.price
@@ -265,7 +267,7 @@ class MessageBackupsFlowViewModel(
*/
@OptIn(FlowPreview::class)
private suspend fun handleSuccess(result: BillingPurchaseResult.Success, inAppPaymentId: InAppPaymentTable.InAppPaymentId) {
withContext(Dispatchers.IO) {
withContext(SignalDispatchers.IO) {
Log.d(TAG, "Setting purchase token data on InAppPayment and InAppPaymentSubscriber.")
ensureSubscriberIdForBackups(IAPSubscriptionId.GooglePlayBillingPurchaseToken(result.purchaseToken))
@@ -287,7 +289,7 @@ class MessageBackupsFlowViewModel(
InAppPaymentPurchaseTokenJob.createJobChain(inAppPayment).enqueue()
}
val terminalInAppPayment = withContext(Dispatchers.IO) {
val terminalInAppPayment = withContext(SignalDispatchers.IO) {
Log.d(TAG, "Awaiting completion of job chain for up to 10 seconds.")
InAppPaymentsRepository.observeUpdates(inAppPaymentId).asFlow()
.filter { it.state == InAppPaymentTable.State.END }