mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-03-02 07:23:38 +00:00
Add BackupSubscriptionCheckJob.
This commit is contained in:
committed by
Greyson Parrelli
parent
24209756e3
commit
5bc8435d25
@@ -112,20 +112,6 @@ object BackupRepository {
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun canAccessRemoteBackupSettings(): Boolean {
|
||||
// TODO [message-backups]
|
||||
|
||||
// We need to check whether the user can access remote backup settings.
|
||||
|
||||
// 1. Do they have a receipt they need to be able to view?
|
||||
// 2. Do they have a backup they need to be able to manage?
|
||||
|
||||
// The easy thing to do here would actually be to set a ui hint.
|
||||
|
||||
return SignalStore.backup.areBackupsEnabled
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun turnOffAndDeleteBackup() {
|
||||
RecurringInAppPaymentRepository.cancelActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP)
|
||||
|
||||
@@ -260,7 +260,9 @@ class MessageBackupsFlowViewModel(
|
||||
)
|
||||
)
|
||||
|
||||
Log.d(TAG, "Enqueueing InAppPaymentPurchaseTokenJob chain.")
|
||||
Log.d(TAG, "Enabling backups and enqueueing InAppPaymentPurchaseTokenJob chain.")
|
||||
SignalStore.backup.areBackupsEnabled = true
|
||||
SignalStore.uiHints.markHasEverEnabledRemoteBackups()
|
||||
InAppPaymentPurchaseTokenJob.createJobChain(inAppPayment).enqueue()
|
||||
}
|
||||
|
||||
|
||||
@@ -178,10 +178,14 @@ object InAppPaymentsRepository {
|
||||
return when (inAppPayment.type) {
|
||||
InAppPaymentType.UNKNOWN -> error("Unsupported type UNKNOWN.")
|
||||
InAppPaymentType.ONE_TIME_GIFT, InAppPaymentType.ONE_TIME_DONATION -> "$JOB_PREFIX${inAppPayment.id.serialize()}"
|
||||
InAppPaymentType.RECURRING_DONATION, InAppPaymentType.RECURRING_BACKUP -> "$JOB_PREFIX${inAppPayment.type.code}"
|
||||
InAppPaymentType.RECURRING_DONATION, InAppPaymentType.RECURRING_BACKUP -> getRecurringJobQueueKey(inAppPayment.type)
|
||||
}
|
||||
}
|
||||
|
||||
fun getRecurringJobQueueKey(inAppPaymentType: InAppPaymentType): String {
|
||||
return "$JOB_PREFIX${inAppPaymentType.code}"
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a duration to utilize for jobs tied to different payment methods. For long running bank transfers, we need to
|
||||
* allow extra time for completion.
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.jobs
|
||||
|
||||
import org.signal.core.util.billing.BillingPurchaseResult
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentsRepository
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.RecurringInAppPaymentRepository
|
||||
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.CoroutineJob
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
|
||||
/**
|
||||
* Checks and rectifies state pertaining to backups subscriptions.
|
||||
*/
|
||||
class BackupSubscriptionCheckJob private constructor(parameters: Parameters) : CoroutineJob(parameters) {
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(BackupSubscriptionCheckJob::class)
|
||||
|
||||
const val KEY = "BackupSubscriptionCheckJob"
|
||||
|
||||
fun create(): BackupSubscriptionCheckJob {
|
||||
return BackupSubscriptionCheckJob(
|
||||
Parameters.Builder()
|
||||
.setQueue(InAppPaymentsRepository.getRecurringJobQueueKey(InAppPaymentType.RECURRING_BACKUP))
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setMaxAttempts(Parameters.UNLIMITED)
|
||||
.setMaxInstancesForFactory(1)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun doRun(): Result {
|
||||
if (!RemoteConfig.messageBackups) {
|
||||
Log.i(TAG, "Message backups are not enabled. Exiting.")
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (!AppDependencies.billingApi.isApiAvailable()) {
|
||||
Log.i(TAG, "Google Play Billing API is not available on this device. Exiting.")
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
val purchase: BillingPurchaseResult = AppDependencies.billingApi.queryPurchases()
|
||||
val hasActivePurchase = purchase is BillingPurchaseResult.Success && purchase.isAcknowledged && purchase.isWithinTheLastMonth()
|
||||
|
||||
val subscriberId = InAppPaymentsRepository.getSubscriber(InAppPaymentSubscriberRecord.Type.BACKUP)
|
||||
if (subscriberId == null && hasActivePurchase) {
|
||||
Log.w(TAG, "User has active Google Play Billing purchase but no subscriber id! User should cancel backup and resubscribe.")
|
||||
updateLocalState(null)
|
||||
// TODO [message-backups] Set UI flag hint here to launch sheet (designs pending)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
val tier = SignalStore.backup.backupTier
|
||||
if (subscriberId == null && tier == MessageBackupTier.PAID) {
|
||||
Log.w(TAG, "User has no subscriber id but PAID backup tier. Reverting to no backup tier and informing the user.")
|
||||
updateLocalState(null)
|
||||
// TODO [message-backups] Set UI flag hint here to launch sheet (designs pending)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
val activeSubscription = RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP).getOrNull()
|
||||
if (activeSubscription?.isActive == true && tier != MessageBackupTier.PAID) {
|
||||
Log.w(TAG, "User has an active subscription but no backup tier. Setting to PAID and enabling backups.")
|
||||
updateLocalState(MessageBackupTier.PAID)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (activeSubscription?.isActive != true && tier == MessageBackupTier.PAID) {
|
||||
Log.w(TAG, "User subscription is inactive or does not exist. Clearing backup tier.")
|
||||
// TODO [message-backups] Set UI hint?
|
||||
updateLocalState(null)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (activeSubscription?.isActive != true && hasActivePurchase) {
|
||||
Log.w(TAG, "User subscription is inactive but user has a recent purchase. Clearing backup tier.")
|
||||
// TODO [message-backups] Set UI hint?
|
||||
updateLocalState(null)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private fun updateLocalState(backupTier: MessageBackupTier?) {
|
||||
synchronized(InAppPaymentSubscriberRecord.Type.BACKUP) {
|
||||
SignalStore.backup.backupTier = backupTier
|
||||
}
|
||||
}
|
||||
|
||||
override fun serialize(): ByteArray? = null
|
||||
|
||||
override fun getFactoryKey(): String = KEY
|
||||
|
||||
override fun onFailure() = Unit
|
||||
|
||||
class Factory : Job.Factory<BackupSubscriptionCheckJob> {
|
||||
override fun create(parameters: Parameters, serializedData: ByteArray?): BackupSubscriptionCheckJob {
|
||||
return BackupSubscriptionCheckJob(parameters)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -255,10 +255,8 @@ class InAppPaymentRedemptionJob private constructor(
|
||||
)
|
||||
|
||||
if (inAppPayment.type == InAppPaymentType.RECURRING_BACKUP) {
|
||||
Log.i(TAG, "Enabling backups and setting backup tier to PAID", true)
|
||||
SignalStore.backup.areBackupsEnabled = true
|
||||
Log.i(TAG, "Setting backup tier to PAID", true)
|
||||
SignalStore.backup.backupTier = MessageBackupTier.PAID
|
||||
SignalStore.uiHints.markHasEverEnabledRemoteBackups()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ public final class JobManagerFactories {
|
||||
put(BackupRestoreJob.KEY, new BackupRestoreJob.Factory());
|
||||
put(BackupRestoreMediaJob.KEY, new BackupRestoreMediaJob.Factory());
|
||||
put(BoostReceiptRequestResponseJob.KEY, new BoostReceiptRequestResponseJob.Factory());
|
||||
put(BackupSubscriptionCheckJob.KEY, new BackupSubscriptionCheckJob.Factory());
|
||||
put(BuildExpirationConfirmationJob.KEY, new BuildExpirationConfirmationJob.Factory());
|
||||
put(CallLinkPeekJob.KEY, new CallLinkPeekJob.Factory());
|
||||
put(CallLinkUpdateSendJob.KEY, new CallLinkUpdateSendJob.Factory());
|
||||
|
||||
Reference in New Issue
Block a user