Merge branch 'nt/nse-fix'
This commit is contained in:
commit
bc8a6af25c
@ -6,7 +6,7 @@ import Foundation
|
||||
import SignalServiceKit
|
||||
import SignalMessaging
|
||||
|
||||
class NotificationServiceExtensionContext: NSObject, AppContext {
|
||||
class NSEContext: NSObject, AppContext {
|
||||
let isMainApp = false
|
||||
let isMainAppAndActive = false
|
||||
|
||||
172
NotificationServiceExtension/NSEEnvironment.swift
Normal file
172
NotificationServiceExtension/NSEEnvironment.swift
Normal file
@ -0,0 +1,172 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalServiceKit
|
||||
import SignalMessaging
|
||||
|
||||
class NSEEnvironment: Dependencies {
|
||||
var isProcessingMessages = AtomicBool(false)
|
||||
|
||||
// MARK: - Main App Comms
|
||||
|
||||
func askMainAppToHandleReceipt(handledCallback: @escaping (_ mainAppHandledReceipt: Bool) -> Void) {
|
||||
DispatchQueue.main.async {
|
||||
// We track whether we've ever handled the call back to ensure
|
||||
// we only notify the caller once and avoid any races that may
|
||||
// occur between the notification observer and the dispatch
|
||||
// after block.
|
||||
var hasCalledBack = false
|
||||
|
||||
// Listen for an indication that the main app is going to handle
|
||||
// this notification. If the main app is active we don't want to
|
||||
// process any messages here.
|
||||
let token = DarwinNotificationCenter.addObserver(for: .mainAppHandledNotification, queue: .main) { token in
|
||||
guard !hasCalledBack else { return }
|
||||
|
||||
hasCalledBack = true
|
||||
|
||||
handledCallback(true)
|
||||
|
||||
if DarwinNotificationCenter.isValidObserver(token) {
|
||||
DarwinNotificationCenter.removeObserver(token)
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the main app that we received new content to process.
|
||||
// If it's running, it will notify us so we can bail out.
|
||||
DarwinNotificationCenter.post(.nseDidReceiveNotification)
|
||||
|
||||
// The main app should notify us nearly instantaneously if it's
|
||||
// going to process this notification so we only wait a fraction
|
||||
// of a second to hear back from it.
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.001) {
|
||||
if DarwinNotificationCenter.isValidObserver(token) {
|
||||
DarwinNotificationCenter.removeObserver(token)
|
||||
}
|
||||
|
||||
guard !hasCalledBack else { return }
|
||||
|
||||
hasCalledBack = true
|
||||
|
||||
// If we haven't called back yet and removed the observer token,
|
||||
// the main app is not running and will not handle receipt of this
|
||||
// notification.
|
||||
handledCallback(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var mainAppLaunchObserverToken = DarwinNotificationInvalidObserver
|
||||
func listenForMainAppLaunch() {
|
||||
guard !DarwinNotificationCenter.isValidObserver(mainAppLaunchObserverToken) else { return }
|
||||
mainAppLaunchObserverToken = DarwinNotificationCenter.addObserver(for: .mainAppLaunched, queue: .global(), using: { _ in
|
||||
// If we're currently processing messages we want to commit
|
||||
// suicide to ensure that we don't try and process messages
|
||||
// while the main app is running. If we're not processing
|
||||
// messages we keep alive since future notifications will
|
||||
// be passed off gracefully to the main app. We only kill
|
||||
// ourselves as a last resort.
|
||||
// TODO: We could eventually make the message fetch process
|
||||
// cancellable to never have to exit here.
|
||||
guard self.isProcessingMessages.get() else { return }
|
||||
Logger.info("Exiting because main app launched while we were processing messages.")
|
||||
Logger.flush()
|
||||
exit(0)
|
||||
})
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
private var isSetup = AtomicBool(false)
|
||||
func setupIfNecessary() {
|
||||
guard isSetup.tryToSetFlag() else { return }
|
||||
DispatchQueue.main.sync { setup() }
|
||||
}
|
||||
|
||||
private var areVersionMigrationsComplete = false
|
||||
private func setup() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
// This should be the first thing we do.
|
||||
SetCurrentAppContext(NSEContext())
|
||||
|
||||
DebugLogger.shared().enableTTYLogging()
|
||||
if _isDebugAssertConfiguration() {
|
||||
DebugLogger.shared().enableFileLogging()
|
||||
} else if OWSPreferences.isLoggingEnabled() {
|
||||
DebugLogger.shared().enableFileLogging()
|
||||
}
|
||||
|
||||
Logger.info("")
|
||||
|
||||
_ = AppVersion.shared()
|
||||
|
||||
Cryptography.seedRandom()
|
||||
|
||||
AppSetup.setupEnvironment(
|
||||
appSpecificSingletonBlock: {
|
||||
SSKEnvironment.shared.callMessageHandlerRef = NSECallMessageHandler()
|
||||
SSKEnvironment.shared.notificationsManagerRef = NotificationPresenter()
|
||||
},
|
||||
migrationCompletion: { [weak self] error in
|
||||
if let error = error {
|
||||
// TODO: Maybe notify that you should open the main app.
|
||||
owsFailDebug("Error \(error)")
|
||||
return
|
||||
}
|
||||
self?.versionMigrationsDidComplete()
|
||||
}
|
||||
)
|
||||
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(storageIsReady),
|
||||
name: .StorageIsReady,
|
||||
object: nil
|
||||
)
|
||||
|
||||
Logger.info("completed.")
|
||||
|
||||
OWSAnalytics.appLaunchDidBegin()
|
||||
|
||||
listenForMainAppLaunch()
|
||||
}
|
||||
|
||||
@objc
|
||||
private func versionMigrationsDidComplete() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
Logger.debug("")
|
||||
|
||||
areVersionMigrationsComplete = true
|
||||
|
||||
checkIsAppReady()
|
||||
}
|
||||
|
||||
@objc
|
||||
private func storageIsReady() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
Logger.debug("")
|
||||
|
||||
checkIsAppReady()
|
||||
}
|
||||
|
||||
@objc
|
||||
private func checkIsAppReady() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
// Only mark the app as ready once.
|
||||
guard !AppReadiness.isAppReady else { return }
|
||||
|
||||
// App isn't ready until storage is ready AND all version migrations are complete.
|
||||
guard storageCoordinator.isStorageReady && areVersionMigrationsComplete else { return }
|
||||
|
||||
// Note that this does much more than set a flag; it will also run all deferred blocks.
|
||||
AppReadiness.setAppIsReady()
|
||||
|
||||
AppVersion.shared().nseLaunchDidComplete()
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,29 @@ import SignalMessaging
|
||||
import SignalServiceKit
|
||||
import PromiseKit
|
||||
|
||||
// The lifecycle of the NSE looks something like the following:
|
||||
// 1) App receives notification
|
||||
// 2) System creates an instance of the extension class
|
||||
// and calls `didReceive` in the background
|
||||
// 3) Extension processes messages / displays whatever
|
||||
// notifications it needs to
|
||||
// 4) Extension notifies its work is complete by calling
|
||||
// the contentHandler
|
||||
// 5) If the extension takes too long to perform its work
|
||||
// (more than 30s), it will be notified and immediately
|
||||
// terminated
|
||||
//
|
||||
// Note that the NSE does *not* always spawn a new process to
|
||||
// handle a new notification and will also try and process notifications
|
||||
// in parallel. `didReceive` could be called twice for the same process,
|
||||
// but it will always be called on different threads. It may or may not be
|
||||
// called on the same instance of `NotificationService` as a previous
|
||||
// notification.
|
||||
//
|
||||
// We keep a global `environment` singleton to ensure that our app context,
|
||||
// database, logging, etc. are only ever setup once per *process*
|
||||
let environment = NSEEnvironment()
|
||||
|
||||
class NotificationService: UNNotificationServiceExtension {
|
||||
|
||||
var contentHandler: ((UNNotificationContent) -> Void)?
|
||||
@ -18,43 +41,25 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
contentHandler?(content)
|
||||
}
|
||||
|
||||
// The lifecycle of the NSE looks something like the following:
|
||||
// 1) App receives notification
|
||||
// 2) System creates an instance of the extension class
|
||||
// and calls this method in the background
|
||||
// 3) Extension processes messages / displays whatever
|
||||
// notifications it needs to
|
||||
// 4) Extension notifies its work is complete by calling
|
||||
// the contentHandler
|
||||
// 5) If the extension takes too long to perform its work
|
||||
// (more than 30s), it will be notified and immediately
|
||||
// terminated
|
||||
//
|
||||
// Note that the NSE does *not* always spawn a new process to
|
||||
// handle a new notification and will also try and process notifications
|
||||
// in parallel. `didReceive` could be called twice for the same process,
|
||||
// but will always be called on different threads. To deal with this we
|
||||
// ensure that we only do setup *once* per process and we dispatch to
|
||||
// the main queue to make sure the calls to the message fetcher job
|
||||
// run serially.
|
||||
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
||||
self.contentHandler = contentHandler
|
||||
|
||||
DispatchQueue.main.sync { self.setupIfNecessary() }
|
||||
environment.setupIfNecessary()
|
||||
|
||||
owsAssertDebug(FeatureFlags.notificationServiceExtension)
|
||||
|
||||
listenForMainAppLaunch()
|
||||
Logger.info("Received notification in class: \(self), thread: \(Thread.current), pid: \(ProcessInfo.processInfo.processIdentifier)")
|
||||
|
||||
askMainAppToHandleReceipt { mainAppHandledReceipt in
|
||||
environment.askMainAppToHandleReceipt { [weak self] mainAppHandledReceipt in
|
||||
guard !mainAppHandledReceipt else {
|
||||
Logger.info("Received notification handled by main application.")
|
||||
return self.completeSilenty()
|
||||
self?.completeSilenty()
|
||||
return
|
||||
}
|
||||
|
||||
Logger.info("Processing received notification.")
|
||||
|
||||
AppReadiness.runNowOrWhenAppDidBecomeReadySync { self.fetchAndProcessMessages() }
|
||||
AppReadiness.runNowOrWhenAppDidBecomeReadySync { self?.fetchAndProcessMessages() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,161 +73,6 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
completeSilenty()
|
||||
}
|
||||
|
||||
private var hasSetup = false
|
||||
func setupIfNecessary() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
// The NSE will often re-use the same process, so if we're
|
||||
// already setup we want to do nothing. We're already ready
|
||||
// to process new messages.
|
||||
guard !hasSetup else { return }
|
||||
|
||||
hasSetup = true
|
||||
|
||||
// This should be the first thing we do.
|
||||
SetCurrentAppContext(NotificationServiceExtensionContext())
|
||||
|
||||
DebugLogger.shared().enableTTYLogging()
|
||||
if _isDebugAssertConfiguration() {
|
||||
DebugLogger.shared().enableFileLogging()
|
||||
} else if OWSPreferences.isLoggingEnabled() {
|
||||
DebugLogger.shared().enableFileLogging()
|
||||
}
|
||||
|
||||
Logger.info("")
|
||||
|
||||
_ = AppVersion.shared()
|
||||
|
||||
Cryptography.seedRandom()
|
||||
|
||||
AppSetup.setupEnvironment(
|
||||
appSpecificSingletonBlock: {
|
||||
SSKEnvironment.shared.callMessageHandlerRef = NSECallMessageHandler()
|
||||
SSKEnvironment.shared.notificationsManagerRef = NotificationPresenter()
|
||||
},
|
||||
migrationCompletion: { [weak self] error in
|
||||
if let error = error {
|
||||
// TODO: Maybe notify that you should open the main app.
|
||||
owsFailDebug("Error \(error)")
|
||||
return
|
||||
}
|
||||
self?.versionMigrationsDidComplete()
|
||||
}
|
||||
)
|
||||
|
||||
NotificationCenter.default.addObserver(self,
|
||||
selector: #selector(storageIsReady),
|
||||
name: .StorageIsReady,
|
||||
object: nil)
|
||||
|
||||
Logger.info("completed.")
|
||||
|
||||
OWSAnalytics.appLaunchDidBegin()
|
||||
}
|
||||
|
||||
@objc
|
||||
func versionMigrationsDidComplete() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
Logger.debug("")
|
||||
|
||||
areVersionMigrationsComplete = true
|
||||
|
||||
checkIsAppReady()
|
||||
}
|
||||
|
||||
@objc
|
||||
func storageIsReady() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
Logger.debug("")
|
||||
|
||||
checkIsAppReady()
|
||||
}
|
||||
|
||||
@objc
|
||||
func checkIsAppReady() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
// Only mark the app as ready once.
|
||||
guard !AppReadiness.isAppReady else { return }
|
||||
|
||||
// App isn't ready until storage is ready AND all version migrations are complete.
|
||||
guard storageCoordinator.isStorageReady && areVersionMigrationsComplete else { return }
|
||||
|
||||
// Note that this does much more than set a flag; it will also run all deferred blocks.
|
||||
AppReadiness.setAppIsReady()
|
||||
|
||||
AppVersion.shared().nseLaunchDidComplete()
|
||||
}
|
||||
|
||||
func askMainAppToHandleReceipt(handledCallback: @escaping (_ mainAppHandledReceipt: Bool) -> Void) {
|
||||
DispatchQueue.main.async {
|
||||
// We track whether we've ever handled the call back to ensure
|
||||
// we only notify the caller once and avoid any races that may
|
||||
// occur between the notification observer and the dispatch
|
||||
// after block.
|
||||
var hasCalledBack = false
|
||||
|
||||
// Listen for an indication that the main app is going to handle
|
||||
// this notification. If the main app is active we don't want to
|
||||
// process any messages here.
|
||||
let token = DarwinNotificationCenter.addObserver(for: .mainAppHandledNotification, queue: .main) { token in
|
||||
guard !hasCalledBack else { return }
|
||||
|
||||
hasCalledBack = true
|
||||
|
||||
handledCallback(true)
|
||||
|
||||
if DarwinNotificationCenter.isValidObserver(token) {
|
||||
DarwinNotificationCenter.removeObserver(token)
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the main app that we received new content to process.
|
||||
// If it's running, it will notify us so we can bail out.
|
||||
DarwinNotificationCenter.post(.nseDidReceiveNotification)
|
||||
|
||||
// The main app should notify us nearly instantaneously if it's
|
||||
// going to process this notification so we only wait a fraction
|
||||
// of a second to hear back from it.
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.001) {
|
||||
if DarwinNotificationCenter.isValidObserver(token) {
|
||||
DarwinNotificationCenter.removeObserver(token)
|
||||
}
|
||||
|
||||
guard !hasCalledBack else { return }
|
||||
|
||||
hasCalledBack = true
|
||||
|
||||
// If we haven't called back yet and removed the observer token,
|
||||
// the main app is not running and will not handle receipt of this
|
||||
// notification.
|
||||
handledCallback(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var mainAppLaunchObserverToken = DarwinNotificationInvalidObserver
|
||||
func listenForMainAppLaunch() {
|
||||
guard !DarwinNotificationCenter.isValidObserver(mainAppLaunchObserverToken) else { return }
|
||||
mainAppLaunchObserverToken = DarwinNotificationCenter.addObserver(for: .mainAppLaunched, queue: .global(), using: { _ in
|
||||
// If we're currently processing messages we want to commit
|
||||
// suicide to ensure that we don't try and process messages
|
||||
// while the main app is running. If we're not processing
|
||||
// messages we keep alive since future notifications will
|
||||
// be passed off gracefully to the main app. We only kill
|
||||
// ourselves as a last resort.
|
||||
// TODO: We could eventually make the message fetch process
|
||||
// cancellable to never have to exit here.
|
||||
guard self.isProcessingMessages.get() else { return }
|
||||
Logger.info("Exiting because main app launched while we were processing messages.")
|
||||
exit(0)
|
||||
})
|
||||
}
|
||||
|
||||
private let isProcessingMessages = AtomicBool(false)
|
||||
|
||||
func fetchAndProcessMessages() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
@ -231,16 +81,18 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
return completeSilenty()
|
||||
}
|
||||
|
||||
isProcessingMessages.set(true)
|
||||
environment.isProcessingMessages.set(true)
|
||||
|
||||
Logger.info("Beginning message fetch.")
|
||||
|
||||
messageFetcherJob.run().promise.then {
|
||||
messageFetcherJob.run().promise.then { [weak self] () -> Promise<Void> in
|
||||
Logger.info("Waiting for processing to complete.")
|
||||
guard let self = self else { return Promise.value(()) }
|
||||
return self.messageProcessor.processingCompletePromise()
|
||||
}.ensure {
|
||||
}.ensure { [weak self] in
|
||||
Logger.info("Message fetch completed.")
|
||||
self.isProcessingMessages.set(false)
|
||||
self.completeSilenty()
|
||||
environment.isProcessingMessages.set(false)
|
||||
self?.completeSilenty()
|
||||
}.catch { error in
|
||||
Logger.warn("Error: \(error)")
|
||||
}
|
||||
|
||||
@ -722,6 +722,7 @@
|
||||
88411B60249B0759005D10AA /* ConversationViewController+LastVisibleSortId.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88411B5F249B0757005D10AA /* ConversationViewController+LastVisibleSortId.swift */; };
|
||||
8841584C252F9F1C0078903D /* SignalCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8841584B252F9F1C0078903D /* SignalCall.swift */; };
|
||||
8845B0C9264F12F800FA694C /* GroupDescriptionPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8845B0C8264F12F800FA694C /* GroupDescriptionPreviewView.swift */; };
|
||||
88489AFB266AB59800EE1166 /* NSEEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88489AFA266AB59800EE1166 /* NSEEnvironment.swift */; };
|
||||
884EFBAC251478D0006B9457 /* ResearchMegaphone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 884EFBAB251478D0006B9457 /* ResearchMegaphone.swift */; };
|
||||
885091C02525650100428A37 /* PHPhotoLibrary+Xcode11.swift in Sources */ = {isa = PBXBuildFile; fileRef = 885091BF2525650100428A37 /* PHPhotoLibrary+Xcode11.swift */; };
|
||||
8851DB3F24CCE9C8001EACD2 /* MentionTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8851DB3E24CCE9C8001EACD2 /* MentionTextView.swift */; };
|
||||
@ -801,7 +802,7 @@
|
||||
88A4CC1D246D00090082211F /* DeviceTransferProgressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A4CC1C246D00090082211F /* DeviceTransferProgressViewController.swift */; };
|
||||
88A505F423DA16E10005C012 /* ExperienceUpgradeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A505F323DA16E10005C012 /* ExperienceUpgradeManager.swift */; };
|
||||
88A505FA23DBA1360005C012 /* IntroducingPINs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A505F923DBA1360005C012 /* IntroducingPINs.swift */; };
|
||||
88A595E323AB48E80029E835 /* NotificationServiceExtensionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A595E223AB48E80029E835 /* NotificationServiceExtensionContext.swift */; };
|
||||
88A595E323AB48E80029E835 /* NSEContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A595E223AB48E80029E835 /* NSEContext.swift */; };
|
||||
88A9419524099F7E000E9700 /* attachment_dark.json in Resources */ = {isa = PBXBuildFile; fileRef = 88A9419424099F7E000E9700 /* attachment_dark.json */; };
|
||||
88A9419724099F85000E9700 /* attachment_light.json in Resources */ = {isa = PBXBuildFile; fileRef = 88A9419624099F85000E9700 /* attachment_light.json */; };
|
||||
88A941992409A391000E9700 /* LottieToggleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A941982409A391000E9700 /* LottieToggleButton.swift */; };
|
||||
@ -1808,6 +1809,7 @@
|
||||
884596EF24B93E13002F66D3 /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = translations/cy.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
884596F024B93E32002F66D3 /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = translations/cy.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
8845B0C8264F12F800FA694C /* GroupDescriptionPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupDescriptionPreviewView.swift; sourceTree = "<group>"; };
|
||||
88489AFA266AB59800EE1166 /* NSEEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEEnvironment.swift; sourceTree = "<group>"; };
|
||||
884EFBAB251478D0006B9457 /* ResearchMegaphone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResearchMegaphone.swift; sourceTree = "<group>"; };
|
||||
885091BF2525650100428A37 /* PHPhotoLibrary+Xcode11.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PHPhotoLibrary+Xcode11.swift"; sourceTree = "<group>"; };
|
||||
8851DB3E24CCE9C8001EACD2 /* MentionTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionTextView.swift; sourceTree = "<group>"; };
|
||||
@ -1958,7 +1960,7 @@
|
||||
88A4CC1C246D00090082211F /* DeviceTransferProgressViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceTransferProgressViewController.swift; sourceTree = "<group>"; };
|
||||
88A505F323DA16E10005C012 /* ExperienceUpgradeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExperienceUpgradeManager.swift; sourceTree = "<group>"; };
|
||||
88A505F923DBA1360005C012 /* IntroducingPINs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroducingPINs.swift; sourceTree = "<group>"; };
|
||||
88A595E223AB48E80029E835 /* NotificationServiceExtensionContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtensionContext.swift; sourceTree = "<group>"; };
|
||||
88A595E223AB48E80029E835 /* NSEContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEContext.swift; sourceTree = "<group>"; };
|
||||
88A695BC232C18DF002F7B9B /* AudioWaveformProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioWaveformProgressView.swift; sourceTree = "<group>"; };
|
||||
88A9419424099F7E000E9700 /* attachment_dark.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = attachment_dark.json; sourceTree = "<group>"; };
|
||||
88A9419624099F85000E9700 /* attachment_light.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = attachment_light.json; sourceTree = "<group>"; };
|
||||
@ -3573,10 +3575,11 @@
|
||||
children = (
|
||||
885AC57023AB428C0077705E /* NotificationServiceExtension.entitlements */,
|
||||
8872409323E12DF500824D62 /* NotificationServiceExtension-AppStore.entitlements */,
|
||||
885AC56623AB42430077705E /* NotificationService.swift */,
|
||||
885AC56823AB42430077705E /* Info.plist */,
|
||||
88A595E223AB48E80029E835 /* NotificationServiceExtensionContext.swift */,
|
||||
885AC56623AB42430077705E /* NotificationService.swift */,
|
||||
88D7BA9B266804C40088D1C2 /* NSECallMessageHandler.swift */,
|
||||
88A595E223AB48E80029E835 /* NSEContext.swift */,
|
||||
88489AFA266AB59800EE1166 /* NSEEnvironment.swift */,
|
||||
);
|
||||
path = NotificationServiceExtension;
|
||||
sourceTree = "<group>";
|
||||
@ -5120,8 +5123,9 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
88489AFB266AB59800EE1166 /* NSEEnvironment.swift in Sources */,
|
||||
88D7BA9C266804C40088D1C2 /* NSECallMessageHandler.swift in Sources */,
|
||||
88A595E323AB48E80029E835 /* NotificationServiceExtensionContext.swift in Sources */,
|
||||
88A595E323AB48E80029E835 /* NSEContext.swift in Sources */,
|
||||
885AC56723AB42430077705E /* NotificationService.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
@ -18,28 +18,30 @@ public class StorageServiceManager: NSObject, StorageServiceManagerProtocol {
|
||||
|
||||
SwiftSingletons.register(self)
|
||||
|
||||
AppReadiness.runNowOrWhenAppWillBecomeReady {
|
||||
self.cleanUpUnknownData()
|
||||
}
|
||||
if CurrentAppContext().hasUI {
|
||||
AppReadiness.runNowOrWhenAppWillBecomeReady {
|
||||
self.cleanUpUnknownData()
|
||||
}
|
||||
|
||||
AppReadiness.runNowOrWhenAppDidBecomeReadySync {
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(self.willResignActive),
|
||||
name: .OWSApplicationWillResignActive,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
AppReadiness.runNowOrWhenAppDidBecomeReadySync {
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(self.willResignActive),
|
||||
name: .OWSApplicationWillResignActive,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
AppReadiness.runNowOrWhenAppDidBecomeReadyAsync {
|
||||
guard self.tsAccountManager.isRegisteredAndReady else { return }
|
||||
AppReadiness.runNowOrWhenAppDidBecomeReadyAsync {
|
||||
guard self.tsAccountManager.isRegisteredAndReady else { return }
|
||||
|
||||
// Schedule a restore. This will do nothing unless we've never
|
||||
// registered a manifest before.
|
||||
self.restoreOrCreateManifestIfNecessary()
|
||||
// Schedule a restore. This will do nothing unless we've never
|
||||
// registered a manifest before.
|
||||
self.restoreOrCreateManifestIfNecessary()
|
||||
|
||||
// If we have any pending changes since we last launch, back them up now.
|
||||
self.backupPendingChanges()
|
||||
// If we have any pending changes since we last launch, back them up now.
|
||||
self.backupPendingChanges()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ public class MessageFetcherJob: NSObject {
|
||||
|
||||
SwiftSingletons.register(self)
|
||||
|
||||
if CurrentAppContext().shouldProcessIncomingMessages {
|
||||
if CurrentAppContext().shouldProcessIncomingMessages && CurrentAppContext().isMainApp {
|
||||
AppReadiness.runNowOrWhenAppDidBecomeReadySync {
|
||||
// Fetch messages as soon as possible after launching. In particular, when
|
||||
// launching from the background, without this, we end up waiting some extra
|
||||
|
||||
Loading…
Reference in New Issue
Block a user