mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			323 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Objective-C
		
	
			
		
		
	
	
			323 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Objective-C
		
	
//
 | 
						|
//  Copyright (c) 2019 Open Whisper Systems. All rights reserved.
 | 
						|
//
 | 
						|
 | 
						|
#import "MainAppContext.h"
 | 
						|
#import "Session-Swift.h"
 | 
						|
#import <SignalCoreKit/Threading.h>
 | 
						|
#import <SessionMessagingKit/Environment.h>
 | 
						|
#import <SignalUtilitiesKit/OWSProfileManager.h>
 | 
						|
#import <SignalUtilitiesKit/SignalUtilitiesKit-Swift.h>
 | 
						|
#import <SessionMessagingKit/OWSIdentityManager.h>
 | 
						|
 | 
						|
NS_ASSUME_NONNULL_BEGIN
 | 
						|
 | 
						|
NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplicationStateDidChangeNotification";
 | 
						|
 | 
						|
@interface MainAppContext ()
 | 
						|
 | 
						|
@property (atomic) UIApplicationState reportedApplicationState;
 | 
						|
 | 
						|
@property (nonatomic, nullable) NSMutableArray<AppActiveBlock> *appActiveBlocks;
 | 
						|
 | 
						|
@end
 | 
						|
 | 
						|
#pragma mark -
 | 
						|
 | 
						|
@implementation MainAppContext
 | 
						|
 | 
						|
@synthesize mainWindow = _mainWindow;
 | 
						|
@synthesize appLaunchTime = _appLaunchTime;
 | 
						|
@synthesize wasWokenUpByPushNotification = _wasWokenUpByPushNotification;
 | 
						|
 | 
						|
- (instancetype)init
 | 
						|
{
 | 
						|
    self = [super init];
 | 
						|
 | 
						|
    if (!self) {
 | 
						|
        return self;
 | 
						|
    }
 | 
						|
 | 
						|
    self.reportedApplicationState = UIApplicationStateInactive;
 | 
						|
 | 
						|
    _appLaunchTime = [NSDate new];
 | 
						|
    _wasWokenUpByPushNotification = false;
 | 
						|
 | 
						|
    [[NSNotificationCenter defaultCenter] addObserver:self
 | 
						|
                                             selector:@selector(applicationWillEnterForeground:)
 | 
						|
                                                 name:UIApplicationWillEnterForegroundNotification
 | 
						|
                                               object:nil];
 | 
						|
    [[NSNotificationCenter defaultCenter] addObserver:self
 | 
						|
                                             selector:@selector(applicationDidEnterBackground:)
 | 
						|
                                                 name:UIApplicationDidEnterBackgroundNotification
 | 
						|
                                               object:nil];
 | 
						|
    [[NSNotificationCenter defaultCenter] addObserver:self
 | 
						|
                                             selector:@selector(applicationWillResignActive:)
 | 
						|
                                                 name:UIApplicationWillResignActiveNotification
 | 
						|
                                               object:nil];
 | 
						|
    [[NSNotificationCenter defaultCenter] addObserver:self
 | 
						|
                                             selector:@selector(applicationDidBecomeActive:)
 | 
						|
                                                 name:UIApplicationDidBecomeActiveNotification
 | 
						|
                                               object:nil];
 | 
						|
    [[NSNotificationCenter defaultCenter] addObserver:self
 | 
						|
                                             selector:@selector(applicationWillTerminate:)
 | 
						|
                                                 name:UIApplicationWillTerminateNotification
 | 
						|
                                               object:nil];
 | 
						|
 | 
						|
    // We can't use OWSSingletonAssert() since it uses the app context.
 | 
						|
 | 
						|
    self.appActiveBlocks = [NSMutableArray new];
 | 
						|
 | 
						|
    return self;
 | 
						|
}
 | 
						|
 | 
						|
- (void)dealloc
 | 
						|
{
 | 
						|
    [[NSNotificationCenter defaultCenter] removeObserver:self];
 | 
						|
}
 | 
						|
 | 
						|
#pragma mark - Notifications
 | 
						|
 | 
						|
- (void)setReportedApplicationState:(UIApplicationState)reportedApplicationState
 | 
						|
{
 | 
						|
    OWSAssertIsOnMainThread();
 | 
						|
 | 
						|
    if (_reportedApplicationState == reportedApplicationState) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    _reportedApplicationState = reportedApplicationState;
 | 
						|
 | 
						|
    [[NSNotificationCenter defaultCenter] postNotificationName:ReportedApplicationStateDidChangeNotification
 | 
						|
                                                        object:nil
 | 
						|
                                                      userInfo:nil];
 | 
						|
}
 | 
						|
 | 
						|
- (void)applicationWillEnterForeground:(NSNotification *)notification
 | 
						|
{
 | 
						|
    OWSAssertIsOnMainThread();
 | 
						|
 | 
						|
    self.reportedApplicationState = UIApplicationStateInactive;
 | 
						|
 | 
						|
    OWSLogInfo(@"");
 | 
						|
 | 
						|
    [NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationWillEnterForegroundNotification object:nil];
 | 
						|
}
 | 
						|
 | 
						|
- (void)applicationDidEnterBackground:(NSNotification *)notification
 | 
						|
{
 | 
						|
    OWSAssertIsOnMainThread();
 | 
						|
 | 
						|
    self.reportedApplicationState = UIApplicationStateBackground;
 | 
						|
 | 
						|
    OWSLogInfo(@"");
 | 
						|
    [DDLog flushLog];
 | 
						|
 | 
						|
    [NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationDidEnterBackgroundNotification object:nil];
 | 
						|
}
 | 
						|
 | 
						|
- (void)applicationWillResignActive:(NSNotification *)notification
 | 
						|
{
 | 
						|
    OWSAssertIsOnMainThread();
 | 
						|
 | 
						|
    self.reportedApplicationState = UIApplicationStateInactive;
 | 
						|
 | 
						|
    OWSLogInfo(@"");
 | 
						|
    [DDLog flushLog];
 | 
						|
 | 
						|
    [NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationWillResignActiveNotification object:nil];
 | 
						|
}
 | 
						|
 | 
						|
- (void)applicationDidBecomeActive:(NSNotification *)notification
 | 
						|
{
 | 
						|
    OWSAssertIsOnMainThread();
 | 
						|
 | 
						|
    self.reportedApplicationState = UIApplicationStateActive;
 | 
						|
 | 
						|
    OWSLogInfo(@"");
 | 
						|
 | 
						|
    [NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationDidBecomeActiveNotification object:nil];
 | 
						|
 | 
						|
    [self runAppActiveBlocks];
 | 
						|
}
 | 
						|
 | 
						|
- (void)applicationWillTerminate:(NSNotification *)notification
 | 
						|
{
 | 
						|
    OWSAssertIsOnMainThread();
 | 
						|
 | 
						|
    OWSLogInfo(@"");
 | 
						|
    [DDLog flushLog];
 | 
						|
}
 | 
						|
 | 
						|
#pragma mark -
 | 
						|
 | 
						|
- (BOOL)isMainApp
 | 
						|
{
 | 
						|
    return YES;
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)isMainAppAndActive
 | 
						|
{
 | 
						|
    return [UIApplication sharedApplication].applicationState == UIApplicationStateActive;
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)isRTL
 | 
						|
{
 | 
						|
    static BOOL isRTL = NO;
 | 
						|
    static dispatch_once_t onceToken;
 | 
						|
    dispatch_once(&onceToken, ^{
 | 
						|
        isRTL = [[UIApplication sharedApplication] userInterfaceLayoutDirection]
 | 
						|
            == UIUserInterfaceLayoutDirectionRightToLeft;
 | 
						|
    });
 | 
						|
    return isRTL;
 | 
						|
}
 | 
						|
 | 
						|
- (void)setStatusBarHidden:(BOOL)isHidden animated:(BOOL)isAnimated
 | 
						|
{
 | 
						|
    [[UIApplication sharedApplication] setStatusBarHidden:isHidden animated:isAnimated];
 | 
						|
}
 | 
						|
 | 
						|
- (CGFloat)statusBarHeight
 | 
						|
{
 | 
						|
    return [UIApplication sharedApplication].statusBarFrame.size.height;
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)isInBackground
 | 
						|
{
 | 
						|
    return self.reportedApplicationState == UIApplicationStateBackground;
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)isAppForegroundAndActive
 | 
						|
{
 | 
						|
    return self.reportedApplicationState == UIApplicationStateActive;
 | 
						|
}
 | 
						|
 | 
						|
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:
 | 
						|
    (BackgroundTaskExpirationHandler)expirationHandler
 | 
						|
{
 | 
						|
    return [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:expirationHandler];
 | 
						|
}
 | 
						|
 | 
						|
- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)backgroundTaskIdentifier
 | 
						|
{
 | 
						|
    [UIApplication.sharedApplication endBackgroundTask:backgroundTaskIdentifier];
 | 
						|
}
 | 
						|
 | 
						|
- (void)ensureSleepBlocking:(BOOL)shouldBeBlocking blockingObjects:(NSArray<id> *)blockingObjects
 | 
						|
{
 | 
						|
    if (UIApplication.sharedApplication.isIdleTimerDisabled != shouldBeBlocking) {
 | 
						|
        if (shouldBeBlocking) {
 | 
						|
            NSMutableString *logString =
 | 
						|
                [NSMutableString stringWithFormat:@"Blocking sleep because of: %@", blockingObjects.firstObject];
 | 
						|
            if (blockingObjects.count > 1) {
 | 
						|
                [logString appendString:[NSString stringWithFormat:@"(and %lu others)", blockingObjects.count - 1]];
 | 
						|
            }
 | 
						|
            OWSLogInfo(@"%@", logString);
 | 
						|
        } else {
 | 
						|
            OWSLogInfo(@"Unblocking Sleep.");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    UIApplication.sharedApplication.idleTimerDisabled = shouldBeBlocking;
 | 
						|
}
 | 
						|
 | 
						|
- (void)setMainAppBadgeNumber:(NSInteger)value
 | 
						|
{
 | 
						|
    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:value];
 | 
						|
}
 | 
						|
 | 
						|
- (nullable UIViewController *)frontmostViewController
 | 
						|
{
 | 
						|
    return UIApplication.sharedApplication.frontmostViewControllerIgnoringAlerts;
 | 
						|
}
 | 
						|
 | 
						|
- (nullable UIAlertAction *)openSystemSettingsAction
 | 
						|
{
 | 
						|
    return [UIAlertAction actionWithTitle:CommonStrings.openSettingsButton
 | 
						|
                  accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"system_settings")
 | 
						|
                                    style:UIAlertActionStyleDefault
 | 
						|
                                  handler:^(UIAlertAction *_Nonnull action) {
 | 
						|
                                      [UIApplication.sharedApplication openSystemSettings];
 | 
						|
                                  }];
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)isRunningTests
 | 
						|
{
 | 
						|
    return getenv("runningTests_dontStartApp");
 | 
						|
}
 | 
						|
 | 
						|
- (void)setNetworkActivityIndicatorVisible:(BOOL)value
 | 
						|
{
 | 
						|
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:value];
 | 
						|
}
 | 
						|
 | 
						|
#pragma mark -
 | 
						|
 | 
						|
- (void)runNowOrWhenMainAppIsActive:(AppActiveBlock)block
 | 
						|
{
 | 
						|
    OWSAssertDebug(block);
 | 
						|
 | 
						|
    DispatchMainThreadSafe(^{
 | 
						|
        if (self.isMainAppAndActive) {
 | 
						|
            // App active blocks typically will be used to safely access the
 | 
						|
            // shared data container, so use a background task to protect this
 | 
						|
            // work.
 | 
						|
            OWSBackgroundTask *_Nullable backgroundTask =
 | 
						|
                [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
 | 
						|
            block();
 | 
						|
            OWSAssertDebug(backgroundTask);
 | 
						|
            backgroundTask = nil;
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        [self.appActiveBlocks addObject:block];
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
- (void)runAppActiveBlocks
 | 
						|
{
 | 
						|
    OWSAssertIsOnMainThread();
 | 
						|
    OWSAssertDebug(self.isMainAppAndActive);
 | 
						|
 | 
						|
    // App active blocks typically will be used to safely access the
 | 
						|
    // shared data container, so use a background task to protect this
 | 
						|
    // work.
 | 
						|
    OWSBackgroundTask *_Nullable backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
 | 
						|
 | 
						|
    NSArray<AppActiveBlock> *appActiveBlocks = [self.appActiveBlocks copy];
 | 
						|
    [self.appActiveBlocks removeAllObjects];
 | 
						|
    for (AppActiveBlock block in appActiveBlocks) {
 | 
						|
        block();
 | 
						|
    }
 | 
						|
 | 
						|
    OWSAssertDebug(backgroundTask);
 | 
						|
    backgroundTask = nil;
 | 
						|
}
 | 
						|
 | 
						|
- (id<SSKKeychainStorage>)keychainStorage
 | 
						|
{
 | 
						|
    return [SSKDefaultKeychainStorage shared];
 | 
						|
}
 | 
						|
 | 
						|
- (NSString *)appDocumentDirectoryPath
 | 
						|
{
 | 
						|
    NSFileManager *fileManager = [NSFileManager defaultManager];
 | 
						|
    NSURL *documentDirectoryURL =
 | 
						|
        [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
 | 
						|
    return [documentDirectoryURL path];
 | 
						|
}
 | 
						|
 | 
						|
- (NSString *)appSharedDataDirectoryPath
 | 
						|
{
 | 
						|
    NSURL *groupContainerDirectoryURL =
 | 
						|
        [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:SignalApplicationGroup];
 | 
						|
    return [groupContainerDirectoryURL path];
 | 
						|
}
 | 
						|
 | 
						|
- (NSUserDefaults *)appUserDefaults
 | 
						|
{
 | 
						|
    return [[NSUserDefaults alloc] initWithSuiteName:SignalApplicationGroup];
 | 
						|
}
 | 
						|
 | 
						|
@end
 | 
						|
 | 
						|
NS_ASSUME_NONNULL_END
 |