From a1f30b222be669c187b45f539f7bca70bc7dbe1e Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Tue, 20 Jun 2023 17:08:05 +0200 Subject: [PATCH] finally works! made also the feature flag --- .../Sources/Application/AppCoordinator.swift | 10 ++++++++ .../Sources/Application/AppSettings.swift | 4 ++++ .../Sources/Services/Client/ClientProxy.swift | 21 +++++++++++------ .../NotificationServiceExtension.swift | 23 +++++++++++++------ NSE/Sources/Other/NSESettings.swift | 4 ++++ NSE/Sources/Other/NSEUserSession.swift | 6 ++++- 6 files changed, 53 insertions(+), 15 deletions(-) diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 5f9990236b..114d2f72a1 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -553,6 +553,16 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate, selector: #selector(applicationDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) + + NotificationCenter.default.addObserver(self, + selector: #selector(applicationWillTerminate), + name: UIApplication.willTerminateNotification, + object: nil) + } + + @objc + private func applicationWillTerminate() { + userSession?.clientProxy.stopSync() } @objc diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index 4a99a8049d..d3a4f0456f 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -162,6 +162,10 @@ final class AppSettings { /// Tag describing which set of device specific rules a pusher executes. @UserPreference(key: UserDefaultsKeys.pusherProfileTag, storageType: .userDefaults(store)) var pusherProfileTag: String? + + /// Tag describing if the app and the NSE should use the encryption sync + @UserPreference(key: SharedUserDefaultsKeys.isEncryptionSyncEnabled, initialValue: true, storageType: .userDefaults(store)) + var isEncryptionSyncEnabled // MARK: - Other diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 96674cffbb..f4a2b8e546 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -51,6 +51,7 @@ class ClientProxy: ClientProxyProtocol { private var roomListStateUpdateTaskHandle: TaskHandle? private var encryptionSyncService: EncryptionSync? + private var isEncryptionSyncing = false var roomSummaryProvider: RoomSummaryProviderProtocol? var inviteSummaryProvider: RoomSummaryProviderProtocol? @@ -72,7 +73,7 @@ class ClientProxy: ClientProxyProtocol { deinit { // These need to be inlined instead of using stopSync() // as we can't call async methods safely from deinit - encryptionSyncService?.stop() + stopEncryptionSyncService() client.setDelegate(delegate: nil) roomListSyncTaskHandle?.cancel() } @@ -146,9 +147,11 @@ class ClientProxy: ClientProxyProtocol { roomListSyncTaskHandle = nil } - private var isEncryptionSyncing = false - private func stopEncryptionSyncService() { + guard ServiceLocator.shared.settings.isEncryptionSyncEnabled else { + return + } + MXLog.info("Stopping Encryption Sync service") isEncryptionSyncing = false guard let encryptionSyncService else { return @@ -394,19 +397,23 @@ class ClientProxy: ClientProxyProtocol { } private func startEncryptionSyncService() { + guard ServiceLocator.shared.settings.isEncryptionSyncEnabled else { + return + } guard encryptionSyncService == nil else { fatalError("This shouldn't be called more than once") } + configureEncryptionSyncService() + } + + private func configureEncryptionSyncService() { do { let listener = EncryptionSyncListenerProxy { [weak self] in MXLog.info("Encryption Sync did terminate for user: \(self?.userID ?? "unknown")") guard let self, isEncryptionSyncing else { return } - // To avoid the nested block on error - Task { - self.startEncryptionSyncService() - } + self.configureEncryptionSyncService() } let encryptionSync = try client.mainEncryptionSync(id: "Main App", listener: listener) encryptionSync.reloadCaches() diff --git a/NSE/Sources/NotificationServiceExtension.swift b/NSE/Sources/NotificationServiceExtension.swift index 460e911693..3c2a8e1b3a 100644 --- a/NSE/Sources/NotificationServiceExtension.swift +++ b/NSE/Sources/NotificationServiceExtension.swift @@ -19,12 +19,12 @@ import MatrixRustSDK import UserNotifications class NotificationServiceExtension: UNNotificationServiceExtension { - private static var userSession: [String: NSEUserSession] = [:] private let settings = NSESettings() private lazy var keychainController = KeychainController(service: .sessions, accessGroup: InfoPlistReader.main.keychainAccessGroupIdentifier) private var handler: ((UNNotificationContent) -> Void)? private var modifiedContent: UNMutableNotificationContent? + private var userSession: NSEUserSession? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { @@ -72,9 +72,11 @@ class NotificationServiceExtension: UNNotificationServiceExtension { do { let userSession = try NSEUserSession(credentials: credentials) - + self.userSession = userSession var itemProxy = await userSession.notificationItemProxy(roomID: roomId, eventID: eventId) - if itemProxy.isEncrypted, let _ = try? userSession.startEncryptionSync() { + if settings.isEncryptionSyncEnabled, + itemProxy.isEncrypted, + let _ = try? userSession.startEncryptionSync() { // TODO: The following wait with a timeout should be handled by the SDK // We try to decrypt the notification for 10 seconds at most let date = Date() @@ -117,23 +119,30 @@ class NotificationServiceExtension: UNNotificationServiceExtension { } handler?(modifiedContent) - handler = nil - self.modifiedContent = nil + cleanUp() } private func discard() { MXLog.info("\(tag) discard") handler?(UNMutableNotificationContent()) - handler = nil - modifiedContent = nil + cleanUp() } private var tag: String { "[NSE][\(Unmanaged.passUnretained(self).toOpaque())][\(Unmanaged.passUnretained(Thread.current).toOpaque())]" } + private func cleanUp() { + handler = nil + modifiedContent = nil + if settings.isEncryptionSyncEnabled { + userSession?.stopEncryptionSync() + } + } + deinit { + cleanUp() NSELogger.logMemory(with: tag) MXLog.info("\(tag) deinit") } diff --git a/NSE/Sources/Other/NSESettings.swift b/NSE/Sources/Other/NSESettings.swift index d0dd2cbb82..e53f841cb2 100644 --- a/NSE/Sources/Other/NSESettings.swift +++ b/NSE/Sources/Other/NSESettings.swift @@ -21,4 +21,8 @@ final class NSESettings { /// UserDefaults to be used on reads and writes. private static var store: UserDefaults! = UserDefaults(suiteName: suiteName) + + /// Tag describing if the app and the NSE should use the encryption sync + @UserPreference(key: SharedUserDefaultsKeys.isEncryptionSyncEnabled, defaultValue: true, storageType: .userDefaults(store)) + var isEncryptionSyncEnabled } diff --git a/NSE/Sources/Other/NSEUserSession.swift b/NSE/Sources/Other/NSEUserSession.swift index 659339eae5..a2ca51c2e3 100644 --- a/NSE/Sources/Other/NSEUserSession.swift +++ b/NSE/Sources/Other/NSEUserSession.swift @@ -56,8 +56,12 @@ final class NSEUserSession { } } + func stopEncryptionSync() { + encryptionSyncService?.stop() + } + deinit { MXLog.info("NSE: NSEUserSession deinit called for user: \(userID)") - encryptionSyncService?.stop() + stopEncryptionSync() } }