You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-ios/SignalMessaging/environment/VersionMigrations.m

212 lines
8.9 KiB
Objective-C

//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "VersionMigrations.h"
#import "Environment.h"
#import "OWSDatabaseMigrationRunner.h"
#import "SignalKeyingStorage.h"
#import <SignalMessaging/SignalMessaging-Swift.h>
#import <SignalServiceKit/AppContext.h>
#import <SignalServiceKit/AppVersion.h>
#import <SignalServiceKit/NSUserDefaults+OWS.h>
#import <SignalServiceKit/OWSPrimaryStorage+Loki.h>
#import <SignalServiceKit/OWSRequestFactory.h>
#import <SignalServiceKit/TSAccountManager.h>
#import <SignalServiceKit/TSNetworkManager.h>
#import <SignalServiceKit/TSThread.h>
#import <SignalServiceKit/TSGroupThread.h>
#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
#pragma mark - Dependencies
+ (TSAccountManager *)tsAccountManager
{
OWSAssertDebug(SSKEnvironment.shared.tsAccountManager);
return SSKEnvironment.shared.tsAccountManager;
}
#pragma mark - Utility methods
+ (void)performUpdateCheckWithCompletion:(VersionMigrationCompletion)completion
{
OWSLogInfo(@"");
// performUpdateCheck must be invoked after Environment has been initialized because
// upgrade process may depend on Environment.
OWSAssertDebug(Environment.shared);
OWSAssertDebug(completion);
NSString *previousVersion = AppVersion.sharedInstance.lastAppVersion;
NSString *currentVersion = AppVersion.sharedInstance.currentAppVersion;
OWSLogInfo(@"Checking migrations. currentVersion: %@, lastRanVersion: %@", currentVersion, previousVersion);
if (!previousVersion) {
OWSLogInfo(@"No previous version found. Probably first launch since install - nothing to migrate.");
OWSDatabaseMigrationRunner *runner = [[OWSDatabaseMigrationRunner alloc] init];
[runner assumeAllExistingMigrationsRun];
dispatch_async(dispatch_get_main_queue(), ^{
completion();
});
return;
}
/*
if ([self isVersion:previousVersion atLeast:@"1.0.2" andLessThan:@"2.0"]) {
OWSLogError(@"Migrating from RedPhone no longer supported. Quitting.");
// Not translating these as so few are affected.
UIAlertController *alert = [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) {
OWSFail(@"Obsolete install.");
}];
[alert addAction:quitAction];
[CurrentAppContext().frontmostViewController presentAlert:alert];
}
*/
if ([self isVersion:previousVersion atLeast:@"2.0.0" andLessThan:@"2.1.70"] && [self.tsAccountManager isRegistered]) {
[self clearVideoCache];
}
if ([self isVersion:previousVersion atLeast:@"2.0.0" andLessThan:@"2.3.0"] && [self.tsAccountManager isRegistered]) {
[self clearBloomFilterCache];
}
// Loki
if ([self isVersion:previousVersion lessThan:@"1.2.1"] && [self.tsAccountManager isRegistered]) {
[self updatePublicChatMapping];
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[[OWSDatabaseMigrationRunner alloc] init] runAllOutstandingWithCompletion:completion];
});
}
+ (BOOL)isVersion:(NSString *)thisVersionString
atLeast:(NSString *)openLowerBoundVersionString
andLessThan:(NSString *)closedUpperBoundVersionString
{
return [self isVersion:thisVersionString atLeast:openLowerBoundVersionString] &&
[self isVersion:thisVersionString lessThan:closedUpperBoundVersionString];
}
+ (BOOL)isVersion:(NSString *)thisVersionString atLeast:(NSString *)thatVersionString
{
return [thisVersionString compare:thatVersionString options:NSNumericSearch] != NSOrderedAscending;
}
+ (BOOL)isVersion:(NSString *)thisVersionString lessThan:(NSString *)thatVersionString
{
return [thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedAscending;
}
#pragma mark Upgrading to 2.1 - Removing video cache folder
+ (void)clearVideoCache
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
basePath = [basePath stringByAppendingPathComponent:@"videos"];
NSError *error;
if ([[NSFileManager defaultManager] fileExistsAtPath:basePath]) {
[NSFileManager.defaultManager removeItemAtPath:basePath error:&error];
}
if (error) {
OWSLogError(
@"An error occured while removing the videos cache folder from old location: %@", error.debugDescription);
}
}
#pragma mark Upgrading to 2.3.0
// We removed bloom filter contact discovery. Clean up any local bloom filter data.
+ (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]) {
OWSLogInfo(@"Successfully removed bloom filter cache.");
[OWSPrimaryStorage.dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeAllObjectsInCollection:@"TSRecipient"];
}];
OWSLogInfo(@"Removed all TSRecipient records - will be replaced by SignalRecipients at next address sync.");
} else {
OWSLogError(@"Failed to remove bloom filter cache with error: %@", deleteError.localizedDescription);
}
} else {
OWSLogDebug(@"No bloom filter cache to remove.");
}
}
# pragma mark Loki - Upgrading to Public Chat Manager
// Versions less than or equal to 1.2.0 didn't store public chat mappings
+ (void)updatePublicChatMapping
{
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) {
for (LKPublicChat *chat in LKPublicChatAPI.defaultChats) {
TSGroupThread *thread = [TSGroupThread threadWithGroupId:[LKGroupUtilities getEncodedOpenGroupIDAsData:chat.id] transaction:transaction];
if (thread != nil) {
[LKDatabaseUtilities setPublicChat:chat threadID:thread.uniqueId transaction:transaction];
} else {
// Update the group type and group ID for private group chat version.
// If the thread is still using the old group ID, it needs to be updated.
thread = [TSGroupThread threadWithGroupId:chat.idAsData transaction:transaction];
if (thread != nil) {
thread.groupModel.groupType = openGroup;
[thread.groupModel updateGroupId:[LKGroupUtilities getEncodedOpenGroupIDAsData:chat.id]];
[thread saveWithTransaction:transaction];
[LKDatabaseUtilities setPublicChat:chat threadID:thread.uniqueId transaction:transaction];
}
}
}
// Update RSS feeds here
LKRSSFeed *lokiNewsFeed = [[LKRSSFeed alloc] initWithId:@"loki.network.feed" server:@"https://loki.network/feed/" displayName:NSLocalizedString(@"Loki News", @"") isDeletable:true];
LKRSSFeed *lokiMessengerUpdatesFeed = [[LKRSSFeed alloc] initWithId:@"loki.network.messenger-updates.feed" server:@"https://loki.network/category/messenger-updates/feed/" displayName:NSLocalizedString(@"Session Updates", @"") isDeletable:false];
NSArray *feeds = @[ lokiNewsFeed, lokiMessengerUpdatesFeed ];
for (LKRSSFeed *feed in feeds) {
TSGroupThread *thread = [TSGroupThread threadWithGroupId:[feed.id dataUsingEncoding:NSUTF8StringEncoding] transaction:transaction];
if (thread != nil) {
thread.groupModel.groupType = rssFeed;
[thread.groupModel updateGroupId:[LKGroupUtilities getEncodedRSSFeedIDAsData:feed.id]];
[thread saveWithTransaction:transaction];
}
}
}];
}
@end
NS_ASSUME_NONNULL_END