Merge branch 'charlesmchen/preventYdbReversion' into release/2.44.0

This commit is contained in:
Matthew Chen 2019-10-11 14:42:33 -03:00
commit 4a690669ee
5 changed files with 82 additions and 20 deletions

View File

@ -53,6 +53,12 @@ static NSString *const kURLHostAddStickersPrefix = @"addstickers";
static NSTimeInterval launchStartedAt;
typedef NS_ENUM(NSUInteger, LaunchFailure) {
LaunchFailure_None,
LaunchFailure_CouldNotLoadDatabase,
LaunchFailure_UnknownDatabaseVersion,
};
@interface AppDelegate () <UNUserNotificationCenterDelegate>
@property (nonatomic) BOOL hasInitialRootViewController;
@ -230,17 +236,21 @@ static NSTimeInterval launchStartedAt;
// We need to do this _after_ we set up logging, when the keychain is unlocked,
// but before we access YapDatabase, files on disk, or NSUserDefaults
NSError *error;
if (![YDBLegacyMigration ensureIsYDBReadyForAppExtensions:&error]) {
if (error != nil) {
[self showLaunchFailureUI:error];
}
NSError *_Nullable launchError = nil;
LaunchFailure launchFailure = LaunchFailure_None;
// If this method has failed; do nothing.
//
// ensureIsReadyForAppExtensions will show a failure mode UI that
// lets users report this error.
BOOL isYdbNotReady = ![YDBLegacyMigration ensureIsYDBReadyForAppExtensions:&launchError];
if (isYdbNotReady || launchError != nil) {
launchFailure = LaunchFailure_CouldNotLoadDatabase;
} else if (StorageCoordinator.hasInvalidDatabaseVersion) {
// Prevent:
// * Users who have used GRDB revert to using YDB.
// * Users with an unknown GRDB schema revert to using an earlier GRDB schema.
launchFailure = LaunchFailure_UnknownDatabaseVersion;
}
if (launchFailure != LaunchFailure_None) {
OWSLogInfo(@"application: didFinishLaunchingWithOptions failed.");
[self showUIForLaunchFailure:launchFailure];
return YES;
}
@ -374,7 +384,7 @@ static NSTimeInterval launchStartedAt;
exit(0);
}
- (void)showLaunchFailureUI:(NSError *)error
- (void)showUIForLaunchFailure:(LaunchFailure)launchFailure
{
// Disable normal functioning of app.
self.didAppLaunchFail = YES;
@ -386,17 +396,36 @@ static NSTimeInterval launchStartedAt;
self.window = [[OWSWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Show the launch screen
self.window.rootViewController =
[[UIStoryboard storyboardWithName:@"Launch Screen" bundle:nil] instantiateInitialViewController];
UIViewController *viewController = [[UIStoryboard storyboardWithName:@"Launch Screen"
bundle:nil] instantiateInitialViewController];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:NSLocalizedString(@"APP_LAUNCH_FAILURE_ALERT_TITLE",
@"Title for the 'app launch failed' alert.")
message:NSLocalizedString(@"APP_LAUNCH_FAILURE_ALERT_MESSAGE",
@"Message for the 'app launch failed' alert.")
preferredStyle:UIAlertControllerStyleAlert];
NSString *alertTitle;
NSString *alertMessage
= NSLocalizedString(@"APP_LAUNCH_FAILURE_ALERT_MESSAGE", @"Message for the 'app launch failed' alert.");
switch (launchFailure) {
case LaunchFailure_CouldNotLoadDatabase:
alertTitle = NSLocalizedString(@"APP_LAUNCH_FAILURE_COULD_NOT_LOAD_DATABASE",
@"Error indicating that the app could not launch because the database could not be loaded.");
break;
case LaunchFailure_UnknownDatabaseVersion:
alertTitle = NSLocalizedString(@"APP_LAUNCH_FAILURE_INVALID_DATABASE_VERSION_TITLE",
@"Error indicating that the app could not launch without reverting unknown database migrations.");
alertMessage = NSLocalizedString(@"APP_LAUNCH_FAILURE_INVALID_DATABASE_VERSION_MESSAGE",
@"Error indicating that the app could not launch without reverting unknown database migrations.");
break;
default:
OWSFailDebug(@"Unknown launch failure.");
alertTitle
= NSLocalizedString(@"APP_LAUNCH_FAILURE_ALERT_TITLE", @"Title for the 'app launch failed' alert.");
break;
}
UIAlertController *alert = [UIAlertController alertControllerWithTitle:alertTitle
message:alertMessage
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"SETTINGS_ADVANCED_SUBMIT_DEBUGLOG", nil)
style:UIAlertActionStyleDefault
@ -405,8 +434,7 @@ static NSTimeInterval launchStartedAt;
OWSFail(@"exiting after sharing debug logs.");
}];
}]];
UIViewController *fromViewController = [[UIApplication sharedApplication] frontmostViewController];
[fromViewController presentAlert:alert];
[viewController presentAlert:alert];
}
- (void)startupLogging
@ -1024,6 +1052,10 @@ static NSTimeInterval launchStartedAt;
- (UIInterfaceOrientationMask)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window
{
if (self.didAppLaunchFail) {
return UIInterfaceOrientationMaskPortrait;
}
if (self.hasCall) {
OWSLogInfo(@"has call");
// The call-banner window is only suitable for portrait display

View File

@ -74,6 +74,15 @@
/* Title for the 'app launch failed' alert. */
"APP_LAUNCH_FAILURE_ALERT_TITLE" = "Error";
/* Error indicating that the app could not launch because the database could not be loaded. */
"APP_LAUNCH_FAILURE_COULD_NOT_LOAD_DATABASE" = "Could Not Load Database";
/* Error indicating that the app could not launch without reverting unknown database migrations. */
"APP_LAUNCH_FAILURE_INVALID_DATABASE_VERSION_TITLE" = "Unknown Database Version.";
/* Error indicating that the app could not launch without reverting unknown database migrations. */
"APP_LAUNCH_FAILURE_INVALID_DATABASE_VERSION_MESSAGE" = "Please upgrade to the latest version of Signal.";
/* Text prompting user to edit their profile name. */
"APP_SETTINGS_EDIT_PROFILE_NAME_PROMPT" = "Enter your name";

View File

@ -38,6 +38,8 @@ NSString *NSStringFromStorageCoordinatorState(StorageCoordinatorState value);
@property (class, nonatomic, readonly) BOOL hasYdbFile;
@property (class, nonatomic, readonly) BOOL hasGrdbFile;
@property (class, nonatomic, readonly) BOOL hasInvalidDatabaseVersion;
- (BOOL)isDatabasePasswordAccessible;
#ifdef TESTABLE_BUILD

View File

@ -71,6 +71,17 @@ NSString *NSStringFromStorageCoordinatorState(StorageCoordinatorState value)
return [OWSFileSystem fileOrFolderExistsAtPath:grdbFilePath];
}
+ (BOOL)hasInvalidDatabaseVersion
{
// A check to avoid trying to revert to YDB when we've already migrated to GRDB.
return (SSKFeatureFlags.storageMode == StorageModeYdb && self.hasGrdbFile && [SSKPreferences isYdbMigrated] &&
// Allow developers to do this, but not QA, internal,
// public beta or production.
!SSKFeatureFlags.canRevertToYDB);
// TODO: also return true if unknown GRDB version.
}
- (StorageCoordinatorState)storageCoordinatorState
{
return self.state;

View File

@ -106,6 +106,14 @@ public class FeatureFlags: NSObject {
@objc
public static let preserveYdb = true
@objc
public static var canRevertToYDB: Bool {
// Only developers should be allowed to use YDB after migrating to GRDB.
// We don't want to let QA, public beta or production users risk
// data loss.
return build == .dev
}
@objc
public static var audibleErrorLogging = build.includes(.internalPreview)