Notify about accidentally disabled backups.

fork-5.53.8
Greyson Parrelli 2020-10-29 13:32:55 -04:00 zatwierdzone przez GitHub
rodzic d1478c5ce0
commit b5d6cb2a8d
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
10 zmienionych plików z 135 dodań i 43 usunięć

Wyświetl plik

@ -18,10 +18,10 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels;
import java.io.IOException;
public enum BackupFileIOError {
ACCESS_ERROR(R.string.LocalBackupJobApi29_backups_disabled, R.string.LocalBackupJobApi29_your_backup_directory_has_been_deleted_or_moved),
ACCESS_ERROR(R.string.LocalBackupJobApi29_backup_failed, R.string.LocalBackupJobApi29_your_backup_directory_has_been_deleted_or_moved),
FILE_TOO_LARGE(R.string.LocalBackupJobApi29_backup_failed, R.string.LocalBackupJobApi29_your_backup_file_is_too_large),
NOT_ENOUGH_SPACE(R.string.LocalBackupJobApi29_backup_failed, R.string.LocalBackupJobApi29_there_is_not_enough_space),
UNKNOWN(R.string.LocalBackupJobApi29_backup_failed, R.string.LocalBackupJobApi29_backup_failed_for_an_unknown_reason);
UNKNOWN(R.string.LocalBackupJobApi29_backup_failed, R.string.LocalBackupJobApi29_tap_to_manage_backups);
private static final short BACKUP_FAILED_ID = 31321;
@ -42,8 +42,8 @@ public enum BackupFileIOError {
intent.putExtra(ApplicationPreferencesActivity.LAUNCH_TO_BACKUPS_FRAGMENT, true);
PendingIntent pendingIntent = PendingIntent.getActivity(context, -1, intent, 0);
Notification backupFailedNotification = new NotificationCompat.Builder(context, NotificationChannels.BACKUPS)
PendingIntent pendingIntent = PendingIntent.getActivity(context, -1, intent, 0);
Notification backupFailedNotification = new NotificationCompat.Builder(context, NotificationChannels.FAILURES)
.setSmallIcon(R.drawable.ic_signal_backup)
.setContentTitle(context.getString(titleId))
.setContentText(context.getString(messageId))

Wyświetl plik

@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.jobmanager.migrations.SendReadReceiptsJobMigra
import org.thoughtcrime.securesms.migrations.AttributesMigrationJob;
import org.thoughtcrime.securesms.migrations.AvatarIdRemovalMigrationJob;
import org.thoughtcrime.securesms.migrations.AvatarMigrationJob;
import org.thoughtcrime.securesms.migrations.BackupNotificationMigrationJob;
import org.thoughtcrime.securesms.migrations.CachedAttachmentsMigrationJob;
import org.thoughtcrime.securesms.migrations.DatabaseMigrationJob;
import org.thoughtcrime.securesms.migrations.DirectoryRefreshMigrationJob;
@ -135,6 +136,7 @@ public final class JobManagerFactories {
put(AttributesMigrationJob.KEY, new AttributesMigrationJob.Factory());
put(AvatarIdRemovalMigrationJob.KEY, new AvatarIdRemovalMigrationJob.Factory());
put(AvatarMigrationJob.KEY, new AvatarMigrationJob.Factory());
put(BackupNotificationMigrationJob.KEY, new BackupNotificationMigrationJob.Factory());
put(CachedAttachmentsMigrationJob.KEY, new CachedAttachmentsMigrationJob.Factory());
put(DatabaseMigrationJob.KEY, new DatabaseMigrationJob.Factory());
put(DirectoryRefreshMigrationJob.KEY, new DirectoryRefreshMigrationJob.Factory());

Wyświetl plik

@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.jobs;
import android.Manifest;
import android.content.Context;
import androidx.annotation.NonNull;
@ -94,7 +93,7 @@ public final class LocalBackupJob extends BaseJob {
notification.setIndeterminateProgress();
String backupPassword = BackupPassphrase.get(context);
File backupDirectory = StorageUtil.getBackupDirectory();
File backupDirectory = StorageUtil.getOrCreateBackupDirectory();
String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US).format(new Date());
String fileName = String.format("signal-%s.backup", timestamp);
File backupFile = new File(backupDirectory, fileName);

Wyświetl plik

@ -89,7 +89,6 @@ public final class LocalBackupJobApi29 extends BaseJob {
String fileName = String.format("signal-%s.backup", timestamp);
if (backupDirectory == null || !backupDirectory.canWrite()) {
BackupUtil.disableBackups(context);
BackupFileIOError.ACCESS_ERROR.postNotification(context);
throw new IOException("Cannot write to backup directory location.");
}

Wyświetl plik

@ -39,31 +39,32 @@ public class ApplicationMigrations {
private static final int LEGACY_CANONICAL_VERSION = 455;
public static final int CURRENT_VERSION = 22;
public static final int CURRENT_VERSION = 23;
private static final class Version {
static final int LEGACY = 1;
static final int RECIPIENT_ID = 2;
static final int RECIPIENT_SEARCH = 3;
static final int RECIPIENT_CLEANUP = 4;
static final int AVATAR_MIGRATION = 5;
static final int UUIDS = 6;
static final int CACHED_ATTACHMENTS = 7;
static final int STICKERS_LAUNCH = 8;
static final int LEGACY = 1;
static final int RECIPIENT_ID = 2;
static final int RECIPIENT_SEARCH = 3;
static final int RECIPIENT_CLEANUP = 4;
static final int AVATAR_MIGRATION = 5;
static final int UUIDS = 6;
static final int CACHED_ATTACHMENTS = 7;
static final int STICKERS_LAUNCH = 8;
//static final int TEST_ARGON2 = 9;
static final int SWOON_STICKERS = 10;
static final int STORAGE_SERVICE = 11;
static final int SWOON_STICKERS = 10;
static final int STORAGE_SERVICE = 11;
//static final int STORAGE_KEY_ROTATE = 12;
static final int REMOVE_AVATAR_ID = 13;
static final int STORAGE_CAPABILITY = 14;
static final int PIN_REMINDER = 15;
static final int VERSIONED_PROFILE = 16;
static final int PIN_OPT_OUT = 17;
static final int TRIM_SETTINGS = 18;
static final int THUMBNAIL_CLEANUP = 19;
static final int GV2 = 20;
static final int GV2_2 = 21;
static final int CDS = 22;
static final int REMOVE_AVATAR_ID = 13;
static final int STORAGE_CAPABILITY = 14;
static final int PIN_REMINDER = 15;
static final int VERSIONED_PROFILE = 16;
static final int PIN_OPT_OUT = 17;
static final int TRIM_SETTINGS = 18;
static final int THUMBNAIL_CLEANUP = 19;
static final int GV2 = 20;
static final int GV2_2 = 21;
static final int CDS = 22;
static final int BACKUP_NOTIFICATION = 23;
}
/**
@ -267,6 +268,10 @@ public class ApplicationMigrations {
jobs.put(Version.CDS, new DirectoryRefreshMigrationJob());
}
if (lastSeenVersion < Version.BACKUP_NOTIFICATION) {
jobs.put(Version.BACKUP_NOTIFICATION, new BackupNotificationMigrationJob());
}
return jobs;
}

Wyświetl plik

@ -0,0 +1,68 @@
package org.thoughtcrime.securesms.migrations;
import android.os.Build;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.backup.BackupFileIOError;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.BackupUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.io.IOException;
import java.util.Locale;
/**
* Handles showing a notification if we think backups were unintentionally disabled.
*/
public final class BackupNotificationMigrationJob extends MigrationJob {
private static final String TAG = Log.tag(BackupNotificationMigrationJob.class);
public static final String KEY = "BackupNotificationMigrationJob";
BackupNotificationMigrationJob() {
this(new Parameters.Builder().build());
}
private BackupNotificationMigrationJob(@NonNull Parameters parameters) {
super(parameters);
}
@Override
public boolean isUiBlocking() {
return false;
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public void performMigration() {
if (Build.VERSION.SDK_INT >= 29 && !TextSecurePreferences.isBackupEnabled(context) && BackupUtil.hasBackupFiles(context)) {
Log.w(TAG, "Stranded backup! Notifying.");
BackupFileIOError.UNKNOWN.postNotification(context);
} else {
Log.w(TAG, String.format(Locale.US, "Does not meet criteria. API: %d, BackupsEnabled: %s, HasFiles: %s",
Build.VERSION.SDK_INT,
TextSecurePreferences.isBackupEnabled(context),
BackupUtil.hasBackupFiles(context)));
}
}
@Override
boolean shouldRetry(@NonNull Exception e) {
return e instanceof IOException;
}
public static class Factory implements Job.Factory<BackupNotificationMigrationJob> {
@Override
public @NonNull BackupNotificationMigrationJob create(@NonNull Parameters parameters, @NonNull Data data) {
return new BackupNotificationMigrationJob(parameters);
}
}
}

Wyświetl plik

@ -18,7 +18,6 @@ import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.text.HtmlCompat;
import androidx.documentfile.provider.DocumentFile;
import androidx.fragment.app.Fragment;
import org.greenrobot.eventbus.EventBus;
@ -165,7 +164,7 @@ public class BackupsPreferenceFragment extends Fragment {
} else if (StorageUtil.canWriteInSignalStorageDir()) {
try {
folder.setVisibility(View.VISIBLE);
folderName.setText(StorageUtil.getBackupDirectory().getPath());
folderName.setText(StorageUtil.getOrCreateBackupDirectory().getPath());
} catch (NoExternalStorageException e) {
Log.w(TAG, "Could not display folder name.", e);
}

Wyświetl plik

@ -15,7 +15,6 @@ import androidx.documentfile.provider.DocumentFile;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.backup.BackupPassphrase;
import org.thoughtcrime.securesms.database.NoExternalStorageException;
import org.thoughtcrime.securesms.database.documents.Document;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.Log;
@ -181,7 +180,7 @@ public class BackupUtil {
}
private static List<BackupInfo> getAllBackupsNewestFirstLegacy() throws NoExternalStorageException {
File backupDirectory = StorageUtil.getBackupDirectory();
File backupDirectory = StorageUtil.getOrCreateBackupDirectory();
File[] files = backupDirectory.listFiles();
List<BackupInfo> backups = new ArrayList<>(files.length);
@ -213,6 +212,20 @@ public class BackupUtil {
return result;
}
public static boolean hasBackupFiles(@NonNull Context context) {
if (Permissions.hasAll(context, Manifest.permission.READ_EXTERNAL_STORAGE)) {
try {
File directory = StorageUtil.getBackupDirectory();
return directory.exists() && directory.isDirectory() && directory.listFiles().length > 0;
} catch (NoExternalStorageException e) {
Log.w(TAG, "Failed to read storage!", e);
return false;
}
} else {
return false;
}
}
private static long getBackupTimestamp(@NonNull String backupName) {
String[] prefixSuffix = backupName.split("[.]");

Wyświetl plik

@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.database.NoExternalStorageException;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.whispersystems.libsignal.util.guava.Optional;
import java.io.File;
import java.util.List;
@ -28,20 +29,14 @@ public class StorageUtil {
private static final String PRODUCTION_PACKAGE_ID = "org.thoughtcrime.securesms";
public static File getBackupDirectory() throws NoExternalStorageException {
public static File getOrCreateBackupDirectory() throws NoExternalStorageException {
File storage = Environment.getExternalStorageDirectory();
if (!storage.canWrite()) {
throw new NoExternalStorageException();
}
File signal = new File(storage, "Signal");
File backups = new File(signal, "Backups");
//noinspection ConstantConditions
if (BuildConfig.APPLICATION_ID.startsWith(PRODUCTION_PACKAGE_ID + ".")) {
backups = new File(backups, BuildConfig.APPLICATION_ID.substring(PRODUCTION_PACKAGE_ID.length() + 1));
}
File backups = getBackupDirectory();
if (!backups.exists()) {
if (!backups.mkdirs()) {
@ -52,6 +47,19 @@ public class StorageUtil {
return backups;
}
public static File getBackupDirectory() throws NoExternalStorageException {
File storage = Environment.getExternalStorageDirectory();
File signal = new File(storage, "Signal");
File backups = new File(signal, "Backups");
//noinspection ConstantConditions
if (BuildConfig.APPLICATION_ID.startsWith(PRODUCTION_PACKAGE_ID + ".")) {
backups = new File(backups, BuildConfig.APPLICATION_ID.substring(PRODUCTION_PACKAGE_ID.length() + 1));
}
return backups;
}
@RequiresApi(24)
public static @NonNull String getDisplayPath(@NonNull Context context, @NonNull Uri uri) {
String lastPathSegment = Objects.requireNonNull(uri.getLastPathSegment());

Wyświetl plik

@ -2625,12 +2625,11 @@
<string name="ChatsPreferenceFragment_last_backup_s">Last backup: %s</string>
<string name="ChatsPreferenceFragment_in_progress">In progress</string>
<string name="LocalBackupJob_creating_backup">Creating backup…</string>
<string name="LocalBackupJobApi29_backups_disabled">Backups disabled.</string>
<string name="LocalBackupJobApi29_backup_failed">Backup failed.</string>
<string name="LocalBackupJobApi29_backup_failed">Backup failed</string>
<string name="LocalBackupJobApi29_your_backup_directory_has_been_deleted_or_moved">Your backup directory has been deleted or moved.</string>
<string name="LocalBackupJobApi29_your_backup_file_is_too_large">Your backup file is too large to store on this volume.</string>
<string name="LocalBackupJobApi29_there_is_not_enough_space">There is not enough space to store your backup.</string>
<string name="LocalBackupJobApi29_backup_failed_for_an_unknown_reason">Backup failed for an unknown reason.</string>
<string name="LocalBackupJobApi29_tap_to_manage_backups">Tap to manage backups.</string>
<string name="ProgressPreference_d_messages_so_far">%d messages so far</string>
<string name="RegistrationActivity_please_enter_the_verification_code_sent_to_s">Please enter the verification code sent to %s.</string>
<string name="RegistrationActivity_wrong_number">Wrong number</string>