diff --git a/Telegram/NotificationService/Sources/NotificationService.swift b/Telegram/NotificationService/Sources/NotificationService.swift index d197693858..533a22512c 100644 --- a/Telegram/NotificationService/Sources/NotificationService.swift +++ b/Telegram/NotificationService/Sources/NotificationService.swift @@ -729,6 +729,7 @@ private final class NotificationServiceHandler { var accessHash: Int64 var fromId: PeerId var updates: String + var accountId: Int64 } var callData: CallData? @@ -761,7 +762,8 @@ private final class NotificationServiceHandler { id: callId, accessHash: callAccessHash, fromId: peerId, - updates: updates + updates: updates, + accountId: recordId.int64 ) } } @@ -908,7 +910,8 @@ private final class NotificationServiceHandler { "call_id": "\(callData.id)", "call_ah": "\(callData.accessHash)", "from_id": "\(callData.fromId.id._internalGetInt64Value())", - "updates": callData.updates + "updates": callData.updates, + "accountId": "\(callData.accountId)" ] Logger.shared.log("NotificationService \(episode)", "Will report voip notification") let content = NotificationContent() diff --git a/submodules/TelegramCallsUI/Sources/CallKitIntegration.swift b/submodules/TelegramCallsUI/Sources/CallKitIntegration.swift index 1b261aee5d..3e5259e716 100644 --- a/submodules/TelegramCallsUI/Sources/CallKitIntegration.swift +++ b/submodules/TelegramCallsUI/Sources/CallKitIntegration.swift @@ -9,7 +9,13 @@ import SwiftSignalKit import AppBundle import AccountContext -private var sharedProviderDelegate: AnyObject? +private let sharedProviderDelegate: AnyObject? = { + if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { + return CallKitProviderDelegate() + } else { + return nil + } +}() public final class CallKitIntegration { public static var isAvailable: Bool { @@ -42,9 +48,6 @@ public final class CallKitIntegration { audioSessionActivationChanged: @escaping (Bool) -> Void ) { if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { - if sharedProviderDelegate == nil { - sharedProviderDelegate = CallKitProviderDelegate() - } (sharedProviderDelegate as? CallKitProviderDelegate)?.setup(audioSessionActivePromise: self.audioSessionActivePromise, startCall: startCall, answerCall: answerCall, endCall: endCall, setCallMuted: setCallMuted, audioSessionActivationChanged: audioSessionActivationChanged) } } diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index 0abf31498d..b67767f9c0 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -710,6 +710,13 @@ private func extractAccountManagerState(records: AccountRecordsView Void) { + Logger.shared.log("App \(self.episodeId) PushRegistry", "pushRegistry didReceiveIncomingPushWith \(payload.dictionaryPayload)") + self.pushRegistryImpl(registry, didReceiveIncomingPushWith: payload, for: type, completion: completion) } public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) { + Logger.shared.log("App \(self.episodeId) PushRegistry", "pushRegistry didReceiveIncomingPushWith \(payload.dictionaryPayload)") + self.pushRegistryImpl(registry, didReceiveIncomingPushWith: payload, for: type, completion: {}) } private func pushRegistryImpl(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { - Logger.shared.log("App \(self.episodeId) PushRegistry", "pushRegistry didReceiveIncomingPushWith") + Logger.shared.log("App \(self.episodeId) PushRegistry", "pushRegistry processing push notification") - guard var encryptedPayload = payload.dictionaryPayload["p"] as? String else { - Logger.shared.log("App \(self.episodeId) PushRegistry", "encryptedPayload is nil") - completion() - return - } - encryptedPayload = encryptedPayload.replacingOccurrences(of: "-", with: "+") - encryptedPayload = encryptedPayload.replacingOccurrences(of: "_", with: "/") - while encryptedPayload.count % 4 != 0 { - encryptedPayload.append("=") - } - guard let payloadData = Data(base64Encoded: encryptedPayload) else { - Logger.shared.log("App \(self.episodeId) PushRegistry", "Couldn't decode encryptedPayload") - completion() - return - } - guard let keyId = notificationPayloadKeyId(data: payloadData) else { - Logger.shared.log("App \(self.episodeId) PushRegistry", "Couldn't parse payload key id") - completion() - return - } - guard let accountManagerState = self.accountManagerState else { - Logger.shared.log("App \(self.episodeId) PushRegistry", "accountManagerState is nil") - completion() - return - } - - var maybeAccountId: AccountRecordId? - var maybeNotificationKey: MasterNotificationKey? - - for key in accountManagerState.notificationKeys { - if key.id == keyId { - maybeAccountId = key.accountId - maybeNotificationKey = MasterNotificationKey(id: key.id, data: key.key) - break + let decryptedPayloadAndAccountId: ([AnyHashable: Any], AccountRecordId)? + + if let accountIdString = payload.dictionaryPayload["accountId"] as? String, let accountId = Int64(accountIdString) { + decryptedPayloadAndAccountId = (payload.dictionaryPayload, AccountRecordId(rawValue: accountId)) + } else { + guard var encryptedPayload = payload.dictionaryPayload["p"] as? String else { + Logger.shared.log("App \(self.episodeId) PushRegistry", "encryptedPayload is nil") + completion() + return + } + encryptedPayload = encryptedPayload.replacingOccurrences(of: "-", with: "+") + encryptedPayload = encryptedPayload.replacingOccurrences(of: "_", with: "/") + while encryptedPayload.count % 4 != 0 { + encryptedPayload.append("=") + } + guard let payloadData = Data(base64Encoded: encryptedPayload) else { + Logger.shared.log("App \(self.episodeId) PushRegistry", "Couldn't decode encryptedPayload") + completion() + return + } + guard let keyId = notificationPayloadKeyId(data: payloadData) else { + Logger.shared.log("App \(self.episodeId) PushRegistry", "Couldn't parse payload key id") + completion() + return + } + guard let accountManagerState = self.accountManagerState else { + Logger.shared.log("App \(self.episodeId) PushRegistry", "accountManagerState is nil") + completion() + return } - } - guard let accountId = maybeAccountId, let notificationKey = maybeNotificationKey else { - Logger.shared.log("App \(self.episodeId) PushRegistry", "accountId or notificationKey is nil") - completion() - return - } - guard let decryptedPayload = decryptedNotificationPayload(key: notificationKey, data: payloadData) else { - Logger.shared.log("App \(self.episodeId) PushRegistry", "Couldn't decrypt payload") - completion() - return - } - guard let payloadJson = try? JSONSerialization.jsonObject(with: decryptedPayload, options: []) as? [String: Any] else { - Logger.shared.log("App \(self.episodeId) PushRegistry", "Couldn't decode payload json") + var maybeAccountId: AccountRecordId? + var maybeNotificationKey: MasterNotificationKey? + + for key in accountManagerState.notificationKeys { + if key.id == keyId { + maybeAccountId = key.accountId + maybeNotificationKey = MasterNotificationKey(id: key.id, data: key.key) + break + } + } + + guard let accountId = maybeAccountId, let notificationKey = maybeNotificationKey else { + Logger.shared.log("App \(self.episodeId) PushRegistry", "accountId or notificationKey is nil") + completion() + return + } + guard let decryptedPayload = decryptedNotificationPayload(key: notificationKey, data: payloadData) else { + Logger.shared.log("App \(self.episodeId) PushRegistry", "Couldn't decrypt payload") + completion() + return + } + guard let payloadJson = try? JSONSerialization.jsonObject(with: decryptedPayload, options: []) as? [AnyHashable: Any] else { + Logger.shared.log("App \(self.episodeId) PushRegistry", "Couldn't decode payload json") + completion() + return + } + + decryptedPayloadAndAccountId = (payloadJson, accountId) + } + + guard let (payloadJson, accountId) = decryptedPayloadAndAccountId else { + Logger.shared.log("App \(self.episodeId) PushRegistry", "decryptedPayloadAndAccountId is nil") completion() return } + guard var updateString = payloadJson["updates"] as? String else { Logger.shared.log("App \(self.episodeId) PushRegistry", "updates is nil") completion() @@ -1543,56 +1562,23 @@ private func extractAccountManagerState(records: AccountRecordsView take(1) |> deliverOnMainQueue).start(next: { sharedApplicationContext in - if var encryptedPayload = payload.dictionaryPayload["p"] as? String { - encryptedPayload = encryptedPayload.replacingOccurrences(of: "-", with: "+") - encryptedPayload = encryptedPayload.replacingOccurrences(of: "_", with: "/") - while encryptedPayload.count % 4 != 0 { - encryptedPayload.append("=") - } - if let data = Data(base64Encoded: encryptedPayload) { - let _ = (sharedApplicationContext.sharedContext.activeAccountContexts - |> take(1) - |> mapToSignal { activeAccounts -> Signal<[(Account, MasterNotificationKey)], NoError> in - return combineLatest(activeAccounts.accounts.map { context -> Signal<(Account, MasterNotificationKey), NoError> in - return masterNotificationsKey(account: context.1.account, ignoreDisabled: true) - |> map { key -> (Account, MasterNotificationKey) in - return (context.1.account, key) - } + let _ = (sharedApplicationContext.sharedContext.activeAccountContexts + |> take(1) + |> deliverOnMainQueue).start(next: { activeAccounts in + for (_, context, _) in activeAccounts.accounts { + if context.account.id == accountId { + context.account.stateManager.processIncomingCallUpdate(data: updateData, completion: { _ in }) + + break } - |> deliverOnMainQueue).start(next: { accountsAndKeys in - var accountAndDecryptedPayload: (Account, Data)? - for (account, key) in accountsAndKeys { - if let decryptedData = decryptedNotificationPayload(key: key, data: data) { - accountAndDecryptedPayload = (account, decryptedData) - break - } - } - - if let (account, decryptedData) = accountAndDecryptedPayload { - if let decryptedDict = (try? JSONSerialization.jsonObject(with: decryptedData, options: [])) as? [AnyHashable: Any] { - if var updateString = decryptedDict["updates"] as? String { - updateString = updateString.replacingOccurrences(of: "-", with: "+") - updateString = updateString.replacingOccurrences(of: "_", with: "/") - while updateString.count % 4 != 0 { - updateString.append("=") - } - if let updateData = Data(base64Encoded: updateString) { - account.stateManager.processIncomingCallUpdate(data: updateData, completion: { _ in - }) - } - } - } - } - }) } - } + }) + sharedApplicationContext.wakeupManager.allowBackgroundTimeExtension(timeout: 2.0) if case PKPushType.voIP = type { diff --git a/submodules/TelegramUI/Sources/SharedNotificationManager.swift b/submodules/TelegramUI/Sources/SharedNotificationManager.swift index 54e872d58c..6643e32e3f 100644 --- a/submodules/TelegramUI/Sources/SharedNotificationManager.swift +++ b/submodules/TelegramUI/Sources/SharedNotificationManager.swift @@ -172,19 +172,28 @@ public final class SharedNotificationManager { } var decryptedNotifications: [(Account, Bool, [AnyHashable: Any])] = [] for notification in self.notifications { - if var encryptedPayload = notification.dict["p"] as? String { - encryptedPayload = encryptedPayload.replacingOccurrences(of: "-", with: "+") - encryptedPayload = encryptedPayload.replacingOccurrences(of: "_", with: "/") - while encryptedPayload.count % 4 != 0 { - encryptedPayload.append("=") + if let accountIdString = notification.dict["accountId"] as? String, let accountId = Int64(accountIdString) { + inner: for (account, isCurrent, _) in accountsAndKeys { + if account.id.int64 == accountId { + decryptedNotifications.append((account, isCurrent, notification.dict)) + break inner + } } - if let data = Data(base64Encoded: encryptedPayload) { - inner: for (account, isCurrent, key) in accountsAndKeys { - if let decryptedData = decryptedNotificationPayload(key: key, data: data) { - if let decryptedDict = (try? JSONSerialization.jsonObject(with: decryptedData, options: [])) as? [AnyHashable: Any] { - decryptedNotifications.append((account, isCurrent, decryptedDict)) + } else { + if var encryptedPayload = notification.dict["p"] as? String { + encryptedPayload = encryptedPayload.replacingOccurrences(of: "-", with: "+") + encryptedPayload = encryptedPayload.replacingOccurrences(of: "_", with: "/") + while encryptedPayload.count % 4 != 0 { + encryptedPayload.append("=") + } + if let data = Data(base64Encoded: encryptedPayload) { + inner: for (account, isCurrent, key) in accountsAndKeys { + if let decryptedData = decryptedNotificationPayload(key: key, data: data) { + if let decryptedDict = (try? JSONSerialization.jsonObject(with: decryptedData, options: [])) as? [AnyHashable: Any] { + decryptedNotifications.append((account, isCurrent, decryptedDict)) + } + break inner } - break inner } } }