Skip to content

Commit

Permalink
Include additional settings in backup.
Browse files Browse the repository at this point in the history
  • Loading branch information
cody-signal authored and greyson-signal committed Mar 17, 2021
1 parent 1f9afb6 commit faa19ac
Show file tree
Hide file tree
Showing 26 changed files with 279 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public static void onPostBackupRestore(@NonNull Context context) {
ApplicationDependencies.getMegaphoneRepository().onFirstEverAppLaunch();
SignalStore.onFirstEverAppLaunch();
SignalStore.onboarding().clearAll();
TextSecurePreferences.onPostBackupRestore(context);
ApplicationDependencies.getJobManager().add(StickerPackDownloadJob.forInstall(BlessedPacks.ZOZO.getPackId(), BlessedPacks.ZOZO.getPackKey(), false));
ApplicationDependencies.getJobManager().add(StickerPackDownloadJob.forInstall(BlessedPacks.BANDIT.getPackId(), BlessedPacks.BANDIT.getPackKey(), false));
ApplicationDependencies.getJobManager().add(StickerPackDownloadJob.forInstall(BlessedPacks.DAY_BY_DAY.getPackId(), BlessedPacks.DAY_BY_DAY.getPackKey(), false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
import org.thoughtcrime.securesms.database.KeyValueDatabase;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.OneTimePreKeyDatabase;
Expand All @@ -33,6 +34,9 @@
import org.thoughtcrime.securesms.database.SignedPreKeyDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.StickerDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.KeyValueDataSet;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.util.SetUtil;
import org.thoughtcrime.securesms.util.Stopwatch;
Expand Down Expand Up @@ -64,7 +68,6 @@

public class FullBackupExporter extends FullBackupBase {

@SuppressWarnings("unused")
private static final String TAG = FullBackupExporter.class.getSimpleName();

private static final Set<String> BLACKLISTED_TABLES = SetUtil.newHashSet(
Expand Down Expand Up @@ -165,6 +168,10 @@ private static void internalExport(@NonNull Context context,

stopwatch.split("prefs");

count = exportKeyValues(outputStream, SignalStore.getKeysToIncludeInBackup(), count, cancellationSignal);

stopwatch.split("key_values");

for (AvatarHelper.Avatar avatar : AvatarHelper.getAvatars(context)) {
throwIfCanceled(cancellationSignal);
if (avatar != null) {
Expand Down Expand Up @@ -351,6 +358,46 @@ private static long calculateVeryOldStreamLength(@NonNull AttachmentSecret attac
return result;
}

private static int exportKeyValues(@NonNull BackupFrameOutputStream outputStream,
@NonNull List<String> keysToIncludeInBackup,
int count,
BackupCancellationSignal cancellationSignal) throws IOException
{
KeyValueDataSet dataSet = KeyValueDatabase.getInstance(ApplicationDependencies.getApplication())
.getDataSet();

for (String key : keysToIncludeInBackup) {
throwIfCanceled(cancellationSignal);
if (!dataSet.containsKey(key)) {
continue;
}
BackupProtos.KeyValue.Builder builder = BackupProtos.KeyValue.newBuilder()
.setKey(key);

Class<?> type = dataSet.getType(key);
if (type == byte[].class) {
builder.setBlobValue(ByteString.copyFrom(dataSet.getBlob(key, null)));
} else if (type == Boolean.class) {
builder.setBooleanValue(dataSet.getBoolean(key, false));
} else if (type == Float.class) {
builder.setFloatValue(dataSet.getFloat(key, 0));
} else if (type == Integer.class) {
builder.setIntegerValue(dataSet.getInteger(key, 0));
} else if (type == Long.class) {
builder.setLongValue(dataSet.getLong(key, 0));
} else if (type == String.class) {
builder.setStringValue(dataSet.getString(key, null));
} else {
throw new AssertionError("Unknown type: " + type);
}

EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, ++count));
outputStream.write(builder.build());
}

return count;
}

private static boolean isNonExpiringMmsMessage(@NonNull Cursor cursor) {
return cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsColumns.EXPIRES_IN)) <= 0 &&
cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.VIEW_ONCE)) <= 0;
Expand Down Expand Up @@ -422,6 +469,10 @@ public void write(BackupProtos.SharedPreference preference) throws IOException {
write(outputStream, BackupProtos.BackupFrame.newBuilder().setPreference(preference).build());
}

public void write(BackupProtos.KeyValue keyValue) throws IOException {
write(outputStream, BackupProtos.BackupFrame.newBuilder().setKeyValue(keyValue).build());
}

public void write(BackupProtos.SqlStatement statement) throws IOException {
write(outputStream, BackupProtos.BackupFrame.newBuilder().setStatement(statement).build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.KeyValueDatabase;
import org.thoughtcrime.securesms.database.SearchDatabase;
import org.thoughtcrime.securesms.database.StickerDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.KeyValueDataSet;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.BackupUtil;
Expand All @@ -45,6 +48,7 @@
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -78,10 +82,12 @@ public static void importFile(@NonNull Context context, @NonNull AttachmentSecre
{
int count = 0;

SQLiteDatabase keyValueDatabase = KeyValueDatabase.getInstance(ApplicationDependencies.getApplication()).getSqlCipherDatabase();
try {
BackupRecordInputStream inputStream = new BackupRecordInputStream(is, passphrase);

db.beginTransaction();
keyValueDatabase.beginTransaction();

dropAllTables(db);

Expand All @@ -97,12 +103,15 @@ public static void importFile(@NonNull Context context, @NonNull AttachmentSecre
else if (frame.hasAttachment()) processAttachment(context, attachmentSecret, db, frame.getAttachment(), inputStream);
else if (frame.hasSticker()) processSticker(context, attachmentSecret, db, frame.getSticker(), inputStream);
else if (frame.hasAvatar()) processAvatar(context, db, frame.getAvatar(), inputStream);
else if (frame.hasKeyValue()) processKeyValue(frame.getKeyValue());
else count--;
}

db.setTransactionSuccessful();
keyValueDatabase.setTransactionSuccessful();
} finally {
db.endTransaction();
keyValueDatabase.endTransaction();
}

EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.FINISHED, count));
Expand Down Expand Up @@ -213,6 +222,29 @@ private static void processAvatar(@NonNull Context context, @NonNull SQLiteDatab
}
}

private static void processKeyValue(BackupProtos.KeyValue keyValue) {
KeyValueDataSet dataSet = new KeyValueDataSet();

if (keyValue.hasBlobValue()) {
dataSet.putBlob(keyValue.getKey(), keyValue.getBlobValue().toByteArray());
} else if (keyValue.hasBooleanValue()) {
dataSet.putBoolean(keyValue.getKey(), keyValue.getBooleanValue());
} else if (keyValue.hasFloatValue()) {
dataSet.putFloat(keyValue.getKey(), keyValue.getFloatValue());
} else if (keyValue.hasIntegerValue()) {
dataSet.putInteger(keyValue.getKey(), keyValue.getIntegerValue());
} else if (keyValue.hasLongValue()) {
dataSet.putLong(keyValue.getKey(), keyValue.getLongValue());
} else if (keyValue.hasStringValue()) {
dataSet.putString(keyValue.getKey(), keyValue.getStringValue());
} else {
Log.i(TAG, "Unknown KeyValue backup value, skipping");
return;
}

KeyValueDatabase.getInstance(ApplicationDependencies.getApplication()).writeDataSet(dataSet, Collections.emptyList());
}

@SuppressLint("ApplySharedPref")
private static void processPreference(@NonNull Context context, SharedPreference preference) {
SharedPreferences preferences = context.getSharedPreferences(preference.getFile(), 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;

import java.util.Collections;
import java.util.List;

public final class CertificateValues extends SignalStoreValues {

private static final String UD_CERTIFICATE_UUID_AND_E164 = "certificate.uuidAndE164";
Expand All @@ -17,6 +20,11 @@ public final class CertificateValues extends SignalStoreValues {
void onFirstEverAppLaunch() {
}

@Override
@NonNull List<String> getKeysToIncludeInBackup() {
return Collections.emptyList();
}

@WorkerThread
public void setUnidentifiedAccessCertificate(@NonNull CertificateType certificateType,
@Nullable byte[] certificate)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

import org.thoughtcrime.securesms.components.emoji.EmojiUtil;

import java.util.Collections;
import java.util.List;

public class EmojiValues extends SignalStoreValues {

private static final String PREFIX = "emojiPref__";
Expand All @@ -17,6 +20,11 @@ void onFirstEverAppLaunch() {

}

@Override
@NonNull List<String> getKeysToIncludeInBackup() {
return Collections.emptyList();
}

public void setPreferredVariation(@NonNull String emoji) {
String canonical = EmojiUtil.getCanonicalRepresentation(emoji);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package org.thoughtcrime.securesms.keyvalue;

import androidx.annotation.NonNull;

import org.thoughtcrime.securesms.util.FeatureFlags;

import java.util.Collections;
import java.util.List;

public final class InternalValues extends SignalStoreValues {

public static final String GV2_DO_NOT_CREATE_GV2 = "internal.gv2.do_not_create_gv2";
Expand All @@ -21,6 +26,11 @@ public final class InternalValues extends SignalStoreValues {
void onFirstEverAppLaunch() {
}

@Override
@NonNull List<String> getKeysToIncludeInBackup() {
return Collections.emptyList();
}

/**
* Do not attempt to create GV2 groups, i.e. will force creation of GV1 or MMS groups.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

import java.io.IOException;
import java.security.SecureRandom;
import java.util.Collections;
import java.util.List;

public final class KbsValues extends SignalStoreValues {

Expand All @@ -30,6 +32,11 @@ public final class KbsValues extends SignalStoreValues {
void onFirstEverAppLaunch() {
}

@Override
@NonNull List<String> getKeysToIncludeInBackup() {
return Collections.emptyList();
}

/**
* Deliberately does not clear the {@link #MASTER_KEY}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ public String getString(@NonNull String key, String defaultValue) {
}
}

boolean containsKey(@NonNull String key) {
@Override
public boolean containsKey(@NonNull String key) {
return values.containsKey(key);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ interface KeyValueReader {
int getInteger(@NonNull String key, int defaultValue);
long getLong(@NonNull String key, long defaultValue);
String getString(@NonNull String key, String defaultValue);
boolean containsKey(@NonNull String key);
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ public synchronized String getString(@NonNull String key, String defaultValue) {
return dataSet.getString(key, defaultValue);
}

@AnyThread
@Override
public synchronized boolean containsKey(@NonNull String key) {
initializeIfNecessary();
return dataSet.containsKey(key);
}

/**
* @return A writer that allows writing and removing multiple entries in a single atomic
* transaction.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import androidx.annotation.NonNull;

import java.util.Collections;
import java.util.List;

public final class MiscellaneousValues extends SignalStoreValues {

private static final String LAST_PREKEY_REFRESH_TIME = "last_prekey_refresh_time";
Expand All @@ -21,6 +24,11 @@ void onFirstEverAppLaunch() {
putLong(MESSAGE_REQUEST_ENABLE_TIME, 0);
}

@Override
@NonNull List<String> getKeysToIncludeInBackup() {
return Collections.emptyList();
}

public long getLastPrekeyRefreshTime() {
return getLong(LAST_PREKEY_REFRESH_TIME, 0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
import org.thoughtcrime.securesms.util.Util;

import java.util.Collections;
import java.util.List;

public final class OnboardingValues extends SignalStoreValues {

private static final String SHOW_NEW_GROUP = "onboarding.new_group";
Expand All @@ -24,6 +27,11 @@ void onFirstEverAppLaunch() {
putBoolean(SHOW_SMS, true);
}

@Override
@NonNull List<String> getKeysToIncludeInBackup() {
return Collections.emptyList();
}

public void clearAll() {
setShowNewGroup(false);
setShowInviteFriends(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public final class PhoneNumberPrivacyValues extends SignalStoreValues {

Expand All @@ -29,6 +30,11 @@ void onFirstEverAppLaunch() {
// .apply();
}

@Override
@NonNull List<String> getKeysToIncludeInBackup() {
return Arrays.asList(SHARING_MODE, LISTING_MODE);
}

public @NonNull PhoneNumberSharingMode getPhoneNumberSharingMode() {
if (!FeatureFlags.phoneNumberPrivacy()) return PhoneNumberSharingMode.EVERYONE;
return PhoneNumberSharingMode.values()[getInteger(SHARING_MODE, PhoneNumberSharingMode.EVERYONE.ordinal())];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import org.thoughtcrime.securesms.lock.v2.PinKeyboardType;
import org.thoughtcrime.securesms.util.TextSecurePreferences;

import java.util.Collections;
import java.util.List;

/**
* Specifically handles just the UI/UX state around PINs. For actual keys, see {@link KbsValues}.
*/
Expand All @@ -30,6 +33,11 @@ public final class PinValues extends SignalStoreValues {
void onFirstEverAppLaunch() {
}

@Override
@NonNull List<String> getKeysToIncludeInBackup() {
return Collections.emptyList();
}

public void onEntrySuccess(@NonNull String pin) {
long nextInterval = SignalPinReminders.getNextInterval(getCurrentInterval());
Log.i(TAG, "onEntrySuccess() nextInterval: " + nextInterval);
Expand Down

0 comments on commit faa19ac

Please sign in to comment.