Add new subscription multi device sync message.

This commit is contained in:
Alex Hart 2021-11-30 13:59:25 -04:00 committed by Greyson Parrelli
parent 9f9bf3c604
commit ae1f834619
10 changed files with 99 additions and 6 deletions

View file

@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.DonationE
import org.thoughtcrime.securesms.components.settings.app.subscription.DonationExceptions
import org.thoughtcrime.securesms.components.settings.app.subscription.DonationPaymentRepository
import org.thoughtcrime.securesms.components.settings.app.subscription.SubscriptionsRepository
import org.thoughtcrime.securesms.jobs.MultiDeviceSubscriptionSyncRequestJob
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.subscription.LevelUpdate
import org.thoughtcrime.securesms.subscription.Subscriber
@ -169,6 +170,7 @@ class SubscribeViewModel(
SignalStore.donationsValues().setLastEndOfPeriod(0L)
SignalStore.donationsValues().clearLevelOperations()
SignalStore.donationsValues().shouldCancelSubscriptionBeforeNextSubscribeAttempt = false
MultiDeviceSubscriptionSyncRequestJob.enqueue()
}
} else {
Completable.complete()
@ -185,6 +187,7 @@ class SubscribeViewModel(
SignalStore.donationsValues().clearLevelOperations()
SignalStore.donationsValues().markUserManuallyCancelled()
refreshActiveSubscription()
MultiDeviceSubscriptionSyncRequestJob.enqueue()
store.update { it.copy(stage = SubscribeState.Stage.READY) }
},
onError = { throwable ->

View file

@ -111,6 +111,7 @@ public final class JobManagerFactories {
put(MultiDeviceStickerPackOperationJob.KEY, new MultiDeviceStickerPackOperationJob.Factory());
put(MultiDeviceStickerPackSyncJob.KEY, new MultiDeviceStickerPackSyncJob.Factory());
put(MultiDeviceStorageSyncRequestJob.KEY, new MultiDeviceStorageSyncRequestJob.Factory());
put(MultiDeviceSubscriptionSyncRequestJob.KEY, new MultiDeviceSubscriptionSyncRequestJob.Factory());
put(MultiDeviceVerifiedUpdateJob.KEY, new MultiDeviceVerifiedUpdateJob.Factory());
put(MultiDeviceViewOnceOpenJob.KEY, new MultiDeviceViewOnceOpenJob.Factory());
put(MultiDeviceViewedUpdateJob.KEY, new MultiDeviceViewedUpdateJob.Factory());

View file

@ -0,0 +1,76 @@
package org.thoughtcrime.securesms.jobs
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.jobmanager.Data
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.net.NotPushRegisteredException
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException
/**
* Sends a sync message to linked devices to notify them to refresh subscription status.
*/
class MultiDeviceSubscriptionSyncRequestJob private constructor(parameters: Parameters) : BaseJob(parameters) {
companion object {
const val KEY = "MultiDeviceSubscriptionSyncRequestJob"
private val TAG = Log.tag(MultiDeviceSubscriptionSyncRequestJob::class.java)
@JvmStatic
fun enqueue() {
val job = MultiDeviceSubscriptionSyncRequestJob(
Parameters.Builder()
.setQueue("MultiDeviceSubscriptionSyncRequestJob")
.setMaxInstancesForFactory(2)
.addConstraint(NetworkConstraint.KEY)
.setMaxAttempts(10)
.build()
)
ApplicationDependencies.getJobManager().add(job)
}
}
override fun serialize(): Data = Data.EMPTY
override fun getFactoryKey(): String = KEY
override fun onFailure() {
Log.w(TAG, "Did not succeed!")
}
override fun onRun() {
if (!Recipient.self().isRegistered) {
throw NotPushRegisteredException()
}
if (!TextSecurePreferences.isMultiDevice(context)) {
Log.i(TAG, "Not multi device, aborting...")
return
}
val messageSender = ApplicationDependencies.getSignalServiceMessageSender()
messageSender.sendSyncMessage(
SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.SUBSCRIPTION_STATUS),
UnidentifiedAccessUtil.getAccessForSync(context)
)
}
override fun onShouldRetry(e: Exception): Boolean {
return e is PushNetworkException && e !is ServerRejectedException
}
class Factory : Job.Factory<MultiDeviceSubscriptionSyncRequestJob> {
override fun create(parameters: Parameters, data: Data): MultiDeviceSubscriptionSyncRequestJob {
return MultiDeviceSubscriptionSyncRequestJob(parameters)
}
}
}

View file

@ -218,6 +218,7 @@ public class RefreshOwnProfileJob extends BaseJob {
if (!SignalStore.donationsValues().isUserManuallyCancelled()) {
Log.d(TAG, "Detected an unexpected subscription expiry.", true);
MultiDeviceSubscriptionSyncRequestJob.enqueue();
SignalStore.donationsValues().setShouldCancelSubscriptionBeforeNextSubscribeAttempt(true);
}
} else if (!remoteHasBoostBadges && localHasBoostBadges) {

View file

@ -104,6 +104,7 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob {
public void onFailure() {
DonorBadgeNotifications.RedemptionFailed.INSTANCE.show(context);
SignalStore.donationsValues().markSubscriptionRedemptionFailed();
MultiDeviceSubscriptionSyncRequestJob.enqueue();
}
@Override
@ -128,6 +129,7 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob {
} else {
Log.i(TAG, "Recording end of period from active subscription.", true);
SignalStore.donationsValues().setLastEndOfPeriod(subscription.getEndOfCurrentPeriod());
MultiDeviceSubscriptionSyncRequestJob.enqueue();
}
if (requestContext == null) {
@ -240,6 +242,7 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob {
private void onPaymentFailure() {
SignalStore.donationsValues().setShouldCancelSubscriptionBeforeNextSubscribeAttempt(true);
setOutputData(new Data.Builder().putBoolean(DonationReceiptRedemptionJob.INPUT_PAYMENT_FAILURE, true).build());
MultiDeviceSubscriptionSyncRequestJob.enqueue();
}
/**

View file

@ -967,6 +967,9 @@ public final class MessageContentProcessor {
case STORAGE_MANIFEST:
StorageSyncHelper.scheduleSyncForDataChange();
break;
case SUBSCRIPTION_STATUS:
warn(TAG, "Dropping subscription status fetch message.");
break;
default:
warn(TAG, "Received a fetch message for an unknown type.");
}

View file

@ -1214,6 +1214,9 @@ public class SignalServiceMessageSender {
case STORAGE_MANIFEST:
fetchMessage.setType(SyncMessage.FetchLatest.Type.STORAGE_MANIFEST);
break;
case SUBSCRIPTION_STATUS:
fetchMessage.setType(SyncMessage.FetchLatest.Type.SUBSCRIPTION_STATUS);
break;
default:
Log.w(TAG, "Unknown fetch type!");
break;

View file

@ -741,8 +741,9 @@ public final class SignalServiceContent {
if (content.hasFetchLatest() && content.getFetchLatest().hasType()) {
switch (content.getFetchLatest().getType()) {
case LOCAL_PROFILE: return SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.LOCAL_PROFILE);
case STORAGE_MANIFEST: return SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.STORAGE_MANIFEST);
case LOCAL_PROFILE: return SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.LOCAL_PROFILE);
case STORAGE_MANIFEST: return SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.STORAGE_MANIFEST);
case SUBSCRIPTION_STATUS: return SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.SUBSCRIPTION_STATUS);
}
}

View file

@ -434,6 +434,7 @@ public class SignalServiceSyncMessage {
public enum FetchType {
LOCAL_PROFILE,
STORAGE_MANIFEST
STORAGE_MANIFEST,
SUBSCRIPTION_STATUS
}
}

View file

@ -447,9 +447,10 @@ message SyncMessage {
message FetchLatest {
enum Type {
UNKNOWN = 0;
LOCAL_PROFILE = 1;
STORAGE_MANIFEST = 2;
UNKNOWN = 0;
LOCAL_PROFILE = 1;
STORAGE_MANIFEST = 2;
SUBSCRIPTION_STATUS = 3;
}
optional Type type = 1;