From eb2e16872edee553ba8ec8095a42bc38ea8e6915 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 2 Nov 2018 13:51:46 -0400 Subject: [PATCH 1/3] Distinguish 'app will/did become ready' events. --- Signal/src/AppDelegate.m | 22 ++++---- Signal/src/network/PushManager.m | 6 +-- Signal/src/util/OWSScreenLockUI.m | 4 +- SignalMessaging/contacts/OWSSyncManager.m | 2 +- .../contacts/SystemContactsFetcher.swift | 2 +- SignalMessaging/profiles/OWSProfileManager.m | 4 +- .../src/Account/TSAccountManager.m | 4 +- .../src/Messages/OWSBatchMessageProcessor.m | 2 +- .../src/Messages/OWSBlockingManager.m | 2 +- .../src/Messages/OWSDisappearingMessagesJob.m | 4 +- .../src/Messages/OWSIdentityManager.m | 2 +- .../src/Messages/OWSMessageManager.m | 2 +- .../src/Messages/OWSMessageReceiver.m | 2 +- .../src/Messages/OWSOutgoingReceiptManager.m | 2 +- .../src/Messages/OWSReadReceiptManager.m | 2 +- .../src/Messages/UD/OWSUDManager.swift | 2 +- .../src/Network/WebSockets/OWSWebSocket.m | 2 +- SignalServiceKit/src/Util/AppReadiness.h | 9 +++- SignalServiceKit/src/Util/AppReadiness.m | 52 +++++++++++++++---- .../ShareViewController.swift | 2 +- 20 files changed, 85 insertions(+), 44 deletions(-) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 5571ea35c..56ed19a1a 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -550,7 +550,7 @@ static NSTimeInterval launchStartedAt; if (!AppReadiness.isAppReady) { OWSLogWarn(@"Ignoring openURL: app not ready."); - // We don't need to use [AppReadiness runNowOrWhenAppIsReady:]; + // We don't need to use [AppReadiness runNowOrWhenAppDidBecomeReady:]; // the only URLs we handle in Signal iOS at the moment are used // for resuming the verification step of the registration flow. return NO; @@ -596,7 +596,7 @@ static NSTimeInterval launchStartedAt; [self ensureRootViewController]; - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self handleActivation]; }]; @@ -616,7 +616,7 @@ static NSTimeInterval launchStartedAt; - (void)enableBackgroundRefreshIfNecessary { - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ if (OWS2FAManager.sharedManager.is2FAEnabled && [self.tsAccountManager isRegistered]) { // Ping server once a day to keep-alive 2FA clients. const NSTimeInterval kBackgroundRefreshInterval = 24 * 60 * 60; @@ -732,7 +732,7 @@ static NSTimeInterval launchStartedAt; OWSAssertIsOnMainThread(); [SignalApp clearAllNotifications]; - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [OWSMessageUtils.sharedManager updateApplicationBadgeCount]; }]; } @@ -747,7 +747,7 @@ static NSTimeInterval launchStartedAt; return; } - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ if (![self.tsAccountManager isRegistered]) { UIAlertController *controller = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"REGISTER_CONTACTS_WELCOME", nil) @@ -818,7 +818,7 @@ static NSTimeInterval launchStartedAt; return NO; } - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ NSString *_Nullable phoneNumber = handle; if ([handle hasPrefix:CallKitCallManager.kAnonymousCallHandlePrefix]) { phoneNumber = [self.primaryStorage phoneNumberForCallKitId:handle]; @@ -875,7 +875,7 @@ static NSTimeInterval launchStartedAt; return NO; } - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ NSString *_Nullable phoneNumber = handle; if ([handle hasPrefix:CallKitCallManager.kAnonymousCallHandlePrefix]) { phoneNumber = [self.primaryStorage phoneNumberForCallKitId:handle]; @@ -980,7 +980,7 @@ static NSTimeInterval launchStartedAt; } OWSLogInfo(@"%@", notification); - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [[PushManager sharedManager] application:application didReceiveLocalNotification:notification]; }]; } @@ -1003,7 +1003,7 @@ static NSTimeInterval launchStartedAt; // later, after this method returns. // // https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623068-application?language=objc - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [[PushManager sharedManager] application:application handleActionWithIdentifier:identifier forLocalNotification:notification @@ -1032,7 +1032,7 @@ static NSTimeInterval launchStartedAt; // later, after this method returns. // // https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623068-application?language=objc - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [[PushManager sharedManager] application:application handleActionWithIdentifier:identifier forLocalNotification:notification @@ -1045,7 +1045,7 @@ static NSTimeInterval launchStartedAt; performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler { OWSLogInfo(@"performing background fetch"); - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ __block AnyPromise *job = [AppEnvironment.shared.messageFetcherJob run].then(^{ // HACK: Call completion handler after n seconds. // diff --git a/Signal/src/network/PushManager.m b/Signal/src/network/PushManager.m index 59edfd871..5bb0e7064 100644 --- a/Signal/src/network/PushManager.m +++ b/Signal/src/network/PushManager.m @@ -105,13 +105,13 @@ NSString *const Signal_Message_MarkAsRead_Identifier = @"Signal_Message_MarkAsRe { OWSLogInfo(@"received remote notification"); - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self.messageFetcherJob run]; }]; } - (void)applicationDidBecomeActive { - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self.messageFetcherJob run]; }]; } @@ -130,7 +130,7 @@ NSString *const Signal_Message_MarkAsRead_Identifier = @"Signal_Message_MarkAsRe // If we want to re-introduce silent pushes we can remove this assert. OWSFailDebug(@"Unexpected content-available push."); - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 20 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ completionHandler(UIBackgroundFetchResultNewData); }); diff --git a/Signal/src/util/OWSScreenLockUI.m b/Signal/src/util/OWSScreenLockUI.m index 8733561cb..3397272ac 100644 --- a/Signal/src/util/OWSScreenLockUI.m +++ b/Signal/src/util/OWSScreenLockUI.m @@ -138,7 +138,7 @@ NS_ASSUME_NONNULL_BEGIN // // It's not safe to access OWSScreenLock.isScreenLockEnabled // until the app is ready. - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppWillBecomeReady:^{ self.isScreenLockLocked = OWSScreenLock.sharedManager.isScreenLockEnabled; [self ensureUI]; @@ -251,7 +251,7 @@ NS_ASSUME_NONNULL_BEGIN OWSAssertIsOnMainThread(); if (!AppReadiness.isAppReady) { - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppWillBecomeReady:^{ [self ensureUI]; }]; return; diff --git a/SignalMessaging/contacts/OWSSyncManager.m b/SignalMessaging/contacts/OWSSyncManager.m index d2b2ac0bc..5aed90189 100644 --- a/SignalMessaging/contacts/OWSSyncManager.m +++ b/SignalMessaging/contacts/OWSSyncManager.m @@ -214,7 +214,7 @@ NSString *const kSyncManagerLastContactSyncKey = @"kTSStorageManagerOWSSyncManag } - (void)sendConfigurationSyncMessage { - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self sendConfigurationSyncMessage_AppReady]; }]; } diff --git a/SignalMessaging/contacts/SystemContactsFetcher.swift b/SignalMessaging/contacts/SystemContactsFetcher.swift index 4932ee240..82433ab4d 100644 --- a/SignalMessaging/contacts/SystemContactsFetcher.swift +++ b/SignalMessaging/contacts/SystemContactsFetcher.swift @@ -64,7 +64,7 @@ class ContactsFrameworkContactStoreAdaptee: NSObject, ContactStoreAdaptee { @objc func didBecomeActive() { - AppReadiness.runNowOrWhenAppIsReady { + AppReadiness.runNowOrWhenAppDidBecomeReady { let currentSortOrder = CNContactsUserDefaults.shared().sortOrder guard currentSortOrder != self.lastSortOrder else { diff --git a/SignalMessaging/profiles/OWSProfileManager.m b/SignalMessaging/profiles/OWSProfileManager.m index cbebf20b2..3f66e4766 100644 --- a/SignalMessaging/profiles/OWSProfileManager.m +++ b/SignalMessaging/profiles/OWSProfileManager.m @@ -94,7 +94,7 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error); OWSSingletonAssert(); - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self rotateLocalProfileKeyIfNecessary]; }]; @@ -1479,7 +1479,7 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error); - (void)blockListDidChange:(NSNotification *)notification { OWSAssertIsOnMainThread(); - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self rotateLocalProfileKeyIfNecessary]; }]; } diff --git a/SignalServiceKit/src/Account/TSAccountManager.m b/SignalServiceKit/src/Account/TSAccountManager.m index 01b124339..e8e6165b9 100644 --- a/SignalServiceKit/src/Account/TSAccountManager.m +++ b/SignalServiceKit/src/Account/TSAccountManager.m @@ -85,7 +85,7 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa object:nil]; } - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self updateAccountAttributesIfNecessary]; }]; @@ -683,7 +683,7 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa - (void)reachabilityChanged { OWSAssertIsOnMainThread(); - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self updateAccountAttributesIfNecessary]; }]; } diff --git a/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m b/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m index 49f05fc88..ac9968280 100644 --- a/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m +++ b/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m @@ -269,7 +269,7 @@ NSString *const OWSMessageContentJobFinderExtensionGroup = @"OWSMessageContentJo object:nil]; // Start processing. - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self drainQueue]; }]; diff --git a/SignalServiceKit/src/Messages/OWSBlockingManager.m b/SignalServiceKit/src/Messages/OWSBlockingManager.m index 9c81aa91c..873193adf 100644 --- a/SignalServiceKit/src/Messages/OWSBlockingManager.m +++ b/SignalServiceKit/src/Messages/OWSBlockingManager.m @@ -422,7 +422,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedGroupIdsKey = @"kOWSBlockingMan { OWSAssertIsOnMainThread(); - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ @synchronized(self) { [self syncBlockListIfNecessary]; diff --git a/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m b/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m index 8765de154..63c3d2cd9 100644 --- a/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m +++ b/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m @@ -69,7 +69,7 @@ void AssertIsOnDisappearingMessagesQueue() // suspenders in case a deletion schedule is missed. NSTimeInterval kFallBackTimerInterval = 5 * kMinuteInterval; - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ if (CurrentAppContext().isMainApp) { self.fallbackTimer = [NSTimer weakScheduledTimerWithTimeInterval:kFallBackTimerInterval target:self @@ -405,7 +405,7 @@ void AssertIsOnDisappearingMessagesQueue() { OWSAssertIsOnMainThread(); - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ dispatch_async(OWSDisappearingMessagesJob.serialQueue, ^{ [self runLoop]; }); diff --git a/SignalServiceKit/src/Messages/OWSIdentityManager.m b/SignalServiceKit/src/Messages/OWSIdentityManager.m index c9cd36a15..a17d6f442 100644 --- a/SignalServiceKit/src/Messages/OWSIdentityManager.m +++ b/SignalServiceKit/src/Messages/OWSIdentityManager.m @@ -569,7 +569,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa { OWSAssertIsOnMainThread(); - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self syncQueuedVerificationStates]; }]; } diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 39fee3fac..e25af91e6 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -185,7 +185,7 @@ NS_ASSUME_NONNULL_BEGIN } else { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [OWSMessageUtils.sharedManager updateApplicationBadgeCount]; }]; }); diff --git a/SignalServiceKit/src/Messages/OWSMessageReceiver.m b/SignalServiceKit/src/Messages/OWSMessageReceiver.m index 5ad0c8f94..d9acc5ece 100644 --- a/SignalServiceKit/src/Messages/OWSMessageReceiver.m +++ b/SignalServiceKit/src/Messages/OWSMessageReceiver.m @@ -248,7 +248,7 @@ NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessin _finder = finder; _isDrainingQueue = NO; - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self drainQueue]; }]; diff --git a/SignalServiceKit/src/Messages/OWSOutgoingReceiptManager.m b/SignalServiceKit/src/Messages/OWSOutgoingReceiptManager.m index c81b161ef..9c341988e 100644 --- a/SignalServiceKit/src/Messages/OWSOutgoingReceiptManager.m +++ b/SignalServiceKit/src/Messages/OWSOutgoingReceiptManager.m @@ -65,7 +65,7 @@ NSString *const kOutgoingReadReceiptManagerCollection = @"kOutgoingReadReceiptMa object:nil]; // Start processing. - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self process]; }]; diff --git a/SignalServiceKit/src/Messages/OWSReadReceiptManager.m b/SignalServiceKit/src/Messages/OWSReadReceiptManager.m index ce42b8962..b106fbb3b 100644 --- a/SignalServiceKit/src/Messages/OWSReadReceiptManager.m +++ b/SignalServiceKit/src/Messages/OWSReadReceiptManager.m @@ -157,7 +157,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE OWSSingletonAssert(); // Start processing. - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self scheduleProcessing]; }]; diff --git a/SignalServiceKit/src/Messages/UD/OWSUDManager.swift b/SignalServiceKit/src/Messages/UD/OWSUDManager.swift index 012c03eed..e2dfef96d 100644 --- a/SignalServiceKit/src/Messages/UD/OWSUDManager.swift +++ b/SignalServiceKit/src/Messages/UD/OWSUDManager.swift @@ -122,7 +122,7 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager { } @objc public func setup() { - AppReadiness.runNowOrWhenAppIsReady { + AppReadiness.runNowOrWhenAppDidBecomeReady { guard TSAccountManager.isRegistered() else { return } diff --git a/SignalServiceKit/src/Network/WebSockets/OWSWebSocket.m b/SignalServiceKit/src/Network/WebSockets/OWSWebSocket.m index b2f514781..7b284baba 100644 --- a/SignalServiceKit/src/Network/WebSockets/OWSWebSocket.m +++ b/SignalServiceKit/src/Network/WebSockets/OWSWebSocket.m @@ -1048,7 +1048,7 @@ NSString *NSStringFromOWSWebSocketType(OWSWebSocketType type) if (!AppReadiness.isAppReady) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - [AppReadiness runNowOrWhenAppIsReady:^{ + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ [self applyDesiredSocketState]; }]; }); diff --git a/SignalServiceKit/src/Util/AppReadiness.h b/SignalServiceKit/src/Util/AppReadiness.h index 8a446fe93..32ddecd70 100755 --- a/SignalServiceKit/src/Util/AppReadiness.h +++ b/SignalServiceKit/src/Util/AppReadiness.h @@ -21,7 +21,14 @@ typedef void (^AppReadyBlock)(void); // // This method should only be called on the main thread. // The block will always be called on the main thread. -+ (void)runNowOrWhenAppIsReady:(AppReadyBlock)block NS_SWIFT_NAME(runNowOrWhenAppIsReady(_:)); ++ (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block NS_SWIFT_NAME(runNowOrWhenAppWillBecomeReady(_:)); + +// If the app is ready, the block is called immediately; +// otherwise it is called when the app becomes ready. +// +// This method should only be called on the main thread. +// The block will always be called on the main thread. ++ (void)runNowOrWhenAppDidBecomeReady:(AppReadyBlock)block NS_SWIFT_NAME(runNowOrWhenAppDidBecomeReady(_:)); @end diff --git a/SignalServiceKit/src/Util/AppReadiness.m b/SignalServiceKit/src/Util/AppReadiness.m index f8ec61506..efed97e16 100755 --- a/SignalServiceKit/src/Util/AppReadiness.m +++ b/SignalServiceKit/src/Util/AppReadiness.m @@ -11,7 +11,8 @@ NS_ASSUME_NONNULL_BEGIN @property (atomic) BOOL isAppReady; -@property (nonatomic) NSMutableArray *appReadyBlocks; +@property (nonatomic) NSMutableArray *appWillBecomeReadyBlocks; +@property (nonatomic) NSMutableArray *appDidBecomeReadyBlocks; @end @@ -39,7 +40,8 @@ NS_ASSUME_NONNULL_BEGIN OWSSingletonAssert(); - self.appReadyBlocks = [NSMutableArray new]; + self.appWillBecomeReadyBlocks = [NSMutableArray new]; + self.appDidBecomeReadyBlocks = [NSMutableArray new]; return self; } @@ -49,14 +51,14 @@ NS_ASSUME_NONNULL_BEGIN return [self.sharedManager isAppReady]; } -+ (void)runNowOrWhenAppIsReady:(AppReadyBlock)block ++ (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block { DispatchMainThreadSafe(^{ - [self.sharedManager runNowOrWhenAppIsReady:block]; + [self.sharedManager runNowOrWhenAppWillBecomeReady:block]; }); } -- (void)runNowOrWhenAppIsReady:(AppReadyBlock)block +- (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block { OWSAssertIsOnMainThread(); OWSAssertDebug(block); @@ -72,7 +74,33 @@ NS_ASSUME_NONNULL_BEGIN return; } - [self.appReadyBlocks addObject:block]; + [self.appWillBecomeReadyBlocks addObject:block]; +} + ++ (void)runNowOrWhenAppDidBecomeReady:(AppReadyBlock)block +{ + DispatchMainThreadSafe(^{ + [self.sharedManager runNowOrWhenAppDidBecomeReady:block]; + }); +} + +- (void)runNowOrWhenAppDidBecomeReady:(AppReadyBlock)block +{ + OWSAssertIsOnMainThread(); + OWSAssertDebug(block); + + if (CurrentAppContext().isRunningTests) { + // We don't need to an any "on app ready" work + // in the tests. + return; + } + + if (self.isAppReady) { + block(); + return; + } + + [self.appDidBecomeReadyBlocks addObject:block]; } + (void)setAppIsReady @@ -97,10 +125,16 @@ NS_ASSUME_NONNULL_BEGIN OWSAssertIsOnMainThread(); OWSAssertDebug(self.isAppReady); - NSArray *appReadyBlocks = [self.appReadyBlocks copy]; - [self.appReadyBlocks removeAllObjects]; + NSArray *appWillBecomeReadyBlocks = [self.appWillBecomeReadyBlocks copy]; + [self.appWillBecomeReadyBlocks removeAllObjects]; + NSArray *appDidBecomeReadyBlocks = [self.appDidBecomeReadyBlocks copy]; + [self.appDidBecomeReadyBlocks removeAllObjects]; - for (AppReadyBlock block in appReadyBlocks) { + // We invoke the _will become_ blocks before the _did become_ blocks. + for (AppReadyBlock block in appWillBecomeReadyBlocks) { + block(); + } + for (AppReadyBlock block in appDidBecomeReadyBlocks) { block(); } } diff --git a/SignalShareExtension/ShareViewController.swift b/SignalShareExtension/ShareViewController.swift index 7dbe23962..d390825da 100644 --- a/SignalShareExtension/ShareViewController.swift +++ b/SignalShareExtension/ShareViewController.swift @@ -402,7 +402,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed Logger.debug("") if isReadyForAppExtensions { - AppReadiness.runNowOrWhenAppIsReady { [weak self] in + AppReadiness.runNowOrWhenAppDidBecomeReady { [weak self] in AssertIsOnMainThread() guard let strongSelf = self else { return } strongSelf.activate() From 39c820b8666bd689abc6c2ad5a7367f0046121b6 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 2 Nov 2018 14:13:54 -0400 Subject: [PATCH 2/3] Distinguish 'app will/did become ready' events. --- Signal/src/AppDelegate.m | 8 -------- Signal/src/Jobs/SessionResetJob.swift | 9 +++++++++ SignalMessaging/contacts/OWSContactsManager.h | 4 ---- SignalMessaging/contacts/OWSContactsManager.m | 7 +++++++ .../src/Messages/OWSBatchMessageProcessor.h | 2 -- .../src/Messages/OWSBatchMessageProcessor.m | 11 ++++++----- SignalServiceKit/src/Messages/OWSMessageReceiver.h | 1 - SignalServiceKit/src/Messages/OWSMessageReceiver.m | 11 ++++++----- .../src/Network/MessageSenderJobQueue.swift | 9 +++++++++ SignalServiceKit/src/Util/AppReadiness.h | 13 +++++++------ SignalServiceKit/src/Util/AppReadiness.m | 6 ++---- SignalServiceKit/src/Util/JobQueue.swift | 12 ++++++++---- SignalServiceKit/src/Util/TypingIndicators.swift | 2 +- SignalShareExtension/ShareViewController.swift | 3 --- 14 files changed, 55 insertions(+), 43 deletions(-) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 56ed19a1a..414ea5ab8 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -1130,17 +1130,9 @@ static NSTimeInterval launchStartedAt; [AppVersion.sharedInstance mainAppLaunchDidComplete]; - [Environment.shared.contactsManager setup]; - [Environment.shared.contactsManager startObserving]; - - // If there were any messages in our local queue which we hadn't yet processed. - [SSKEnvironment.shared.messageReceiver handleAnyUnprocessedEnvelopesAsync]; - [SSKEnvironment.shared.batchMessageProcessor handleAnyUnprocessedEnvelopesAsync]; [Environment.shared.audioSession setup]; [SSKEnvironment.shared.reachabilityManager setup]; - [SSKEnvironment.shared.messageSenderJobQueue setup]; - [AppEnvironment.shared.sessionResetJobQueue setup]; if (!Environment.shared.preferences.hasGeneratedThumbnails) { [self.primaryStorage.newDatabaseConnection diff --git a/Signal/src/Jobs/SessionResetJob.swift b/Signal/src/Jobs/SessionResetJob.swift index 7f68eaf5c..4fbac02b2 100644 --- a/Signal/src/Jobs/SessionResetJob.swift +++ b/Signal/src/Jobs/SessionResetJob.swift @@ -23,6 +23,15 @@ public class SessionResetJobQueue: NSObject, JobQueue { public let requiresInternet: Bool = true public var runningOperations: [SessionResetOperation] = [] + @objc + public override init() { + super.init() + + AppReadiness.runNowOrWhenAppWillBecomeReady { + self.setup() + } + } + @objc public func setup() { defaultSetup() diff --git a/SignalMessaging/contacts/OWSContactsManager.h b/SignalMessaging/contacts/OWSContactsManager.h index 4a6f2ed70..7e8ba009c 100644 --- a/SignalMessaging/contacts/OWSContactsManager.h +++ b/SignalMessaging/contacts/OWSContactsManager.h @@ -25,8 +25,6 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; - (id)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage; -- (void)startObserving; - #pragma mark - Accessors @property (nonnull, readonly) ImageCache *avatarCache; @@ -44,8 +42,6 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; - (SignalAccount *)fetchOrBuildSignalAccountForRecipientId:(NSString *)recipientId; - (BOOL)hasSignalAccountForRecipientId:(NSString *)recipientId; -- (void)setup; - #pragma mark - System Contact Fetching // Must call `requestSystemContactsOnce` before accessing this method diff --git a/SignalMessaging/contacts/OWSContactsManager.m b/SignalMessaging/contacts/OWSContactsManager.m index 5a3158bc7..b1dba3516 100644 --- a/SignalMessaging/contacts/OWSContactsManager.m +++ b/SignalMessaging/contacts/OWSContactsManager.m @@ -82,6 +82,13 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan OWSSingletonAssert(); + [AppReadiness runNowOrWhenAppWillBecomeReady:^{ + [self setup]; + }]; + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ + [self startObserving]; + }]; + return self; } diff --git a/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.h b/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.h index 017dc21ab..c9664e5aa 100644 --- a/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.h +++ b/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.h @@ -24,8 +24,6 @@ NS_ASSUME_NONNULL_BEGIN plaintextData:(NSData *_Nullable)plaintextData transaction:(YapDatabaseReadWriteTransaction *)transaction; -- (void)handleAnyUnprocessedEnvelopesAsync; - @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m b/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m index ac9968280..54cd702c8 100644 --- a/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m +++ b/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m @@ -458,6 +458,12 @@ NSString *const OWSMessageContentJobFinderExtensionGroup = @"OWSMessageContentJo _processingQueue = processingQueue; + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ + if (CurrentAppContext().isMainApp) { + [self.processingQueue drainQueue]; + } + }]; + return self; } @@ -475,11 +481,6 @@ NSString *const OWSMessageContentJobFinderExtensionGroup = @"OWSMessageContentJo #pragma mark - instance methods -- (void)handleAnyUnprocessedEnvelopesAsync -{ - [self.processingQueue drainQueue]; -} - - (void)enqueueEnvelopeData:(NSData *)envelopeData plaintextData:(NSData *_Nullable)plaintextData transaction:(YapDatabaseReadWriteTransaction *)transaction diff --git a/SignalServiceKit/src/Messages/OWSMessageReceiver.h b/SignalServiceKit/src/Messages/OWSMessageReceiver.h index bff0571ba..b9c103090 100644 --- a/SignalServiceKit/src/Messages/OWSMessageReceiver.h +++ b/SignalServiceKit/src/Messages/OWSMessageReceiver.h @@ -20,7 +20,6 @@ NS_ASSUME_NONNULL_BEGIN + (void)asyncRegisterDatabaseExtension:(OWSStorage *)storage; - (void)handleReceivedEnvelopeData:(NSData *)envelopeData; -- (void)handleAnyUnprocessedEnvelopesAsync; @end diff --git a/SignalServiceKit/src/Messages/OWSMessageReceiver.m b/SignalServiceKit/src/Messages/OWSMessageReceiver.m index d9acc5ece..606f46fc7 100644 --- a/SignalServiceKit/src/Messages/OWSMessageReceiver.m +++ b/SignalServiceKit/src/Messages/OWSMessageReceiver.m @@ -414,6 +414,12 @@ NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessin _processingQueue = processingQueue; + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ + if (CurrentAppContext().isMainApp) { + [self.processingQueue drainQueue]; + } + }]; + return self; } @@ -431,11 +437,6 @@ NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessin #pragma mark - instance methods -- (void)handleAnyUnprocessedEnvelopesAsync -{ - [self.processingQueue drainQueue]; -} - - (void)handleReceivedEnvelopeData:(NSData *)envelopeData { if (envelopeData.length < 1) { diff --git a/SignalServiceKit/src/Network/MessageSenderJobQueue.swift b/SignalServiceKit/src/Network/MessageSenderJobQueue.swift index 755f6ecdb..62d8aa500 100644 --- a/SignalServiceKit/src/Network/MessageSenderJobQueue.swift +++ b/SignalServiceKit/src/Network/MessageSenderJobQueue.swift @@ -25,6 +25,15 @@ import Foundation @objc(SSKMessageSenderJobQueue) public class MessageSenderJobQueue: NSObject, JobQueue { + @objc + public override init() { + super.init() + + AppReadiness.runNowOrWhenAppWillBecomeReady { + self.setup() + } + } + // MARK: @objc(addMessage:transaction:) diff --git a/SignalServiceKit/src/Util/AppReadiness.h b/SignalServiceKit/src/Util/AppReadiness.h index 32ddecd70..f07ee3741 100755 --- a/SignalServiceKit/src/Util/AppReadiness.h +++ b/SignalServiceKit/src/Util/AppReadiness.h @@ -21,13 +21,14 @@ typedef void (^AppReadyBlock)(void); // // This method should only be called on the main thread. // The block will always be called on the main thread. -+ (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block NS_SWIFT_NAME(runNowOrWhenAppWillBecomeReady(_:)); - -// If the app is ready, the block is called immediately; -// otherwise it is called when the app becomes ready. // -// This method should only be called on the main thread. -// The block will always be called on the main thread. +// * The "will become ready" blocks are called before the "did become ready" blocks. +// * The "will become ready" blocks should be used for internal setup of components +// so that they are ready to interact with other components of the system. +// * The "did become ready" blocks should be used for any work that should be done +// on app launch, especially work that uses other components. +// * We should usually use "did become ready" blocks since they are safer. ++ (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block NS_SWIFT_NAME(runNowOrWhenAppWillBecomeReady(_:)); + (void)runNowOrWhenAppDidBecomeReady:(AppReadyBlock)block NS_SWIFT_NAME(runNowOrWhenAppDidBecomeReady(_:)); @end diff --git a/SignalServiceKit/src/Util/AppReadiness.m b/SignalServiceKit/src/Util/AppReadiness.m index efed97e16..fb90398d6 100755 --- a/SignalServiceKit/src/Util/AppReadiness.m +++ b/SignalServiceKit/src/Util/AppReadiness.m @@ -64,8 +64,7 @@ NS_ASSUME_NONNULL_BEGIN OWSAssertDebug(block); if (CurrentAppContext().isRunningTests) { - // We don't need to an any "on app ready" work - // in the tests. + // We don't need to do any "on app ready" work in the tests. return; } @@ -90,8 +89,7 @@ NS_ASSUME_NONNULL_BEGIN OWSAssertDebug(block); if (CurrentAppContext().isRunningTests) { - // We don't need to an any "on app ready" work - // in the tests. + // We don't need to do any "on app ready" work in the tests. return; } diff --git a/SignalServiceKit/src/Util/JobQueue.swift b/SignalServiceKit/src/Util/JobQueue.swift index 588688707..f773bccfd 100644 --- a/SignalServiceKit/src/Util/JobQueue.swift +++ b/SignalServiceKit/src/Util/JobQueue.swift @@ -88,7 +88,7 @@ public protocol JobQueue: DurableOperationDelegate { public extension JobQueue { - // MARK: Depenencies + // MARK: Dependencies var dbConnection: YapDatabaseConnection { return SSKEnvironment.shared.primaryStorage.dbReadWriteConnection @@ -109,7 +109,11 @@ public extension JobQueue { jobRecord.save(with: transaction) transaction.addCompletionQueue(.global()) { - self.workStep() + AppReadiness.runNowOrWhenAppDidBecomeReady { + DispatchQueue.global().async { + self.workStep() + } + } } } @@ -283,7 +287,7 @@ public class JobRecordFinder: NSObject, Finder { func allRecords(label: String, status: SSKJobRecordStatus, transaction: YapDatabaseReadTransaction) -> [SSKJobRecord] { var result: [SSKJobRecord] = [] - self.enumerateJobRecords(label: label, status: status, transaction: transaction) { jobRecord, stopPointer in + self.enumerateJobRecords(label: label, status: status, transaction: transaction) { jobRecord, _ in result.append(jobRecord) } return result @@ -293,7 +297,7 @@ public class JobRecordFinder: NSObject, Finder { let queryFormat = String(format: "WHERE %@ = ? AND %@ = ? ORDER BY %@", JobRecordField.status.rawValue, JobRecordField.label.rawValue, JobRecordField.sortId.rawValue) let query = YapDatabaseQuery(string: queryFormat, parameters: [status.rawValue, label]) - self.ext(transaction: transaction).enumerateKeysAndObjects(matching: query) { collection, key, object, stopPointer in + self.ext(transaction: transaction).enumerateKeysAndObjects(matching: query) { _, _, object, stopPointer in guard let jobRecord = object as? SSKJobRecord else { owsFailDebug("expecting jobRecord but found: \(object)") return diff --git a/SignalServiceKit/src/Util/TypingIndicators.swift b/SignalServiceKit/src/Util/TypingIndicators.swift index 898248d13..b608eb821 100644 --- a/SignalServiceKit/src/Util/TypingIndicators.swift +++ b/SignalServiceKit/src/Util/TypingIndicators.swift @@ -56,7 +56,7 @@ public class TypingIndicatorsImpl: NSObject, TypingIndicators { public override init() { super.init() - AppReadiness.runNowOrWhenAppIsReady { + AppReadiness.runNowOrWhenAppWillBecomeReady { self.setup() } } diff --git a/SignalShareExtension/ShareViewController.swift b/SignalShareExtension/ShareViewController.swift index d390825da..3d0581de0 100644 --- a/SignalShareExtension/ShareViewController.swift +++ b/SignalShareExtension/ShareViewController.swift @@ -262,9 +262,6 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed AppVersion.sharedInstance().saeLaunchDidComplete() - Environment.shared.contactsManager.setup() - Environment.shared.contactsManager.startObserving() - ensureRootViewController() // We don't need to use OWSMessageReceiver in the SAE. From 1c7add2b8ffd6e7f774fcd102e8345e602ca71b0 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 5 Nov 2018 09:16:17 -0500 Subject: [PATCH 3/3] Respond to CR. --- SignalMessaging/contacts/OWSContactsManager.m | 11 ++++++----- .../src/Messages/OWSBatchMessageProcessor.m | 4 +++- SignalServiceKit/src/Messages/OWSMessageReceiver.m | 4 +++- .../src/Network/MessageSenderJobQueue.swift | 2 ++ SignalServiceKit/src/Util/JobQueue.swift | 1 + 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/SignalMessaging/contacts/OWSContactsManager.m b/SignalMessaging/contacts/OWSContactsManager.m index b1dba3516..f0c80d672 100644 --- a/SignalMessaging/contacts/OWSContactsManager.m +++ b/SignalMessaging/contacts/OWSContactsManager.m @@ -84,8 +84,7 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan [AppReadiness runNowOrWhenAppWillBecomeReady:^{ [self setup]; - }]; - [AppReadiness runNowOrWhenAppDidBecomeReady:^{ + [self startObserving]; }]; @@ -409,10 +408,12 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan { OWSAssertIsOnMainThread(); - NSString *recipientId = notification.userInfo[kNSNotificationKey_ProfileRecipientId]; - OWSAssertDebug(recipientId.length > 0); + [AppReadiness runNowOrWhenAppDidBecomeReady:^{ + NSString *recipientId = notification.userInfo[kNSNotificationKey_ProfileRecipientId]; + OWSAssertDebug(recipientId.length > 0); - [self.avatarCache removeAllImagesForKey:recipientId]; + [self.avatarCache removeAllImagesForKey:recipientId]; + }]; } - (void)updateWithContacts:(NSArray *)contacts diff --git a/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m b/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m index 54cd702c8..1ac05f937 100644 --- a/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m +++ b/SignalServiceKit/src/Messages/OWSBatchMessageProcessor.m @@ -270,7 +270,9 @@ NSString *const OWSMessageContentJobFinderExtensionGroup = @"OWSMessageContentJo // Start processing. [AppReadiness runNowOrWhenAppDidBecomeReady:^{ - [self drainQueue]; + if (CurrentAppContext().isMainApp) { + [self drainQueue]; + } }]; return self; diff --git a/SignalServiceKit/src/Messages/OWSMessageReceiver.m b/SignalServiceKit/src/Messages/OWSMessageReceiver.m index 606f46fc7..4b484414d 100644 --- a/SignalServiceKit/src/Messages/OWSMessageReceiver.m +++ b/SignalServiceKit/src/Messages/OWSMessageReceiver.m @@ -249,7 +249,9 @@ NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessin _isDrainingQueue = NO; [AppReadiness runNowOrWhenAppDidBecomeReady:^{ - [self drainQueue]; + if (CurrentAppContext().isMainApp) { + [self drainQueue]; + } }]; return self; diff --git a/SignalServiceKit/src/Network/MessageSenderJobQueue.swift b/SignalServiceKit/src/Network/MessageSenderJobQueue.swift index 62d8aa500..3fc626876 100644 --- a/SignalServiceKit/src/Network/MessageSenderJobQueue.swift +++ b/SignalServiceKit/src/Network/MessageSenderJobQueue.swift @@ -65,6 +65,8 @@ public class MessageSenderJobQueue: NSObject, JobQueue { } private func add(message: TSOutgoingMessage, removeMessageAfterSending: Bool, transaction: YapDatabaseReadWriteTransaction) { + assert(AppReadiness.isAppReady()) + let jobRecord: SSKMessageSenderJobRecord do { jobRecord = try SSKMessageSenderJobRecord(message: message, removeMessageAfterSending: false, label: self.jobRecordLabel) diff --git a/SignalServiceKit/src/Util/JobQueue.swift b/SignalServiceKit/src/Util/JobQueue.swift index f773bccfd..12851fdef 100644 --- a/SignalServiceKit/src/Util/JobQueue.swift +++ b/SignalServiceKit/src/Util/JobQueue.swift @@ -106,6 +106,7 @@ public extension JobQueue { func add(jobRecord: JobRecordType, transaction: YapDatabaseReadWriteTransaction) { assert(jobRecord.status == .ready) + jobRecord.save(with: transaction) transaction.addCompletionQueue(.global()) {