2017-01-17 22:01:19 +01:00
//
2019-01-08 17:47:40 +01:00
// Copyright ( c ) 2019 Open Whisper Systems . All rights reserved .
2017-01-17 22:01:19 +01:00
//
2014-05-06 19:41:08 +02:00
# import "AppDelegate.h"
2014-08-09 01:01:05 +02:00
# import "DebugLogger.h"
2018-04-24 19:15:11 +02:00
# import "HomeViewController.h"
2017-11-29 20:51:39 +01:00
# import "MainAppContext.h"
2018-03-01 20:41:45 +01:00
# import "OWS2FASettingsViewController.h"
2018-03-06 16:10:22 +01:00
# import "OWSBackup.h"
2018-08-02 21:18:40 +02:00
# import "OWSOrphanDataCleaner.h"
2018-03-21 20:46:23 +01:00
# import "OWSScreenLockUI.h"
2017-03-23 14:55:39 +01:00
# import "Pastelog.h"
2019-05-02 23:58:48 +02:00
# import "Session-Swift.h"
2017-12-04 16:35:47 +01:00
# import "SignalApp.h"
2017-07-10 22:04:03 +02:00
# import "SignalsNavigationController.h"
2017-04-28 18:18:42 +02:00
# import "ViewControllerUtils.h"
2018-03-05 21:13:19 +01:00
# import < PromiseKit / AnyPromise . h >
2018-09-21 21:41:10 +02:00
# import < SignalCoreKit / iOSVersions . h >
2017-12-07 19:53:13 +01:00
# import < SignalMessaging / AppSetup . h >
2017-12-19 03:50:51 +01:00
# import < SignalMessaging / Environment . h >
# import < SignalMessaging / OWSContactsManager . h >
2018-05-17 04:42:00 +02:00
# import < SignalMessaging / OWSNavigationController . h >
2017-12-19 03:50:51 +01:00
# import < SignalMessaging / OWSPreferences . h >
2017-12-04 16:35:47 +01:00
# import < SignalMessaging / OWSProfileManager . h >
2017-11-30 16:02:04 +01:00
# import < SignalMessaging / SignalMessaging . h >
2017-12-19 03:50:51 +01:00
# import < SignalMessaging / VersionMigrations . h >
2018-01-26 21:53:26 +01:00
# import < SignalServiceKit / AppReadiness . h >
2017-11-28 19:46:26 +01:00
# import < SignalServiceKit / NSUserDefaults + OWS . h >
2018-03-01 20:41:45 +01:00
# import < SignalServiceKit / OWS2FAManager . h >
2017-09-13 18:49:19 +02:00
# import < SignalServiceKit / OWSBatchMessageProcessor . h >
2016-09-21 14:37:51 +02:00
# import < SignalServiceKit / OWSDisappearingMessagesJob . h >
2017-03-29 00:01:31 +02:00
# import < SignalServiceKit / OWSFailedAttachmentDownloadsJob . h >
2017-02-09 19:53:03 +01:00
# import < SignalServiceKit / OWSFailedMessagesJob . h >
2018-07-11 15:58:02 +02:00
# import < SignalServiceKit / OWSIncompleteCallsJob . h >
2019-01-24 19:28:54 +01:00
# import < SignalServiceKit / OWSMath . h >
2017-09-14 17:00:30 +02:00
# import < SignalServiceKit / OWSMessageManager . h >
2016-10-14 22:59:58 +02:00
# import < SignalServiceKit / OWSMessageSender . h >
2018-03-05 15:30:58 +01:00
# import < SignalServiceKit / OWSPrimaryStorage + Calling . h >
2017-09-21 22:58:07 +02:00
# import < SignalServiceKit / OWSReadReceiptManager . h >
2018-08-31 19:12:40 +02:00
# import < SignalServiceKit / SSKEnvironment . h >
2018-10-01 17:38:40 +02:00
# import < SignalServiceKit / SignalServiceKit - Swift . h >
2016-10-10 22:02:09 +02:00
# import < SignalServiceKit / TSAccountManager . h >
2017-06-15 19:43:18 +02:00
# import < SignalServiceKit / TSDatabaseView . h >
2017-02-10 22:24:48 +01:00
# import < SignalServiceKit / TSPreKeyManager . h >
2017-05-27 02:41:27 +02:00
# import < SignalServiceKit / TSSocketManager . h >
2018-01-24 23:11:18 +01:00
# import < YapDatabase / YapDatabaseCryptoUtils . h >
2018-10-25 16:18:09 +02:00
# import < sys / utsname . h >
2019-09-04 06:41:38 +02:00
# import < Mixpanel / Mixpanel . h >
2019-09-05 02:40:30 +02:00
# import < FirebaseCore / FirebaseCore . h >
2016-10-10 22:02:09 +02:00
2016-11-12 18:22:29 +01:00
@ import WebRTC ;
2017-02-01 23:49:32 +01:00
@ import Intents ;
2016-11-12 18:22:29 +01:00
2016-10-10 22:02:09 +02:00
NSString * const AppDelegateStoryboardMain = @ "Main" ;
2014-10-05 19:18:18 +02:00
2015-12-22 12:45:09 +01:00
static NSString * const kInitialViewControllerIdentifier = @ "UserInitialViewController" ;
static NSString * const kURLSchemeSGNLKey = @ "sgnl" ;
static NSString * const kURLHostVerifyPrefix = @ "verify" ;
2015-07-10 15:00:14 +02:00
2018-04-23 15:30:37 +02:00
static NSTimeInterval launchStartedAt ;
2019-09-20 07:53:24 +02:00
@ interface AppDelegate ( ) < UNUserNotificationCenterDelegate >
2014-05-06 19:41:08 +02:00
2017-06-15 23:15:56 +02:00
@ property ( nonatomic ) BOOL hasInitialRootViewController ;
2018-01-30 17:27:44 +01:00
@ property ( nonatomic ) BOOL areVersionMigrationsComplete ;
2018-02-12 17:41:22 +01:00
@ property ( nonatomic ) BOOL didAppLaunchFail ;
2019-08-29 07:21:45 +02:00
// Loki
2019-08-21 03:50:23 +02:00
@ property ( nonatomic ) LKP2PServer * lokiP2PServer ;
2019-08-29 07:21:45 +02:00
@ property ( nonatomic ) LKLongPoller * lokiLongPoller ;
2019-08-21 03:50:23 +02:00
@ property ( nonatomic ) LKGroupChatPoller * lokiPublicChatPoller ;
2019-08-27 08:48:53 +02:00
@ property ( nonatomic ) LKRSSFeedPoller * lokiNewsFeedPoller ;
@ property ( nonatomic ) LKRSSFeedPoller * lokiMessengerUpdatesFeedPoller ;
2014-09-15 01:32:19 +02:00
2014-05-06 19:41:08 +02:00
@ end
2017-07-04 19:24:25 +02:00
# pragma mark -
2014-08-01 07:53:58 +02:00
@ implementation AppDelegate
2014-05-06 19:41:08 +02:00
2017-07-10 22:04:03 +02:00
@ synthesize window = _window ;
2018-10-22 18:31:28 +02:00
# pragma mark - Dependencies
- ( OWSProfileManager * ) profileManager
{
return [ OWSProfileManager sharedManager ] ;
}
- ( OWSReadReceiptManager * ) readReceiptManager
{
return [ OWSReadReceiptManager sharedManager ] ;
}
- ( id < OWSUDManager > ) udManager
{
OWSAssertDebug ( SSKEnvironment . shared . udManager ) ;
return SSKEnvironment . shared . udManager ;
}
- ( OWSPrimaryStorage * ) primaryStorage
{
OWSAssertDebug ( SSKEnvironment . shared . primaryStorage ) ;
return SSKEnvironment . shared . primaryStorage ;
}
- ( PushRegistrationManager * ) pushRegistrationManager
{
OWSAssertDebug ( AppEnvironment . shared . pushRegistrationManager ) ;
return AppEnvironment . shared . pushRegistrationManager ;
}
- ( TSAccountManager * ) tsAccountManager
{
OWSAssertDebug ( SSKEnvironment . shared . tsAccountManager ) ;
return SSKEnvironment . shared . tsAccountManager ;
}
- ( OWSDisappearingMessagesJob * ) disappearingMessagesJob
{
OWSAssertDebug ( SSKEnvironment . shared . disappearingMessagesJob ) ;
return SSKEnvironment . shared . disappearingMessagesJob ;
}
- ( TSSocketManager * ) socketManager
{
OWSAssertDebug ( SSKEnvironment . shared . socketManager ) ;
return SSKEnvironment . shared . socketManager ;
}
- ( OWSMessageManager * ) messageManager
{
OWSAssertDebug ( SSKEnvironment . shared . messageManager ) ;
return SSKEnvironment . shared . messageManager ;
}
2018-10-25 19:02:30 +02:00
- ( OWSWindowManager * ) windowManager
{
return Environment . shared . windowManager ;
}
2018-11-21 23:52:34 +01:00
- ( OWSBackup * ) backup
{
return AppEnvironment . shared . backup ;
}
2019-01-18 18:54:09 +01:00
- ( OWSNotificationPresenter * ) notificationPresenter
{
return AppEnvironment . shared . notificationPresenter ;
}
2019-01-31 01:09:45 +01:00
- ( OWSUserNotificationActionHandler * ) userNotificationActionHandler
{
return AppEnvironment . shared . userNotificationActionHandler ;
}
- ( OWSLegacyNotificationActionHandler * ) legacyNotificationActionHandler
{
return AppEnvironment . shared . legacyNotificationActionHandler ;
}
2019-05-22 05:09:01 +02:00
- ( LKFriendRequestExpirationJob * ) lokiFriendRequestExpirationJob
2019-05-20 03:17:58 +02:00
{
2019-05-22 05:09:01 +02:00
return SSKEnvironment . shared . lokiFriendRequestExpirationJob ;
2019-05-20 03:17:58 +02:00
}
2018-10-22 18:31:28 +02:00
# pragma mark -
2019-02-22 01:05:18 +01:00
- ( void ) applicationDidEnterBackground : ( UIApplication * ) application
{
OWSLogInfo ( @ "applicationDidEnterBackground." ) ;
2019-01-28 17:48:49 +01:00
2017-02-14 17:05:59 +01:00
[ DDLog flushLog ] ;
2019-06-11 08:22:35 +02:00
2019-08-29 07:21:45 +02:00
[ self stopLongPollerIfNeeded ] ;
2017-01-17 23:10:57 +01:00
}
2019-02-22 01:05:18 +01:00
- ( void ) applicationWillEnterForeground : ( UIApplication * ) application
{
OWSLogInfo ( @ "applicationWillEnterForeground." ) ;
2015-09-01 19:22:08 +02:00
}
2017-01-23 19:31:23 +01:00
- ( void ) applicationDidReceiveMemoryWarning : ( UIApplication * ) application
{
2019-02-22 01:05:18 +01:00
OWSLogInfo ( @ "applicationDidReceiveMemoryWarning." ) ;
2017-01-23 19:31:23 +01:00
}
- ( void ) applicationWillTerminate : ( UIApplication * ) application
{
2019-02-22 01:05:18 +01:00
OWSLogInfo ( @ "applicationWillTerminate." ) ;
2017-11-08 19:03:51 +01:00
2017-02-14 17:05:59 +01:00
[ DDLog flushLog ] ;
2019-05-22 02:34:08 +02:00
2019-08-29 07:21:45 +02:00
[ self stopLongPollerIfNeeded ] ;
2019-05-22 06:29:59 +02:00
if ( self . lokiP2PServer ) { [ self . lokiP2PServer stop ] ; }
2017-01-23 19:31:23 +01:00
}
2014-05-06 19:41:08 +02:00
- ( BOOL ) application : ( UIApplication * ) application didFinishLaunchingWithOptions : ( NSDictionary * ) launchOptions {
2017-11-29 17:01:30 +01:00
// This should be the first thing we do .
2017-11-29 20:51:39 +01:00
SetCurrentAppContext ( [ MainAppContext new ] ) ;
2017-11-29 17:01:30 +01:00
2018-04-23 15:30:37 +02:00
launchStartedAt = CACurrentMediaTime ( ) ;
2017-12-01 18:20:09 +01:00
BOOL isLoggingEnabled ;
2017-01-24 00:25:59 +01:00
# ifdef DEBUG
// Specified at Product -> Scheme -> Edit Scheme -> Test -> Arguments -> Environment to avoid things like
// the phone directory being looked up during tests .
2017-12-01 18:20:09 +01:00
isLoggingEnabled = TRUE ;
2017-01-24 00:25:59 +01:00
[ DebugLogger . sharedLogger enableTTYLogging ] ;
# elif RELEASE
2017-12-01 18:20:09 +01:00
isLoggingEnabled = OWSPreferences . isLoggingEnabled ;
2017-01-24 00:25:59 +01:00
# endif
2017-12-01 18:20:09 +01:00
if ( isLoggingEnabled ) {
2017-01-24 00:25:59 +01:00
[ DebugLogger . sharedLogger enableFileLogging ] ;
}
2015-12-22 12:45:09 +01:00
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "application: didFinishLaunchingWithOptions." ) ;
2018-08-03 01:21:01 +02:00
[ Cryptography seedRandom ] ;
2018-01-19 16:42:07 +01:00
2018-03-05 15:30:58 +01:00
// XXX - careful when moving this . It must happen before we initialize OWSPrimaryStorage .
2018-01-19 16:42:07 +01:00
[ self verifyDBKeysAvailableBeforeBackgroundLaunch ] ;
2017-11-28 19:46:26 +01:00
# if RELEASE
2017-11-28 22:30:08 +01:00
// ensureIsReadyForAppExtensions may have changed the state of the logging
2017-11-30 16:02:04 +01:00
// preference ( due to [ NSUserDefaults migrateToSharedUserDefaults ] ) , so honor
// that change if necessary .
2017-12-01 18:20:09 +01:00
if ( isLoggingEnabled && ! OWSPreferences . isLoggingEnabled ) {
2017-11-28 19:46:26 +01:00
[ DebugLogger . sharedLogger disableFileLogging ] ;
}
# endif
2018-01-19 16:42:07 +01:00
// 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
2018-02-12 17:41:22 +01:00
if ( ! [ self ensureIsReadyForAppExtensions ] ) {
// If this method has failed ; do nothing .
//
// ensureIsReadyForAppExtensions will show a failure mode UI that
// lets users report this error .
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "application: didFinishLaunchingWithOptions failed." ) ;
2018-02-12 17:41:22 +01:00
return YES ;
}
2018-01-19 16:42:07 +01:00
2018-08-02 21:18:40 +02:00
[ AppVersion sharedInstance ] ;
2017-05-09 21:58:40 +02:00
2017-09-14 21:24:31 +02:00
[ self startupLogging ] ;
2017-07-06 18:52:44 +02:00
// Prevent the device from sleeping during database view async registration
// ( e . g . long database upgrades ) .
//
2017-12-19 04:56:02 +01:00
// This block will be cleared in storageIsReady .
2017-07-06 18:52:44 +02:00
[ DeviceSleepManager . sharedInstance addBlockWithBlockObject : self ] ;
2018-09-17 15:27:58 +02:00
[ AppSetup
setupEnvironmentWithAppSpecificSingletonBlock : ^ {
2018-10-15 20:34:41 +02:00
// Create AppEnvironment .
2018-10-15 21:51:43 +02:00
[ AppEnvironment . shared setup ] ;
2018-10-15 20:34:41 +02:00
[ SignalApp . sharedApp setup ] ;
2018-04-23 21:49:20 +02:00
}
migrationCompletion : ^ {
OWSAssertIsOnMainThread ( ) ;
[ self versionMigrationsDidComplete ] ;
2017-12-07 19:53:13 +01:00
} ] ;
2015-12-22 12:45:09 +01:00
2018-06-30 00:17:49 +02:00
[ UIUtil setupSignalAppearence ] ;
2016-09-11 22:53:12 +02:00
2017-12-04 18:38:44 +01:00
if ( CurrentAppContext ( ) . isRunningTests ) {
2016-09-11 22:53:12 +02:00
return YES ;
}
2018-04-16 23:19:06 +02:00
UIWindow * mainWindow = [ [ UIWindow alloc ] initWithFrame : [ [ UIScreen mainScreen ] bounds ] ] ;
self . window = mainWindow ;
CurrentAppContext ( ) . mainWindow = mainWindow ;
2018-04-23 15:30:37 +02:00
// Show LoadingViewController until the async database view registrations are complete .
mainWindow . rootViewController = [ LoadingViewController new ] ;
2018-04-16 23:19:06 +02:00
[ mainWindow makeKeyAndVisible ] ;
2015-12-22 12:45:09 +01:00
2019-01-18 18:54:09 +01:00
if ( @ available ( iOS 11 , * ) ) {
// This must happen in appDidFinishLaunching or earlier to ensure we don ' t
// miss notifications .
// Setting the delegate also seems to prevent us from getting the legacy notification
// notification callbacks upon launch e . g . ' didReceiveLocalNotification '
UNUserNotificationCenter . currentNotificationCenter . delegate = self ;
}
2015-12-22 12:45:09 +01:00
// Accept push notification when app is not open
2014-08-13 02:02:29 +02:00
NSDictionary * remoteNotif = launchOptions [ UIApplicationLaunchOptionsRemoteNotificationKey ] ;
2014-05-06 19:41:08 +02:00
if ( remoteNotif ) {
2018-08-27 18:00:28 +02:00
OWSLogInfo ( @ "Application was launched by tapping a push notification." ) ;
2015-12-22 12:45:09 +01:00
[ self application : application didReceiveRemoteNotification : remoteNotif ] ;
2014-05-06 19:41:08 +02:00
}
2015-12-22 12:45:09 +01:00
2018-03-21 20:46:23 +01:00
[ OWSScreenLockUI . sharedManager setupWithRootWindow : self . window ] ;
2018-04-24 23:00:39 +02:00
[ [ OWSWindowManager sharedManager ] setupWithRootWindow : self . window
screenBlockingWindow : OWSScreenLockUI . sharedManager . screenBlockingWindow ] ;
[ OWSScreenLockUI . sharedManager startObserving ] ;
2015-12-22 12:45:09 +01:00
2017-06-15 19:43:18 +02:00
[ [ NSNotificationCenter defaultCenter ] addObserver : self
2017-12-19 04:56:02 +01:00
selector : @ selector ( storageIsReady )
name : StorageIsReadyNotification
2017-06-15 19:43:18 +02:00
object : nil ] ;
2017-09-14 21:29:59 +02:00
[ [ NSNotificationCenter defaultCenter ] addObserver : self
selector : @ selector ( registrationStateDidChange )
2017-12-04 18:38:44 +01:00
name : RegistrationStateDidChangeNotification
2017-09-14 21:29:59 +02:00
object : nil ] ;
2018-03-05 21:13:19 +01:00
[ [ NSNotificationCenter defaultCenter ] addObserver : self
selector : @ selector ( registrationLockDidChange : )
name : NSNotificationName_2FAStateDidChange
object : nil ] ;
2019-06-11 08:22:35 +02:00
2019-06-12 06:23:01 +02:00
// Loki - Observe messages received notifications
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( handleNewMessagesReceived : ) name : NSNotification . newMessagesReceived object : nil ] ;
2019-09-11 02:39:32 +02:00
// Loki - Observe thread deletion notifications
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( handleThreadDeleted : ) name : NSNotification . threadDeleted object : nil ] ;
2017-06-15 19:43:18 +02:00
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "application: didFinishLaunchingWithOptions completed." ) ;
2017-06-20 18:05:06 +02:00
2017-07-21 17:49:38 +02:00
[ OWSAnalytics appLaunchDidBegin ] ;
2019-05-22 02:34:08 +02:00
// Loki
2019-06-14 03:40:54 +02:00
// self . lokiP2PServer = [ LKP2PServer new ] ;
2019-05-22 03:52:32 +02:00
// We try to bind to 8081 , if we can ' t then we just fallback to any random port
2019-06-14 03:40:54 +02:00
// NSArray * ports = @ [ @ 8081 , @ 0 ] ;
// for ( NSNumber * port in ports ) {
// if ( self . lokiP2PServer . isRunning ) { break ; }
// BOOL isStarted = [ self . lokiP2PServer startOnPort : port . unsignedIntegerValue ] ;
// if ( isStarted ) {
// NSURL * serverURL = self . lokiP2PServer . serverURL ;
// [ LKP2PAPI setOurP2PAddressWithUrl : self . lokiP2PServer . serverURL ] ;
// NSString * serverURLDescription = serverURL . absoluteString ;
// if ( [ serverURLDescription hasSuffix : @ "/" ] ) {
// serverURLDescription = [ serverURLDescription substringToIndex : serverURLDescription . length - 1 ] ;
// }
// NSLog ( @ "[Loki] Started server at %@." , serverURLDescription ) ;
// break ;
// }
// }
2019-05-22 03:52:32 +02:00
2019-06-14 03:40:54 +02:00
// if ( ! self . lokiP2PServer . isRunning ) {
// NSLog ( @ "[Loki] Failed to start P2P server." ) ;
// }
2019-05-22 03:52:32 +02:00
2019-09-04 06:41:38 +02:00
// Loki - Set up beta analytics
[ Mixpanel sharedInstanceWithToken : @ "0410357303b7b6b45b740e6f0e6d34be" ] ;
2019-09-04 07:55:17 +02:00
LKAnalytics . shared . trackImplementation = ^ ( NSString * event ) {
NSDictionary * properties = @ { @ "configuration" : LKBuildConfiguration . current } ;
[ Mixpanel . sharedInstance track : event properties : properties ] ;
} ;
2019-09-18 05:58:07 +02:00
# if DEBUG
# else
2019-09-05 02:40:30 +02:00
[ FIRApp configure ] ;
2019-09-18 05:58:07 +02:00
# endif
2019-09-04 06:41:38 +02:00
2014-05-06 19:41:08 +02:00
return YES ;
}
2017-12-05 17:35:43 +01:00
/ * *
* The user must unlock the device once after reboot before the database encryption key can be accessed .
* /
- ( void ) verifyDBKeysAvailableBeforeBackgroundLaunch
{
2017-12-05 19:44:25 +01:00
if ( [ UIApplication sharedApplication ] . applicationState ! = UIApplicationStateBackground ) {
2017-12-05 17:35:43 +01:00
return ;
}
2018-03-05 15:30:58 +01:00
if ( ! [ OWSPrimaryStorage isDatabasePasswordAccessible ] ) {
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "exiting because we are in the background and the database password is not accessible." ) ;
2018-06-04 20:00:45 +02:00
UILocalNotification * notification = [ UILocalNotification new ] ;
NSString * messageFormat = NSLocalizedString ( @ "NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" ,
@ "Lock screen notification text presented after user powers on their device without unlocking. Embeds "
@ "{{device model}} (either 'iPad' or 'iPhone')" ) ;
notification . alertBody = [ NSString stringWithFormat : messageFormat , UIDevice . currentDevice . localizedModel ] ;
// Make sure we clear any existing notifications so that they don ' t start stacking up
// if the user receives multiple pushes .
[ UIApplication . sharedApplication cancelAllLocalNotifications ] ;
[ UIApplication . sharedApplication setApplicationIconBadgeNumber : 0 ] ;
2019-05-10 04:02:04 +02:00
[ UIApplication . sharedApplication scheduleLocalNotification : notification ] ;
2018-06-04 20:00:45 +02:00
[ UIApplication . sharedApplication setApplicationIconBadgeNumber : 1 ] ;
2018-11-19 18:20:19 +01:00
[ DDLog flushLog ] ;
exit ( 0 ) ;
2017-12-05 17:35:43 +01:00
}
}
2018-02-12 17:41:22 +01:00
- ( BOOL ) ensureIsReadyForAppExtensions
2017-11-28 19:46:26 +01:00
{
2018-02-20 23:37:14 +01:00
// Given how sensitive this migration is , we verbosely
// log the contents of all involved paths before and after .
//
// TODO : Remove this logging once we have high confidence
// in our migration logic .
NSArray < NSString * > * paths = @ [
2018-03-05 15:30:58 +01:00
OWSPrimaryStorage . legacyDatabaseFilePath ,
OWSPrimaryStorage . legacyDatabaseFilePath_SHM ,
OWSPrimaryStorage . legacyDatabaseFilePath_WAL ,
OWSPrimaryStorage . sharedDataDatabaseFilePath ,
OWSPrimaryStorage . sharedDataDatabaseFilePath_SHM ,
OWSPrimaryStorage . sharedDataDatabaseFilePath_WAL ,
2018-02-20 23:37:14 +01:00
] ;
NSFileManager * fileManager = [ NSFileManager defaultManager ] ;
for ( NSString * path in paths ) {
if ( [ fileManager fileExistsAtPath : path ] ) {
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "storage file: %@, %@" , path , [ OWSFileSystem fileSizeOfPath : path ] ) ;
2018-02-20 23:37:14 +01:00
}
}
2017-11-28 22:30:08 +01:00
if ( [ OWSPreferences isReadyForAppExtensions ] ) {
2018-02-12 17:41:22 +01:00
return YES ;
2017-11-28 19:46:26 +01:00
}
2018-02-22 19:45:19 +01:00
OWSBackgroundTask * _Nullable backgroundTask = [ OWSBackgroundTask backgroundTaskWithLabelStr : __PRETTY _FUNCTION __ ] ;
2018-07-18 04:20:31 +02:00
SUPPRESS_DEADSTORE _WARNING ( backgroundTask ) ;
2018-02-22 19:45:19 +01:00
2018-03-05 15:30:58 +01:00
if ( [ NSFileManager . defaultManager fileExistsAtPath : OWSPrimaryStorage . legacyDatabaseFilePath ] ) {
2018-08-27 18:51:32 +02:00
OWSLogInfo (
@ "Legacy Database file size: %@" , [ OWSFileSystem fileSizeOfPath : OWSPrimaryStorage . legacyDatabaseFilePath ] ) ;
OWSLogInfo ( @ "\t Legacy SHM file size: %@" ,
2018-03-05 15:30:58 +01:00
[ OWSFileSystem fileSizeOfPath : OWSPrimaryStorage . legacyDatabaseFilePath_SHM ] ) ;
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "\t Legacy WAL file size: %@" ,
2018-03-05 15:30:58 +01:00
[ OWSFileSystem fileSizeOfPath : OWSPrimaryStorage . legacyDatabaseFilePath_WAL ] ) ;
2018-01-30 18:39:27 +01:00
}
2018-01-29 16:58:38 +01:00
2018-01-24 23:11:18 +01:00
NSError * _Nullable error = [ self convertDatabaseIfNecessary ] ;
2018-02-20 23:37:14 +01:00
if ( ! error ) {
[ NSUserDefaults migrateToSharedUserDefaults ] ;
}
if ( ! error ) {
2018-03-05 15:30:58 +01:00
error = [ OWSPrimaryStorage migrateToSharedData ] ;
2018-02-20 23:37:14 +01:00
}
if ( ! error ) {
2018-08-01 15:39:21 +02:00
error = [ OWSUserProfile migrateToSharedData ] ;
2018-02-20 23:37:14 +01:00
}
if ( ! error ) {
error = [ TSAttachmentStream migrateToSharedData ] ;
}
2018-02-12 17:41:22 +01:00
if ( error ) {
2018-08-27 18:51:32 +02:00
OWSFailDebug ( @ "database conversion failed: %@" , error ) ;
2018-02-12 17:41:22 +01:00
[ self showLaunchFailureUI : error ] ;
return NO ;
}
2018-01-18 22:32:15 +01:00
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( backgroundTask ) ;
2018-02-22 19:45:19 +01:00
backgroundTask = nil ;
2018-02-12 17:41:22 +01:00
return YES ;
}
- ( void ) showLaunchFailureUI : ( NSError * ) error
{
// Disable normal functioning of app .
self . didAppLaunchFail = YES ;
// We perform a subset of the [ application : didFinishLaunchingWithOptions : ] .
2018-08-02 21:18:40 +02:00
[ AppVersion sharedInstance ] ;
2018-02-12 17:41:22 +01:00
[ self startupLogging ] ;
self . window = [ [ UIWindow alloc ] initWithFrame : [ [ UIScreen mainScreen ] bounds ] ] ;
2018-04-23 15:30:37 +02:00
// Show the launch screen
self . window . rootViewController =
[ [ UIStoryboard storyboardWithName : @ "Launch Screen" bundle : nil ] instantiateInitialViewController ] ;
2018-02-12 17:41:22 +01:00
[ self . window makeKeyAndVisible ] ;
2019-03-21 15:55:04 +01:00
UIAlertController * alert =
2018-02-12 17:41:22 +01:00
[ 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 ] ;
2019-03-21 15:55:04 +01:00
[ alert addAction : [ UIAlertAction actionWithTitle : NSLocalizedString ( @ "SETTINGS_ADVANCED_SUBMIT_DEBUGLOG" , nil )
style : UIAlertActionStyleDefault
handler : ^ ( UIAlertAction * _Nonnull action ) {
[ Pastelog submitLogsWithCompletion : ^ {
OWSFail ( @ "exiting after sharing debug logs." ) ;
} ] ;
} ] ] ;
2018-02-12 17:41:22 +01:00
UIViewController * fromViewController = [ [ UIApplication sharedApplication ] frontmostViewController ] ;
2019-03-21 15:55:04 +01:00
[ fromViewController presentAlert : alert ] ;
2017-11-28 19:46:26 +01:00
}
2018-01-24 23:11:18 +01:00
- ( nullable NSError * ) convertDatabaseIfNecessary
{
2018-08-27 18:09:39 +02:00
OWSLogInfo ( @ "" ) ;
2018-02-20 23:37:14 +01:00
2018-03-05 15:30:58 +01:00
NSString * databaseFilePath = [ OWSPrimaryStorage legacyDatabaseFilePath ] ;
2018-01-30 17:54:50 +01:00
if ( ! [ [ NSFileManager defaultManager ] fileExistsAtPath : databaseFilePath ] ) {
2018-08-27 18:51:32 +02:00
OWSLogVerbose ( @ "no legacy database file found" ) ;
2018-01-30 17:54:50 +01:00
return nil ;
}
2018-01-24 23:11:18 +01:00
2018-02-21 22:12:21 +01:00
NSError * _Nullable error ;
2018-01-31 18:15:16 +01:00
NSData * _Nullable databasePassword = [ OWSStorage tryToLoadDatabaseLegacyPassphrase : & error ] ;
2018-01-24 23:11:18 +01:00
if ( ! databasePassword || error ) {
return ( error
? : OWSErrorWithCodeDescription (
OWSErrorCodeDatabaseConversionFatalError , @ "Failed to load database password" ) ) ;
}
2018-02-01 02:13:42 +01:00
YapRecordDatabaseSaltBlock recordSaltBlock = ^ ( NSData * saltData ) {
2018-08-27 18:51:32 +02:00
OWSLogVerbose ( @ "saltData: %@" , saltData . hexadecimalString ) ;
2018-01-31 18:15:16 +01:00
// Derive and store the raw cipher key spec , to avoid the ongoing tax of future KDF
2018-02-01 02:13:42 +01:00
NSData * _Nullable keySpecData =
2018-01-31 18:15:16 +01:00
[ YapDatabaseCryptoUtils deriveDatabaseKeySpecForPassword : databasePassword saltData : saltData ] ;
2018-02-01 02:13:42 +01:00
if ( ! keySpecData ) {
2018-08-27 18:51:32 +02:00
OWSLogError ( @ "Failed to derive key spec." ) ;
2018-02-01 02:13:42 +01:00
return NO ;
}
2018-01-31 18:15:16 +01:00
[ OWSStorage storeDatabaseCipherKeySpec : keySpecData ] ;
2018-02-01 02:13:42 +01:00
return YES ;
2018-01-24 23:11:18 +01:00
} ;
2019-01-11 23:20:32 +01:00
YapDatabaseOptions * dbOptions = [ OWSStorage defaultDatabaseOptions ] ;
2018-02-21 22:12:21 +01:00
error = [ YapDatabaseCryptoUtils convertDatabaseIfNecessary : databaseFilePath
databasePassword : databasePassword
2019-01-11 23:20:32 +01:00
options : dbOptions
2018-02-21 22:12:21 +01:00
recordSaltBlock : recordSaltBlock ] ;
if ( ! error ) {
[ OWSStorage removeLegacyPassphrase ] ;
}
return error ;
2018-01-24 23:11:18 +01:00
}
2017-09-14 21:24:31 +02:00
- ( void ) startupLogging
{
2018-08-27 18:00:28 +02:00
OWSLogInfo ( @ "iOS Version: %@" , [ UIDevice currentDevice ] . systemVersion ) ;
2017-09-14 21:24:31 +02:00
NSString * localeIdentifier = [ NSLocale . currentLocale objectForKey : NSLocaleIdentifier ] ;
if ( localeIdentifier . length > 0 ) {
2018-08-27 18:00:28 +02:00
OWSLogInfo ( @ "Locale Identifier: %@" , localeIdentifier ) ;
2017-09-14 21:24:31 +02:00
}
NSString * countryCode = [ NSLocale . currentLocale objectForKey : NSLocaleCountryCode ] ;
if ( countryCode . length > 0 ) {
2018-08-27 18:00:28 +02:00
OWSLogInfo ( @ "Country Code: %@" , countryCode ) ;
2017-09-14 21:24:31 +02:00
}
NSString * languageCode = [ NSLocale . currentLocale objectForKey : NSLocaleLanguageCode ] ;
if ( languageCode . length > 0 ) {
2018-08-27 18:00:28 +02:00
OWSLogInfo ( @ "Language Code: %@" , languageCode ) ;
2017-09-14 21:24:31 +02:00
}
2018-03-02 15:04:55 +01:00
2018-10-25 16:18:09 +02:00
struct utsname systemInfo ;
uname ( & systemInfo ) ;
OWSLogInfo ( @ "Device Model: %@ (%@)" ,
UIDevice . currentDevice . model ,
[ NSString stringWithCString : systemInfo . machine encoding : NSUTF8StringEncoding ] ) ;
2018-03-02 15:04:55 +01:00
2018-10-25 22:08:02 +02:00
NSDictionary < NSString * , NSString * > * buildDetails =
[ [ NSBundle mainBundle ] objectForInfoDictionaryKey : @ "BuildDetails" ] ;
OWSLogInfo ( @ "WebRTC Commit: %@" , buildDetails [ @ "WebRTCCommit" ] ) ;
OWSLogInfo ( @ "Build XCode Version: %@" , buildDetails [ @ "XCodeVersion" ] ) ;
OWSLogInfo ( @ "Build OS X Version: %@" , buildDetails [ @ "OSXVersion" ] ) ;
OWSLogInfo ( @ "Build Cocoapods Version: %@" , buildDetails [ @ "CocoapodsVersion" ] ) ;
OWSLogInfo ( @ "Build Carthage Version: %@" , buildDetails [ @ "CarthageVersion" ] ) ;
OWSLogInfo ( @ "Build Date/Time: %@" , buildDetails [ @ "DateTime" ] ) ;
2017-09-14 21:24:31 +02:00
}
2016-09-14 18:19:05 +02:00
- ( void ) application : ( UIApplication * ) application didRegisterForRemoteNotificationsWithDeviceToken : ( NSData * ) deviceToken
{
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-02-12 17:41:22 +01:00
return ;
}
2019-02-25 21:19:41 +01:00
OWSLogInfo ( @ "registered vanilla push token" ) ;
2018-10-22 18:31:28 +02:00
[ self . pushRegistrationManager didReceiveVanillaPushToken : deviceToken ] ;
2014-05-06 19:41:08 +02:00
}
2014-08-01 07:53:58 +02:00
2016-09-14 18:19:05 +02:00
- ( void ) application : ( UIApplication * ) application didFailToRegisterForRemoteNotificationsWithError : ( NSError * ) error
{
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-02-12 17:41:22 +01:00
return ;
}
2018-08-27 18:51:32 +02:00
OWSLogError ( @ "failed to register vanilla push token with error: %@" , error ) ;
2015-01-18 10:28:11 +01:00
# ifdef DEBUG
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "We're in debug mode. Faking success for remote registration with a fake push identifier" ) ;
2018-10-22 18:31:28 +02:00
[ self . pushRegistrationManager didReceiveVanillaPushToken : [ [ NSMutableData dataWithLength : 32 ] copy ] ] ;
2015-01-18 10:28:11 +01:00
# else
2017-10-06 18:00:29 +02:00
OWSProdError ( [ OWSAnalyticsEvents appDelegateErrorFailedToRegisterForRemoteNotifications ] ) ;
2018-10-22 18:31:28 +02:00
[ self . pushRegistrationManager didFailToReceiveVanillaPushTokenWithError : error ] ;
2015-01-18 10:28:11 +01:00
# endif
2014-09-15 01:32:19 +02:00
}
2015-12-22 12:45:09 +01:00
- ( void ) application : ( UIApplication * ) application
2017-10-06 18:00:29 +02:00
didRegisterUserNotificationSettings : ( UIUserNotificationSettings * ) notificationSettings
{
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-02-12 17:41:22 +01:00
return ;
}
2019-01-18 18:54:09 +01:00
OWSLogInfo ( @ "registered legacy notification settings" ) ;
[ self . notificationPresenter didRegisterLegacyNotificationSettings ] ;
2014-05-06 19:41:08 +02:00
}
2015-12-22 12:45:09 +01:00
- ( BOOL ) application : ( UIApplication * ) application
2017-12-07 20:52:38 +01:00
openURL : ( NSURL * ) url
sourceApplication : ( NSString * ) sourceApplication
annotation : ( id ) annotation
{
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-02-12 17:41:22 +01:00
return NO ;
}
2018-01-29 17:25:23 +01:00
if ( ! AppReadiness . isAppReady ) {
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "Ignoring openURL: app not ready." ) ;
2018-11-02 18:51:46 +01:00
// We don ' t need to use [ AppReadiness runNowOrWhenAppDidBecomeReady : ] ;
2018-02-12 18:56:58 +01:00
// the only URLs we handle in Signal iOS at the moment are used
// for resuming the verification step of the registration flow .
2018-01-29 17:25:23 +01:00
return NO ;
}
2015-07-10 15:00:14 +02:00
if ( [ url . scheme isEqualToString : kURLSchemeSGNLKey ] ) {
2018-10-22 18:31:28 +02:00
if ( [ url . host hasPrefix : kURLHostVerifyPrefix ] && ! [ self . tsAccountManager isRegistered ] ) {
2017-12-04 16:56:59 +01:00
id signupController = SignalApp . sharedApp . signUpFlowNavigationController ;
2018-05-17 04:42:00 +02:00
if ( [ signupController isKindOfClass : [ OWSNavigationController class ] ] ) {
OWSNavigationController * navController = ( OWSNavigationController * ) signupController ;
UIViewController * controller = [ navController . childViewControllers lastObject ] ;
2019-02-20 23:35:46 +01:00
if ( [ controller isKindOfClass : [ OnboardingVerificationViewController class ] ] ) {
OnboardingVerificationViewController * verificationView
= ( OnboardingVerificationViewController * ) controller ;
2015-12-22 12:45:09 +01:00
NSString * verificationCode = [ url . path substringFromIndex : 1 ] ;
2019-02-20 23:35:46 +01:00
[ verificationView setVerificationCodeAndTryToVerify : verificationCode ] ;
2017-12-07 20:52:38 +01:00
return YES ;
2015-12-22 12:45:09 +01:00
} else {
2018-08-27 18:00:28 +02:00
OWSLogWarn ( @ "Not the verification view controller we expected. Got %@ instead" ,
NSStringFromClass ( controller . class ) ) ;
2014-12-31 21:30:20 +01:00
}
2014-11-25 23:52:53 +01:00
}
2015-12-22 12:45:09 +01:00
} else {
2018-08-27 16:29:51 +02:00
OWSFailDebug ( @ "Application opened with an unknown URL action: %@" , url . host ) ;
2017-04-25 04:30:46 +02:00
}
2014-11-25 23:52:53 +01:00
} else {
2018-08-27 16:29:51 +02:00
OWSFailDebug ( @ "Application opened with an unknown URL scheme: %@" , url . scheme ) ;
2014-11-25 23:52:53 +01:00
}
return NO ;
}
2015-12-22 12:45:09 +01:00
- ( void ) applicationDidBecomeActive : ( UIApplication * ) application {
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-02-12 17:41:22 +01:00
return ;
}
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "applicationDidBecomeActive." ) ;
2017-12-04 18:38:44 +01:00
if ( CurrentAppContext ( ) . isRunningTests ) {
2015-12-24 18:20:04 +01:00
return ;
}
2017-02-10 22:24:48 +01:00
2017-06-15 23:15:56 +02:00
[ self ensureRootViewController ] ;
2017-06-15 19:43:18 +02:00
2018-11-02 18:51:46 +01:00
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ {
2018-01-26 21:53:26 +01:00
[ self handleActivation ] ;
} ] ;
2018-05-10 19:55:31 +02:00
// Clear all notifications whenever we become active .
// When opening the app from a notification ,
// AppDelegate . didReceiveLocalNotification will always
// be called _before _ we become active .
2018-05-11 21:45:38 +02:00
[ self clearAllNotificationsAndRestoreBadgeCount ] ;
2018-05-10 19:55:31 +02:00
2019-03-26 22:45:12 +01:00
// On every activation , clear old temp directories .
ClearOldTemporaryDirectories ( ) ;
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "applicationDidBecomeActive completed." ) ;
2018-01-26 21:53:26 +01:00
}
2018-03-05 21:13:19 +01:00
- ( void ) enableBackgroundRefreshIfNecessary
{
2018-11-02 18:51:46 +01:00
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ {
2019-05-10 04:04:39 +02:00
[ UIApplication . sharedApplication setMinimumBackgroundFetchInterval : UIApplicationBackgroundFetchIntervalMinimum ] ;
2019-05-08 03:30:02 +02:00
// Loki : Original code
// === === = =
// if ( OWS2FAManager . sharedManager . is2FAEnabled && [ self . tsAccountManager isRegisteredAndReady ] ) {
// // Ping server once a day to keep - alive 2 FA clients .
// const NSTimeInterval kBackgroundRefreshInterval = 24 * 60 * 60 ;
// [ [ UIApplication sharedApplication ] setMinimumBackgroundFetchInterval : kBackgroundRefreshInterval ] ;
// } else {
// [ [ UIApplication sharedApplication ]
// setMinimumBackgroundFetchInterval : UIApplicationBackgroundFetchIntervalNever ] ;
// }
// === === = =
2018-03-05 21:13:19 +01:00
} ] ;
}
2018-01-26 21:53:26 +01:00
- ( void ) handleActivation
{
OWSAssertIsOnMainThread ( ) ;
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "handleActivation." ) ;
2018-01-26 21:53:26 +01:00
2017-02-17 18:43:43 +01:00
// Always check prekeys after app launches , and sometimes check on app activation .
[ TSPreKeyManager checkPreKeysIfNecessary ] ;
2017-06-20 18:05:06 +02:00
2017-07-05 23:54:22 +02:00
static dispatch_once _t onceToken ;
dispatch_once ( & onceToken , ^ {
2017-08-04 15:42:15 +02:00
RTCInitializeSSL ( ) ;
2018-10-22 18:31:28 +02:00
if ( [ self . tsAccountManager isRegistered ] ) {
2017-08-04 15:42:15 +02:00
// At this point , potentially lengthy DB locking migrations could be running .
// Avoid blocking app launch by putting all further possible DB access in async block
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _DEFAULT , 0 ) , ^ {
2018-10-22 18:31:28 +02:00
OWSLogInfo ( @ "running post launch block for registered user: %@" , [ self . tsAccountManager localNumber ] ) ;
2017-11-08 19:03:51 +01:00
2017-08-04 15:42:15 +02:00
// Clean up any messages that expired since last launch immediately
// and continue cleaning in the background .
2018-10-22 18:31:28 +02:00
[ self . disappearingMessagesJob startIfNecessary ] ;
2019-05-20 03:17:58 +02:00
2019-05-20 06:52:26 +02:00
// Start Loki friend request expire job
2019-05-22 05:09:01 +02:00
[ self . lokiFriendRequestExpirationJob startIfNecessary ] ;
2017-09-20 17:15:46 +02:00
2018-03-05 21:13:19 +01:00
[ self enableBackgroundRefreshIfNecessary ] ;
2017-08-04 15:42:15 +02:00
// Mark all "attempting out" messages as "unsent" , i . e . any messages that were not successfully
// sent before the app exited should be marked as failures .
2018-10-22 18:31:28 +02:00
[ [ [ OWSFailedMessagesJob alloc ] initWithPrimaryStorage : self . primaryStorage ] run ] ;
2018-07-11 15:58:02 +02:00
// Mark all "incomplete" calls as missed , e . g . any incoming or outgoing calls that were not
// connected , failed or hung up before the app existed should be marked as missed .
2018-10-22 18:31:28 +02:00
[ [ [ OWSIncompleteCallsJob alloc ] initWithPrimaryStorage : self . primaryStorage ] run ] ;
[ [ [ OWSFailedAttachmentDownloadsJob alloc ] initWithPrimaryStorage : self . primaryStorage ] run ] ;
2017-08-04 15:42:15 +02:00
} ) ;
} else {
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "running post launch block for unregistered user." ) ;
2017-08-04 15:42:15 +02:00
// Unregistered user should have no unread messages . e . g . if you delete your account .
2019-02-13 00:57:37 +01:00
[ AppEnvironment . shared . notificationPresenter clearAllNotifications ] ;
2017-08-04 15:42:15 +02:00
2018-10-22 18:31:28 +02:00
[ self . socketManager requestSocketOpen ] ;
2017-08-04 15:42:15 +02:00
UITapGestureRecognizer * gesture =
[ [ UITapGestureRecognizer alloc ] initWithTarget : [ Pastelog class ] action : @ selector ( submitLogs ) ] ;
gesture . numberOfTapsRequired = 8 ;
[ self . window addGestureRecognizer : gesture ] ;
}
} ) ; // end dispatchOnce for first time we become active
// Every time we become active . . .
2018-10-22 18:31:28 +02:00
if ( [ self . tsAccountManager isRegistered ] ) {
2017-07-05 23:54:22 +02:00
// At this point , potentially lengthy DB locking migrations could be running .
2017-08-04 15:42:15 +02:00
// Avoid blocking app launch by putting all further possible DB access in async block
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
2018-10-22 18:31:28 +02:00
[ self . socketManager requestSocketOpen ] ;
2018-08-31 19:16:31 +02:00
[ Environment . shared . contactsManager fetchSystemContactsOnceIfAlreadyAuthorized ] ;
2019-05-14 08:37:25 +02:00
2019-06-11 08:22:35 +02:00
// Loki : Start long polling
2019-08-29 07:21:45 +02:00
[ self startLongPollerIfNeeded ] ;
2019-05-08 04:37:38 +02:00
2019-05-23 03:49:05 +02:00
// Loki : Tell our friends that we are online
2019-06-12 06:50:36 +02:00
[ LKP2PAPI broadcastOnlineStatus ] ;
2019-05-08 03:42:31 +02:00
2017-10-11 16:23:24 +02:00
if ( ! [ UIApplication sharedApplication ] . isRegisteredForRemoteNotifications ) {
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "Retrying to register for remote notifications since user hasn't registered yet." ) ;
2017-10-11 16:23:24 +02:00
// Push tokens don ' t normally change while the app is launched , so checking once during launch is
// usually sufficient , but e . g . on iOS11 , users who have disabled "Allow Notifications" and disabled
// "Background App Refresh" will not be able to obtain an APN token . Enabling those settings does not
// restart the app , so we check every activation for users who haven ' t yet registered .
2019-05-08 07:51:08 +02:00
__unused AnyPromise * promise =
[ OWSSyncPushTokensJob runWithAccountManager : AppEnvironment . shared . accountManager
preferences : Environment . shared . preferences ] ;
2017-10-11 16:23:24 +02:00
}
2018-03-01 20:41:45 +01:00
if ( [ OWS2FAManager sharedManager ] . isDueForReminder ) {
if ( ! self . hasInitialRootViewController || self . window . rootViewController = = nil ) {
2018-08-27 18:51:32 +02:00
OWSLogDebug ( @ "Skipping 2FA reminder since there isn't yet an initial view controller" ) ;
2018-03-01 20:41:45 +01:00
} else {
UIViewController * rootViewController = self . window . rootViewController ;
2018-05-17 04:42:00 +02:00
OWSNavigationController * reminderNavController =
2018-03-01 20:41:45 +01:00
[ OWS2FAReminderViewController wrappedInNavController ] ;
[ rootViewController presentViewController : reminderNavController animated : YES completion : nil ] ;
}
}
2017-08-04 15:42:15 +02:00
} ) ;
}
2017-07-06 00:12:06 +02:00
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "handleActivation completed." ) ;
2014-12-01 23:24:35 +01:00
}
2019-02-22 01:05:18 +01:00
- ( void ) applicationWillResignActive : ( UIApplication * ) application
{
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-02-12 17:41:22 +01:00
return ;
}
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "applicationWillResignActive." ) ;
2015-12-22 12:45:09 +01:00
2019-02-13 00:57:37 +01:00
[ self clearAllNotificationsAndRestoreBadgeCount ] ;
2019-01-28 17:48:49 +01:00
2017-02-14 17:05:59 +01:00
[ DDLog flushLog ] ;
2014-09-15 01:32:19 +02:00
}
2018-05-11 21:45:38 +02:00
- ( void ) clearAllNotificationsAndRestoreBadgeCount
{
OWSAssertIsOnMainThread ( ) ;
2018-11-02 18:51:46 +01:00
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ {
2019-02-13 00:57:37 +01:00
[ AppEnvironment . shared . notificationPresenter clearAllNotifications ] ;
2018-05-11 21:45:38 +02:00
[ OWSMessageUtils . sharedManager updateApplicationBadgeCount ] ;
} ] ;
}
2015-10-31 23:13:28 +01:00
- ( void ) application : ( UIApplication * ) application
2015-12-22 12:45:09 +01:00
performActionForShortcutItem : ( UIApplicationShortcutItem * ) shortcutItem
completionHandler : ( void ( ^ ) ( BOOL succeeded ) ) completionHandler {
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-11-21 23:52:34 +01:00
completionHandler ( NO ) ;
return ;
}
2018-02-12 17:41:22 +01:00
2018-11-02 18:51:46 +01:00
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ {
2018-11-26 17:19:11 +01:00
if ( ! [ self . tsAccountManager isRegisteredAndReady ] ) {
2018-02-12 18:56:58 +01:00
UIAlertController * controller =
[ UIAlertController alertControllerWithTitle : NSLocalizedString ( @ "REGISTER_CONTACTS_WELCOME" , nil )
message : NSLocalizedString ( @ "REGISTRATION_RESTRICTED_MESSAGE" , nil )
preferredStyle : UIAlertControllerStyleAlert ] ;
[ controller addAction : [ UIAlertAction actionWithTitle : NSLocalizedString ( @ "OK" , nil )
style : UIAlertActionStyleDefault
handler : ^ ( UIAlertAction * _Nonnull action ) {
} ] ] ;
UIViewController * fromViewController = [ [ UIApplication sharedApplication ] frontmostViewController ] ;
[ fromViewController presentViewController : controller
animated : YES
completion : ^ {
completionHandler ( NO ) ;
} ] ;
return ;
}
2018-01-29 17:25:23 +01:00
2017-12-04 16:35:47 +01:00
[ SignalApp . sharedApp . homeViewController showNewConversationView ] ;
2018-02-12 18:56:58 +01:00
2018-02-13 04:41:52 +01:00
completionHandler ( YES ) ;
} ] ;
2015-10-31 23:13:28 +01:00
}
2016-11-12 18:22:29 +01:00
/ * *
* Among other things , this is used by "call back" callkit dialog and calling from native contacts app .
2018-02-13 04:41:52 +01:00
*
* We always return YES if we are going to try to handle the user activity since
* we never want iOS to contact us again using a URL .
*
* From https : // developer . apple . com / documentation / uikit / uiapplicationdelegate / 1623072 - application ? language = objc :
*
* If you do not implement this method or if your implementation returns NO , iOS tries to
* create a document for your app to open using a URL .
2016-11-12 18:22:29 +01:00
* /
2018-01-29 17:25:23 +01:00
- ( BOOL ) application : ( UIApplication * ) application
continueUserActivity : ( nonnull NSUserActivity * ) userActivity
restorationHandler : ( nonnull void ( ^ ) ( NSArray * _Nullable ) ) restorationHandler
2016-11-12 18:22:29 +01:00
{
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-02-12 17:41:22 +01:00
return NO ;
}
2017-01-18 23:29:47 +01:00
if ( [ userActivity . activityType isEqualToString : @ "INStartVideoCallIntent" ] ) {
2017-02-03 17:25:57 +01:00
if ( ! SYSTEM_VERSION _GREATER _THAN _OR _EQUAL _TO ( 10 , 0 ) ) {
2018-08-27 18:51:32 +02:00
OWSLogError ( @ "unexpectedly received INStartVideoCallIntent pre iOS10" ) ;
2017-02-03 17:25:57 +01:00
return NO ;
}
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "got start video call intent" ) ;
2017-02-03 17:25:57 +01:00
INInteraction * interaction = [ userActivity interaction ] ;
INIntent * intent = interaction . intent ;
if ( ! [ intent isKindOfClass : [ INStartVideoCallIntent class ] ] ) {
2018-08-27 18:51:32 +02:00
OWSLogError ( @ "unexpected class for start call video: %@" , intent ) ;
2017-02-03 17:25:57 +01:00
return NO ;
}
INStartVideoCallIntent * startCallIntent = ( INStartVideoCallIntent * ) intent ;
NSString * _Nullable handle = startCallIntent . contacts . firstObject . personHandle . value ;
if ( ! handle ) {
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "unable to find handle in startCallIntent: %@" , startCallIntent ) ;
2017-02-03 17:25:57 +01:00
return NO ;
}
2018-11-02 18:51:46 +01:00
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ {
2018-11-26 17:19:11 +01:00
if ( ! [ self . tsAccountManager isRegisteredAndReady ] ) {
OWSLogInfo ( @ "Ignoring user activity; app not ready." ) ;
return ;
}
2019-03-21 19:48:23 +01:00
NSString * _Nullable phoneNumber = [ self phoneNumberForIntentHandle : handle ] ;
if ( phoneNumber . length < 1 ) {
OWSLogWarn ( @ "ignoring attempt to initiate video call to unknown user." ) ;
return ;
2017-02-22 15:50:41 +01:00
}
2018-02-12 18:56:58 +01:00
// This intent can be received from more than one user interaction .
//
// * It can be received if the user taps the "video" button in the CallKit UI for an
// an ongoing call . If so , the correct response is to try to activate the local
// video for that call .
// * It can be received if the user taps the "video" button for a contact in the
// contacts app . If so , the correct response is to try to initiate a new call
// to that user - unless there already is another call in progress .
2018-10-15 20:58:15 +02:00
if ( AppEnvironment . shared . callService . call ! = nil ) {
if ( [ phoneNumber isEqualToString : AppEnvironment . shared . callService . call . remotePhoneNumber ] ) {
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "trying to upgrade ongoing call to video." ) ;
2018-10-15 20:58:15 +02:00
[ AppEnvironment . shared . callService handleCallKitStartVideo ] ;
2018-02-12 18:56:58 +01:00
return ;
} else {
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "ignoring INStartVideoCallIntent due to ongoing WebRTC call with another party." ) ;
2018-02-12 18:56:58 +01:00
return ;
}
2017-02-03 17:25:57 +01:00
}
2018-10-15 20:58:15 +02:00
OutboundCallInitiator * outboundCallInitiator = AppEnvironment . shared . outboundCallInitiator ;
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( outboundCallInitiator ) ;
2018-02-12 18:56:58 +01:00
[ outboundCallInitiator initiateCallWithHandle : phoneNumber ] ;
} ] ;
return YES ;
2017-02-01 23:49:32 +01:00
} else if ( [ userActivity . activityType isEqualToString : @ "INStartAudioCallIntent" ] ) {
2017-02-02 00:51:49 +01:00
if ( ! SYSTEM_VERSION _GREATER _THAN _OR _EQUAL _TO ( 10 , 0 ) ) {
2018-08-27 18:51:32 +02:00
OWSLogError ( @ "unexpectedly received INStartAudioCallIntent pre iOS10" ) ;
2017-02-02 00:51:49 +01:00
return NO ;
}
2017-02-01 23:49:32 +01:00
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "got start audio call intent" ) ;
2017-02-01 23:49:32 +01:00
INInteraction * interaction = [ userActivity interaction ] ;
INIntent * intent = interaction . intent ;
if ( ! [ intent isKindOfClass : [ INStartAudioCallIntent class ] ] ) {
2018-08-27 18:51:32 +02:00
OWSLogError ( @ "unexpected class for start call audio: %@" , intent ) ;
2017-02-01 23:49:32 +01:00
return NO ;
}
INStartAudioCallIntent * startCallIntent = ( INStartAudioCallIntent * ) intent ;
NSString * _Nullable handle = startCallIntent . contacts . firstObject . personHandle . value ;
if ( ! handle ) {
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "unable to find handle in startCallIntent: %@" , startCallIntent ) ;
2017-02-01 23:49:32 +01:00
return NO ;
}
2018-11-02 18:51:46 +01:00
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ {
2018-11-26 17:19:11 +01:00
if ( ! [ self . tsAccountManager isRegisteredAndReady ] ) {
OWSLogInfo ( @ "Ignoring user activity; app not ready." ) ;
return ;
}
2019-03-21 19:48:23 +01:00
NSString * _Nullable phoneNumber = [ self phoneNumberForIntentHandle : handle ] ;
if ( phoneNumber . length < 1 ) {
OWSLogWarn ( @ "ignoring attempt to initiate audio call to unknown user." ) ;
return ;
2017-02-22 15:50:41 +01:00
}
2018-10-15 20:58:15 +02:00
if ( AppEnvironment . shared . callService . call ! = nil ) {
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "ignoring INStartAudioCallIntent due to ongoing WebRTC call." ) ;
2018-02-12 18:56:58 +01:00
return ;
}
2017-02-03 17:25:57 +01:00
2018-10-15 20:58:15 +02:00
OutboundCallInitiator * outboundCallInitiator = AppEnvironment . shared . outboundCallInitiator ;
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( outboundCallInitiator ) ;
2018-02-12 18:56:58 +01:00
[ outboundCallInitiator initiateCallWithHandle : phoneNumber ] ;
} ] ;
return YES ;
2017-01-18 23:29:47 +01:00
} else {
2018-08-27 18:51:32 +02:00
OWSLogWarn ( @ "userActivity: %@, but not yet supported." , userActivity . activityType ) ;
2017-01-18 23:29:47 +01:00
}
2016-11-12 18:22:29 +01:00
// TODO Something like . . .
// * phoneNumber = [ [ [ [ [ [ userActivity interaction ] intent ] contacts ] firstObject ] personHandle ] value ]
// thread = blah
2017-01-06 14:40:13 +01:00
// [ callUIAdapter startCall : thread ]
2016-11-12 18:22:29 +01:00
//
2017-01-06 14:40:13 +01:00
// Here ' s the Speakerbox Example for intent / NSUserActivity handling :
//
// func application ( _ application : UIApplication , continue userActivity : NSUserActivity , restorationHandler : @ escaping ( [ Any ] ? ) -> Void ) -> Bool {
// guard let handle = userActivity . startCallHandle else {
// print ( "Could not determine start call handle from user activity: \(userActivity)" )
// return false
// }
//
// guard let video = userActivity . video else {
// print ( "Could not determine video from user activity: \(userActivity)" )
// return false
// }
//
// callManager . startCall ( handle : handle , video : video )
// return true
// }
2018-02-13 04:41:52 +01:00
2016-11-12 18:22:29 +01:00
return NO ;
}
2019-03-21 19:48:23 +01:00
- ( nullable NSString * ) phoneNumberForIntentHandle : ( NSString * ) handle
{
OWSAssertDebug ( handle . length > 0 ) ;
if ( [ handle hasPrefix : CallKitCallManager . kAnonymousCallHandlePrefix ] ) {
NSString * _Nullable phoneNumber = [ self . primaryStorage phoneNumberForCallKitId : handle ] ;
if ( phoneNumber . length < 1 ) {
OWSLogWarn ( @ "ignoring attempt to initiate audio call to unknown anonymous signal user." ) ;
return nil ;
}
return phoneNumber ;
}
for ( PhoneNumber * phoneNumber in
[ PhoneNumber tryParsePhoneNumbersFromsUserSpecifiedText : handle
clientPhoneNumber : [ TSAccountManager localNumber ] ] ) {
return phoneNumber . toE164 ;
}
return nil ;
}
2018-10-25 19:02:30 +02:00
# pragma mark - Orientation
- ( UIInterfaceOrientationMask ) application : ( UIApplication * ) application
supportedInterfaceOrientationsForWindow : ( nullable UIWindow * ) window
{
2019-02-27 03:21:29 +01:00
if ( self . hasCall ) {
2019-02-22 01:05:18 +01:00
OWSLogInfo ( @ "has call" ) ;
2019-01-09 16:03:28 +01:00
// The call - banner window is only suitable for portrait display
return UIInterfaceOrientationMaskPortrait ;
}
2018-10-25 19:02:30 +02:00
2019-02-27 03:21:29 +01:00
UIViewController * _Nullable rootViewController = self . window . rootViewController ;
if ( ! rootViewController ) {
return UIInterfaceOrientationMaskAllButUpsideDown ;
}
return rootViewController . supportedInterfaceOrientations ;
}
- ( BOOL ) hasCall
{
return self . windowManager . hasCall ;
2018-10-25 19:02:30 +02:00
}
2015-04-14 21:49:00 +02:00
# pragma mark Push Notifications Delegate Methods
- ( void ) application : ( UIApplication * ) application didReceiveRemoteNotification : ( NSDictionary * ) userInfo {
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-02-12 17:41:22 +01:00
return ;
}
2018-11-26 17:19:11 +01:00
if ( ! ( AppReadiness . isAppReady && [ self . tsAccountManager isRegisteredAndReady ] ) ) {
OWSLogInfo ( @ "Ignoring remote notification; app not ready." ) ;
2018-11-21 23:52:34 +01:00
return ;
}
2015-04-14 21:49:00 +02:00
}
2017-01-17 23:10:57 +01:00
2015-12-22 12:45:09 +01:00
- ( void ) application : ( UIApplication * ) application
didReceiveRemoteNotification : ( NSDictionary * ) userInfo
fetchCompletionHandler : ( void ( ^ ) ( UIBackgroundFetchResult ) ) completionHandler {
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-02-12 17:41:22 +01:00
return ;
}
2018-11-26 17:19:11 +01:00
if ( ! ( AppReadiness . isAppReady && [ self . tsAccountManager isRegisteredAndReady ] ) ) {
OWSLogInfo ( @ "Ignoring remote notification; app not ready." ) ;
2018-11-21 23:52:34 +01:00
return ;
}
2015-04-14 21:49:00 +02:00
}
2015-12-22 12:45:09 +01:00
- ( void ) application : ( UIApplication * ) application didReceiveLocalNotification : ( UILocalNotification * ) notification {
2017-12-19 17:38:25 +01:00
OWSAssertIsOnMainThread ( ) ;
2017-11-06 18:37:15 +01:00
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-02-12 17:41:22 +01:00
return ;
}
2018-08-27 18:09:39 +02:00
OWSLogInfo ( @ "%@" , notification ) ;
2018-11-02 18:51:46 +01:00
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ {
2018-11-26 17:19:11 +01:00
if ( ! [ self . tsAccountManager isRegisteredAndReady ] ) {
OWSLogInfo ( @ "Ignoring action; app not ready." ) ;
return ;
}
2019-01-31 01:09:45 +01:00
[ self . legacyNotificationActionHandler
handleNotificationResponseWithActionIdentifier : OWSLegacyNotificationActionHandler . kDefaultActionIdentifier
2019-01-18 18:54:09 +01:00
notification : notification
responseInfo : @ { }
completionHandler : ^ {
} ] ;
2018-01-29 17:25:23 +01:00
} ] ;
2015-04-14 21:49:00 +02:00
}
2015-12-22 12:45:09 +01:00
- ( void ) application : ( UIApplication * ) application
handleActionWithIdentifier : ( NSString * ) identifier
forLocalNotification : ( UILocalNotification * ) notification
2018-07-18 04:20:31 +02:00
completionHandler : ( void ( ^ ) ( ) ) completionHandler
2017-09-20 17:15:46 +02:00
{
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-11-21 23:52:34 +01:00
completionHandler ( ) ;
return ;
}
2018-02-12 17:41:22 +01:00
2018-02-12 18:56:58 +01:00
// The docs for handleActionWithIdentifier : . . . state :
// "You must call [completionHandler] at the end of your method." .
// Nonetheless , it is presumably safe to call the completion handler
// later , after this method returns .
//
// https : // developer . apple . com / documentation / uikit / uiapplicationdelegate / 1623068 - application ? language = objc
2018-11-02 18:51:46 +01:00
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ {
2018-11-26 17:19:11 +01:00
if ( ! [ self . tsAccountManager isRegisteredAndReady ] ) {
OWSLogInfo ( @ "Ignoring action; app not ready." ) ;
completionHandler ( ) ;
return ;
}
2019-01-31 01:09:45 +01:00
[ self . legacyNotificationActionHandler handleNotificationResponseWithActionIdentifier : identifier
notification : notification
responseInfo : @ { }
completionHandler : completionHandler ] ;
2018-02-12 18:56:58 +01:00
} ] ;
2015-04-14 21:49:00 +02:00
}
2015-12-22 12:45:09 +01:00
- ( void ) application : ( UIApplication * ) application
handleActionWithIdentifier : ( NSString * ) identifier
forLocalNotification : ( UILocalNotification * ) notification
withResponseInfo : ( NSDictionary * ) responseInfo
2018-05-25 23:17:15 +02:00
completionHandler : ( void ( ^ ) ( ) ) completionHandler
2017-09-20 17:15:46 +02:00
{
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "handling action with identifier: %@" , identifier ) ;
2018-07-07 01:55:37 +02:00
2018-01-29 17:25:23 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-02-12 17:41:22 +01:00
if ( self . didAppLaunchFail ) {
2018-08-27 18:09:39 +02:00
OWSFailDebug ( @ "app launch failed" ) ;
2018-11-21 23:52:34 +01:00
completionHandler ( ) ;
return ;
}
2018-02-12 17:41:22 +01:00
2018-02-12 18:56:58 +01:00
// The docs for handleActionWithIdentifier : . . . state :
// "You must call [completionHandler] at the end of your method." .
// Nonetheless , it is presumably safe to call the completion handler
// later , after this method returns .
//
// https : // developer . apple . com / documentation / uikit / uiapplicationdelegate / 1623068 - application ? language = objc
2018-11-02 18:51:46 +01:00
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ {
2018-11-26 17:19:11 +01:00
if ( ! [ self . tsAccountManager isRegisteredAndReady ] ) {
OWSLogInfo ( @ "Ignoring action; app not ready." ) ;
completionHandler ( ) ;
return ;
}
2019-01-31 01:09:45 +01:00
[ self . legacyNotificationActionHandler handleNotificationResponseWithActionIdentifier : identifier
notification : notification
responseInfo : responseInfo
completionHandler : completionHandler ] ;
2018-02-12 18:56:58 +01:00
} ] ;
2015-09-01 19:22:08 +02:00
}
2018-03-05 21:13:19 +01:00
- ( void ) application : ( UIApplication * ) application
performFetchWithCompletionHandler : ( void ( ^ ) ( UIBackgroundFetchResult result ) ) completionHandler
{
2019-06-17 06:53:20 +02:00
NSLog ( @ "[Loki] Performing background fetch." ) ;
2018-11-02 18:51:46 +01:00
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ {
2019-05-10 03:17:09 +02:00
__block AnyPromise * job = [ AppEnvironment . shared . messageFetcherJob run ] . then ( ^ {
2019-06-17 06:53:20 +02:00
completionHandler ( UIBackgroundFetchResultNewData ) ;
job = nil ;
} ) . catch ( ^ {
completionHandler ( UIBackgroundFetchResultFailed ) ;
job = nil ;
2019-05-10 03:17:09 +02:00
} ) ;
[ job retainUntilComplete ] ;
2018-03-05 21:13:19 +01:00
} ] ;
}
2018-01-30 17:27:44 +01:00
- ( void ) versionMigrationsDidComplete
{
OWSAssertIsOnMainThread ( ) ;
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "versionMigrationsDidComplete" ) ;
2018-01-30 17:27:44 +01:00
self . areVersionMigrationsComplete = YES ;
[ self checkIfAppIsReady ] ;
}
2017-12-19 04:56:02 +01:00
- ( void ) storageIsReady
2017-06-15 19:43:18 +02:00
{
2018-01-26 21:53:26 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "storageIsReady" ) ;
2017-06-15 19:43:18 +02:00
2018-01-30 17:27:44 +01:00
[ self checkIfAppIsReady ] ;
}
- ( void ) checkIfAppIsReady
{
OWSAssertIsOnMainThread ( ) ;
// App isn ' t ready until storage is ready AND all version migrations are complete .
if ( ! self . areVersionMigrationsComplete ) {
return ;
}
if ( ! [ OWSStorage isStorageReady ] ) {
return ;
}
if ( [ AppReadiness isAppReady ] ) {
// Only mark the app as ready once .
return ;
}
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "checkIfAppIsReady" ) ;
2018-01-30 17:27:44 +01:00
2018-02-12 16:00:20 +01:00
// TODO : Once "app ready" logic is moved into AppSetup , move this line there .
2018-10-22 18:31:28 +02:00
[ self . profileManager ensureLocalProfileCached ] ;
2018-01-29 19:43:37 +01:00
// Note that this does much more than set a flag ;
// it will also run all deferred blocks .
2018-01-26 21:58:36 +01:00
[ AppReadiness setAppIsReady ] ;
2018-01-26 21:53:26 +01:00
2018-09-28 16:56:53 +02:00
if ( CurrentAppContext ( ) . isRunningTests ) {
OWSLogVerbose ( @ "Skipping post-launch logic in tests." ) ;
return ;
}
2018-10-22 18:31:28 +02:00
if ( [ self . tsAccountManager isRegistered ] ) {
2018-10-22 18:33:09 +02:00
OWSLogInfo ( @ "localNumber: %@" , [ TSAccountManager localNumber ] ) ;
2017-10-06 18:00:29 +02:00
// This should happen at any launch , background or foreground .
2019-05-08 07:51:08 +02:00
__unused AnyPromise * pushTokenpromise =
[ OWSSyncPushTokensJob runWithAccountManager : AppEnvironment . shared . accountManager
preferences : Environment . shared . preferences ] ;
2017-09-14 21:30:22 +02:00
}
2017-07-06 18:52:44 +02:00
[ DeviceSleepManager . sharedInstance removeBlockWithBlockObject : self ] ;
2018-08-02 21:18:40 +02:00
[ AppVersion . sharedInstance mainAppLaunchDidComplete ] ;
2017-06-16 16:52:36 +02:00
2018-10-23 02:55:39 +02:00
[ Environment . shared . audioSession setup ] ;
2017-08-29 19:07:34 +02:00
2018-10-22 17:42:53 +02:00
[ SSKEnvironment . shared . reachabilityManager setup ] ;
2018-10-20 19:51:48 +02:00
2018-08-31 19:44:13 +02:00
if ( ! Environment . shared . preferences . hasGeneratedThumbnails ) {
2018-10-22 18:31:28 +02:00
[ self . primaryStorage . newDatabaseConnection
2018-03-19 18:00:19 +01:00
asyncReadWithBlock : ^ ( YapDatabaseReadTransaction * _Nonnull transaction ) {
[ TSAttachmentStream enumerateCollectionObjectsUsingBlock : ^ ( id _Nonnull obj , BOOL * _Nonnull stop ) {
// no - op . It ' s sufficient to initWithCoder : each object .
} ] ;
}
completionBlock : ^ {
2018-08-31 19:44:13 +02:00
[ Environment . shared . preferences setHasGeneratedThumbnails : YES ] ;
2018-03-19 18:00:19 +01:00
} ] ;
}
2018-01-29 19:54:25 +01:00
# ifdef DEBUG
// A bug in orphan cleanup could be disastrous so let ' s only
// run it in DEBUG builds for a few releases .
//
// TODO : Release to production once we have analytics .
// TODO : Orphan cleanup is somewhat expensive - not least in doing a bunch
// of disk access . We might want to only run it "once per version"
// or something like that in production .
2018-08-02 21:18:40 +02:00
[ OWSOrphanDataCleaner auditOnLaunchIfNecessary ] ;
2018-01-29 19:54:25 +01:00
# endif
2018-10-22 18:31:28 +02:00
[ self . profileManager fetchLocalUsersProfile ] ;
[ self . readReceiptManager prepareCachedValues ] ;
2017-12-19 03:34:22 +01:00
// Disable the SAE until the main app has successfully completed launch process
// at least once in the post - SAE world .
[ OWSPreferences setIsReadyForAppExtensions ] ;
2017-12-19 04:56:02 +01:00
[ self ensureRootViewController ] ;
2018-03-06 16:10:22 +01:00
2018-10-22 18:31:28 +02:00
[ self . messageManager startObserving ] ;
2018-09-20 18:52:43 +02:00
2018-10-22 18:31:28 +02:00
[ self . udManager setup ] ;
2018-12-13 17:40:52 +01:00
[ self preheatDatabaseViews ] ;
2018-12-19 21:26:34 +01:00
2019-01-24 16:22:15 +01:00
[ self . primaryStorage touchDbAsync ] ;
2019-01-29 22:32:30 +01:00
// Every time the user upgrades to a new version :
//
// * Update account attributes .
// * Sync configuration .
2018-12-19 21:26:34 +01:00
if ( [ self . tsAccountManager isRegistered ] ) {
AppVersion * appVersion = AppVersion . sharedInstance ;
if ( appVersion . lastAppVersion . length > 0
&& ! [ appVersion . lastAppVersion isEqualToString : appVersion . currentAppVersion ] ) {
[ [ self . tsAccountManager updateAccountAttributes ] retainUntilComplete ] ;
2019-01-29 22:32:30 +01:00
[ SSKEnvironment . shared . syncManager sendConfigurationSyncMessage ] ;
2018-12-19 21:26:34 +01:00
}
}
2018-12-13 17:40:52 +01:00
}
- ( void ) preheatDatabaseViews
{
[ self . primaryStorage . uiDatabaseConnection asyncReadWithBlock : ^ ( YapDatabaseReadTransaction * transaction ) {
for ( NSString * viewName in @ [
TSThreadDatabaseViewExtensionName ,
TSMessageDatabaseViewExtensionName ,
TSThreadOutgoingMessageDatabaseViewExtensionName ,
2018-12-13 18:27:38 +01:00
TSUnreadDatabaseViewExtensionName ,
TSUnseenDatabaseViewExtensionName ,
TSThreadSpecialMessagesDatabaseViewExtensionName ,
2018-12-13 17:40:52 +01:00
] ) {
YapDatabaseViewTransaction * databaseView = [ transaction ext : viewName ] ;
OWSAssertDebug ( [ databaseView isKindOfClass : [ YapDatabaseViewTransaction class ] ] ) ;
}
} ] ;
2017-06-15 19:43:18 +02:00
}
2017-09-14 21:29:59 +02:00
- ( void ) registrationStateDidChange
{
2017-12-19 17:38:25 +01:00
OWSAssertIsOnMainThread ( ) ;
2017-09-14 21:29:59 +02:00
2018-08-27 18:00:28 +02:00
OWSLogInfo ( @ "registrationStateDidChange" ) ;
2017-09-14 21:29:59 +02:00
2018-03-05 21:13:19 +01:00
[ self enableBackgroundRefreshIfNecessary ] ;
2018-10-22 18:31:28 +02:00
if ( [ self . tsAccountManager isRegistered ] ) {
OWSLogInfo ( @ "localNumber: %@" , [ self . tsAccountManager localNumber ] ) ;
2017-09-14 21:29:59 +02:00
2018-10-22 18:31:28 +02:00
[ self . primaryStorage . newDatabaseConnection
2017-09-14 21:29:59 +02:00
readWriteWithBlock : ^ ( YapDatabaseReadWriteTransaction * _Nonnull transaction ) {
2017-12-07 16:33:27 +01:00
[ ExperienceUpgradeFinder . sharedManager markAllAsSeenWithTransaction : transaction ] ;
2017-09-14 21:29:59 +02:00
} ] ;
// Start running the disappearing messages job in case the newly registered user
// enables this feature
2018-10-22 18:31:28 +02:00
[ self . disappearingMessagesJob startIfNecessary ] ;
[ self . profileManager ensureLocalProfileCached ] ;
2019-05-20 03:17:58 +02:00
2019-05-20 06:52:26 +02:00
// Start Loki friend request expire job
2019-05-22 05:09:01 +02:00
[ self . lokiFriendRequestExpirationJob startIfNecessary ] ;
2017-09-14 22:01:10 +02:00
// For non - legacy users , read receipts are on by default .
2018-10-22 18:31:28 +02:00
[ self . readReceiptManager setAreReadReceiptsEnabled : YES ] ;
2019-06-11 08:22:35 +02:00
2019-08-29 07:21:45 +02:00
// Loki : Start long polling
[ self startLongPollerIfNeeded ] ;
2017-09-14 21:29:59 +02:00
}
}
2018-03-05 21:13:19 +01:00
- ( void ) registrationLockDidChange : ( NSNotification * ) notification
{
[ self enableBackgroundRefreshIfNecessary ] ;
}
2017-06-15 23:15:56 +02:00
- ( void ) ensureRootViewController
2017-06-15 19:43:18 +02:00
{
2018-01-26 21:53:26 +01:00
OWSAssertIsOnMainThread ( ) ;
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "ensureRootViewController" ) ;
2017-06-15 19:43:18 +02:00
2018-01-30 17:34:00 +01:00
if ( ! AppReadiness . isAppReady || self . hasInitialRootViewController ) {
2017-06-15 19:43:18 +02:00
return ;
}
2017-06-15 23:15:56 +02:00
self . hasInitialRootViewController = YES ;
2017-06-15 19:43:18 +02:00
2018-04-23 15:30:37 +02:00
NSTimeInterval startupDuration = CACurrentMediaTime ( ) - launchStartedAt ;
2018-08-27 18:51:32 +02:00
OWSLogInfo ( @ "Presenting app %.2f seconds after launch started." , startupDuration ) ;
2017-06-15 19:43:18 +02:00
2018-11-21 23:52:34 +01:00
UIViewController * rootViewController ;
2018-11-22 01:39:40 +01:00
BOOL navigationBarHidden = NO ;
2018-10-22 18:31:28 +02:00
if ( [ self . tsAccountManager isRegistered ] ) {
2018-11-21 23:52:34 +01:00
if ( self . backup . hasPendingRestoreDecision ) {
rootViewController = [ BackupRestoreViewController new ] ;
} else {
rootViewController = [ HomeViewController new ] ;
}
2017-06-15 23:15:56 +02:00
} else {
2019-02-20 16:23:11 +01:00
rootViewController = [ [ OnboardingController new ] initialViewController ] ;
2018-11-22 01:39:40 +01:00
navigationBarHidden = YES ;
2017-06-15 19:43:18 +02:00
}
2018-11-21 23:52:34 +01:00
OWSAssertDebug ( rootViewController ) ;
OWSNavigationController * navigationController =
[ [ OWSNavigationController alloc ] initWithRootViewController : rootViewController ] ;
2018-11-22 01:39:40 +01:00
navigationController . navigationBarHidden = navigationBarHidden ;
2018-11-21 23:52:34 +01:00
self . window . rootViewController = navigationController ;
2017-07-04 19:24:25 +02:00
[ AppUpdateNag . sharedInstance showAppUpgradeNagIfNecessary ] ;
2019-01-16 21:24:19 +01:00
[ UIViewController attemptRotationToDeviceOrientation ] ;
2017-06-15 19:43:18 +02:00
}
2018-05-18 15:37:59 +02:00
# pragma mark - status bar touches
- ( void ) touchesBegan : ( NSSet * ) touches withEvent : ( UIEvent * ) event
{
[ super touchesBegan : touches withEvent : event ] ;
CGPoint location = [ [ [ event allTouches ] anyObject ] locationInView : [ self window ] ] ;
CGRect statusBarFrame = [ UIApplication sharedApplication ] . statusBarFrame ;
if ( CGRectContainsPoint ( statusBarFrame , location ) ) {
2018-08-27 18:51:32 +02:00
OWSLogDebug ( @ "touched status bar" ) ;
2018-05-18 15:37:59 +02:00
[ [ NSNotificationCenter defaultCenter ] postNotificationName : TappedStatusBarNotification object : nil ] ;
}
}
2019-01-18 18:54:09 +01:00
# pragma mark - UNUserNotificationsDelegate
// The method will be called on the delegate only if the application is in the foreground . If the method is not
// implemented or the handler is not called in a timely manner then the notification will not be presented . The
// application can choose to have the notification presented as a sound , badge , alert and / or in the notification list .
// This decision should be based on whether the information in the notification is otherwise visible to the user .
- ( void ) userNotificationCenter : ( UNUserNotificationCenter * ) center
willPresentNotification : ( UNNotification * ) notification
withCompletionHandler : ( void ( ^ ) ( UNNotificationPresentationOptions options ) ) completionHandler
__IOS _AVAILABLE ( 10.0 ) __TVOS _AVAILABLE ( 10.0 ) __WATCHOS _AVAILABLE ( 3.0 ) __OSX _AVAILABLE ( 10.14 )
{
OWSLogInfo ( @ "" ) ;
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ ( ) {
2019-01-30 23:27:53 +01:00
// We need to respect the in - app notification sound preference . This method , which is called
// for modern UNUserNotification users , could be a place to do that , but since we ' d still
// need to handle this behavior for legacy UINotification users anyway , we "allow" all
// notification options here , and rely on the shared logic in NotificationPresenter to
// honor notification sound preferences for both modern and legacy users .
2019-01-18 18:54:09 +01:00
UNNotificationPresentationOptions options = UNNotificationPresentationOptionAlert
| UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound ;
completionHandler ( options ) ;
} ] ;
}
// The method will be called on the delegate when the user responded to the notification by opening the application ,
// dismissing the notification or choosing a UNNotificationAction . The delegate must be set before the application
// returns from application : didFinishLaunchingWithOptions : .
- ( void ) userNotificationCenter : ( UNUserNotificationCenter * ) center
didReceiveNotificationResponse : ( UNNotificationResponse * ) response
withCompletionHandler : ( void ( ^ ) ( void ) ) completionHandler __IOS _AVAILABLE ( 10.0 ) __WATCHOS _AVAILABLE ( 3.0 )
__OSX _AVAILABLE ( 10.14 ) __TVOS _PROHIBITED
{
OWSLogInfo ( @ "" ) ;
[ AppReadiness runNowOrWhenAppDidBecomeReady : ^ ( ) {
2019-01-31 01:09:45 +01:00
[ self . userNotificationActionHandler handleNotificationResponse : response completionHandler : completionHandler ] ;
2019-01-18 18:54:09 +01:00
} ] ;
}
// The method will be called on the delegate when the application is launched in response to the user ' s request to view
// in - app notification settings . Add UNAuthorizationOptionProvidesAppNotificationSettings as an option in
// requestAuthorizationWithOptions : completionHandler : to add a button to inline notification settings view and the
// notification settings view in Settings . The notification will be nil when opened from Settings .
- ( void ) userNotificationCenter : ( UNUserNotificationCenter * ) center
openSettingsForNotification : ( nullable UNNotification * ) notification __IOS _AVAILABLE ( 12.0 )
__OSX _AVAILABLE ( 10.14 ) __WATCHOS _PROHIBITED __TVOS _PROHIBITED
{
OWSLogInfo ( @ "" ) ;
}
2019-08-21 03:50:23 +02:00
# pragma mark - Loki
2019-08-29 07:21:45 +02:00
- ( void ) setUpLongPollerIfNeeded
{
if ( self . lokiLongPoller ! = nil ) { return ; }
NSString * userHexEncodedPublicKey = OWSIdentityManager . sharedManager . identityKeyPair . hexEncodedPublicKey ;
if ( userHexEncodedPublicKey = = nil ) { return ; }
self . lokiLongPoller = [ [ LKLongPoller alloc ] initOnMessagesReceived : ^ ( NSArray < SSKProtoEnvelope * > * messages ) {
for ( SSKProtoEnvelope * message in messages ) {
NSData * data = [ message serializedDataAndReturnError : nil ] ;
if ( data ! = nil ) {
[ SSKEnvironment . shared . messageReceiver handleReceivedEnvelopeData : data ] ;
} else {
NSLog ( @ "[Loki] Failed to deserialize envelope." ) ;
}
}
} ] ;
}
- ( void ) startLongPollerIfNeeded
{
[ self setUpLongPollerIfNeeded ] ;
[ self . lokiLongPoller startIfNeeded ] ;
}
- ( void ) stopLongPollerIfNeeded
{
[ self . lokiLongPoller stopIfNeeded ] ;
}
2019-08-27 05:42:57 +02:00
- ( LKGroupChat * ) lokiPublicChat
2019-08-27 02:44:00 +02:00
{
2019-08-28 08:07:14 +02:00
return [ [ LKGroupChat alloc ] initWithServerID : LKGroupChatAPI . publicChatServerID server : LKGroupChatAPI . publicChatServer displayName : NSLocalizedString ( @ "Loki Public Chat" , @ "" ) isDeletable : true ] ;
2019-08-27 05:42:57 +02:00
}
2019-08-27 08:48:53 +02:00
- ( LKRSSFeed * ) lokiNewsFeed
2019-08-27 05:42:57 +02:00
{
2019-08-27 08:48:53 +02:00
return [ [ LKRSSFeed alloc ] initWithId : @ "loki.network.feed" server : @ "https://loki.network/feed/" displayName : NSLocalizedString ( @ "Loki News" , @ "" ) isDeletable : true ] ;
2019-08-27 05:42:57 +02:00
}
2019-08-27 08:48:53 +02:00
- ( LKRSSFeed * ) lokiMessengerUpdatesFeed
2019-08-27 05:42:57 +02:00
{
2019-08-28 05:47:56 +02:00
return [ [ LKRSSFeed alloc ] initWithId : @ "loki.network.messenger-updates.feed" server : @ "https://loki.network/category/messenger-updates/feed/" displayName : NSLocalizedString ( @ "Loki Messenger Updates" , @ "" ) isDeletable : false ] ;
2019-08-27 02:44:00 +02:00
}
2019-08-27 05:42:57 +02:00
- ( void ) createGroupChatsIfNeeded
2019-08-27 02:44:00 +02:00
{
2019-08-27 08:48:53 +02:00
LKGroupChat * publicChat = self . lokiPublicChat ;
2019-08-27 04:45:01 +02:00
NSString * userHexEncodedPublicKey = OWSIdentityManager . sharedManager . identityKeyPair . hexEncodedPublicKey ;
2019-08-27 08:48:53 +02:00
NSString * userDefaultsKey = [ @ "isGroupChatSetUp." stringByAppendingString : publicChat . id ] ;
BOOL isChatSetUp = [ NSUserDefaults . standardUserDefaults boolForKey : userDefaultsKey ] ;
if ( ! isChatSetUp || ! publicChat . isDeletable ) {
TSGroupModel * group = [ [ TSGroupModel alloc ] initWithTitle : publicChat . displayName memberIds : @ [ userHexEncodedPublicKey , publicChat . server ] image : nil groupId : [ publicChat . id dataUsingEncoding : NSUTF8StringEncoding ] ] ;
__block TSGroupThread * thread ;
[ OWSPrimaryStorage . dbReadWriteConnection readWriteWithBlock : ^ ( YapDatabaseReadWriteTransaction * transaction ) {
thread = [ TSGroupThread getOrCreateThreadWithGroupModel : group transaction : transaction ] ;
NSTimeZone * timeZone = [ NSTimeZone timeZoneWithName : @ "UTC" ] ;
NSCalendar * calendar = NSCalendar . currentCalendar ;
[ calendar setTimeZone : timeZone ] ;
NSDateComponents * dateComponents = [ NSDateComponents new ] ;
[ dateComponents setYear : 999 ] ;
NSDate * date = [ calendar dateByAddingComponents : dateComponents toDate : [ NSDate new ] options : 0 ] ;
[ thread updateWithMutedUntilDate : date transaction : transaction ] ;
} ] ;
[ OWSProfileManager . sharedManager addThreadToProfileWhitelist : thread ] ;
[ NSUserDefaults . standardUserDefaults setBool : YES forKey : userDefaultsKey ] ;
}
}
- ( void ) createRSSFeedsIfNeeded
{
NSArray * feeds = @ [ self . lokiNewsFeed , self . lokiMessengerUpdatesFeed ] ;
NSString * userHexEncodedPublicKey = OWSIdentityManager . sharedManager . identityKeyPair . hexEncodedPublicKey ;
for ( LKRSSFeed * feed in feeds ) {
NSString * userDefaultsKey = [ @ "isRSSFeedSetUp." stringByAppendingString : feed . id ] ;
BOOL isFeedSetUp = [ NSUserDefaults . standardUserDefaults boolForKey : userDefaultsKey ] ;
if ( ! isFeedSetUp || ! feed . isDeletable ) {
TSGroupModel * group = [ [ TSGroupModel alloc ] initWithTitle : feed . displayName memberIds : @ [ userHexEncodedPublicKey , feed . server ] image : nil groupId : [ feed . id dataUsingEncoding : NSUTF8StringEncoding ] ] ;
2019-08-27 06:56:33 +02:00
__block TSGroupThread * thread ;
[ OWSPrimaryStorage . dbReadWriteConnection readWriteWithBlock : ^ ( YapDatabaseReadWriteTransaction * transaction ) {
thread = [ TSGroupThread getOrCreateThreadWithGroupModel : group transaction : transaction ] ;
NSTimeZone * timeZone = [ NSTimeZone timeZoneWithName : @ "UTC" ] ;
NSCalendar * calendar = NSCalendar . currentCalendar ;
[ calendar setTimeZone : timeZone ] ;
NSDateComponents * dateComponents = [ NSDateComponents new ] ;
[ dateComponents setYear : 999 ] ;
NSDate * date = [ calendar dateByAddingComponents : dateComponents toDate : [ NSDate new ] options : 0 ] ;
[ thread updateWithMutedUntilDate : date transaction : transaction ] ;
} ] ;
[ OWSProfileManager . sharedManager addThreadToProfileWhitelist : thread ] ;
[ NSUserDefaults . standardUserDefaults setBool : YES forKey : userDefaultsKey ] ;
}
2019-08-27 02:44:00 +02:00
}
}
2019-08-27 05:42:57 +02:00
- ( void ) createGroupChatPollersIfNeeded
2019-08-27 02:44:00 +02:00
{
2019-09-12 02:06:42 +02:00
// Only create the group chat pollers if their threads aren ' t deleted
2019-09-11 02:39:32 +02:00
__block TSGroupThread * thread ;
2019-09-12 02:06:42 +02:00
[ OWSPrimaryStorage . dbReadConnection readWithBlock : ^ ( YapDatabaseReadTransaction * transaction ) {
2019-09-11 02:39:32 +02:00
thread = [ TSGroupThread threadWithGroupId : [ self . lokiPublicChat . id dataUsingEncoding : NSUTF8StringEncoding ] transaction : transaction ] ;
} ] ;
if ( thread ! = nil && self . lokiPublicChatPoller = = nil ) {
self . lokiPublicChatPoller = [ [ LKGroupChatPoller alloc ] initForGroup : self . lokiPublicChat ] ;
}
2019-08-27 08:48:53 +02:00
}
- ( void ) createRSSFeedPollersIfNeeded
{
2019-09-12 02:06:42 +02:00
// Only create the RSS feed pollers if their threads aren ' t deleted
2019-09-11 02:39:32 +02:00
__block TSGroupThread * lokiNewsFeedThread ;
2019-09-12 02:06:42 +02:00
[ OWSPrimaryStorage . dbReadConnection readWithBlock : ^ ( YapDatabaseReadTransaction * transaction ) {
2019-09-11 02:39:32 +02:00
lokiNewsFeedThread = [ TSGroupThread threadWithGroupId : [ self . lokiNewsFeed . id dataUsingEncoding : NSUTF8StringEncoding ] transaction : transaction ] ;
} ] ;
if ( lokiNewsFeedThread ! = nil && self . lokiNewsFeedPoller = = nil ) {
self . lokiNewsFeedPoller = [ [ LKRSSFeedPoller alloc ] initForFeed : self . lokiNewsFeed ] ;
}
2019-09-12 02:06:42 +02:00
// The user can ' t delete the Loki Messenger Updates RSS feed
if ( self . lokiMessengerUpdatesFeedPoller = = nil ) {
self . lokiMessengerUpdatesFeedPoller = [ [ LKRSSFeedPoller alloc ] initForFeed : self . lokiMessengerUpdatesFeed ] ;
}
2019-08-21 03:50:23 +02:00
}
2019-08-27 05:42:57 +02:00
- ( void ) startGroupChatPollersIfNeeded
2019-08-21 03:50:23 +02:00
{
2019-08-27 05:42:57 +02:00
[ self createGroupChatPollersIfNeeded ] ;
2019-09-11 02:39:32 +02:00
if ( self . lokiPublicChatPoller ! = nil ) { [ self . lokiPublicChatPoller startIfNeeded ] ; }
2019-08-27 08:48:53 +02:00
}
- ( void ) startRSSFeedPollersIfNeeded
{
[ self createRSSFeedPollersIfNeeded ] ;
2019-09-11 02:39:32 +02:00
if ( self . lokiNewsFeedPoller ! = nil ) { [ self . lokiNewsFeedPoller startIfNeeded ] ; }
if ( self . lokiMessengerUpdatesFeedPoller ! = nil ) { [ self . lokiMessengerUpdatesFeedPoller startIfNeeded ] ; }
}
- ( void ) handleThreadDeleted : ( NSNotification * ) notification {
NSDictionary * userInfo = notification . userInfo ;
2019-09-12 02:06:42 +02:00
NSString * threadID = ( NSString * ) userInfo [ @ "threadId" ] ;
if ( threadID = = nil ) { return ; }
if ( [ threadID isEqualToString : [ TSGroupThread threadIdFromGroupId : [ self . lokiPublicChat . id dataUsingEncoding : NSUTF8StringEncoding ] ] ] && self . lokiPublicChatPoller ! = nil ) {
2019-09-11 02:39:32 +02:00
[ self . lokiPublicChatPoller stop ] ;
self . lokiPublicChatPoller = nil ;
}
2019-09-12 02:06:42 +02:00
if ( [ threadID isEqualToString : [ TSGroupThread threadIdFromGroupId : [ self . lokiNewsFeed . id dataUsingEncoding : NSUTF8StringEncoding ] ] ] && self . lokiNewsFeedPoller ! = nil ) {
2019-09-11 02:39:32 +02:00
[ self . lokiNewsFeedPoller stop ] ;
self . lokiNewsFeedPoller = nil ;
}
2019-08-21 03:50:23 +02:00
}
2014-05-06 19:41:08 +02:00
@ end