Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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 "FirebaseMessaging/Sources/FIRMessagingUtilities.h"
18
 
19
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
20
#import <GoogleUtilities/GULUserDefaults.h>
21
#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
22
#import "FirebaseMessaging/Sources/FIRMessagingLogger.h"
23
 
24
static const uint64_t kBytesToMegabytesDivisor = 1024 * 1024LL;
25
NSString *const kFIRMessagingInstanceIDUserDefaultsKeyLocale =
26
    @"com.firebase.instanceid.user_defaults.locale";  // locale key stored in GULUserDefaults
27
static NSString *const kFIRMessagingAPNSSandboxPrefix = @"s_";
28
static NSString *const kFIRMessagingAPNSProdPrefix = @"p_";
29
 
30
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
31
static NSString *const kEntitlementsAPSEnvironmentKey = @"Entitlements.aps-environment";
32
#else
33
static NSString *const kEntitlementsAPSEnvironmentKey =
34
    @"Entitlements.com.apple.developer.aps-environment";
35
#endif
36
static NSString *const kAPSEnvironmentDevelopmentValue = @"development";
37
 
38
#pragma mark - URL Helpers
39
 
40
NSString *FIRMessagingTokenRegisterServer() {
41
  return @"https://fcmtoken.googleapis.com/register";
42
}
43
 
44
#pragma mark - Time
45
 
46
int64_t FIRMessagingCurrentTimestampInSeconds(void) {
47
  return (int64_t)[[NSDate date] timeIntervalSince1970];
48
}
49
 
50
int64_t FIRMessagingCurrentTimestampInMilliseconds(void) {
51
  return (int64_t)(FIRMessagingCurrentTimestampInSeconds() * 1000.0);
52
}
53
 
54
#pragma mark - App Info
55
 
56
NSString *FIRMessagingCurrentAppVersion(void) {
57
  NSString *version = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"];
58
  if (![version length]) {
59
    FIRMessagingLoggerError(kFIRMessagingMessageCodeUtilities000,
60
                            @"Could not find current app version");
61
    return @"";
62
  }
63
  return version;
64
}
65
 
66
NSString *FIRMessagingBundleIDByRemovingLastPartFrom(NSString *bundleID) {
67
  NSString *bundleIDComponentsSeparator = @".";
68
 
69
  NSMutableArray<NSString *> *bundleIDComponents =
70
      [[bundleID componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy];
71
  [bundleIDComponents removeLastObject];
72
 
73
  return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator];
74
}
75
 
76
NSString *FIRMessagingAppIdentifier(void) {
77
  NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
78
#if TARGET_OS_WATCH
79
  // The code is running in watchKit extension target but the actually bundleID is in the watchKit
80
  // target. So we need to remove the last part of the bundle ID in watchKit extension to match
81
  // the one in watchKit target.
82
  return FIRMessagingBundleIDByRemovingLastPartFrom(bundleID);
83
#else
84
  return bundleID;
85
#endif
86
}
87
 
88
NSString *FIRMessagingFirebaseAppID() {
89
  return [FIROptions defaultOptions].googleAppID;
90
}
91
 
92
uint64_t FIRMessagingGetFreeDiskSpaceInMB(void) {
93
  NSError *error;
94
  NSArray *paths =
95
      NSSearchPathForDirectoriesInDomains(FIRMessagingSupportedDirectory(), NSUserDomainMask, YES);
96
 
97
  NSDictionary *attributesMap =
98
      [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject]
99
                                                              error:&error];
100
  if (attributesMap) {
101
    uint64_t totalSizeInBytes __unused = [attributesMap[NSFileSystemSize] longLongValue];
102
    uint64_t freeSizeInBytes = [attributesMap[NSFileSystemFreeSize] longLongValue];
103
    FIRMessagingLoggerDebug(
104
        kFIRMessagingMessageCodeUtilities001, @"Device has capacity %llu MB with %llu MB free.",
105
        totalSizeInBytes / kBytesToMegabytesDivisor, freeSizeInBytes / kBytesToMegabytesDivisor);
106
    return ((double)freeSizeInBytes) / kBytesToMegabytesDivisor;
107
  } else {
108
    FIRMessagingLoggerError(kFIRMessagingMessageCodeUtilities002,
109
                            @"Error in retreiving device's free memory %@", error);
110
    return 0;
111
  }
112
}
113
 
114
NSSearchPathDirectory FIRMessagingSupportedDirectory(void) {
115
#if TARGET_OS_TV
116
  return NSCachesDirectory;
117
#else
118
  return NSApplicationSupportDirectory;
119
#endif
120
}
121
 
122
#pragma mark - Locales
123
 
124
NSDictionary *FIRMessagingFirebaselocalesMap(void) {
125
  return @{
126
    // Albanian
127
    @"sq" : @[ @"sq_AL" ],
128
    // Belarusian
129
    @"be" : @[ @"be_BY" ],
130
    // Bulgarian
131
    @"bg" : @[ @"bg_BG" ],
132
    // Catalan
133
    @"ca" : @[ @"ca", @"ca_ES" ],
134
    // Croatian
135
    @"hr" : @[ @"hr", @"hr_HR" ],
136
    // Czech
137
    @"cs" : @[ @"cs", @"cs_CZ" ],
138
    // Danish
139
    @"da" : @[ @"da", @"da_DK" ],
140
    // Estonian
141
    @"et" : @[ @"et_EE" ],
142
    // Finnish
143
    @"fi" : @[ @"fi", @"fi_FI" ],
144
    // Hebrew
145
    @"he" : @[ @"he", @"iw_IL" ],
146
    // Hindi
147
    @"hi" : @[ @"hi_IN" ],
148
    // Hungarian
149
    @"hu" : @[ @"hu", @"hu_HU" ],
150
    // Icelandic
151
    @"is" : @[ @"is_IS" ],
152
    // Indonesian
153
    @"id" : @[ @"id", @"in_ID", @"id_ID" ],
154
    // Irish
155
    @"ga" : @[ @"ga_IE" ],
156
    // Korean
157
    @"ko" : @[ @"ko", @"ko_KR", @"ko-KR" ],
158
    // Latvian
159
    @"lv" : @[ @"lv_LV" ],
160
    // Lithuanian
161
    @"lt" : @[ @"lt_LT" ],
162
    // Macedonian
163
    @"mk" : @[ @"mk_MK" ],
164
    // Malay
165
    @"ms" : @[ @"ms_MY" ],
166
    // Maltese
167
    @"mt" : @[ @"mt_MT" ],
168
    // Polish
169
    @"pl" : @[ @"pl", @"pl_PL", @"pl-PL" ],
170
    // Romanian
171
    @"ro" : @[ @"ro", @"ro_RO" ],
172
    // Russian
173
    @"ru" : @[ @"ru_RU", @"ru", @"ru_BY", @"ru_KZ", @"ru-RU" ],
174
    // Slovak
175
    @"sk" : @[ @"sk", @"sk_SK" ],
176
    // Slovenian
177
    @"sl" : @[ @"sl_SI" ],
178
    // Swedish
179
    @"sv" : @[ @"sv", @"sv_SE", @"sv-SE" ],
180
    // Turkish
181
    @"tr" : @[ @"tr", @"tr-TR", @"tr_TR" ],
182
    // Ukrainian
183
    @"uk" : @[ @"uk", @"uk_UA" ],
184
    // Vietnamese
185
    @"vi" : @[ @"vi", @"vi_VN" ],
186
    // The following are groups of locales or locales that sub-divide a
187
    // language).
188
    // Arabic
189
    @"ar" : @[
190
      @"ar",    @"ar_DZ", @"ar_BH", @"ar_EG", @"ar_IQ", @"ar_JO", @"ar_KW",
191
      @"ar_LB", @"ar_LY", @"ar_MA", @"ar_OM", @"ar_QA", @"ar_SA", @"ar_SD",
192
      @"ar_SY", @"ar_TN", @"ar_AE", @"ar_YE", @"ar_GB", @"ar-IQ", @"ar_US"
193
    ],
194
    // Simplified Chinese
195
    @"zh_Hans" : @[ @"zh_CN", @"zh_SG", @"zh-Hans" ],
196
    // Traditional Chinese
197
    @"zh_Hant" : @[ @"zh_HK", @"zh_TW", @"zh-Hant", @"zh-HK", @"zh-TW" ],
198
    // Dutch
199
    @"nl" : @[ @"nl", @"nl_BE", @"nl_NL", @"nl-NL" ],
200
    // English
201
    @"en" : @[
202
      @"en",    @"en_AU", @"en_CA", @"en_IN", @"en_IE", @"en_MT", @"en_NZ", @"en_PH",
203
      @"en_SG", @"en_ZA", @"en_GB", @"en_US", @"en_AE", @"en-AE", @"en_AS", @"en-AU",
204
      @"en_BD", @"en-CA", @"en_EG", @"en_ES", @"en_GB", @"en-GB", @"en_HK", @"en_ID",
205
      @"en-IN", @"en_NG", @"en-PH", @"en_PK", @"en-SG", @"en-US"
206
    ],
207
    // French
208
 
209
    @"fr" :
210
        @[ @"fr", @"fr_BE", @"fr_CA", @"fr_FR", @"fr_LU", @"fr_CH", @"fr-CA", @"fr-FR", @"fr_MA" ],
211
    // German
212
    @"de" : @[ @"de", @"de_AT", @"de_DE", @"de_LU", @"de_CH", @"de-DE" ],
213
    // Greek
214
    @"el" : @[ @"el", @"el_CY", @"el_GR" ],
215
    // Italian
216
    @"it" : @[ @"it", @"it_IT", @"it_CH", @"it-IT" ],
217
    // Japanese
218
    @"ja" : @[ @"ja", @"ja_JP", @"ja_JP_JP", @"ja-JP" ],
219
    // Norwegian
220
    @"no" : @[ @"nb", @"no_NO", @"no_NO_NY", @"nb_NO" ],
221
    // Brazilian Portuguese
222
    @"pt_BR" : @[ @"pt_BR", @"pt-BR" ],
223
    // European Portuguese
224
    @"pt_PT" : @[ @"pt", @"pt_PT", @"pt-PT" ],
225
    // Serbian
226
    @"sr" : @[ @"sr_BA", @"sr_ME", @"sr_RS", @"sr_Latn_BA", @"sr_Latn_ME", @"sr_Latn_RS" ],
227
    // European Spanish
228
    @"es_ES" : @[ @"es", @"es_ES", @"es-ES" ],
229
    // Mexican Spanish
230
    @"es_MX" : @[ @"es-MX", @"es_MX", @"es_US", @"es-US" ],
231
    // Latin American Spanish
232
    @"es_419" : @[
233
      @"es_AR", @"es_BO", @"es_CL", @"es_CO", @"es_CR", @"es_DO", @"es_EC",
234
      @"es_SV", @"es_GT", @"es_HN", @"es_NI", @"es_PA", @"es_PY", @"es_PE",
235
      @"es_PR", @"es_UY", @"es_VE", @"es-AR", @"es-CL", @"es-CO"
236
    ],
237
    // Thai
238
    @"th" : @[ @"th", @"th_TH", @"th_TH_TH" ],
239
  };
240
}
241
 
242
NSArray *FIRMessagingFirebaseLocales(void) {
243
  NSMutableArray *locales = [NSMutableArray array];
244
  NSDictionary *localesMap = FIRMessagingFirebaselocalesMap();
245
  for (NSString *key in localesMap) {
246
    [locales addObjectsFromArray:localesMap[key]];
247
  }
248
  return locales;
249
}
250
 
251
NSString *FIRMessagingCurrentLocale() {
252
  NSArray *locales = FIRMessagingFirebaseLocales();
253
  NSArray *preferredLocalizations =
254
      [NSBundle preferredLocalizationsFromArray:locales
255
                                 forPreferences:[NSLocale preferredLanguages]];
256
  NSString *legalDocsLanguage = [preferredLocalizations firstObject];
257
  // Use en as the default language
258
  return legalDocsLanguage ? legalDocsLanguage : @"en";
259
}
260
 
261
BOOL FIRMessagingHasLocaleChanged() {
262
  NSString *lastLocale = [[GULUserDefaults standardUserDefaults]
263
      stringForKey:kFIRMessagingInstanceIDUserDefaultsKeyLocale];
264
  NSString *currentLocale = FIRMessagingCurrentLocale();
265
  if (lastLocale) {
266
    if ([currentLocale isEqualToString:lastLocale]) {
267
      return NO;
268
    }
269
  }
270
  return YES;
271
}
272
 
273
NSString *FIRMessagingStringForAPNSDeviceToken(NSData *deviceToken) {
274
  NSMutableString *APNSToken = [NSMutableString string];
275
  unsigned char *bytes = (unsigned char *)[deviceToken bytes];
276
  for (int i = 0; i < (int)deviceToken.length; i++) {
277
    [APNSToken appendFormat:@"%02x", bytes[i]];
278
  }
279
  return APNSToken;
280
}
281
 
282
NSString *FIRMessagingAPNSTupleStringForTokenAndServerType(NSData *deviceToken, BOOL isSandbox) {
283
  if (deviceToken == nil) {
284
    // A nil deviceToken leads to an invalid tuple string, so return nil.
285
    return nil;
286
  }
287
  NSString *prefix = isSandbox ? kFIRMessagingAPNSSandboxPrefix : kFIRMessagingAPNSProdPrefix;
288
  NSString *APNSString = FIRMessagingStringForAPNSDeviceToken(deviceToken);
289
  NSString *APNSTupleString = [NSString stringWithFormat:@"%@%@", prefix, APNSString];
290
 
291
  return APNSTupleString;
292
}
293
 
294
BOOL FIRMessagingIsProductionApp(void) {
295
  const BOOL defaultAppTypeProd = YES;
296
 
297
  NSError *error = nil;
298
  if ([GULAppEnvironmentUtil isSimulator]) {
299
    FIRMessagingLoggerError(kFIRMessagingMessageCodeInstanceID014,
300
                            @"Running InstanceID on a simulator doesn't have APNS. "
301
                            @"Use prod profile by default.");
302
    return defaultAppTypeProd;
303
  }
304
 
305
  if ([GULAppEnvironmentUtil isFromAppStore]) {
306
    // Apps distributed via AppStore or TestFlight use the Production APNS certificates.
307
    return defaultAppTypeProd;
308
  }
309
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
310
  NSString *path = [[[[NSBundle mainBundle] resourcePath] stringByDeletingLastPathComponent]
311
      stringByAppendingPathComponent:@"embedded.provisionprofile"];
312
#elif TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
313
  NSString *path = [[[NSBundle mainBundle] bundlePath]
314
      stringByAppendingPathComponent:@"embedded.mobileprovision"];
315
#endif
316
 
317
  if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox] && !path.length) {
318
    // Distributed via TestFlight
319
    return defaultAppTypeProd;
320
  }
321
 
322
  NSMutableData *profileData = [NSMutableData dataWithContentsOfFile:path options:0 error:&error];
323
 
324
  if (!profileData.length || error) {
325
    NSString *errorString =
326
        [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error];
327
    FIRMessagingLoggerError(kFIRMessagingMessageCodeInstanceID014, @"%@", errorString);
328
    return defaultAppTypeProd;
329
  }
330
 
331
  // The "embedded.mobileprovision" sometimes contains characters with value 0, which signals the
332
  // end of a c-string and halts the ASCII parser, or with value > 127, which violates strict 7-bit
333
  // ASCII. Replace any 0s or invalid characters in the input.
334
  uint8_t *profileBytes = (uint8_t *)profileData.bytes;
335
  for (int i = 0; i < profileData.length; i++) {
336
    uint8_t currentByte = profileBytes[i];
337
    if (!currentByte || currentByte > 127) {
338
      profileBytes[i] = '.';
339
    }
340
  }
341
 
342
  NSString *embeddedProfile = [[NSString alloc] initWithBytesNoCopy:profileBytes
343
                                                             length:profileData.length
344
                                                           encoding:NSASCIIStringEncoding
345
                                                       freeWhenDone:NO];
346
 
347
  if (error || !embeddedProfile.length) {
348
    NSString *errorString =
349
        [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error];
350
    FIRMessagingLoggerError(kFIRMessagingMessageCodeInstanceID014, @"%@", errorString);
351
    return defaultAppTypeProd;
352
  }
353
 
354
  NSScanner *scanner = [NSScanner scannerWithString:embeddedProfile];
355
  NSString *plistContents;
356
  if ([scanner scanUpToString:@"<plist" intoString:nil]) {
357
    if ([scanner scanUpToString:@"</plist>" intoString:&plistContents]) {
358
      plistContents = [plistContents stringByAppendingString:@"</plist>"];
359
    }
360
  }
361
 
362
  if (!plistContents.length) {
363
    return defaultAppTypeProd;
364
  }
365
 
366
  NSData *data = [plistContents dataUsingEncoding:NSUTF8StringEncoding];
367
  if (!data.length) {
368
    FIRMessagingLoggerError(kFIRMessagingMessageCodeInstanceID014,
369
                            @"Couldn't read plist fetched from embedded mobileprovision");
370
    return defaultAppTypeProd;
371
  }
372
 
373
  NSError *plistMapError;
374
  id plistData = [NSPropertyListSerialization propertyListWithData:data
375
                                                           options:NSPropertyListImmutable
376
                                                            format:nil
377
                                                             error:&plistMapError];
378
  if (plistMapError || ![plistData isKindOfClass:[NSDictionary class]]) {
379
    NSString *errorString =
380
        [NSString stringWithFormat:@"Error while converting assumed plist to dict %@",
381
                                   plistMapError.localizedDescription];
382
    FIRMessagingLoggerError(kFIRMessagingMessageCodeInstanceID014, @"%@", errorString);
383
    return defaultAppTypeProd;
384
  }
385
  NSDictionary *plistMap = (NSDictionary *)plistData;
386
 
387
  if ([plistMap valueForKeyPath:@"ProvisionedDevices"]) {
388
    FIRMessagingLoggerDebug(kFIRMessagingMessageCodeInstanceID012,
389
                            @"Provisioning profile has specifically provisioned devices, "
390
                            @"most likely a Dev profile.");
391
  }
392
 
393
  NSString *apsEnvironment = [plistMap valueForKeyPath:kEntitlementsAPSEnvironmentKey];
394
  NSString *debugString __unused =
395
      [NSString stringWithFormat:@"APNS Environment in profile: %@", apsEnvironment];
396
  FIRMessagingLoggerDebug(kFIRMessagingMessageCodeInstanceID013, @"%@", debugString);
397
 
398
  // No aps-environment in the profile.
399
  if (!apsEnvironment.length) {
400
    FIRMessagingLoggerError(kFIRMessagingMessageCodeInstanceID014,
401
                            @"No aps-environment set. If testing on a device APNS is not "
402
                            @"correctly configured. Please recheck your provisioning "
403
                            @"profiles. If testing on a simulator this is fine since APNS "
404
                            @"doesn't work on the simulator.");
405
    return defaultAppTypeProd;
406
  }
407
 
408
  if ([apsEnvironment isEqualToString:kAPSEnvironmentDevelopmentValue]) {
409
    return NO;
410
  }
411
 
412
  return defaultAppTypeProd;
413
}
414
 
415
BOOL FIRMessagingIsSandboxApp(void) {
416
  static BOOL isSandboxApp = YES;
417
  static dispatch_once_t onceToken;
418
  dispatch_once(&onceToken, ^{
419
    isSandboxApp = !FIRMessagingIsProductionApp();
420
  });
421
  return isSandboxApp;
422
}