You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
5.8 KiB

6 years ago
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "FIRMessagingReceiver.h"
  17. #import <UIKit/UIKit.h>
  18. #import "FIRMessaging.h"
  19. #import "FIRMessaging_Private.h"
  20. #import "FIRMessagingLogger.h"
  21. static NSString *const kUpstreamMessageIDUserInfoKey = @"messageID";
  22. static NSString *const kUpstreamErrorUserInfoKey = @"error";
  23. // Copied from Apple's header in case it is missing in some cases.
  24. #ifndef NSFoundationVersionNumber_iOS_9_x_Max
  25. #define NSFoundationVersionNumber_iOS_9_x_Max 1299
  26. #endif
  27. static int downstreamMessageID = 0;
  28. @implementation FIRMessagingReceiver
  29. #pragma mark - FIRMessagingDataMessageManager protocol
  30. - (void)didReceiveMessage:(NSDictionary *)message withIdentifier:(nullable NSString *)messageID {
  31. if (![messageID length]) {
  32. messageID = [[self class] nextMessageID];
  33. }
  34. if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
  35. // Use delegate method for iOS 10
  36. [self scheduleIos10NotificationForMessage:message withIdentifier:messageID];
  37. } else {
  38. // Post notification directly to AppDelegate handlers. This is valid pre-iOS 10.
  39. [self scheduleNotificationForMessage:message];
  40. }
  41. }
  42. - (void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error {
  43. NSNotification *notification;
  44. if (error) {
  45. NSDictionary *userInfo = @{
  46. kUpstreamMessageIDUserInfoKey : [messageID copy],
  47. kUpstreamErrorUserInfoKey : error
  48. };
  49. notification = [NSNotification notificationWithName:FIRMessagingSendErrorNotification
  50. object:nil
  51. userInfo:userInfo];
  52. [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];
  53. FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver000,
  54. @"Fail to send upstream message: %@ error: %@", messageID, error);
  55. } else {
  56. FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver001, @"Will send upstream message: %@",
  57. messageID);
  58. }
  59. }
  60. - (void)didSendDataMessageWithID:(NSString *)messageID {
  61. // invoke the callbacks asynchronously
  62. FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver002, @"Did send upstream message: %@",
  63. messageID);
  64. NSNotification * notification =
  65. [NSNotification notificationWithName:FIRMessagingSendSuccessNotification
  66. object:nil
  67. userInfo:@{ kUpstreamMessageIDUserInfoKey : [messageID copy] }];
  68. [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];
  69. }
  70. - (void)didDeleteMessagesOnServer {
  71. FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver003,
  72. @"Will send deleted messages notification");
  73. NSNotification * notification =
  74. [NSNotification notificationWithName:FIRMessagingMessagesDeletedNotification
  75. object:nil];
  76. [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];
  77. }
  78. #pragma mark - Private Helpers
  79. // As the new UserNotifications framework in iOS 10 doesn't support constructor/mutation for
  80. // UNNotification object, FCM can't inject the message to the app with UserNotifications framework.
  81. // Define our own protocol, which means app developers need to implement two interfaces to receive
  82. // display notifications and data messages respectively for devices running iOS 10 or above. Devices
  83. // running iOS 9 or below are not affected.
  84. - (void)scheduleIos10NotificationForMessage:(NSDictionary *)message
  85. withIdentifier:(NSString *)messageID {
  86. FIRMessagingRemoteMessage *wrappedMessage = [[FIRMessagingRemoteMessage alloc] init];
  87. // TODO: wrap title, body, badge and other fields
  88. wrappedMessage.appData = [message copy];
  89. [self.delegate receiver:self receivedRemoteMessage:wrappedMessage];
  90. }
  91. - (void)scheduleNotificationForMessage:(NSDictionary *)message {
  92. SEL newNotificationSelector =
  93. @selector(application:didReceiveRemoteNotification:fetchCompletionHandler:);
  94. SEL oldNotificationSelector = @selector(application:didReceiveRemoteNotification:);
  95. dispatch_async(dispatch_get_main_queue(), ^{
  96. id<UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
  97. if ([appDelegate respondsToSelector:newNotificationSelector]) {
  98. // Try the new remote notification callback
  99. [appDelegate application:[UIApplication sharedApplication]
  100. didReceiveRemoteNotification:message
  101. fetchCompletionHandler:^(UIBackgroundFetchResult result) {}];
  102. } else if ([appDelegate respondsToSelector:oldNotificationSelector]) {
  103. // Try the old remote notification callback
  104. #pragma clang diagnostic push
  105. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  106. [appDelegate application:
  107. [UIApplication sharedApplication] didReceiveRemoteNotification:message];
  108. #pragma clang diagnostic pop
  109. } else {
  110. FIRMessagingLoggerError(kFIRMessagingMessageCodeReceiver005,
  111. @"None of the remote notification callbacks implemented by "
  112. @"UIApplicationDelegate");
  113. }
  114. });
  115. }
  116. + (NSString *)nextMessageID {
  117. @synchronized (self) {
  118. ++downstreamMessageID;
  119. return [NSString stringWithFormat:@"gcm-%d", downstreamMessageID];
  120. }
  121. }
  122. @end