session-ios/SignalMessaging/environment/VersionMigrations.m

206 lines
8.1 KiB
Mathematica
Raw Normal View History

//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "VersionMigrations.h"
#import "Environment.h"
#import "LockInteractionController.h"
#import "OWSDatabaseMigrationRunner.h"
#import "SignalKeyingStorage.h"
2017-12-04 22:09:26 +01:00
#import <SignalServiceKit/AppContext.h>
#import <SignalServiceKit/AppVersion.h>
2017-11-28 19:46:26 +01:00
#import <SignalServiceKit/NSUserDefaults+OWS.h>
2018-03-02 04:49:05 +01:00
#import <SignalServiceKit/OWSRequestFactory.h>
2017-11-28 19:46:26 +01:00
#import <SignalServiceKit/TSAccountManager.h>
#import <SignalServiceKit/TSNetworkManager.h>
2017-12-19 03:42:50 +01:00
#import <YapDatabase/YapDatabase.h>
NS_ASSUME_NONNULL_BEGIN
#define NEEDS_TO_REGISTER_PUSH_KEY @"Register For Push"
#define NEEDS_TO_REGISTER_ATTRIBUTES @"Register Attributes"
@interface SignalKeyingStorage (VersionMigrations)
+ (void)storeString:(NSString *)string forKey:(NSString *)key;
+ (void)storeData:(NSData *)data forKey:(NSString *)key;
@end
@implementation VersionMigrations
2015-04-25 16:59:32 +02:00
#pragma mark Utility methods
+ (void)performUpdateCheckWithCompletion:(VersionMigrationCompletion)completion
{
DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__);
// performUpdateCheck must be invoked after Environment has been initialized because
// upgrade process may depend on Environment.
OWSAssert([Environment current]);
OWSAssert(completion);
2018-08-02 21:18:40 +02:00
NSString *previousVersion = AppVersion.sharedInstance.lastAppVersion;
NSString *currentVersion = AppVersion.sharedInstance.currentAppVersion;
2017-11-08 20:04:51 +01:00
DDLogInfo(@"%@ Checking migrations. currentVersion: %@, lastRanVersion: %@",
self.logTag,
currentVersion,
previousVersion);
2015-04-25 16:59:32 +02:00
if (!previousVersion) {
DDLogInfo(@"No previous version found. Probably first launch since install - nothing to migrate.");
OWSDatabaseMigrationRunner *runner =
[[OWSDatabaseMigrationRunner alloc] initWithPrimaryStorage:[OWSPrimaryStorage sharedManager]];
[runner assumeAllExistingMigrationsRun];
dispatch_async(dispatch_get_main_queue(), ^{
completion();
});
2015-04-25 16:59:32 +02:00
return;
}
if ([self isVersion:previousVersion atLeast:@"1.0.2" andLessThan:@"2.0"]) {
DDLogError(@"Migrating from RedPhone no longer supported. Quitting.");
// Not translating these as so few are affected.
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:@"You must reinstall Signal"
message:
@"Sorry, your installation is too old for us to update. You'll have to start fresh."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *quitAction = [UIAlertAction actionWithTitle:@"Quit"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
[DDLog flushLog];
exit(0);
}];
[alertController addAction:quitAction];
2017-12-04 22:09:26 +01:00
[CurrentAppContext().frontmostViewController presentViewController:alertController animated:YES completion:nil];
2015-04-25 16:59:32 +02:00
}
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
if ([self isVersion:previousVersion atLeast:@"2.0.0" andLessThan:@"2.1.70"] && [TSAccountManager isRegistered]) {
2015-04-25 16:59:32 +02:00
[self clearVideoCache];
[self blockingAttributesUpdate];
}
if ([self isVersion:previousVersion atLeast:@"2.0.0" andLessThan:@"2.3.0"] && [TSAccountManager isRegistered]) {
[self clearBloomFilterCache];
}
2018-04-24 19:15:11 +02:00
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[[OWSDatabaseMigrationRunner alloc] initWithPrimaryStorage:[OWSPrimaryStorage sharedManager]]
runAllOutstandingWithCompletion:completion];
});
}
+ (BOOL)isVersion:(NSString *)thisVersionString
atLeast:(NSString *)openLowerBoundVersionString
2017-12-04 18:38:44 +01:00
andLessThan:(NSString *)closedUpperBoundVersionString
{
return [self isVersion:thisVersionString atLeast:openLowerBoundVersionString] &&
2017-12-04 18:38:44 +01:00
[self isVersion:thisVersionString lessThan:closedUpperBoundVersionString];
2015-04-25 16:59:32 +02:00
}
2017-12-04 18:38:44 +01:00
+ (BOOL)isVersion:(NSString *)thisVersionString atLeast:(NSString *)thatVersionString
{
2015-04-25 16:59:32 +02:00
return [thisVersionString compare:thatVersionString options:NSNumericSearch] != NSOrderedAscending;
}
2017-12-04 18:38:44 +01:00
+ (BOOL)isVersion:(NSString *)thisVersionString lessThan:(NSString *)thatVersionString
{
2015-04-25 16:59:32 +02:00
return [thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedAscending;
}
2017-07-24 17:06:19 +02:00
#pragma mark Upgrading to 2.1 - Removing video cache folder
2017-12-04 18:38:44 +01:00
+ (void)clearVideoCache
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
2015-04-25 16:59:32 +02:00
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
2017-12-04 18:38:44 +01:00
basePath = [basePath stringByAppendingPathComponent:@"videos"];
2015-04-25 16:59:32 +02:00
NSError *error;
if ([[NSFileManager defaultManager] fileExistsAtPath:basePath]) {
2015-04-25 16:59:32 +02:00
[NSFileManager.defaultManager removeItemAtPath:basePath error:&error];
}
if (error) {
2017-12-04 18:38:44 +01:00
DDLogError(
@"An error occured while removing the videos cache folder from old location: %@", error.debugDescription);
}
}
#pragma mark Upgrading to 2.1.3 - Adding VOIP flag on TS Server
2017-12-04 18:38:44 +01:00
+ (void)blockingAttributesUpdate
{
LIControllerBlockingOperation blockingOperation = ^BOOL(void) {
2017-11-28 19:46:26 +01:00
[[NSUserDefaults appUserDefaults] setObject:@YES forKey:NEEDS_TO_REGISTER_ATTRIBUTES];
2017-11-28 19:46:26 +01:00
__block dispatch_semaphore_t sema = dispatch_semaphore_create(0);
2017-11-28 19:46:26 +01:00
__block BOOL success;
2018-03-02 04:49:05 +01:00
TSRequest *request = [OWSRequestFactory updateAttributesRequestWithManualMessageFetching:NO];
2017-11-28 19:46:26 +01:00
[[TSNetworkManager sharedManager] makeRequest:request
success:^(NSURLSessionDataTask *task, id responseObject) {
success = YES;
dispatch_semaphore_signal(sema);
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
if (!IsNSErrorNetworkFailure(error)) {
OWSProdError([OWSAnalyticsEvents errorUpdateAttributesRequestFailed]);
}
success = NO;
DDLogError(@"Updating attributess failed with error: %@", error.description);
dispatch_semaphore_signal(sema);
}];
2017-11-28 19:46:26 +01:00
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
2017-11-28 19:46:26 +01:00
return success;
};
LIControllerRetryBlock retryBlock = [LockInteractionController defaultNetworkRetry];
[LockInteractionController performBlock:blockingOperation
completionBlock:^{
2017-11-28 19:46:26 +01:00
[[NSUserDefaults appUserDefaults] removeObjectForKey:NEEDS_TO_REGISTER_ATTRIBUTES];
DDLogWarn(@"Successfully updated attributes.");
}
retryBlock:retryBlock
usesNetwork:YES];
2015-04-25 16:59:32 +02:00
}
#pragma mark Upgrading to 2.3.0
// We removed bloom filter contact discovery. Clean up any local bloom filter data.
2017-12-04 18:38:44 +01:00
+ (void)clearBloomFilterCache
{
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *cachesDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *bloomFilterPath = [[cachesDir objectAtIndex:0] stringByAppendingPathComponent:@"bloomfilter"];
if ([fm fileExistsAtPath:bloomFilterPath]) {
NSError *deleteError;
if ([fm removeItemAtPath:bloomFilterPath error:&deleteError]) {
DDLogInfo(@"Successfully removed bloom filter cache.");
[OWSPrimaryStorage.dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeAllObjectsInCollection:@"TSRecipient"];
}];
DDLogInfo(@"Removed all TSRecipient records - will be replaced by SignalRecipients at next address sync.");
} else {
DDLogError(@"Failed to remove bloom filter cache with error: %@", deleteError.localizedDescription);
}
} else {
DDLogDebug(@"No bloom filter cache to remove.");
}
}
@end
NS_ASSUME_NONNULL_END