2017-01-17 22:01:19 +01:00
|
|
|
//
|
|
|
|
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
|
|
|
//
|
|
|
|
|
2014-05-06 19:41:08 +02:00
|
|
|
#import "AppDelegate.h"
|
2015-08-24 00:28:50 +02:00
|
|
|
#import "AppStoreRating.h"
|
2017-07-04 19:24:25 +02:00
|
|
|
#import "AppUpdateNag.h"
|
2015-12-22 12:45:09 +01:00
|
|
|
#import "CodeVerificationViewController.h"
|
2014-08-09 01:01:05 +02:00
|
|
|
#import "DebugLogger.h"
|
2014-08-02 01:24:26 +02:00
|
|
|
#import "Environment.h"
|
2017-11-29 20:51:39 +01:00
|
|
|
#import "MainAppContext.h"
|
2015-12-22 12:45:09 +01:00
|
|
|
#import "NotificationsManager.h"
|
2016-09-01 21:30:46 +02:00
|
|
|
#import "OWSContactsManager.h"
|
2017-04-18 23:06:21 +02:00
|
|
|
#import "OWSContactsSyncing.h"
|
2017-08-17 18:37:21 +02:00
|
|
|
#import "OWSNavigationController.h"
|
2017-09-14 21:45:04 +02:00
|
|
|
#import "OWSPreferences.h"
|
2017-03-23 14:55:39 +01:00
|
|
|
#import "Pastelog.h"
|
2014-08-01 07:53:58 +02:00
|
|
|
#import "PushManager.h"
|
2017-05-24 21:55:22 +02:00
|
|
|
#import "RegistrationViewController.h"
|
2014-05-06 19:41:08 +02:00
|
|
|
#import "Release.h"
|
2016-10-10 22:02:09 +02:00
|
|
|
#import "Signal-Swift.h"
|
2017-12-04 16:35:47 +01:00
|
|
|
#import "SignalApp.h"
|
2017-07-10 22:04:03 +02:00
|
|
|
#import "SignalsNavigationController.h"
|
2014-08-02 01:24:26 +02:00
|
|
|
#import "VersionMigrations.h"
|
2017-04-28 18:18:42 +02:00
|
|
|
#import "ViewControllerUtils.h"
|
2017-01-23 00:14:00 +01:00
|
|
|
#import <AxolotlKit/SessionCipher.h>
|
2017-12-07 19:53:13 +01:00
|
|
|
#import <SignalMessaging/AppSetup.h>
|
2017-12-01 21:17:29 +01:00
|
|
|
#import <SignalMessaging/OWSMath.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-11-28 19:46:26 +01:00
|
|
|
#import <SignalServiceKit/NSUserDefaults+OWS.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>
|
2017-09-14 17:00:30 +02:00
|
|
|
#import <SignalServiceKit/OWSMessageManager.h>
|
2016-10-14 22:59:58 +02:00
|
|
|
#import <SignalServiceKit/OWSMessageSender.h>
|
2017-10-22 03:16:31 +02:00
|
|
|
#import <SignalServiceKit/OWSOrphanedDataCleaner.h>
|
2017-09-21 22:58:07 +02:00
|
|
|
#import <SignalServiceKit/OWSReadReceiptManager.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>
|
|
|
|
#import <SignalServiceKit/TSStorageManager+Calling.h>
|
|
|
|
#import <SignalServiceKit/TextSecureKitEnv.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
|
|
|
|
2017-11-29 20:51:39 +01:00
|
|
|
@interface AppDelegate ()
|
2014-05-06 19:41:08 +02:00
|
|
|
|
2017-06-15 19:43:18 +02:00
|
|
|
@property (nonatomic) UIWindow *screenProtectionWindow;
|
2017-06-15 23:15:56 +02:00
|
|
|
@property (nonatomic) BOOL hasInitialRootViewController;
|
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;
|
|
|
|
|
2017-01-17 23:10:57 +01:00
|
|
|
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ applicationDidEnterBackground.", self.logTag);
|
|
|
|
|
2017-02-14 17:05:59 +01:00
|
|
|
[DDLog flushLog];
|
2017-01-17 23:10:57 +01:00
|
|
|
}
|
|
|
|
|
2015-09-01 19:22:08 +02:00
|
|
|
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ applicationWillEnterForeground.", self.logTag);
|
|
|
|
|
2015-09-01 19:22:08 +02:00
|
|
|
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
|
|
|
|
}
|
|
|
|
|
2017-01-23 19:31:23 +01:00
|
|
|
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
|
|
|
|
{
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ applicationDidReceiveMemoryWarning.", self.logTag);
|
2017-01-23 19:31:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)applicationWillTerminate:(UIApplication *)application
|
|
|
|
{
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ applicationWillTerminate.", self.logTag);
|
|
|
|
|
2017-02-14 17:05:59 +01:00
|
|
|
[DDLog flushLog];
|
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
|
|
|
|
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
|
|
|
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ application: didFinishLaunchingWithOptions.", self.logTag);
|
2017-01-24 20:40:44 +01:00
|
|
|
|
2017-11-30 16:02:04 +01:00
|
|
|
// We need to do this _after_ we set up logging but _before_ we do
|
2017-11-28 19:46:26 +01:00
|
|
|
// anything else.
|
2017-11-28 22:30:08 +01:00
|
|
|
[self ensureIsReadyForAppExtensions];
|
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
|
|
|
|
|
2017-05-09 21:58:40 +02:00
|
|
|
[AppVersion instance];
|
|
|
|
|
2017-09-14 21:24:31 +02:00
|
|
|
[self startupLogging];
|
|
|
|
|
2017-12-01 21:17:29 +01:00
|
|
|
SetRandFunctionSeed();
|
2017-02-10 22:24:48 +01:00
|
|
|
|
2017-01-23 23:26:35 +01:00
|
|
|
// XXX - careful when moving this. It must happen before we initialize TSStorageManager.
|
2017-12-05 17:35:43 +01:00
|
|
|
[self verifyDBKeysAvailableBeforeBackgroundLaunch];
|
2017-01-23 23:26:35 +01:00
|
|
|
|
2017-07-06 18:52:44 +02:00
|
|
|
// Prevent the device from sleeping during database view async registration
|
|
|
|
// (e.g. long database upgrades).
|
|
|
|
//
|
|
|
|
// This block will be cleared in databaseViewRegistrationComplete.
|
|
|
|
[DeviceSleepManager.sharedInstance addBlockWithBlockObject:self];
|
|
|
|
|
2017-12-07 19:53:13 +01:00
|
|
|
[AppSetup setupEnvironment:^{
|
|
|
|
return SignalApp.sharedApp.callMessageHandler;
|
|
|
|
}
|
|
|
|
notificationsProtocolBlock:^{
|
|
|
|
return SignalApp.sharedApp.notificationsManager;
|
|
|
|
}];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2016-11-15 18:51:55 +01:00
|
|
|
[UIUtil applySignalAppearence];
|
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;
|
|
|
|
}
|
|
|
|
|
2017-05-24 21:55:22 +02:00
|
|
|
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
|
|
|
|
2017-06-15 23:15:56 +02:00
|
|
|
// Show the launch screen until the async database view registrations are complete.
|
|
|
|
self.window.rootViewController = [self loadingRootViewController];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-02-20 17:02:31 +01:00
|
|
|
[self.window makeKeyAndVisible];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2017-03-13 14:33:58 +01:00
|
|
|
// performUpdateCheck must be invoked after Environment has been initialized because
|
|
|
|
// upgrade process may depend on Environment.
|
|
|
|
[VersionMigrations performUpdateCheck];
|
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) {
|
2014-07-20 00:25:22 +02:00
|
|
|
DDLogInfo(@"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
|
|
|
|
2016-08-10 15:58:34 +02:00
|
|
|
[self prepareScreenProtection];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2017-12-07 19:53:13 +01:00
|
|
|
// Ensure OWSContactsSyncing is instantiated.
|
2017-12-06 21:53:19 +01:00
|
|
|
[OWSContactsSyncing sharedManager];
|
2017-04-18 23:06:21 +02:00
|
|
|
|
2017-06-15 19:43:18 +02:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(databaseViewRegistrationComplete)
|
2017-12-04 18:38:44 +01:00
|
|
|
name:DatabaseViewRegistrationCompleteNotification
|
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];
|
2017-06-15 19:43:18 +02:00
|
|
|
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ application: didFinishLaunchingWithOptions completed.", self.logTag);
|
2017-06-20 18:05:06 +02:00
|
|
|
|
2017-07-21 17:49:38 +02:00
|
|
|
[OWSAnalytics appLaunchDidBegin];
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (![TSStorageManager isDatabasePasswordAccessible]) {
|
|
|
|
DDLogInfo(
|
|
|
|
@"%@ exiting because we are in the background and the database password is not accessible.", self.logTag);
|
|
|
|
[DDLog flushLog];
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-28 22:30:08 +01:00
|
|
|
- (void)ensureIsReadyForAppExtensions
|
2017-11-28 19:46:26 +01:00
|
|
|
{
|
2017-11-28 22:30:08 +01:00
|
|
|
if ([OWSPreferences isReadyForAppExtensions]) {
|
2017-11-28 19:46:26 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
[NSUserDefaults migrateToSharedUserDefaults];
|
|
|
|
|
|
|
|
[TSStorageManager migrateToSharedData];
|
|
|
|
[OWSProfileManager migrateToSharedData];
|
|
|
|
[TSAttachmentStream migrateToSharedData];
|
|
|
|
|
2017-11-28 22:30:08 +01:00
|
|
|
[OWSPreferences setIsReadyForAppExtensions:YES];
|
2017-11-28 19:46:26 +01:00
|
|
|
}
|
|
|
|
|
2017-09-14 21:24:31 +02:00
|
|
|
- (void)startupLogging
|
|
|
|
{
|
|
|
|
DDLogInfo(@"iOS Version: %@", [UIDevice currentDevice].systemVersion);
|
|
|
|
|
|
|
|
NSString *localeIdentifier = [NSLocale.currentLocale objectForKey:NSLocaleIdentifier];
|
|
|
|
if (localeIdentifier.length > 0) {
|
|
|
|
DDLogInfo(@"Locale Identifier: %@", localeIdentifier);
|
|
|
|
}
|
|
|
|
NSString *countryCode = [NSLocale.currentLocale objectForKey:NSLocaleCountryCode];
|
|
|
|
if (countryCode.length > 0) {
|
|
|
|
DDLogInfo(@"Country Code: %@", countryCode);
|
|
|
|
}
|
|
|
|
NSString *languageCode = [NSLocale.currentLocale objectForKey:NSLocaleLanguageCode];
|
|
|
|
if (languageCode.length > 0) {
|
|
|
|
DDLogInfo(@"Language Code: %@", languageCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-15 23:15:56 +02:00
|
|
|
- (UIViewController *)loadingRootViewController
|
|
|
|
{
|
|
|
|
UIViewController *viewController =
|
|
|
|
[[UIStoryboard storyboardWithName:@"Launch Screen" bundle:nil] instantiateInitialViewController];
|
|
|
|
|
2017-07-06 21:10:47 +02:00
|
|
|
NSString *lastLaunchedAppVersion = AppVersion.instance.lastAppVersion;
|
2017-06-20 22:53:02 +02:00
|
|
|
NSString *lastCompletedLaunchAppVersion = AppVersion.instance.lastCompletedLaunchAppVersion;
|
2017-09-15 21:28:44 +02:00
|
|
|
// Every time we change or add a database view in such a way that
|
|
|
|
// might cause a delay on launch, we need to bump this constant.
|
2017-07-27 17:53:29 +02:00
|
|
|
//
|
2017-09-22 05:42:42 +02:00
|
|
|
// We added a number of database views in v2.13.0.
|
|
|
|
NSString *kLastVersionWithDatabaseViewChange = @"2.13.0";
|
2017-07-06 21:10:47 +02:00
|
|
|
BOOL mayNeedUpgrade = ([TSAccountManager isRegistered] && lastLaunchedAppVersion
|
2017-07-06 20:54:00 +02:00
|
|
|
&& (!lastCompletedLaunchAppVersion ||
|
|
|
|
[VersionMigrations isVersion:lastCompletedLaunchAppVersion
|
2017-07-06 21:10:47 +02:00
|
|
|
lessThan:kLastVersionWithDatabaseViewChange]));
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ mayNeedUpgrade: %d", self.logTag, mayNeedUpgrade);
|
2017-07-06 21:10:47 +02:00
|
|
|
if (mayNeedUpgrade) {
|
2017-06-15 23:15:56 +02:00
|
|
|
UIView *rootView = viewController.view;
|
|
|
|
UIImageView *iconView = nil;
|
|
|
|
for (UIView *subview in viewController.view.subviews) {
|
|
|
|
if ([subview isKindOfClass:[UIImageView class]]) {
|
|
|
|
iconView = (UIImageView *)subview;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!iconView) {
|
|
|
|
OWSFail(@"Database view registration overlay has unexpected contents.");
|
|
|
|
} else {
|
2017-06-16 16:39:51 +02:00
|
|
|
UILabel *bottomLabel = [UILabel new];
|
|
|
|
bottomLabel.text = NSLocalizedString(
|
|
|
|
@"DATABASE_VIEW_OVERLAY_SUBTITLE", @"Subtitle shown while the app is updating its database.");
|
|
|
|
bottomLabel.font = [UIFont ows_mediumFontWithSize:16.f];
|
|
|
|
bottomLabel.textColor = [UIColor whiteColor];
|
|
|
|
bottomLabel.numberOfLines = 0;
|
|
|
|
bottomLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
|
|
bottomLabel.textAlignment = NSTextAlignmentCenter;
|
|
|
|
[rootView addSubview:bottomLabel];
|
|
|
|
|
|
|
|
UILabel *topLabel = [UILabel new];
|
|
|
|
topLabel.text = NSLocalizedString(
|
|
|
|
@"DATABASE_VIEW_OVERLAY_TITLE", @"Title shown while the app is updating its database.");
|
|
|
|
topLabel.font = [UIFont ows_mediumFontWithSize:20.f];
|
|
|
|
topLabel.textColor = [UIColor whiteColor];
|
|
|
|
topLabel.numberOfLines = 0;
|
|
|
|
topLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
|
|
topLabel.textAlignment = NSTextAlignmentCenter;
|
|
|
|
[rootView addSubview:topLabel];
|
|
|
|
|
|
|
|
[bottomLabel autoPinWidthToSuperviewWithMargin:20.f];
|
|
|
|
[topLabel autoPinWidthToSuperviewWithMargin:20.f];
|
|
|
|
[bottomLabel autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:topLabel withOffset:10.f];
|
|
|
|
[iconView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:bottomLabel withOffset:40.f];
|
2017-06-15 23:15:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return viewController;
|
|
|
|
}
|
|
|
|
|
2016-09-14 18:19:05 +02:00
|
|
|
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
|
|
|
{
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ registered vanilla push token: %@", self.logTag, deviceToken);
|
Rework push registration
== Account Registration ==
Not complete until push tokens are uploaded
== Remote Notifications Registration ==
Extracted from PushManager
- wait for notification-settings registration to complete before
requesting push tokens, otherwise it's possible token requests will
be ignored.
- Less state required for push notification callbacks, specifically, we
no longer need to ensure we've created a promise before the
registration delegate methods get called.
- no more TOCFuture in Signal-iOS (still in SSK for now). It's not in
cases of inexplicable behavior - one a recently, push notification
premature free, in redphone, and more popular use, and I've seen two
futures inexplicably being nil. Instead, let's consolidate around
PromiseKit for popularly used, maintained, strongly-typed futures.
- separate logic for registering for vanilla push/voip notifications
(few dependencies) from responding to UILocalNotifications (lots of
dependencies). Ultimately I'd like to consolidate the remaining
UILocalNotifications logic with the existing NotificationsManager
== Misc ==
more debug logging
more uniform logging
remove stale logic around newly registered user
// FREEBIE
2017-09-20 23:47:12 +02:00
|
|
|
[PushRegistrationManager.sharedManager 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
|
|
|
|
{
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogError(@"%@ failed to register vanilla push token with error: %@", self.logTag, error);
|
2015-01-18 10:28:11 +01:00
|
|
|
#ifdef DEBUG
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(
|
|
|
|
@"%@ We're in debug mode. Faking success for remote registration with a fake push identifier", self.logTag);
|
Rework push registration
== Account Registration ==
Not complete until push tokens are uploaded
== Remote Notifications Registration ==
Extracted from PushManager
- wait for notification-settings registration to complete before
requesting push tokens, otherwise it's possible token requests will
be ignored.
- Less state required for push notification callbacks, specifically, we
no longer need to ensure we've created a promise before the
registration delegate methods get called.
- no more TOCFuture in Signal-iOS (still in SSK for now). It's not in
cases of inexplicable behavior - one a recently, push notification
premature free, in redphone, and more popular use, and I've seen two
futures inexplicably being nil. Instead, let's consolidate around
PromiseKit for popularly used, maintained, strongly-typed futures.
- separate logic for registering for vanilla push/voip notifications
(few dependencies) from responding to UILocalNotifications (lots of
dependencies). Ultimately I'd like to consolidate the remaining
UILocalNotifications logic with the existing NotificationsManager
== Misc ==
more debug logging
more uniform logging
remove stale logic around newly registered user
// FREEBIE
2017-09-20 23:47:12 +02:00
|
|
|
[PushRegistrationManager.sharedManager 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]);
|
Rework push registration
== Account Registration ==
Not complete until push tokens are uploaded
== Remote Notifications Registration ==
Extracted from PushManager
- wait for notification-settings registration to complete before
requesting push tokens, otherwise it's possible token requests will
be ignored.
- Less state required for push notification callbacks, specifically, we
no longer need to ensure we've created a promise before the
registration delegate methods get called.
- no more TOCFuture in Signal-iOS (still in SSK for now). It's not in
cases of inexplicable behavior - one a recently, push notification
premature free, in redphone, and more popular use, and I've seen two
futures inexplicably being nil. Instead, let's consolidate around
PromiseKit for popularly used, maintained, strongly-typed futures.
- separate logic for registering for vanilla push/voip notifications
(few dependencies) from responding to UILocalNotifications (lots of
dependencies). Ultimately I'd like to consolidate the remaining
UILocalNotifications logic with the existing NotificationsManager
== Misc ==
more debug logging
more uniform logging
remove stale logic around newly registered user
// FREEBIE
2017-09-20 23:47:12 +02:00
|
|
|
[PushRegistrationManager.sharedManager 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
|
|
|
|
{
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ registered user notification settings", self.logTag);
|
Rework push registration
== Account Registration ==
Not complete until push tokens are uploaded
== Remote Notifications Registration ==
Extracted from PushManager
- wait for notification-settings registration to complete before
requesting push tokens, otherwise it's possible token requests will
be ignored.
- Less state required for push notification callbacks, specifically, we
no longer need to ensure we've created a promise before the
registration delegate methods get called.
- no more TOCFuture in Signal-iOS (still in SSK for now). It's not in
cases of inexplicable behavior - one a recently, push notification
premature free, in redphone, and more popular use, and I've seen two
futures inexplicably being nil. Instead, let's consolidate around
PromiseKit for popularly used, maintained, strongly-typed futures.
- separate logic for registering for vanilla push/voip notifications
(few dependencies) from responding to UILocalNotifications (lots of
dependencies). Ultimately I'd like to consolidate the remaining
UILocalNotifications logic with the existing NotificationsManager
== Misc ==
more debug logging
more uniform logging
remove stale logic around newly registered user
// FREEBIE
2017-09-20 23:47:12 +02:00
|
|
|
[PushRegistrationManager.sharedManager didRegisterUserNotificationSettings];
|
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
|
|
|
|
{
|
2015-07-10 15:00:14 +02:00
|
|
|
if ([url.scheme isEqualToString:kURLSchemeSGNLKey]) {
|
|
|
|
if ([url.host hasPrefix:kURLHostVerifyPrefix] && ![TSAccountManager isRegistered]) {
|
2017-12-04 16:56:59 +01:00
|
|
|
id signupController = SignalApp.sharedApp.signUpFlowNavigationController;
|
2014-12-31 21:30:20 +01:00
|
|
|
if ([signupController isKindOfClass:[UINavigationController class]]) {
|
2015-12-22 12:45:09 +01:00
|
|
|
UINavigationController *navController = (UINavigationController *)signupController;
|
2014-12-31 21:30:20 +01:00
|
|
|
UIViewController *controller = [navController.childViewControllers lastObject];
|
|
|
|
if ([controller isKindOfClass:[CodeVerificationViewController class]]) {
|
2015-12-22 12:45:09 +01:00
|
|
|
CodeVerificationViewController *cvvc = (CodeVerificationViewController *)controller;
|
|
|
|
NSString *verificationCode = [url.path substringFromIndex:1];
|
2017-02-09 18:02:17 +01:00
|
|
|
[cvvc setVerificationCodeAndTryToVerify:verificationCode];
|
2017-12-07 20:52:38 +01:00
|
|
|
return YES;
|
2015-12-22 12:45:09 +01:00
|
|
|
} else {
|
|
|
|
DDLogWarn(@"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 {
|
2017-12-07 20:52:38 +01:00
|
|
|
OWSFail(@"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 {
|
2017-12-07 20:52:38 +01:00
|
|
|
OWSFail(@"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 {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ applicationDidBecomeActive.", self.logTag);
|
2017-01-17 23:10:57 +01:00
|
|
|
|
2017-12-04 18:38:44 +01:00
|
|
|
if (CurrentAppContext().isRunningTests) {
|
2015-12-24 18:20:04 +01:00
|
|
|
return;
|
|
|
|
}
|
2017-01-03 23:09:50 +01:00
|
|
|
|
2015-04-14 21:49:00 +02:00
|
|
|
[self removeScreenProtection];
|
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
|
|
|
|
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();
|
|
|
|
|
|
|
|
if ([TSAccountManager isRegistered]) {
|
|
|
|
// 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), ^{
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ running post launch block for registered user: %@",
|
|
|
|
self.logTag,
|
|
|
|
[TSAccountManager localNumber]);
|
|
|
|
|
2017-08-04 15:42:15 +02:00
|
|
|
// Clean up any messages that expired since last launch immediately
|
|
|
|
// and continue cleaning in the background.
|
|
|
|
[[OWSDisappearingMessagesJob sharedJob] startIfNecessary];
|
2017-09-20 17:15:46 +02:00
|
|
|
|
|
|
|
// TODO remove this once we're sure our app boot process is coherent.
|
|
|
|
// Currently this happens *before* db registration is complete when
|
|
|
|
// launching the app directly, but *after* db registration is complete when
|
|
|
|
// the app is launched in the background, e.g. from a voip notification.
|
2017-09-07 16:28:19 +02:00
|
|
|
[[OWSProfileManager sharedManager] ensureLocalProfileCached];
|
2017-07-06 16:33:37 +02:00
|
|
|
|
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.
|
|
|
|
[[[OWSFailedMessagesJob alloc] initWithStorageManager:[TSStorageManager sharedManager]] run];
|
|
|
|
[[[OWSFailedAttachmentDownloadsJob alloc] initWithStorageManager:[TSStorageManager sharedManager]] run];
|
|
|
|
|
|
|
|
[AppStoreRating setupRatingLibrary];
|
|
|
|
});
|
|
|
|
} else {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ running post launch block for unregistered user.", self.logTag);
|
2017-08-04 15:42:15 +02:00
|
|
|
|
|
|
|
// Unregistered user should have no unread messages. e.g. if you delete your account.
|
|
|
|
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
|
|
|
|
|
|
|
|
[TSSocketManager requestSocketOpen];
|
|
|
|
|
|
|
|
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...
|
|
|
|
if ([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(), ^{
|
|
|
|
[TSSocketManager requestSocketOpen];
|
2017-12-04 16:35:47 +01:00
|
|
|
[[Environment current].contactsManager fetchSystemContactsOnceIfAlreadyAuthorized];
|
2017-08-04 15:42:15 +02:00
|
|
|
// This will fetch new messages, if we're using domain fronting.
|
|
|
|
[[PushManager sharedManager] applicationDidBecomeActive];
|
2017-10-11 16:23:24 +02:00
|
|
|
|
|
|
|
if (![UIApplication sharedApplication].isRegisteredForRemoteNotifications) {
|
|
|
|
DDLogInfo(
|
2017-11-08 19:03:51 +01:00
|
|
|
@"%@ Retrying to register for remote notifications since user hasn't registered yet.", self.logTag);
|
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.
|
|
|
|
__unused AnyPromise *promise =
|
2017-12-04 16:35:47 +01:00
|
|
|
[OWSSyncPushTokensJob runWithAccountManager:SignalApp.sharedApp.accountManager
|
2017-10-11 16:23:24 +02:00
|
|
|
preferences:[Environment preferences]];
|
|
|
|
}
|
2017-08-04 15:42:15 +02:00
|
|
|
});
|
2017-10-11 16:23:24 +02:00
|
|
|
|
2017-08-04 15:42:15 +02:00
|
|
|
}
|
2017-07-06 00:12:06 +02:00
|
|
|
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ applicationDidBecomeActive completed.", self.logTag);
|
2014-12-01 23:24:35 +01:00
|
|
|
}
|
|
|
|
|
2015-04-14 21:49:00 +02:00
|
|
|
- (void)applicationWillResignActive:(UIApplication *)application {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ applicationWillResignActive.", self.logTag);
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2017-05-25 16:34:55 +02:00
|
|
|
UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:nil];
|
2015-09-01 19:22:08 +02:00
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
2017-05-25 16:34:55 +02:00
|
|
|
if ([TSAccountManager isRegistered]) {
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
|
|
|
|
// If app has not re-entered active, show screen protection if necessary.
|
|
|
|
[self showScreenProtection];
|
|
|
|
}
|
2017-12-04 16:35:47 +01:00
|
|
|
[SignalApp.sharedApp.homeViewController updateInboxCountLabel];
|
2017-05-25 16:34:55 +02:00
|
|
|
[application endBackgroundTask:bgTask];
|
|
|
|
});
|
|
|
|
}
|
2015-09-01 19:22:08 +02:00
|
|
|
});
|
2017-05-25 16:34:55 +02:00
|
|
|
|
2017-02-14 17:05:59 +01:00
|
|
|
[DDLog flushLog];
|
2014-09-15 01:32:19 +02:00
|
|
|
}
|
|
|
|
|
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 {
|
2015-10-31 23:13:28 +01:00
|
|
|
if ([TSAccountManager isRegistered]) {
|
2017-12-04 16:35:47 +01:00
|
|
|
[SignalApp.sharedApp.homeViewController showNewConversationView];
|
2015-10-31 23:13:28 +01:00
|
|
|
completionHandler(YES);
|
2015-12-24 13:07:50 +01:00
|
|
|
} else {
|
|
|
|
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){
|
|
|
|
|
|
|
|
}]];
|
2017-09-12 23:52:23 +02:00
|
|
|
UIViewController *fromViewController = [[UIApplication sharedApplication] frontmostViewController];
|
|
|
|
[fromViewController presentViewController:controller
|
|
|
|
animated:YES
|
|
|
|
completion:^{
|
|
|
|
completionHandler(NO);
|
|
|
|
}];
|
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.
|
|
|
|
*/
|
|
|
|
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray * _Nullable))restorationHandler
|
|
|
|
{
|
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)) {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogError(@"%@ unexpectedly received INStartVideoCallIntent pre iOS10", self.logTag);
|
2017-02-03 17:25:57 +01:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ got start video call intent", self.logTag);
|
2017-02-03 17:25:57 +01:00
|
|
|
|
|
|
|
INInteraction *interaction = [userActivity interaction];
|
|
|
|
INIntent *intent = interaction.intent;
|
|
|
|
|
|
|
|
if (![intent isKindOfClass:[INStartVideoCallIntent class]]) {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogError(@"%@ unexpected class for start call video: %@", self.logTag, 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) {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ unable to find handle in startCallIntent: %@", self.logTag, startCallIntent);
|
2017-02-03 17:25:57 +01:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2017-02-22 15:50:41 +01:00
|
|
|
NSString *_Nullable phoneNumber = handle;
|
|
|
|
if ([handle hasPrefix:CallKitCallManager.kAnonymousCallHandlePrefix]) {
|
|
|
|
phoneNumber = [[TSStorageManager sharedManager] phoneNumberForCallKitId:handle];
|
|
|
|
if (phoneNumber.length < 1) {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ ignoring attempt to initiate video call to unknown anonymous signal user.", self.logTag);
|
2017-02-22 15:50:41 +01:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-03 17:25:57 +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.
|
2017-12-04 16:35:47 +01:00
|
|
|
if (SignalApp.sharedApp.callService.call != nil) {
|
|
|
|
if ([phoneNumber isEqualToString:SignalApp.sharedApp.callService.call.remotePhoneNumber]) {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ trying to upgrade ongoing call to video.", self.logTag);
|
2017-12-04 16:35:47 +01:00
|
|
|
[SignalApp.sharedApp.callService handleCallKitStartVideo];
|
2017-02-03 17:25:57 +01:00
|
|
|
return YES;
|
|
|
|
} else {
|
|
|
|
DDLogWarn(
|
2017-11-08 19:03:51 +01:00
|
|
|
@"%@ ignoring INStartVideoCallIntent due to ongoing WebRTC call with another party.", self.logTag);
|
2017-02-03 17:25:57 +01:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-04 16:35:47 +01:00
|
|
|
OutboundCallInitiator *outboundCallInitiator = SignalApp.sharedApp.outboundCallInitiator;
|
2017-02-03 17:25:57 +01:00
|
|
|
OWSAssert(outboundCallInitiator);
|
2017-02-22 15:50:41 +01:00
|
|
|
return [outboundCallInitiator initiateCallWithHandle:phoneNumber];
|
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)) {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogError(@"%@ unexpectedly received INStartAudioCallIntent pre iOS10", self.logTag);
|
2017-02-02 00:51:49 +01:00
|
|
|
return NO;
|
|
|
|
}
|
2017-02-01 23:49:32 +01:00
|
|
|
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ got start audio call intent", self.logTag);
|
2017-02-01 23:49:32 +01:00
|
|
|
|
|
|
|
INInteraction *interaction = [userActivity interaction];
|
|
|
|
INIntent *intent = interaction.intent;
|
|
|
|
|
|
|
|
if (![intent isKindOfClass:[INStartAudioCallIntent class]]) {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogError(@"%@ unexpected class for start call audio: %@", self.logTag, 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) {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ unable to find handle in startCallIntent: %@", self.logTag, startCallIntent);
|
2017-02-01 23:49:32 +01:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2017-02-22 15:50:41 +01:00
|
|
|
NSString *_Nullable phoneNumber = handle;
|
|
|
|
if ([handle hasPrefix:CallKitCallManager.kAnonymousCallHandlePrefix]) {
|
|
|
|
phoneNumber = [[TSStorageManager sharedManager] phoneNumberForCallKitId:handle];
|
|
|
|
if (phoneNumber.length < 1) {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ ignoring attempt to initiate audio call to unknown anonymous signal user.", self.logTag);
|
2017-02-22 15:50:41 +01:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-04 16:35:47 +01:00
|
|
|
if (SignalApp.sharedApp.callService.call != nil) {
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogWarn(@"%@ ignoring INStartAudioCallIntent due to ongoing WebRTC call.", self.logTag);
|
2017-02-03 17:33:22 +01:00
|
|
|
return NO;
|
2017-02-03 17:25:57 +01:00
|
|
|
}
|
|
|
|
|
2017-12-04 16:35:47 +01:00
|
|
|
OutboundCallInitiator *outboundCallInitiator = SignalApp.sharedApp.outboundCallInitiator;
|
2017-02-02 00:26:47 +01:00
|
|
|
OWSAssert(outboundCallInitiator);
|
2017-02-22 15:50:41 +01:00
|
|
|
return [outboundCallInitiator initiateCallWithHandle:phoneNumber];
|
2017-01-18 23:29:47 +01:00
|
|
|
} else {
|
2017-02-01 23:49:32 +01:00
|
|
|
DDLogWarn(@"%@ called %s with userActivity: %@, but not yet supported.",
|
2017-11-08 19:03:51 +01:00
|
|
|
self.logTag,
|
2017-02-01 23:49:32 +01:00
|
|
|
__PRETTY_FUNCTION__,
|
|
|
|
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
|
|
|
|
// }
|
2016-11-12 18:22:29 +01:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-10 15:58:34 +02:00
|
|
|
/**
|
|
|
|
* Screen protection obscures the app screen shown in the app switcher.
|
|
|
|
*/
|
|
|
|
- (void)prepareScreenProtection
|
|
|
|
{
|
|
|
|
UIWindow *window = [[UIWindow alloc] initWithFrame:self.window.bounds];
|
|
|
|
window.hidden = YES;
|
|
|
|
window.opaque = YES;
|
|
|
|
window.userInteractionEnabled = NO;
|
|
|
|
window.windowLevel = CGFLOAT_MAX;
|
|
|
|
window.backgroundColor = UIColor.ows_materialBlueColor;
|
|
|
|
window.rootViewController =
|
|
|
|
[[UIStoryboard storyboardWithName:@"Launch Screen" bundle:nil] instantiateInitialViewController];
|
|
|
|
|
|
|
|
self.screenProtectionWindow = window;
|
2014-08-09 18:27:26 +02:00
|
|
|
}
|
|
|
|
|
2017-05-09 20:59:28 +02:00
|
|
|
- (void)showScreenProtection
|
|
|
|
{
|
2015-12-22 12:45:09 +01:00
|
|
|
if (Environment.preferences.screenSecurityIsEnabled) {
|
2016-08-10 15:58:34 +02:00
|
|
|
self.screenProtectionWindow.hidden = NO;
|
2014-08-09 18:27:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)removeScreenProtection {
|
2017-05-09 20:59:28 +02:00
|
|
|
self.screenProtectionWindow.hidden = YES;
|
2014-08-09 18:27:26 +02:00
|
|
|
}
|
|
|
|
|
2015-04-14 21:49:00 +02:00
|
|
|
#pragma mark Push Notifications Delegate Methods
|
|
|
|
|
|
|
|
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
|
|
|
|
[[PushManager sharedManager] application:application didReceiveRemoteNotification:userInfo];
|
|
|
|
}
|
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 {
|
|
|
|
[[PushManager sharedManager] application:application
|
|
|
|
didReceiveRemoteNotification:userInfo
|
|
|
|
fetchCompletionHandler:completionHandler];
|
2015-04-14 21:49:00 +02:00
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
|
2017-11-06 18:37:15 +01:00
|
|
|
OWSAssert([NSThread isMainThread]);
|
|
|
|
|
2017-09-20 17:15:46 +02:00
|
|
|
if (!self.isEnvironmentSetup) {
|
2017-11-08 19:03:51 +01:00
|
|
|
OWSFail(@"%@ ignoring %s because environment is not yet set up: %@.",
|
|
|
|
self.logTag,
|
|
|
|
__PRETTY_FUNCTION__,
|
|
|
|
notification);
|
2017-11-03 17:19:45 +01:00
|
|
|
return;
|
|
|
|
}
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ %s %@", self.logTag, __PRETTY_FUNCTION__, notification);
|
2017-09-20 17:15:46 +02:00
|
|
|
|
2016-12-08 10:47:10 +01:00
|
|
|
[AppStoreRating preventPromptAtNextTest];
|
2015-04-14 21:49:00 +02:00
|
|
|
[[PushManager sharedManager] application:application didReceiveLocalNotification:notification];
|
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)application:(UIApplication *)application
|
|
|
|
handleActionWithIdentifier:(NSString *)identifier
|
|
|
|
forLocalNotification:(UILocalNotification *)notification
|
2017-09-20 17:15:46 +02:00
|
|
|
completionHandler:(void (^)())completionHandler
|
|
|
|
{
|
|
|
|
if (!self.isEnvironmentSetup) {
|
2017-11-08 19:03:51 +01:00
|
|
|
OWSFail(@"%@ ignoring %s because environment is not yet set up.", self.logTag, __PRETTY_FUNCTION__);
|
2017-09-20 17:15:46 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
[[PushManager sharedManager] application:application
|
|
|
|
handleActionWithIdentifier:identifier
|
|
|
|
forLocalNotification:notification
|
|
|
|
completionHandler:completionHandler];
|
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
|
2017-09-20 17:15:46 +02:00
|
|
|
completionHandler:(void (^)())completionHandler
|
|
|
|
{
|
|
|
|
if (!self.isEnvironmentSetup) {
|
2017-11-08 19:03:51 +01:00
|
|
|
OWSFail(@"%@ ignoring %s because environment is not yet set up.", self.logTag, __PRETTY_FUNCTION__);
|
2017-09-20 17:15:46 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
[[PushManager sharedManager] application:application
|
|
|
|
handleActionWithIdentifier:identifier
|
|
|
|
forLocalNotification:notification
|
|
|
|
withResponseInfo:responseInfo
|
|
|
|
completionHandler:completionHandler];
|
2015-09-01 19:22:08 +02:00
|
|
|
}
|
|
|
|
|
2017-06-15 19:43:18 +02:00
|
|
|
- (void)databaseViewRegistrationComplete
|
|
|
|
{
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ databaseViewRegistrationComplete", self.logTag);
|
2017-06-15 19:43:18 +02:00
|
|
|
|
2017-12-06 19:53:01 +01:00
|
|
|
[OWSPreferences setIsRegistered:[TSAccountManager isRegistered]];
|
|
|
|
|
2017-09-14 21:30:22 +02:00
|
|
|
if ([TSAccountManager isRegistered]) {
|
|
|
|
DDLogInfo(@"localNumber: %@", [TSAccountManager localNumber]);
|
2017-10-06 18:00:29 +02:00
|
|
|
|
2017-10-06 18:03:41 +02:00
|
|
|
// Fetch messages as soon as possible after launching. In particular, when
|
|
|
|
// launching from the background, without this, we end up waiting some extra
|
|
|
|
// seconds before receiving an actionable push notification.
|
2017-12-04 16:35:47 +01:00
|
|
|
__unused AnyPromise *messagePromise = [SignalApp.sharedApp.messageFetcherJob run];
|
2017-10-06 18:03:41 +02:00
|
|
|
|
2017-10-06 18:00:29 +02:00
|
|
|
// This should happen at any launch, background or foreground.
|
2017-10-14 17:41:54 +02:00
|
|
|
__unused AnyPromise *pushTokenpromise =
|
2017-12-04 16:35:47 +01:00
|
|
|
[OWSSyncPushTokensJob runWithAccountManager:SignalApp.sharedApp.accountManager
|
2017-10-14 17:41:54 +02:00
|
|
|
preferences:[Environment preferences]];
|
2017-09-14 21:30:22 +02:00
|
|
|
}
|
|
|
|
|
2017-07-06 18:52:44 +02:00
|
|
|
[DeviceSleepManager.sharedInstance removeBlockWithBlockObject:self];
|
|
|
|
|
2017-06-16 16:52:36 +02:00
|
|
|
[AppVersion.instance appLaunchDidComplete];
|
|
|
|
|
2017-06-15 23:15:56 +02:00
|
|
|
[self ensureRootViewController];
|
2017-07-28 23:04:52 +02:00
|
|
|
|
|
|
|
// If there were any messages in our local queue which we hadn't yet processed.
|
|
|
|
[[OWSMessageReceiver sharedInstance] handleAnyUnprocessedEnvelopesAsync];
|
2017-09-13 18:49:19 +02:00
|
|
|
[[OWSBatchMessageProcessor sharedInstance] handleAnyUnprocessedEnvelopesAsync];
|
2017-08-29 19:07:34 +02:00
|
|
|
|
2017-09-20 17:15:46 +02:00
|
|
|
[[OWSProfileManager sharedManager] ensureLocalProfileCached];
|
|
|
|
|
|
|
|
self.isEnvironmentSetup = YES;
|
|
|
|
|
2017-10-22 03:16:31 +02: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.
|
|
|
|
[OWSOrphanedDataCleaner auditAndCleanupAsync:nil];
|
|
|
|
#endif
|
|
|
|
|
2017-08-29 22:31:27 +02:00
|
|
|
[OWSProfileManager.sharedManager fetchLocalUsersProfile];
|
2017-09-25 20:45:50 +02:00
|
|
|
[[OWSReadReceiptManager sharedManager] prepareCachedValues];
|
2017-12-04 16:35:47 +01:00
|
|
|
[[Environment current].contactsManager loadLastKnownContactRecipientIds];
|
2017-06-15 19:43:18 +02:00
|
|
|
}
|
|
|
|
|
2017-09-14 21:29:59 +02:00
|
|
|
- (void)registrationStateDidChange
|
|
|
|
{
|
|
|
|
OWSAssert([NSThread isMainThread]);
|
|
|
|
|
|
|
|
DDLogInfo(@"registrationStateDidChange");
|
|
|
|
|
2017-12-06 19:53:01 +01:00
|
|
|
[OWSPreferences setIsRegistered:[TSAccountManager isRegistered]];
|
|
|
|
|
2017-09-14 21:29:59 +02:00
|
|
|
if ([TSAccountManager isRegistered]) {
|
|
|
|
DDLogInfo(@"localNumber: %@", [TSAccountManager localNumber]);
|
|
|
|
|
|
|
|
[[TSStorageManager sharedManager].newDatabaseConnection
|
|
|
|
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
|
|
|
|
[[OWSDisappearingMessagesJob sharedJob] startIfNecessary];
|
|
|
|
[[OWSProfileManager sharedManager] ensureLocalProfileCached];
|
2017-09-14 22:01:10 +02:00
|
|
|
|
|
|
|
// For non-legacy users, read receipts are on by default.
|
2017-09-15 21:28:44 +02:00
|
|
|
[OWSReadReceiptManager.sharedManager setAreReadReceiptsEnabled:YES];
|
2017-09-14 21:29:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-15 23:15:56 +02:00
|
|
|
- (void)ensureRootViewController
|
2017-06-15 19:43:18 +02:00
|
|
|
{
|
2017-11-08 19:03:51 +01:00
|
|
|
DDLogInfo(@"%@ ensureRootViewController", self.logTag);
|
2017-06-15 19:43:18 +02:00
|
|
|
|
2017-06-15 23:15:56 +02:00
|
|
|
if ([TSDatabaseView hasPendingViewRegistrations] || 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
|
|
|
|
2017-06-15 23:15:56 +02:00
|
|
|
DDLogInfo(@"Presenting initial root view controller");
|
2017-06-15 19:43:18 +02:00
|
|
|
|
2017-06-15 23:15:56 +02:00
|
|
|
if ([TSAccountManager isRegistered]) {
|
2017-09-06 19:59:39 +02:00
|
|
|
HomeViewController *homeView = [HomeViewController new];
|
2017-07-10 22:04:03 +02:00
|
|
|
SignalsNavigationController *navigationController =
|
|
|
|
[[SignalsNavigationController alloc] initWithRootViewController:homeView];
|
|
|
|
self.window.rootViewController = navigationController;
|
2017-06-15 23:15:56 +02:00
|
|
|
} else {
|
|
|
|
RegistrationViewController *viewController = [RegistrationViewController new];
|
2017-08-17 18:37:21 +02:00
|
|
|
OWSNavigationController *navigationController =
|
|
|
|
[[OWSNavigationController alloc] initWithRootViewController:viewController];
|
2017-06-15 23:15:56 +02:00
|
|
|
navigationController.navigationBarHidden = YES;
|
|
|
|
self.window.rootViewController = navigationController;
|
2017-06-15 19:43:18 +02:00
|
|
|
}
|
2017-07-04 19:24:25 +02:00
|
|
|
|
|
|
|
[AppUpdateNag.sharedInstance showAppUpgradeNagIfNecessary];
|
2017-06-15 19:43:18 +02:00
|
|
|
}
|
|
|
|
|
2014-05-06 19:41:08 +02:00
|
|
|
@end
|