Fix notification delivery after powering on a device. (#5035)

* Debugging with Notifications.

* Don't run the NSE until the device is unlocked.

* Let the NSE run long enough to deliver the default notification content.

Turns out that exit(0) results in the notification be discarded when you have the notification filtering entitlement.

* Remove debugging notifications.

---------

Co-authored-by: Stefan Ceriu <stefanc@matrix.org>
This commit is contained in:
Doug
2026-02-03 11:04:32 +00:00
committed by GitHub
parent 9c256d4598
commit dd8f51e065
2 changed files with 35 additions and 14 deletions

View File

@@ -51,7 +51,12 @@ class NotificationServiceExtension: UNNotificationServiceExtension {
appHooks = AppHooks()
appHooks.setUp()
if Self.targetConfiguration == nil {
// If the device is still locked then we can't write to the app group container and
// the target configuration will fail. We could call exit(0) here, however with the
// notification filtering entitlement that results in the notification being discarded
// so we need to wait for the delegate method to be called and bail out there instead.
if !DataProtectionManager.isDeviceLockedAfterReboot(containerURL: URL.appGroupContainerDirectory),
Self.targetConfiguration == nil {
Self.targetConfiguration = Target.nse.configure(logLevel: settings.logLevel,
traceLogPacks: settings.traceLogPacks,
sentryURL: nil,
@@ -67,16 +72,32 @@ class NotificationServiceExtension: UNNotificationServiceExtension {
}
private func handle(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) async {
guard !DataProtectionManager.isDeviceLockedAfterReboot(containerURL: URL.appGroupContainerDirectory),
let roomID = request.content.roomID,
let eventID = request.content.eventID,
let clientID = request.content.pusherNotificationClientIdentifier,
let credentials = keychainController.restorationTokens().first(where: { $0.restorationToken.pusherNotificationClientIdentifier == clientID }) else {
// We cannot process this notification, it might be due to one of these:
// - Device rebooted and locked
// - Not a Matrix notification
// - User is not signed in
// - NotificationID could not be resolved
// If we skipped configuring the target it means we can't write to the app group, so we're unlikely
// to be able to create a session (and even if we could, we would be missing the lightweightTokioRuntime),
// so instead lets deliver the default generic notification and avoid attempting to process the notification.
guard Self.targetConfiguration != nil else {
// swiftlint:disable:next print_deprecation (MXLog isn't configured)
print("Device is locked after reboot, delivering the unmodified notification.")
return contentHandler(request.content)
}
guard let roomID = request.content.roomID else {
MXLog.error("Invalid roomID, bailing out: \(request.content)")
return contentHandler(request.content)
}
guard let eventID = request.content.eventID else {
MXLog.error("Invalid eventID, bailing out: \(request.content)")
return contentHandler(request.content)
}
guard let clientID = request.content.pusherNotificationClientIdentifier else {
MXLog.error("Invalid eventID, bailing out: \(request.content)")
return contentHandler(request.content)
}
guard let credentials = keychainController.restorationTokens().first(where: { $0.restorationToken.pusherNotificationClientIdentifier == clientID }) else {
MXLog.error("Invalid credentials, bailing out: \(request.content)")
return contentHandler(request.content)
}