mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-05-08 09:18:39 +01:00
Register backupIds for all users.
This commit is contained in:
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.thoughtcrime.securesms.jobs
|
||||||
|
|
||||||
|
import org.signal.core.util.logging.Log
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||||
|
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
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
|
import org.whispersystems.signalservice.api.NetworkResult
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserves backupIds for both text+media. The intention is that every registered user should be doing this, so it should happen post-registration
|
||||||
|
* (as well as in a migration for pre-existing users).
|
||||||
|
*
|
||||||
|
* Calling this repeatedly is a no-op from the server's perspective, so no need to be careful around retries or anything.
|
||||||
|
*/
|
||||||
|
class ArchiveBackupIdReservationJob private constructor(parameters: Parameters) : Job(parameters) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TAG = Log.tag(ArchiveBackupIdReservationJob::class)
|
||||||
|
|
||||||
|
const val KEY = "ArchiveBackupIdReservationJob"
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() : this(
|
||||||
|
Parameters.Builder()
|
||||||
|
.setQueue("ArchiveBackupIdReservationJob")
|
||||||
|
.addConstraint(NetworkConstraint.KEY)
|
||||||
|
.setLifespan(Parameters.IMMORTAL)
|
||||||
|
.setMaxAttempts(Parameters.UNLIMITED)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun serialize(): ByteArray? = null
|
||||||
|
|
||||||
|
override fun getFactoryKey(): String = KEY
|
||||||
|
|
||||||
|
override fun run(): Result {
|
||||||
|
if (!SignalStore.account.isRegistered) {
|
||||||
|
Log.w(TAG, "Not registered. Skipping.")
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TextSecurePreferences.isUnauthorizedReceived(context)) {
|
||||||
|
Log.w(TAG, "Not authorized. Skipping.")
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (val result = BackupRepository.triggerBackupIdReservation()) {
|
||||||
|
is NetworkResult.Success -> Result.success()
|
||||||
|
is NetworkResult.NetworkError -> Result.retry(defaultBackoff())
|
||||||
|
is NetworkResult.ApplicationError -> Result.fatalFailure(RuntimeException(result.throwable))
|
||||||
|
is NetworkResult.StatusCodeError -> {
|
||||||
|
when (result.code) {
|
||||||
|
429 -> Result.retry(result.retryAfter()?.inWholeMilliseconds ?: defaultBackoff())
|
||||||
|
else -> {
|
||||||
|
Log.w(TAG, "Failed to reserve backupId with status: ${result.code}. This should only happen on a malformed request or server error. Reducing backoff interval to be safe.")
|
||||||
|
Result.retry(RemoteConfig.serverErrorMaxBackoff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure() = Unit
|
||||||
|
|
||||||
|
class Factory : Job.Factory<ArchiveBackupIdReservationJob> {
|
||||||
|
override fun create(parameters: Parameters, data: ByteArray?): ArchiveBackupIdReservationJob {
|
||||||
|
return ArchiveBackupIdReservationJob(parameters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,6 +47,7 @@ import org.thoughtcrime.securesms.migrations.AccountConsistencyMigrationJob;
|
|||||||
import org.thoughtcrime.securesms.migrations.AccountRecordMigrationJob;
|
import org.thoughtcrime.securesms.migrations.AccountRecordMigrationJob;
|
||||||
import org.thoughtcrime.securesms.migrations.AepMigrationJob;
|
import org.thoughtcrime.securesms.migrations.AepMigrationJob;
|
||||||
import org.thoughtcrime.securesms.migrations.ApplyUnknownFieldsToSelfMigrationJob;
|
import org.thoughtcrime.securesms.migrations.ApplyUnknownFieldsToSelfMigrationJob;
|
||||||
|
import org.thoughtcrime.securesms.migrations.ArchiveBackupIdReservationMigrationJob;
|
||||||
import org.thoughtcrime.securesms.migrations.AttachmentCleanupMigrationJob;
|
import org.thoughtcrime.securesms.migrations.AttachmentCleanupMigrationJob;
|
||||||
import org.thoughtcrime.securesms.migrations.AttachmentHashBackfillMigrationJob;
|
import org.thoughtcrime.securesms.migrations.AttachmentHashBackfillMigrationJob;
|
||||||
import org.thoughtcrime.securesms.migrations.AttributesMigrationJob;
|
import org.thoughtcrime.securesms.migrations.AttributesMigrationJob;
|
||||||
@@ -125,6 +126,7 @@ public final class JobManagerFactories {
|
|||||||
put(ApkUpdateJob.KEY, new ApkUpdateJob.Factory());
|
put(ApkUpdateJob.KEY, new ApkUpdateJob.Factory());
|
||||||
put(ArchiveAttachmentBackfillJob.KEY, new ArchiveAttachmentBackfillJob.Factory());
|
put(ArchiveAttachmentBackfillJob.KEY, new ArchiveAttachmentBackfillJob.Factory());
|
||||||
put(ArchiveAttachmentReconciliationJob.KEY, new ArchiveAttachmentReconciliationJob.Factory());
|
put(ArchiveAttachmentReconciliationJob.KEY, new ArchiveAttachmentReconciliationJob.Factory());
|
||||||
|
put(ArchiveBackupIdReservationJob.KEY, new ArchiveBackupIdReservationJob.Factory());
|
||||||
put(ArchiveCommitAttachmentDeletesJob.KEY, new ArchiveCommitAttachmentDeletesJob.Factory());
|
put(ArchiveCommitAttachmentDeletesJob.KEY, new ArchiveCommitAttachmentDeletesJob.Factory());
|
||||||
put(ArchiveThumbnailUploadJob.KEY, new ArchiveThumbnailUploadJob.Factory());
|
put(ArchiveThumbnailUploadJob.KEY, new ArchiveThumbnailUploadJob.Factory());
|
||||||
put(AttachmentCompressionJob.KEY, new AttachmentCompressionJob.Factory());
|
put(AttachmentCompressionJob.KEY, new AttachmentCompressionJob.Factory());
|
||||||
@@ -284,6 +286,7 @@ public final class JobManagerFactories {
|
|||||||
put(AccountRecordMigrationJob.KEY, new AccountRecordMigrationJob.Factory());
|
put(AccountRecordMigrationJob.KEY, new AccountRecordMigrationJob.Factory());
|
||||||
put(AepMigrationJob.KEY, new AepMigrationJob.Factory());
|
put(AepMigrationJob.KEY, new AepMigrationJob.Factory());
|
||||||
put(ApplyUnknownFieldsToSelfMigrationJob.KEY, new ApplyUnknownFieldsToSelfMigrationJob.Factory());
|
put(ApplyUnknownFieldsToSelfMigrationJob.KEY, new ApplyUnknownFieldsToSelfMigrationJob.Factory());
|
||||||
|
put(ArchiveBackupIdReservationMigrationJob.KEY, new ArchiveBackupIdReservationMigrationJob.Factory());
|
||||||
put(AttachmentCleanupMigrationJob.KEY, new AttachmentCleanupMigrationJob.Factory());
|
put(AttachmentCleanupMigrationJob.KEY, new AttachmentCleanupMigrationJob.Factory());
|
||||||
put(AttachmentHashBackfillMigrationJob.KEY, new AttachmentHashBackfillMigrationJob.Factory());
|
put(AttachmentHashBackfillMigrationJob.KEY, new AttachmentHashBackfillMigrationJob.Factory());
|
||||||
put(AttributesMigrationJob.KEY, new AttributesMigrationJob.Factory());
|
put(AttributesMigrationJob.KEY, new AttributesMigrationJob.Factory());
|
||||||
|
|||||||
@@ -186,9 +186,10 @@ public class ApplicationMigrations {
|
|||||||
static final int STORAGE_LOCAL_UNKNOWNS_FIX_2 = 142;
|
static final int STORAGE_LOCAL_UNKNOWNS_FIX_2 = 142;
|
||||||
static final int SVR2_ENCLAVE_UPDATE_4 = 143;
|
static final int SVR2_ENCLAVE_UPDATE_4 = 143;
|
||||||
static final int RESET_ARCHIVE_TIER = 144;
|
static final int RESET_ARCHIVE_TIER = 144;
|
||||||
|
static final int ARCHIVE_BACKUP_ID = 145;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int CURRENT_VERSION = 144;
|
public static final int CURRENT_VERSION = 145;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
|
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
|
||||||
@@ -859,6 +860,10 @@ public class ApplicationMigrations {
|
|||||||
jobs.put(Version.RESET_ARCHIVE_TIER, new ResetArchiveTierMigrationJob());
|
jobs.put(Version.RESET_ARCHIVE_TIER, new ResetArchiveTierMigrationJob());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lastSeenVersion < Version.ARCHIVE_BACKUP_ID) {
|
||||||
|
jobs.put(Version.ARCHIVE_BACKUP_ID, new ArchiveBackupIdReservationMigrationJob());
|
||||||
|
}
|
||||||
|
|
||||||
return jobs;
|
return jobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
package org.thoughtcrime.securesms.migrations
|
||||||
|
|
||||||
|
import org.signal.core.util.logging.Log
|
||||||
|
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||||
|
import org.thoughtcrime.securesms.jobmanager.Job
|
||||||
|
import org.thoughtcrime.securesms.jobs.ArchiveBackupIdReservationJob
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple migration job to just enqueue a [ArchiveBackupIdReservationJob] to ensure that all users reserve a backupId.
|
||||||
|
*/
|
||||||
|
internal class ArchiveBackupIdReservationMigrationJob(
|
||||||
|
parameters: Parameters = Parameters.Builder().build()
|
||||||
|
) : MigrationJob(parameters) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val TAG = Log.tag(ArchiveBackupIdReservationMigrationJob::class.java)
|
||||||
|
const val KEY = "ArchiveBackupIdReservationMigrationJob"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFactoryKey(): String = KEY
|
||||||
|
|
||||||
|
override fun isUiBlocking(): Boolean = false
|
||||||
|
|
||||||
|
override fun performMigration() {
|
||||||
|
AppDependencies.jobManager.add(ArchiveBackupIdReservationJob())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRetry(e: Exception): Boolean = false
|
||||||
|
|
||||||
|
class Factory : Job.Factory<ArchiveBackupIdReservationMigrationJob> {
|
||||||
|
override fun create(parameters: Parameters, serializedData: ByteArray?): ArchiveBackupIdReservationMigrationJob {
|
||||||
|
return ArchiveBackupIdReservationMigrationJob(parameters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.registration.util;
|
|||||||
|
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
||||||
|
import org.thoughtcrime.securesms.jobs.ArchiveBackupIdReservationJob;
|
||||||
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
|
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
|
||||||
import org.thoughtcrime.securesms.jobs.EmojiSearchIndexDownloadJob;
|
import org.thoughtcrime.securesms.jobs.EmojiSearchIndexDownloadJob;
|
||||||
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
||||||
@@ -53,6 +54,8 @@ public final class RegistrationUtil {
|
|||||||
SignalStore.emoji().clearSearchIndexMetadata();
|
SignalStore.emoji().clearSearchIndexMetadata();
|
||||||
EmojiSearchIndexDownloadJob.scheduleImmediately();
|
EmojiSearchIndexDownloadJob.scheduleImmediately();
|
||||||
|
|
||||||
|
AppDependencies.getJobManager().add(new ArchiveBackupIdReservationJob());
|
||||||
|
|
||||||
} else if (!SignalStore.registration().isRegistrationComplete()) {
|
} else if (!SignalStore.registration().isRegistrationComplete()) {
|
||||||
Log.i(TAG, "Registration is not yet complete.", new Throwable());
|
Log.i(TAG, "Registration is not yet complete.", new Throwable());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -423,15 +423,6 @@ public class TextSecurePreferences {
|
|||||||
setBooleanPreference(context, TYPING_INDICATORS, enabled);
|
setBooleanPreference(context, TYPING_INDICATORS, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Only kept so that we can avoid showing the megaphone for the new link previews setting
|
|
||||||
* ({@link SettingsValues#isLinkPreviewsEnabled()}) when users upgrade. This can be removed after
|
|
||||||
* we stop showing the link previews megaphone.
|
|
||||||
*/
|
|
||||||
public static boolean wereLinkPreviewsEnabled(Context context) {
|
|
||||||
return getBooleanPreference(context, LINK_PREVIEWS, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getNotificationPriority(Context context) {
|
public static int getNotificationPriority(Context context) {
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(getStringPreference(context, NOTIFICATION_PRIORITY_PREF, String.valueOf(NotificationCompat.PRIORITY_HIGH)));
|
return Integer.parseInt(getStringPreference(context, NOTIFICATION_PRIORITY_PREF, String.valueOf(NotificationCompat.PRIORITY_HIGH)));
|
||||||
|
|||||||
Reference in New Issue
Block a user