Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/*
2
 * Copyright 2019 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 "FirebaseMessaging/Sources/Token/FIRMessagingCheckinService.h"
18
 
19
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
20
#import "FirebaseMessaging/Sources/FIRMessagingDefines.h"
21
#import "FirebaseMessaging/Sources/FIRMessagingLogger.h"
22
#import "FirebaseMessaging/Sources/FIRMessagingUtilities.h"
23
#import "FirebaseMessaging/Sources/NSError+FIRMessaging.h"
24
#import "FirebaseMessaging/Sources/Token/FIRMessagingAuthService.h"
25
#import "FirebaseMessaging/Sources/Token/FIRMessagingCheckinPreferences.h"
26
 
27
static NSString *const kDeviceCheckinURL = @"https://device-provisioning.googleapis.com/checkin";
28
 
29
// keys in Checkin preferences
30
NSString *const kFIRMessagingDeviceAuthIdKey = @"GMSInstanceIDDeviceAuthIdKey";
31
NSString *const kFIRMessagingSecretTokenKey = @"GMSInstanceIDSecretTokenKey";
32
NSString *const kFIRMessagingDigestStringKey = @"GMSInstanceIDDigestKey";
33
NSString *const kFIRMessagingLastCheckinTimeKey = @"GMSInstanceIDLastCheckinTimestampKey";
34
NSString *const kFIRMessagingVersionInfoStringKey = @"GMSInstanceIDVersionInfo";
35
NSString *const kFIRMessagingGServicesDictionaryKey = @"GMSInstanceIDGServicesData";
36
NSString *const kFIRMessagingDeviceDataVersionKey = @"GMSInstanceIDDeviceDataVersion";
37
 
38
static NSUInteger const kCheckinType = 2;  // DeviceType IOS in l/w/a/_checkin.proto
39
static NSUInteger const kCheckinVersion = 2;
40
static NSUInteger const kFragment = 0;
41
 
42
@interface FIRMessagingCheckinService ()
43
 
44
@property(nonatomic, readwrite, strong) NSURLSession *session;
45
 
46
@end
47
 
48
@implementation FIRMessagingCheckinService
49
 
50
- (instancetype)init {
51
  self = [super init];
52
  if (self) {
53
    // Create an URLSession once, even though checkin should happen about once a day
54
    NSURLSessionConfiguration *config = NSURLSessionConfiguration.defaultSessionConfiguration;
55
    config.timeoutIntervalForResource = 60.0f;  // 1 minute
56
    config.allowsCellularAccess = YES;
57
 
58
    self.session = [NSURLSession sessionWithConfiguration:config];
59
    self.session.sessionDescription = @"com.google.iid-checkin";
60
  }
61
  return self;
62
}
63
- (void)dealloc {
64
  [self.session invalidateAndCancel];
65
}
66
 
67
- (void)checkinWithExistingCheckin:(FIRMessagingCheckinPreferences *)existingCheckin
68
                        completion:(FIRMessagingDeviceCheckinCompletion)completion {
69
  if (self.session == nil) {
70
    FIRMessagingLoggerError(kFIRMessagingMessageCodeService005,
71
                            @"Inconsistent state: NSURLSession has been invalidated");
72
    NSError *error =
73
        [NSError messagingErrorWithCode:kFIRMessagingErrorCodeRegistrarFailedToCheckIn
74
                          failureReason:@"Failed to checkin. NSURLSession is invalid."];
75
    if (completion) {
76
      completion(nil, error);
77
    }
78
    return;
79
  }
80
  NSURL *url = [NSURL URLWithString:kDeviceCheckinURL];
81
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
82
  [request setValue:@"application/json" forHTTPHeaderField:@"content-type"];
83
  NSDictionary *checkinParameters = [self checkinParametersWithExistingCheckin:existingCheckin];
84
  NSData *checkinData = [NSJSONSerialization dataWithJSONObject:checkinParameters
85
                                                        options:0
86
                                                          error:nil];
87
  request.HTTPMethod = @"POST";
88
  request.HTTPBody = checkinData;
89
 
90
  void (^handler)(NSData *, NSURLResponse *, NSError *) =
91
      ^(NSData *data, NSURLResponse *response, NSError *error) {
92
        if (error) {
93
          FIRMessagingLoggerDebug(kFIRMessagingMessageCodeService000,
94
                                  @"Device checkin HTTP fetch error. Error Code: %ld",
95
                                  (long)error.code);
96
          if (completion) {
97
            completion(nil, error);
98
          }
99
          return;
100
        }
101
 
102
        NSError *serializationError = nil;
103
        NSDictionary *dataResponse = [NSJSONSerialization JSONObjectWithData:data
104
                                                                     options:0
105
                                                                       error:&serializationError];
106
        if (serializationError) {
107
          FIRMessagingLoggerDebug(kFIRMessagingMessageCodeService001,
108
                                  @"Error serializing json object. Error Code: %ld",
109
                                  (long)serializationError.code);
110
          if (completion) {
111
            completion(nil, serializationError);
112
          }
113
          return;
114
        }
115
 
116
        NSString *deviceAuthID = [dataResponse[@"android_id"] stringValue];
117
        NSString *secretToken = [dataResponse[@"security_token"] stringValue];
118
        if ([deviceAuthID length] == 0) {
119
          NSError *error = [NSError messagingErrorWithCode:kFIRMessagingErrorCodeInvalidRequest
120
                                             failureReason:@"Invalid device auth ID."];
121
          if (completion) {
122
            completion(nil, error);
123
          }
124
          return;
125
        }
126
 
127
        int64_t lastCheckinTimestampMillis = [dataResponse[@"time_msec"] longLongValue];
128
        int64_t currentTimestampMillis = FIRMessagingCurrentTimestampInMilliseconds();
129
        // Somehow the server clock gets out of sync with the device clock.
130
        // Reset the last checkin timestamp in case this happens.
131
        if (lastCheckinTimestampMillis > currentTimestampMillis) {
132
          FIRMessagingLoggerDebug(
133
              kFIRMessagingMessageCodeService002, @"Invalid last checkin timestamp %@ in future.",
134
              [NSDate dateWithTimeIntervalSince1970:lastCheckinTimestampMillis / 1000.0]);
135
          lastCheckinTimestampMillis = currentTimestampMillis;
136
        }
137
 
138
        NSString *deviceDataVersionInfo = dataResponse[@"device_data_version_info"] ?: @"";
139
        NSString *digest = dataResponse[@"digest"] ?: @"";
140
 
141
        FIRMessagingLoggerDebug(kFIRMessagingMessageCodeService003,
142
                                @"Checkin successful with authId: %@, "
143
                                @"digest: %@, "
144
                                @"lastCheckinTimestamp: %lld",
145
                                deviceAuthID, digest, lastCheckinTimestampMillis);
146
 
147
        NSString *versionInfo = dataResponse[@"version_info"] ?: @"";
148
        NSMutableDictionary *gservicesData = [NSMutableDictionary dictionary];
149
 
150
        // Read gServices data.
151
        NSArray *flatSettings = dataResponse[@"setting"];
152
        for (NSDictionary *dict in flatSettings) {
153
          if (dict[@"name"] && dict[@"value"]) {
154
            gservicesData[dict[@"name"]] = dict[@"value"];
155
          } else {
156
            FIRMessagingLoggerDebug(kFIRMessagingInvalidSettingResponse,
157
                                    @"Invalid setting in checkin response: (%@: %@)", dict[@"name"],
158
                                    dict[@"value"]);
159
          }
160
        }
161
 
162
        FIRMessagingCheckinPreferences *checkinPreferences =
163
            [[FIRMessagingCheckinPreferences alloc] initWithDeviceID:deviceAuthID
164
                                                         secretToken:secretToken];
165
        NSDictionary *preferences = @{
166
          kFIRMessagingDigestStringKey : digest,
167
          kFIRMessagingVersionInfoStringKey : versionInfo,
168
          kFIRMessagingLastCheckinTimeKey : @(lastCheckinTimestampMillis),
169
          kFIRMessagingGServicesDictionaryKey : gservicesData,
170
          kFIRMessagingDeviceDataVersionKey : deviceDataVersionInfo,
171
        };
172
        [checkinPreferences updateWithCheckinPlistContents:preferences];
173
        if (completion) {
174
          completion(checkinPreferences, nil);
175
        }
176
      };
177
 
178
  NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:handler];
179
  [task resume];
180
}
181
 
182
- (void)stopFetching {
183
  [self.session invalidateAndCancel];
184
  // The session cannot be reused after invalidation. Dispose it to prevent accident reusing.
185
  self.session = nil;
186
}
187
 
188
#pragma mark - Private
189
 
190
- (NSDictionary *)checkinParametersWithExistingCheckin:
191
    (nullable FIRMessagingCheckinPreferences *)checkinPreferences {
192
  NSString *deviceModel = [GULAppEnvironmentUtil deviceModel];
193
  NSString *systemVersion = [GULAppEnvironmentUtil systemVersion];
194
  NSString *osVersion = [NSString stringWithFormat:@"IOS_%@", systemVersion];
195
 
196
  // Get locale from GCM if GCM exists else use system API.
197
  NSString *locale = FIRMessagingCurrentLocale();
198
 
199
  NSInteger userNumber = 0;        // Multi Profile may change this.
200
  NSInteger userSerialNumber = 0;  // Multi Profile may change this
201
 
202
  NSString *timeZone = [NSTimeZone localTimeZone].name;
203
  int64_t lastCheckingTimestampMillis = checkinPreferences.lastCheckinTimestampMillis;
204
 
205
  NSDictionary *checkinParameters = @{
206
    @"checkin" : @{
207
      @"iosbuild" : @{@"model" : deviceModel, @"os_version" : osVersion},
208
      @"type" : @(kCheckinType),
209
      @"user_number" : @(userNumber),
210
      @"last_checkin_msec" : @(lastCheckingTimestampMillis),
211
    },
212
    @"fragment" : @(kFragment),
213
    @"locale" : locale,
214
    @"version" : @(kCheckinVersion),
215
    @"digest" : checkinPreferences.digest ?: @"",
216
    @"time_zone" : timeZone,
217
    @"user_serial_number" : @(userSerialNumber),
218
    @"id" : @([checkinPreferences.deviceID longLongValue]),
219
    @"security_token" : @([checkinPreferences.secretToken longLongValue]),
220
  };
221
 
222
  FIRMessagingLoggerDebug(kFIRMessagingMessageCodeService006, @"Checkin parameters: %@",
223
                          checkinParameters);
224
  return checkinParameters;
225
}
226
 
227
@end