added iOS source code
[wl-app.git] / iOS / Pods / FirebaseMessaging / Firebase / Messaging / FIRMessagingReceiver.m
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
17 #import "FIRMessagingReceiver.h"
18
19 #import <UIKit/UIKit.h>
20
21 #import "FIRMessaging.h"
22 #import "FIRMessagingLogger.h"
23 #import "FIRMessagingUtilities.h"
24 #import "FIRMessaging_Private.h"
25
26 static NSString *const kUpstreamMessageIDUserInfoKey = @"messageID";
27 static NSString *const kUpstreamErrorUserInfoKey = @"error";
28
29 // Copied from Apple's header in case it is missing in some cases.
30 #ifndef NSFoundationVersionNumber_iOS_9_x_Max
31 #define NSFoundationVersionNumber_iOS_9_x_Max 1299
32 #endif
33
34 static int downstreamMessageID = 0;
35
36 @implementation FIRMessagingReceiver
37
38 #pragma mark - FIRMessagingDataMessageManager protocol
39
40 - (void)didReceiveMessage:(NSDictionary *)message withIdentifier:(nullable NSString *)messageID {
41   if (![messageID length]) {
42     messageID = [[self class] nextMessageID];
43   }
44
45   if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
46     // Use delegate method for iOS 10
47     [self scheduleIos10NotificationForMessage:message withIdentifier:messageID];
48   } else {
49     // Post notification directly to AppDelegate handlers. This is valid pre-iOS 10.
50     [self scheduleNotificationForMessage:message];
51   }
52 }
53
54 - (void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error {
55   NSNotification *notification;
56   if (error) {
57     NSDictionary *userInfo = @{
58       kUpstreamMessageIDUserInfoKey : [messageID copy],
59       kUpstreamErrorUserInfoKey : error
60     };
61     notification = [NSNotification notificationWithName:FIRMessagingSendErrorNotification
62                                                  object:nil
63                                                userInfo:userInfo];
64     [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];
65     FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver000,
66                             @"Fail to send upstream message: %@ error: %@", messageID, error);
67   } else {
68     FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver001, @"Will send upstream message: %@",
69                             messageID);
70   }
71 }
72
73 - (void)didSendDataMessageWithID:(NSString *)messageID {
74   // invoke the callbacks asynchronously
75   FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver002, @"Did send upstream message: %@",
76                           messageID);
77   NSNotification * notification =
78       [NSNotification notificationWithName:FIRMessagingSendSuccessNotification
79                                     object:nil
80                                   userInfo:@{ kUpstreamMessageIDUserInfoKey : [messageID copy] }];
81
82   [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];
83 }
84
85 - (void)didDeleteMessagesOnServer {
86   FIRMessagingLoggerDebug(kFIRMessagingMessageCodeReceiver003,
87                           @"Will send deleted messages notification");
88   NSNotification * notification =
89       [NSNotification notificationWithName:FIRMessagingMessagesDeletedNotification
90                                     object:nil];
91
92   [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];
93 }
94
95 #pragma mark - Private Helpers
96 // As the new UserNotifications framework in iOS 10 doesn't support constructor/mutation for
97 // UNNotification object, FCM can't inject the message to the app with UserNotifications framework.
98 // Define our own protocol, which means app developers need to implement two interfaces to receive
99 // display notifications and data messages respectively for devices running iOS 10 or above. Devices
100 // running iOS 9 or below are not affected.
101 - (void)scheduleIos10NotificationForMessage:(NSDictionary *)message
102                              withIdentifier:(NSString *)messageID {
103   FIRMessagingRemoteMessage *wrappedMessage = [[FIRMessagingRemoteMessage alloc] init];
104   // TODO: wrap title, body, badge and other fields
105   wrappedMessage.appData = [message copy];
106   [self.delegate receiver:self receivedRemoteMessage:wrappedMessage];
107 }
108
109 - (void)scheduleNotificationForMessage:(NSDictionary *)message {
110   SEL newNotificationSelector =
111       @selector(application:didReceiveRemoteNotification:fetchCompletionHandler:);
112   SEL oldNotificationSelector = @selector(application:didReceiveRemoteNotification:);
113
114   dispatch_async(dispatch_get_main_queue(), ^{
115     UIApplication *application = FIRMessagingUIApplication();
116     if (!application) {
117       return;
118     }
119     id<UIApplicationDelegate> appDelegate = [application delegate];
120     if ([appDelegate respondsToSelector:newNotificationSelector]) {
121       // Try the new remote notification callback
122       [appDelegate application:application
123           didReceiveRemoteNotification:message
124                 fetchCompletionHandler:^(UIBackgroundFetchResult result) {
125                 }];
126
127     } else if ([appDelegate respondsToSelector:oldNotificationSelector]) {
128       // Try the old remote notification callback
129 #pragma clang diagnostic push
130 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
131       [appDelegate application:application didReceiveRemoteNotification:message];
132 #pragma clang diagnostic pop
133     } else {
134       FIRMessagingLoggerError(kFIRMessagingMessageCodeReceiver005,
135                               @"None of the remote notification callbacks implemented by "
136                               @"UIApplicationDelegate");
137     }
138   });
139 }
140
141 + (NSString *)nextMessageID {
142   @synchronized (self) {
143     ++downstreamMessageID;
144     return [NSString stringWithFormat:@"gcm-%d", downstreamMessageID];
145   }
146 }
147
148 @end