kopia lustrzana https://github.com/ryukoposting/Signal-Android
290 wiersze
12 KiB
Java
290 wiersze
12 KiB
Java
package org.thoughtcrime.securesms.migrations;
|
|
|
|
import android.content.Context;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.preference.PreferenceManager;
|
|
|
|
import org.signal.core.util.logging.Log;
|
|
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|
import org.thoughtcrime.securesms.database.AttachmentTable;
|
|
import org.thoughtcrime.securesms.database.MessageTable;
|
|
import org.thoughtcrime.securesms.database.MessageTable.MmsReader;
|
|
import org.thoughtcrime.securesms.database.PushTable;
|
|
import org.thoughtcrime.securesms.database.SignalDatabase;
|
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
|
import org.thoughtcrime.securesms.jobmanager.Data;
|
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
|
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
|
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob;
|
|
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
|
|
import org.thoughtcrime.securesms.jobs.PreKeysSyncJob;
|
|
import org.thoughtcrime.securesms.jobs.PushDecryptMessageJob;
|
|
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
|
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
|
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
|
import org.thoughtcrime.securesms.util.FileUtils;
|
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
|
import org.thoughtcrime.securesms.util.VersionTracker;
|
|
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
|
|
|
import java.io.File;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Represents all of the migrations that used to take place in {@link ApplicationMigrationActivity}
|
|
* (previously known as DatabaseUpgradeActivity). This job should *never* have new versions or
|
|
* migrations added to it. Instead, create a new {@link MigrationJob} and place it in
|
|
* {@link ApplicationMigrations}.
|
|
*/
|
|
public class LegacyMigrationJob extends MigrationJob {
|
|
|
|
public static final String KEY = "LegacyMigrationJob";
|
|
|
|
private static final String TAG = Log.tag(LegacyMigrationJob.class);
|
|
|
|
public static final int NO_MORE_KEY_EXCHANGE_PREFIX_VERSION = 46;
|
|
public static final int MMS_BODY_VERSION = 46;
|
|
public static final int TOFU_IDENTITIES_VERSION = 50;
|
|
private static final int CURVE25519_VERSION = 63;
|
|
public static final int ASYMMETRIC_MASTER_SECRET_FIX_VERSION = 73;
|
|
private static final int NO_V1_VERSION = 83;
|
|
private static final int SIGNED_PREKEY_VERSION = 83;
|
|
private static final int NO_DECRYPT_QUEUE_VERSION = 113;
|
|
private static final int PUSH_DECRYPT_SERIAL_ID_VERSION = 131;
|
|
private static final int MIGRATE_SESSION_PLAINTEXT = 136;
|
|
private static final int CONTACTS_ACCOUNT_VERSION = 136;
|
|
private static final int MEDIA_DOWNLOAD_CONTROLS_VERSION = 151;
|
|
private static final int REDPHONE_SUPPORT_VERSION = 157;
|
|
private static final int NO_MORE_CANONICAL_DB_VERSION = 276;
|
|
private static final int PROFILES = 289;
|
|
private static final int SCREENSHOTS = 300;
|
|
private static final int PERSISTENT_BLOBS = 317;
|
|
private static final int INTERNALIZE_CONTACTS = 317;
|
|
public static final int SQLCIPHER = 334;
|
|
private static final int SQLCIPHER_COMPLETE = 352;
|
|
private static final int REMOVE_JOURNAL = 353;
|
|
private static final int REMOVE_CACHE = 354;
|
|
private static final int FULL_TEXT_SEARCH = 358;
|
|
private static final int BAD_IMPORT_CLEANUP = 373;
|
|
private static final int IMAGE_CACHE_CLEANUP = 406;
|
|
private static final int WORKMANAGER_MIGRATION = 408;
|
|
private static final int COLOR_MIGRATION = 412;
|
|
private static final int UNIDENTIFIED_DELIVERY = 422;
|
|
private static final int SIGNALING_KEY_DEPRECATION = 447;
|
|
private static final int CONVERSATION_SEARCH = 455;
|
|
|
|
|
|
public LegacyMigrationJob() {
|
|
this(new Parameters.Builder().build());
|
|
}
|
|
|
|
private LegacyMigrationJob(@NonNull Parameters parameters) {
|
|
super(parameters);
|
|
}
|
|
|
|
@Override
|
|
public boolean isUiBlocking() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public @NonNull String getFactoryKey() {
|
|
return KEY;
|
|
}
|
|
|
|
@Override
|
|
void performMigration() throws RetryLaterException {
|
|
Log.i(TAG, "Running background upgrade..");
|
|
int lastSeenVersion = VersionTracker.getLastSeenVersion(context);
|
|
MasterSecret masterSecret = KeyCachingService.getMasterSecret(context);
|
|
|
|
if (lastSeenVersion < SQLCIPHER && masterSecret != null) {
|
|
SignalDatabase.onApplicationLevelUpgrade(context, masterSecret, lastSeenVersion, (progress, total) -> {
|
|
Log.i(TAG, "onApplicationLevelUpgrade: " + progress + "/" + total);
|
|
});
|
|
} else if (lastSeenVersion < SQLCIPHER) {
|
|
throw new RetryLaterException();
|
|
}
|
|
|
|
if (lastSeenVersion < NO_V1_VERSION) {
|
|
File v1sessions = new File(context.getFilesDir(), "sessions");
|
|
|
|
if (v1sessions.exists() && v1sessions.isDirectory()) {
|
|
File[] contents = v1sessions.listFiles();
|
|
|
|
if (contents != null) {
|
|
for (File session : contents) {
|
|
session.delete();
|
|
}
|
|
}
|
|
|
|
v1sessions.delete();
|
|
}
|
|
}
|
|
|
|
if (lastSeenVersion < SIGNED_PREKEY_VERSION) {
|
|
PreKeysSyncJob.enqueueIfNeeded();
|
|
}
|
|
|
|
if (lastSeenVersion < NO_DECRYPT_QUEUE_VERSION) {
|
|
scheduleMessagesInPushDatabase(context);
|
|
}
|
|
|
|
if (lastSeenVersion < PUSH_DECRYPT_SERIAL_ID_VERSION) {
|
|
scheduleMessagesInPushDatabase(context);
|
|
}
|
|
|
|
if (lastSeenVersion < MIGRATE_SESSION_PLAINTEXT) {
|
|
// new TextSecureSessionStore(context, masterSecret).migrateSessions();
|
|
// new TextSecurePreKeyStore(context, masterSecret).migrateRecords();
|
|
|
|
scheduleMessagesInPushDatabase(context);;
|
|
}
|
|
|
|
if (lastSeenVersion < CONTACTS_ACCOUNT_VERSION) {
|
|
ApplicationDependencies.getJobManager().add(new DirectoryRefreshJob(false));
|
|
}
|
|
|
|
if (lastSeenVersion < MEDIA_DOWNLOAD_CONTROLS_VERSION) {
|
|
schedulePendingIncomingParts(context);
|
|
}
|
|
|
|
if (lastSeenVersion < REDPHONE_SUPPORT_VERSION) {
|
|
ApplicationDependencies.getJobManager().add(new RefreshAttributesJob());
|
|
ApplicationDependencies.getJobManager().add(new DirectoryRefreshJob(false));
|
|
}
|
|
|
|
if (lastSeenVersion < PROFILES) {
|
|
ApplicationDependencies.getJobManager().add(new DirectoryRefreshJob(false));
|
|
}
|
|
|
|
if (lastSeenVersion < SCREENSHOTS) {
|
|
boolean screenSecurity = PreferenceManager.getDefaultSharedPreferences(context).getBoolean(TextSecurePreferences.SCREEN_SECURITY_PREF, true);
|
|
TextSecurePreferences.setScreenSecurityEnabled(context, screenSecurity);
|
|
}
|
|
|
|
if (lastSeenVersion < PERSISTENT_BLOBS) {
|
|
File externalDir = context.getExternalFilesDir(null);
|
|
|
|
if (externalDir != null && externalDir.isDirectory() && externalDir.exists()) {
|
|
for (File blob : externalDir.listFiles()) {
|
|
if (blob.exists() && blob.isFile()) blob.delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lastSeenVersion < INTERNALIZE_CONTACTS) {
|
|
if (SignalStore.account().isRegistered()) {
|
|
TextSecurePreferences.setHasSuccessfullyRetrievedDirectory(context, true);
|
|
}
|
|
}
|
|
|
|
if (lastSeenVersion < SQLCIPHER) {
|
|
scheduleMessagesInPushDatabase(context);
|
|
}
|
|
|
|
if (lastSeenVersion < SQLCIPHER_COMPLETE) {
|
|
File file = context.getDatabasePath("messages.db");
|
|
if (file != null && file.exists()) file.delete();
|
|
}
|
|
|
|
if (lastSeenVersion < REMOVE_JOURNAL) {
|
|
File file = context.getDatabasePath("messages.db-journal");
|
|
if (file != null && file.exists()) file.delete();
|
|
}
|
|
|
|
if (lastSeenVersion < REMOVE_CACHE) {
|
|
FileUtils.deleteDirectoryContents(context.getCacheDir());
|
|
}
|
|
|
|
if (lastSeenVersion < IMAGE_CACHE_CLEANUP) {
|
|
FileUtils.deleteDirectoryContents(context.getExternalCacheDir());
|
|
GlideApp.get(context).clearDiskCache();
|
|
}
|
|
|
|
// This migration became unnecessary after switching away from WorkManager
|
|
// if (lastSeenVersion < WORKMANAGER_MIGRATION) {
|
|
// Log.i(TAG, "Beginning migration of existing jobs to WorkManager");
|
|
//
|
|
// JobManager jobManager = ApplicationContext.getInstance(getApplicationContext()).getJobManager();
|
|
// PersistentStorage storage = new PersistentStorage(getApplicationContext(), "TextSecureJobs", new JavaJobSerializer());
|
|
//
|
|
// for (Job job : storage.getAllUnencrypted()) {
|
|
// jobManager.add(job);
|
|
// Log.i(TAG, "Migrated job with class '" + job.getClass().getSimpleName() + "' to run on new JobManager.");
|
|
// }
|
|
// }
|
|
|
|
if (lastSeenVersion < COLOR_MIGRATION) {
|
|
long startTime = System.currentTimeMillis();
|
|
//noinspection deprecation
|
|
SignalDatabase.recipients().updateSystemContactColors();
|
|
Log.i(TAG, "Color migration took " + (System.currentTimeMillis() - startTime) + " ms");
|
|
}
|
|
|
|
if (lastSeenVersion < UNIDENTIFIED_DELIVERY) {
|
|
Log.i(TAG, "Scheduling UD attributes refresh.");
|
|
ApplicationDependencies.getJobManager().add(new RefreshAttributesJob());
|
|
}
|
|
|
|
if (lastSeenVersion < SIGNALING_KEY_DEPRECATION) {
|
|
Log.i(TAG, "Scheduling a RefreshAttributesJob to remove the signaling key remotely.");
|
|
ApplicationDependencies.getJobManager().add(new RefreshAttributesJob());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
boolean shouldRetry(@NonNull Exception e) {
|
|
return e instanceof RetryLaterException;
|
|
}
|
|
|
|
private void schedulePendingIncomingParts(Context context) {
|
|
final AttachmentTable attachmentDb = SignalDatabase.attachments();
|
|
final MessageTable mmsDb = SignalDatabase.messages();
|
|
final List<DatabaseAttachment> pendingAttachments = SignalDatabase.attachments().getPendingAttachments();
|
|
|
|
Log.i(TAG, pendingAttachments.size() + " pending parts.");
|
|
for (DatabaseAttachment attachment : pendingAttachments) {
|
|
final MmsReader reader = MessageTable.mmsReaderFor(mmsDb.getMessageCursor(attachment.getMmsId()));
|
|
final MessageRecord record = reader.getNext();
|
|
|
|
if (attachment.hasData()) {
|
|
Log.i(TAG, "corrected a pending media part " + attachment.getAttachmentId() + "that already had data.");
|
|
attachmentDb.setTransferState(attachment.getMmsId(), attachment.getAttachmentId(), AttachmentTable.TRANSFER_PROGRESS_DONE);
|
|
} else if (record != null && !record.isOutgoing() && record.isPush()) {
|
|
Log.i(TAG, "queuing new attachment download job for incoming push part " + attachment.getAttachmentId() + ".");
|
|
ApplicationDependencies.getJobManager().add(new AttachmentDownloadJob(attachment.getMmsId(), attachment.getAttachmentId(), false));
|
|
}
|
|
reader.close();
|
|
}
|
|
}
|
|
|
|
private static void scheduleMessagesInPushDatabase(@NonNull Context context) {
|
|
PushTable pushDatabase = SignalDatabase.push();
|
|
JobManager jobManager = ApplicationDependencies.getJobManager();
|
|
|
|
try (PushTable.Reader pushReader = pushDatabase.readerFor(pushDatabase.getPending())) {
|
|
SignalServiceEnvelope envelope;
|
|
while ((envelope = pushReader.getNext()) != null) {
|
|
jobManager.add(new PushDecryptMessageJob(envelope));
|
|
}
|
|
}
|
|
}
|
|
|
|
public interface DatabaseUpgradeListener {
|
|
void setProgress(int progress, int total);
|
|
}
|
|
|
|
public static final class Factory implements Job.Factory<LegacyMigrationJob> {
|
|
@Override
|
|
public @NonNull LegacyMigrationJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
|
return new LegacyMigrationJob(parameters);
|
|
}
|
|
}
|
|
}
|