From ee51a1ac12a5698d152d8f6d5eb91a0056c09c28 Mon Sep 17 00:00:00 2001 From: Ryan ZHAO Date: Fri, 24 Jul 2020 10:39:35 +1000 Subject: [PATCH 1/3] support writing messages into database in NSE --- SignalServiceKit/src/Messages/OWSMessageManager.m | 8 ++++---- .../Storage/AxolotlStore/OWSPrimaryStorage+SessionStore.m | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 2c31061d8..dd72453fe 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -1613,10 +1613,10 @@ NS_ASSUME_NONNULL_BEGIN // Update thread preview in inbox [masterThread touchWithTransaction:transaction]; - - [SSKEnvironment.shared.notificationsManager notifyUserForIncomingMessage:incomingMessage - inThread:masterThread - transaction:transaction]; + + if (CurrentAppContext().isMainAppAndActive) { + [SSKEnvironment.shared.notificationsManager notifyUserForIncomingMessage:incomingMessage inThread:masterThread transaction:transaction]; + } dispatch_async(dispatch_get_main_queue(), ^{ [self.typingIndicators didReceiveIncomingMessageInThread:masterThread diff --git a/SignalServiceKit/src/Storage/AxolotlStore/OWSPrimaryStorage+SessionStore.m b/SignalServiceKit/src/Storage/AxolotlStore/OWSPrimaryStorage+SessionStore.m index a96461456..9dea9ebc8 100644 --- a/SignalServiceKit/src/Storage/AxolotlStore/OWSPrimaryStorage+SessionStore.m +++ b/SignalServiceKit/src/Storage/AxolotlStore/OWSPrimaryStorage+SessionStore.m @@ -88,8 +88,6 @@ NSString *const kSessionStoreDBConnectionKey = @"kSessionStoreDBConnectionKey"; OWSAssertDebug(contactIdentifier.length > 0); OWSAssertDebug(deviceId >= 0); OWSAssertDebug([protocolContext isKindOfClass:[YapDatabaseReadWriteTransaction class]]); - // FIXME: This needs a comment from Ryan explaining why it's necessary (it has to do with push notifications) - if (!CurrentAppContext().isMainApp) { return; } YapDatabaseReadWriteTransaction *transaction = protocolContext; From 1eb47ed960a2e553340e8c391c4d43955196ab5a Mon Sep 17 00:00:00 2001 From: Ryan ZHAO Date: Tue, 28 Jul 2020 10:25:48 +1000 Subject: [PATCH 2/3] store messages in NSE --- .../NotificationServiceExtension.swift | 51 ++++++++++--------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/LokiPushNotificationService/NotificationServiceExtension.swift b/LokiPushNotificationService/NotificationServiceExtension.swift index dad989eb9..604c91a19 100644 --- a/LokiPushNotificationService/NotificationServiceExtension.swift +++ b/LokiPushNotificationService/NotificationServiceExtension.swift @@ -15,31 +15,36 @@ final class NotificationServiceExtension : UNNotificationServiceExtension { override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler notificationContent = (request.content.mutableCopy() as? UNMutableNotificationContent) - - DispatchQueue.main.async { - self.setUpIfNecessary() { - if let notificationContent = self.notificationContent { - // Modify the notification content here... - let base64EncodedData = notificationContent.userInfo["ENCRYPTED_DATA"] as! String - let data = Data(base64Encoded: base64EncodedData)! - let decrypter = SSKEnvironment.shared.messageDecrypter - if let envelope = try? MessageWrapper.unwrap(data: data), let data = try? envelope.serializedData() { - decrypter.decryptEnvelope(envelope, - envelopeData: data, - successBlock: { result, transaction in - if (try? SSKProtoEnvelope.parseData(result.envelopeData)) != nil { - self.handleDecryptionResult(result: result, notificationContent: notificationContent, transaction: transaction) - } else { - self.completeWithFailure(content: notificationContent) - } - }, - failureBlock: { + + // The code using DispatchQueue.main.async { self.setUpIfNecessary(){ Modify the notification content } } will somehow cause a freezing when the second PN comes + + DispatchQueue.main.sync { self.setUpIfNecessary(){} } + + AppReadiness.runNowOrWhenAppDidBecomeReady { + if let notificationContent = self.notificationContent { + // Modify the notification content here... + let base64EncodedData = notificationContent.userInfo["ENCRYPTED_DATA"] as! String + let data = Data(base64Encoded: base64EncodedData)! + let decrypter = SSKEnvironment.shared.messageDecrypter + let messageManager = SSKEnvironment.shared.messageManager + if let envelope = try? MessageWrapper.unwrap(data: data), let data = try? envelope.serializedData() { + let wasReceivedByUD = self.wasReceivedByUD(envelope: envelope) + decrypter.decryptEnvelope(envelope, + envelopeData: data, + successBlock: { result, transaction in + if let envelope = try? SSKProtoEnvelope.parseData(result.envelopeData) { + messageManager.throws_processEnvelope(envelope, plaintextData: result.plaintextData, wasReceivedByUD: wasReceivedByUD, transaction: transaction, serverID: 0) + self.handleDecryptionResult(result: result, notificationContent: notificationContent, transaction: transaction) + } else { self.completeWithFailure(content: notificationContent) } - ) - } else { - self.completeWithFailure(content: notificationContent) - } + }, + failureBlock: { + self.completeWithFailure(content: notificationContent) + } + ) + } else { + self.completeWithFailure(content: notificationContent) } } } From 1dab1dfef89b03860b0a244628378fb68c98f81c Mon Sep 17 00:00:00 2001 From: Ryan ZHAO Date: Tue, 28 Jul 2020 10:26:56 +1000 Subject: [PATCH 3/3] fix for the crash in home vc --- Signal/src/Loki/View Controllers/HomeVC.swift | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Signal/src/Loki/View Controllers/HomeVC.swift b/Signal/src/Loki/View Controllers/HomeVC.swift index a7c6b067f..0acc30c59 100644 --- a/Signal/src/Loki/View Controllers/HomeVC.swift +++ b/Signal/src/Loki/View Controllers/HomeVC.swift @@ -212,12 +212,16 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol isObservingDatabase = isViewVisible && CurrentAppContext().isAppForegroundAndActive() } - private func reload() { - AssertIsOnMainThread() + private func updateThreadMapping() { uiDatabaseConnection.beginLongLivedReadTransaction() uiDatabaseConnection.read { transaction in self.threads.update(with: transaction) } + } + + private func reload() { + AssertIsOnMainThread() + updateThreadMapping() threadViewModelCache.removeAll() tableView.reloadData() emptyStateView.isHidden = (threadCount != 0) @@ -235,6 +239,21 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol } return } + // Guard for changes made in Notification Service Extension + // Crashes may happen if there is some modification in NSE + // The YapDBModificationNotification cannot cross process + // So the thread mapping won't update itself if DB modification happened in other process like NSE + // With these code we can sync the mapping before asking for changes from YapDB + if (notifications.count > 0) { + if let firstChangeset = notifications[0].userInfo { + let firstSnapshot = firstChangeset[YapDatabaseSnapshotKey] as! UInt64 + if (self.threads.snapshotOfLastUpdate != firstSnapshot - 1) { + reload() + return + } + } + } + var sectionChanges = NSArray() var rowChanges = NSArray() ext.getSectionChanges(§ionChanges, rowChanges: &rowChanges, for: notifications, with: threads) @@ -261,6 +280,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol @objc private func handleApplicationDidBecomeActiveNotification(_ notification: Notification) { updateIsObservingDatabase() + updateThreadMapping() } @objc private func handleApplicationWillResignActiveNotification(_ notification: Notification) {