diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2020-08-31 23:07:20 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2020-08-31 23:07:20 +0200 |
| commit | 22721a013bdd10d5eb395ba18453585f5f3f1f7f (patch) | |
| tree | 5a920e31d6026ed5dc55265e5fd057febccc50e3 /StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID | |
| parent | d22d51a1ae49680015326857360eb699f31efced (diff) | |
rebuild the ios platform and the plugins
Diffstat (limited to 'StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID')
54 files changed, 7151 insertions, 0 deletions
diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h new file mode 100644 index 00000000..ac1893fa --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h @@ -0,0 +1,147 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +// The format of the debug code will show in the log as: e.g. +// for code 1000, it will show as I-IID001000. +typedef NS_ENUM(NSInteger, FIRInstanceIDMessageCode) { + // DO NOT USE 2000, 2002. + kFIRInstanceIDMessageCodeFIRApp000 = 1000, // I-IID001000 + kFIRInstanceIDMessageCodeFIRApp001 = 1001, + kFIRInstanceIDMessageCodeFIRApp002 = 1002, + kFIRInstanceIDMessageCodeInternal001 = 2001, + kFIRInstanceIDMessageCodeInternal002 = 2002, + // FIRInstanceID.m + // DO NOT USE 4000. + kFIRInstanceIDMessageCodeInstanceID000 = 3000, + kFIRInstanceIDMessageCodeInstanceID001 = 3001, + kFIRInstanceIDMessageCodeInstanceID002 = 3002, + kFIRInstanceIDMessageCodeInstanceID003 = 3003, + kFIRInstanceIDMessageCodeInstanceID004 = 3004, + kFIRInstanceIDMessageCodeInstanceID005 = 3005, + kFIRInstanceIDMessageCodeInstanceID006 = 3006, + kFIRInstanceIDMessageCodeInstanceID007 = 3007, + kFIRInstanceIDMessageCodeInstanceID008 = 3008, + kFIRInstanceIDMessageCodeInstanceID009 = 3009, + kFIRInstanceIDMessageCodeInstanceID010 = 3010, + kFIRInstanceIDMessageCodeInstanceID011 = 3011, + kFIRInstanceIDMessageCodeInstanceID012 = 3012, + kFIRInstanceIDMessageCodeInstanceID013 = 3013, + kFIRInstanceIDMessageCodeInstanceID014 = 3014, + kFIRInstanceIDMessageCodeInstanceID015 = 3015, + kFIRInstanceIDMessageCodeRefetchingTokenForAPNS = 3016, + kFIRInstanceIDMessageCodeInstanceID017 = 3017, + kFIRInstanceIDMessageCodeInstanceID018 = 3018, + // FIRInstanceIDAuthService.m + kFIRInstanceIDMessageCodeAuthService000 = 5000, + kFIRInstanceIDMessageCodeAuthService001 = 5001, + kFIRInstanceIDMessageCodeAuthService002 = 5002, + kFIRInstanceIDMessageCodeAuthService003 = 5003, + kFIRInstanceIDMessageCodeAuthService004 = 5004, + kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress = 5004, + + // FIRInstanceIDBackupExcludedPlist.m + // Do NOT USE 6003 + kFIRInstanceIDMessageCodeBackupExcludedPlist000 = 6000, + kFIRInstanceIDMessageCodeBackupExcludedPlist001 = 6001, + kFIRInstanceIDMessageCodeBackupExcludedPlist002 = 6002, + // FIRInstanceIDCheckinService.m + kFIRInstanceIDMessageCodeService000 = 7000, + kFIRInstanceIDMessageCodeService001 = 7001, + kFIRInstanceIDMessageCodeService002 = 7002, + kFIRInstanceIDMessageCodeService003 = 7003, + kFIRInstanceIDMessageCodeService004 = 7004, + kFIRInstanceIDMessageCodeService005 = 7005, + kFIRInstanceIDMessageCodeService006 = 7006, + kFIRInstanceIDInvalidNetworkSession = 7007, + kFIRInstanceIDInvalidSettingResponse = 7008, + // FIRInstanceIDCheckinStore.m + // DO NOT USE 8002, 8004 - 8008 + kFIRInstanceIDMessageCodeCheckinStore000 = 8000, + kFIRInstanceIDMessageCodeCheckinStore001 = 8001, + kFIRInstanceIDMessageCodeCheckinStore003 = 8003, + kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted = 8009, + kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved = 8010, + + // DO NOT USE 9000 - 9006 + + // DO NOT USE 10000 - 10009 + + // DO NOT USE 11000 - 11002 + + // DO NOT USE 12000 - 12014 + + // FIRInstanceIDStore.m + // DO NOT USE 13004, 13005, 13007, 13008, 13010, 13011, 13013, 13014 + kFIRInstanceIDMessageCodeStore000 = 13000, + kFIRInstanceIDMessageCodeStore001 = 13001, + kFIRInstanceIDMessageCodeStore002 = 13002, + kFIRInstanceIDMessageCodeStore003 = 13003, + kFIRInstanceIDMessageCodeStore006 = 13006, + kFIRInstanceIDMessageCodeStore009 = 13009, + kFIRInstanceIDMessageCodeStore012 = 13012, + // FIRInstanceIDTokenManager.m + // DO NOT USE 14002, 14005 + kFIRInstanceIDMessageCodeTokenManager000 = 14000, + kFIRInstanceIDMessageCodeTokenManager001 = 14001, + kFIRInstanceIDMessageCodeTokenManager003 = 14003, + kFIRInstanceIDMessageCodeTokenManager004 = 14004, + kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset = 14006, + kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset = 14007, + kFIRInstanceIDMessageCodeTokenManagerSavedAppVersion = 14008, + kFIRInstanceIDMessageCodeTokenManagerErrorInvalidatingAllTokens = 14009, + kFIRInstanceIDMessageCodeTokenManagerAPNSChanged = 14010, + kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated = 14011, + kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken = 14012, + // FIRInstanceIDTokenStore.m + // DO NOT USE 15002 - 15013 + kFIRInstanceIDMessageCodeTokenStore000 = 15000, + kFIRInstanceIDMessageCodeTokenStore001 = 15001, + kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo = 15015, + + // DO NOT USE 16000, 18004 + + // FIRInstanceIDUtilities.m + kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier = 18000, + kFIRInstanceIDMessageCodeUtilitiesAppEnvironmentUtilNotAvailable = 18001, + kFIRInstanceIDMessageCodeUtilitiesCannotGetHardwareModel = 18002, + kFIRInstanceIDMessageCodeUtilitiesCannotGetSystemVersion = 18003, + // FIRInstanceIDTokenOperation.m + kFIRInstanceIDMessageCodeTokenOperationFailedToSignParams = 19000, + // FIRInstanceIDTokenFetchOperation.m + // DO NOT USE 20004, 20005 + kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest = 20000, + kFIRInstanceIDMessageCodeTokenFetchOperationRequestError = 20001, + kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse = 20002, + kFIRInstanceIDMessageCodeTokenFetchOperationBadTokenStructure = 20003, + // FIRInstanceIDTokenDeleteOperation.m + kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest = 21000, + kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError = 21001, + kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse = 21002, + // FIRInstanceIDTokenInfo.m + kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo = 22000, + kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged = 22001, + kFIRInstanceIDMessageCodeTokenInfoLocaleChanged = 22002, + // FIRInstanceIDKeychain.m + kFIRInstanceIDKeychainReadItemError = 23000, + kFIRInstanceIDKeychainAddItemError = 23001, + kFIRInstanceIDKeychainDeleteItemError = 23002, + kFIRInstanceIDKeychainCreateKeyPairError = 23003, + kFIRInstanceIDKeychainUpdateItemError = 23004, + + // DO NOT USE 24000, 24001 +}; diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m new file mode 100644 index 00000000..df8ec8ed --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID+Private.h" + +#import "FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h" + +#import <FirebaseInstanceID/FIRInstanceID_Private.h> +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDTokenManager.h" + +@class FIRInstallations; + +@interface FIRInstanceID () + +@property(nonatomic, readonly, strong) FIRInstanceIDTokenManager *tokenManager; + +@end + +@implementation FIRInstanceID (Private) + +// This method just wraps our pre-configured auth service to make the request. +// This method is only needed by first-party users, like Remote Config. +- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler { + [self.tokenManager.authService fetchCheckinInfoWithHandler:handler]; +} + +// TODO(#4486): Delete the method, `self.firebaseInstallationsID` and related +// code for Firebase 7 release. +- (NSString *)appInstanceID:(NSError **)outError { + return self.firebaseInstallationsID; +} + +#pragma mark - Firebase Installations Compatibility + +/// Presence of this method indicates that this version of IID uses FirebaseInstallations under the +/// hood. It is checked by FirebaseInstallations SDK. ++ (BOOL)usesFIS { + return YES; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m new file mode 100644 index 00000000..178a0ce3 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m @@ -0,0 +1,1120 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +#import "FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h" + +#import "FIRInstanceID+Private.h" +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCombinedHandler.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDTokenManager.h" +#import "FIRInstanceIDUtilities.h" +#import "FIRInstanceIDVersionUtilities.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h" +#import "GoogleUtilities/UserDefaults/Private/GULUserDefaults.h" +#import "NSError+FIRInstanceID.h" + +// Public constants +NSString *const kFIRInstanceIDScopeFirebaseMessaging = @"fcm"; + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +const NSNotificationName kFIRInstanceIDTokenRefreshNotification = + @"com.firebase.iid.notif.refresh-token"; +#else +NSString *const kFIRInstanceIDTokenRefreshNotification = @"com.firebase.iid.notif.refresh-token"; +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +NSString *const kFIRInstanceIDInvalidNilHandlerError = @"Invalid nil handler."; + +// Private constants +int64_t const kMaxRetryIntervalForDefaultTokenInSeconds = 20 * 60; // 20 minutes +int64_t const kMinRetryIntervalForDefaultTokenInSeconds = 10; // 10 seconds +// we retry only a max 5 times. +// TODO(chliangGoogle): If we still fail we should listen for the network change notification +// since GCM would have started Reachability. We only start retrying after we see a configuration +// change. +NSInteger const kMaxRetryCountForDefaultToken = 5; + +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH +static NSString *const kEntitlementsAPSEnvironmentKey = @"Entitlements.aps-environment"; +#else +static NSString *const kEntitlementsAPSEnvironmentKey = + @"Entitlements.com.apple.developer.aps-environment"; +#endif +static NSString *const kAPSEnvironmentDevelopmentValue = @"development"; +/// FIRMessaging selector that returns the current FIRMessaging auto init +/// enabled flag. +static NSString *const kFIRInstanceIDFCMSelectorAutoInitEnabled = + @"isAutoInitEnabledWithUserDefaults:"; + +static NSString *const kFIRInstanceIDAPNSTokenType = @"APNSTokenType"; +static NSString *const kFIRIIDAppReadyToConfigureSDKNotification = + @"FIRAppReadyToConfigureSDKNotification"; +static NSString *const kFIRIIDAppNameKey = @"FIRAppNameKey"; +static NSString *const kFIRIIDErrorDomain = @"com.firebase.instanceid"; +static NSString *const kFIRIIDServiceInstanceID = @"InstanceID"; + +/** + * The APNS token type for the app. If the token type is set to `UNKNOWN` + * InstanceID will implicitly try to figure out what the actual token type + * is from the provisioning profile. + * This must match FIRMessagingAPNSTokenType in FIRMessaging.h + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDAPNSTokenType) { + /// Unknown token type. + FIRInstanceIDAPNSTokenTypeUnknown, + /// Sandbox token type. + FIRInstanceIDAPNSTokenTypeSandbox, + /// Production token type. + FIRInstanceIDAPNSTokenTypeProd, +} NS_SWIFT_NAME(InstanceIDAPNSTokenType); + +@interface FIRInstanceIDResult () +@property(nonatomic, readwrite, copy) NSString *instanceID; +@property(nonatomic, readwrite, copy) NSString *token; +@end + +@interface FIRInstanceID () + +// FIRApp configuration objects. +@property(nonatomic, readwrite, copy) NSString *fcmSenderID; +@property(nonatomic, readwrite, copy) NSString *firebaseAppID; + +// Raw APNS token data +@property(nonatomic, readwrite, strong) NSData *apnsTokenData; + +@property(nonatomic, readwrite) FIRInstanceIDAPNSTokenType apnsTokenType; +// String-based, internal representation of APNS token +@property(nonatomic, readwrite, copy) NSString *APNSTupleString; +// Token fetched from the server automatically for the default app. +@property(nonatomic, readwrite, copy) NSString *defaultFCMToken; + +@property(nonatomic, readwrite, strong) FIRInstanceIDTokenManager *tokenManager; +@property(nonatomic, readwrite, strong) FIRInstallations *installations; + +// backoff and retry for default token +@property(nonatomic, readwrite, assign) NSInteger retryCountForDefaultToken; +@property(atomic, strong, nullable) + FIRInstanceIDCombinedHandler<NSString *> *defaultTokenFetchHandler; + +/// A cached value of FID. Should be used only for `-[FIRInstanceID appInstanceID:]`. +@property(atomic, copy, nullable) NSString *firebaseInstallationsID; + +@end + +// InstanceID doesn't provide any functionality to other components, +// so it provides a private, empty protocol that it conforms to and use it for registration. + +@protocol FIRInstanceIDInstanceProvider +@end + +@interface FIRInstanceID () <FIRInstanceIDInstanceProvider, FIRLibrary> +@end + +@implementation FIRInstanceIDResult +- (id)copyWithZone:(NSZone *)zone { + FIRInstanceIDResult *result = [[[self class] allocWithZone:zone] init]; + result.instanceID = self.instanceID; + result.token = self.token; + return result; +} +@end + +@implementation FIRInstanceID + +// File static to support InstanceID tests that call [FIRInstanceID instanceID] after +// [FIRInstanceID instanceIDForTests]. +static FIRInstanceID *gInstanceID; + ++ (instancetype)instanceID { + // If the static instance was created, return it. This should only be set in tests and we should + // eventually use proper dependency injection for a better test structure. + if (gInstanceID != nil) { + return gInstanceID; + } + FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here. + FIRInstanceID *instanceID = + (FIRInstanceID *)FIR_COMPONENT(FIRInstanceIDInstanceProvider, defaultApp.container); + return instanceID; +} + +- (instancetype)initPrivately { + self = [super init]; + if (self != nil) { + // Use automatic detection of sandbox, unless otherwise set by developer + _apnsTokenType = FIRInstanceIDAPNSTokenTypeUnknown; + } + return self; +} + ++ (FIRInstanceID *)instanceIDForTests { + gInstanceID = [[FIRInstanceID alloc] initPrivately]; + [gInstanceID start]; + return gInstanceID; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma mark - Tokens + +- (NSString *)token { + if (!self.fcmSenderID.length) { + return nil; + } + + NSString *cachedToken = [self cachedTokenIfAvailable]; + + if (cachedToken) { + return cachedToken; + } else { + // If we've never had a cached default token, we should fetch one because unrelatedly, + // this request will help us determine whether the locally-generated Instance ID keypair is not + // unique, and therefore generate a new one. + [self defaultTokenWithHandler:nil]; + return nil; + } +} + +- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler { + FIRInstanceID_WEAKIFY(self); + [self getIDWithHandler:^(NSString *identity, NSError *error) { + FIRInstanceID_STRONGIFY(self); + // This is in main queue already + if (error) { + if (handler) { + handler(nil, error); + } + return; + } + FIRInstanceIDResult *result = [[FIRInstanceIDResult alloc] init]; + result.instanceID = identity; + NSString *cachedToken = [self cachedTokenIfAvailable]; + if (cachedToken) { + if (handler) { + result.token = cachedToken; + handler(result, nil); + } + // If no handler, simply return since client has generated iid and token. + return; + } + [self defaultTokenWithHandler:^(NSString *_Nullable token, NSError *_Nullable error) { + if (handler) { + if (error) { + handler(nil, error); + return; + } + result.token = token; + handler(result, nil); + } + }]; + }]; +} + +- (NSString *)cachedTokenIfAvailable { + FIRInstanceIDTokenInfo *cachedTokenInfo = + [self.tokenManager cachedTokenInfoWithAuthorizedEntity:self.fcmSenderID + scope:kFIRInstanceIDDefaultTokenScope]; + return cachedTokenInfo.token; +} + +- (void)setDefaultFCMToken:(NSString *)defaultFCMToken { + // Sending this notification out will ensure that FIRMessaging and FIRInstanceID has the updated + // default FCM token. + // Only notify of token refresh if we have a new valid token that's different than before + if ((defaultFCMToken.length && _defaultFCMToken.length && + ![defaultFCMToken isEqualToString:_defaultFCMToken]) || + defaultFCMToken.length != _defaultFCMToken.length) { + NSNotification *tokenRefreshNotification = + [NSNotification notificationWithName:kFIRInstanceIDTokenRefreshNotification + object:[defaultFCMToken copy]]; + [[NSNotificationQueue defaultQueue] enqueueNotification:tokenRefreshNotification + postingStyle:NSPostASAP]; + } + + _defaultFCMToken = defaultFCMToken; +} + +- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID000, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + // Add internal options + NSMutableDictionary *tokenOptions = [NSMutableDictionary dictionary]; + if (options.count) { + [tokenOptions addEntriesFromDictionary:options]; + } + + NSString *APNSKey = kFIRInstanceIDTokenOptionsAPNSKey; + NSString *serverTypeKey = kFIRInstanceIDTokenOptionsAPNSIsSandboxKey; + if (tokenOptions[APNSKey] != nil && tokenOptions[serverTypeKey] == nil) { + // APNS key was given, but server type is missing. Supply the server type with automatic + // checking. This can happen when the token is requested from FCM, which does not include a + // server type during its request. + tokenOptions[serverTypeKey] = @([self isSandboxApp]); + } + if (self.firebaseAppID) { + tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID; + } + + // comparing enums to ints directly throws a warning + FIRInstanceIDErrorCode noError = INT_MAX; + FIRInstanceIDErrorCode errorCode = noError; + if (FIRInstanceIDIsValidGCMScope(scope) && !tokenOptions[APNSKey]) { + errorCode = kFIRInstanceIDErrorCodeMissingAPNSToken; + } else if (FIRInstanceIDIsValidGCMScope(scope) && + ![tokenOptions[APNSKey] isKindOfClass:[NSData class]]) { + errorCode = kFIRInstanceIDErrorCodeInvalidRequest; + } else if (![authorizedEntity length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity; + } else if (![scope length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidScope; + } else if (!self.installations) { + errorCode = kFIRInstanceIDErrorCodeInvalidStart; + } + + FIRInstanceIDTokenHandler newHandler = ^(NSString *token, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(token, error); + }); + }; + + if (errorCode != noError) { + newHandler(nil, [NSError errorWithFIRInstanceIDErrorCode:errorCode]); + return; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDAuthService *authService = self.tokenManager.authService; + [authService fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, + NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + newHandler(nil, error); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self.installations installationIDWithCompletion:^(NSString *_Nullable identifier, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + newHandler(nil, newError); + + } else { + FIRInstanceIDTokenInfo *cachedTokenInfo = + [self.tokenManager cachedTokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]; + if (cachedTokenInfo) { + FIRInstanceIDAPNSInfo *optionsAPNSInfo = + [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:tokenOptions]; + // Check if APNS Info is changed + if ((!cachedTokenInfo.APNSInfo && !optionsAPNSInfo) || + [cachedTokenInfo.APNSInfo isEqualToAPNSInfo:optionsAPNSInfo]) { + // check if token is fresh + if ([cachedTokenInfo isFreshWithIID:identifier]) { + newHandler(cachedTokenInfo.token, nil); + return; + } + } + } + [self.tokenManager fetchNewTokenWithAuthorizedEntity:[authorizedEntity copy] + scope:[scope copy] + instanceID:identifier + options:tokenOptions + handler:newHandler]; + } + }]; + }]; +} + +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + handler:(FIRInstanceIDDeleteTokenHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID001, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + // comparing enums to ints directly throws a warning + FIRInstanceIDErrorCode noError = INT_MAX; + FIRInstanceIDErrorCode errorCode = noError; + + if (![authorizedEntity length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity; + } else if (![scope length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidScope; + } else if (!self.installations) { + errorCode = kFIRInstanceIDErrorCodeInvalidStart; + } + + FIRInstanceIDDeleteTokenHandler newHandler = ^(NSError *error) { + // If a default token is deleted successfully, reset the defaultFCMToken too. + if (!error && [authorizedEntity isEqualToString:self.fcmSenderID] && + [scope isEqualToString:kFIRInstanceIDDefaultTokenScope]) { + self.defaultFCMToken = nil; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }; + + if (errorCode != noError) { + newHandler([NSError errorWithFIRInstanceIDErrorCode:errorCode]); + return; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDAuthService *authService = self.tokenManager.authService; + [authService + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + newHandler(error); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self.installations installationIDWithCompletion:^(NSString *_Nullable identifier, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + newHandler(newError); + + } else { + [self.tokenManager deleteTokenWithAuthorizedEntity:authorizedEntity + scope:scope + instanceID:identifier + handler:newHandler]; + } + }]; + }]; +} + +#pragma mark - Identity + +- (void)getIDWithHandler:(FIRInstanceIDHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID003, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + // When getID is explicitly called, trigger getToken to make sure token always exists. + // This is to avoid ID conflict (ID is not checked for conflict until we generate a token) + if (identifier) { + [self token]; + } + handler(identifier, error); + }]; +} + +- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID004, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + void (^callHandlerOnMainThread)(NSError *) = ^(NSError *error) { + if ([NSThread isMainThread]) { + handler(error); + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }; + + if (!self.installations) { + FIRInstanceIDErrorCode error = kFIRInstanceIDErrorCodeInvalidStart; + callHandlerOnMainThread([NSError errorWithFIRInstanceIDErrorCode:error]); + return; + } + + FIRInstanceID_WEAKIFY(self); + void (^deleteTokensHandler)(NSError *) = ^void(NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + callHandlerOnMainThread(error); + return; + } + [self deleteIdentityWithHandler:^(NSError *error) { + callHandlerOnMainThread(error); + }]; + }; + + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + callHandlerOnMainThread(newError); + } else { + [self.tokenManager deleteAllTokensWithInstanceID:identifier handler:deleteTokensHandler]; + } + }]; +} + +- (void)notifyIdentityReset { + [self deleteIdentityWithHandler:nil]; +} + +// Delete all the local cache checkin, IID and token. +- (void)deleteIdentityWithHandler:(FIRInstanceIDDeleteHandler)handler { + // Delete tokens. + [self.tokenManager deleteAllTokensLocallyWithHandler:^(NSError *deleteTokenError) { + // Reset FCM token. + self.defaultFCMToken = nil; + if (deleteTokenError) { + if (handler) { + handler(deleteTokenError); + } + return; + } + + // Delete Instance ID. + [self.installations deleteWithCompletion:^(NSError *_Nullable error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + + [self.tokenManager.authService resetCheckinWithHandler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + // Only request new token if FCM auto initialization is + // enabled. + if ([self isFCMAutoInitEnabled]) { + // Deletion succeeds! Requesting new checkin, IID and token. + // TODO(chliangGoogle) see if dispatch_after is necessary + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + [self defaultTokenWithHandler:nil]; + }); + } + if (handler) { + handler(nil); + } + }]; + }]; + }]; +} + +#pragma mark - Checkin + +- (BOOL)tryToLoadValidCheckinInfo { + FIRInstanceIDCheckinPreferences *checkinPreferences = + [self.tokenManager.authService checkinPreferences]; + return [checkinPreferences hasValidCheckinInfo]; +} + +- (NSString *)deviceAuthID { + return [self.tokenManager.authService checkinPreferences].deviceID; +} + +- (NSString *)secretToken { + return [self.tokenManager.authService checkinPreferences].secretToken; +} + +- (NSString *)versionInfo { + return [self.tokenManager.authService checkinPreferences].versionInfo; +} + +#pragma mark - Config + ++ (void)load { + [FIRApp registerInternalLibrary:(Class<FIRLibrary>)self + withName:@"fire-iid" + withVersion:FIRInstanceIDCurrentLibraryVersion()]; +} + ++ (nonnull NSArray<FIRComponent *> *)componentsToRegister { + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + // InstanceID only works with the default app. + if (!container.app.isDefaultApp) { + // Only configure for the default FIRApp. + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeFIRApp002, + @"Firebase Instance ID only works with the default app."); + return nil; + } + + // Ensure it's cached so it returns the same instance every time instanceID is called. + *isCacheable = YES; + FIRInstanceID *instanceID = [[FIRInstanceID alloc] initPrivately]; + [instanceID start]; + [instanceID configureInstanceIDWithOptions:container.app.options]; + return instanceID; + }; + FIRComponent *instanceIDProvider = + [FIRComponent componentWithProtocol:@protocol(FIRInstanceIDInstanceProvider) + instantiationTiming:FIRInstantiationTimingEagerInDefaultApp + dependencies:@[] + creationBlock:creationBlock]; + return @[ instanceIDProvider ]; +} + +- (void)configureInstanceIDWithOptions:(FIROptions *)options { + NSString *GCMSenderID = options.GCMSenderID; + if (!GCMSenderID.length) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeFIRApp000, + @"Firebase not set up correctly, nil or empty senderID."); + [NSException raise:kFIRIIDErrorDomain + format:@"Could not configure Firebase InstanceID. GCMSenderID must not be nil or " + @"empty."]; + } + + self.fcmSenderID = GCMSenderID; + self.firebaseAppID = options.googleAppID; + + [self updateFirebaseInstallationID]; + + // FCM generates a FCM token during app start for sending push notification to device. + // This is not needed for app extension except for watch. +#if TARGET_OS_WATCH + [self didCompleteConfigure]; +#else + if (![GULAppEnvironmentUtil isAppExtension]) { + [self didCompleteConfigure]; + } +#endif +} + +// This is used to start any operations when we receive FirebaseSDK setup notification +// from FIRCore. +- (void)didCompleteConfigure { + NSString *cachedToken = [self cachedTokenIfAvailable]; + // When there is a cached token, do the token refresh. + if (cachedToken) { + // Clean up expired tokens by checking the token refresh policy. + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + if ([self.tokenManager checkTokenRefreshPolicyWithIID:identifier]) { + // Default token is expired, fetch default token from server. + [self defaultTokenWithHandler:nil]; + } + // Notify FCM with the default token. + self.defaultFCMToken = [self token]; + }]; + } else if ([self isFCMAutoInitEnabled]) { + // When there is no cached token, must check auto init is enabled. + // If it's disabled, don't initiate token generation/refresh. + // If no cache token and auto init is enabled, fetch a token from server. + [self defaultTokenWithHandler:nil]; + // Notify FCM with the default token. + self.defaultFCMToken = [self token]; + } + // ONLY checkin when auto data collection is turned on. + if ([self isFCMAutoInitEnabled]) { + [self.tokenManager.authService scheduleCheckin:YES]; + } +} + +- (BOOL)isFCMAutoInitEnabled { + Class messagingClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + // Firebase Messaging is not installed, auto init should be disabled since it's for FCM. + if (!messagingClass) { + return NO; + } + + // Messaging doesn't have the class method, auto init should be enabled since FCM exists. + SEL autoInitSelector = NSSelectorFromString(kFIRInstanceIDFCMSelectorAutoInitEnabled); + if (![messagingClass respondsToSelector:autoInitSelector]) { + return YES; + } + + // Get the autoInitEnabled class method. + IMP isAutoInitEnabledIMP = [messagingClass methodForSelector:autoInitSelector]; + BOOL(*isAutoInitEnabled) + (Class, SEL, GULUserDefaults *) = (BOOL(*)(id, SEL, GULUserDefaults *))isAutoInitEnabledIMP; + + // Check FCM's isAutoInitEnabled property. + return isAutoInitEnabled(messagingClass, autoInitSelector, + [GULUserDefaults standardUserDefaults]); +} + +// Actually makes InstanceID instantiate both the IID and Token-related subsystems. +- (void)start { + if (![FIRInstanceIDStore hasSubDirectory:kFIRInstanceIDSubDirectoryName]) { + [FIRInstanceIDStore createSubDirectory:kFIRInstanceIDSubDirectoryName]; + } + + [self setupTokenManager]; + self.installations = [FIRInstallations installations]; + [self setupNotificationListeners]; +} + +// Creates the token manager, which is used for fetching, caching, and retrieving tokens. +- (void)setupTokenManager { + self.tokenManager = [[FIRInstanceIDTokenManager alloc] init]; +} + +- (void)setupNotificationListeners { + // To prevent double notifications remove observer from all events during setup. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self]; + [center addObserver:self + selector:@selector(notifyIdentityReset) + name:kFIRInstanceIDIdentityInvalidatedNotification + object:nil]; + [center addObserver:self + selector:@selector(notifyAPNSTokenIsSet:) + name:kFIRInstanceIDAPNSTokenNotification + object:nil]; + [self observeFirebaseInstallationIDChanges]; +} + +#pragma mark - Private Helpers +/// Maximum retry count to fetch the default token. ++ (int64_t)maxRetryCountForDefaultToken { + return kMaxRetryCountForDefaultToken; +} + +/// Minimum interval in seconds between retries to fetch the default token. ++ (int64_t)minIntervalForDefaultTokenRetry { + return kMinRetryIntervalForDefaultTokenInSeconds; +} + +/// Maximum retry interval between retries to fetch default token. ++ (int64_t)maxRetryIntervalForDefaultTokenInSeconds { + return kMaxRetryIntervalForDefaultTokenInSeconds; +} + +- (NSInteger)retryIntervalToFetchDefaultToken { + if (self.retryCountForDefaultToken >= [[self class] maxRetryCountForDefaultToken]) { + return (NSInteger)[[self class] maxRetryIntervalForDefaultTokenInSeconds]; + } + // exponential backoff with a fixed initial retry time + // 11s, 22s, 44s, 88s ... + int64_t minInterval = [[self class] minIntervalForDefaultTokenRetry]; + return (NSInteger)MIN( + (1 << self.retryCountForDefaultToken) + minInterval * self.retryCountForDefaultToken, + kMaxRetryIntervalForDefaultTokenInSeconds); +} + +- (void)defaultTokenWithHandler:(nullable FIRInstanceIDTokenHandler)aHandler { + [self defaultTokenWithRetry:NO handler:aHandler]; +} + +/** + * @param retry Indicates if the method is called to perform a retry after a failed attempt. + * If `YES`, then actual token request will be performed even if `self.defaultTokenFetchHandler != + * nil` + */ +- (void)defaultTokenWithRetry:(BOOL)retry handler:(nullable FIRInstanceIDTokenHandler)aHandler { + BOOL shouldPerformRequest = retry || self.defaultTokenFetchHandler == nil; + + if (!self.defaultTokenFetchHandler) { + self.defaultTokenFetchHandler = [[FIRInstanceIDCombinedHandler<NSString *> alloc] init]; + } + + if (aHandler) { + [self.defaultTokenFetchHandler addHandler:aHandler]; + } + + if (!shouldPerformRequest) { + return; + } + + NSDictionary *instanceIDOptions = @{}; + BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil; + if (hasFirebaseMessaging && self.apnsTokenData) { + BOOL isSandboxApp = (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeSandbox); + if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) { + isSandboxApp = [self isSandboxApp]; + } + instanceIDOptions = @{ + kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData, + kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp), + }; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDTokenHandler newHandler = ^void(NSString *token, NSError *error) { + FIRInstanceID_STRONGIFY(self); + + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID009, + @"Failed to fetch default token %@", error); + + // This notification can be sent multiple times since we can't guarantee success at any point + // of time. + NSNotification *tokenFetchFailNotification = + [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenFailNotification + object:[error copy]]; + [[NSNotificationQueue defaultQueue] enqueueNotification:tokenFetchFailNotification + postingStyle:NSPostASAP]; + + self.retryCountForDefaultToken = (NSInteger)MIN(self.retryCountForDefaultToken + 1, + [[self class] maxRetryCountForDefaultToken]); + + // Do not retry beyond the maximum limit. + if (self.retryCountForDefaultToken < [[self class] maxRetryCountForDefaultToken]) { + NSInteger retryInterval = [self retryIntervalToFetchDefaultToken]; + [self retryGetDefaultTokenAfter:retryInterval]; + } else { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID007, + @"Failed to retrieve the default FCM token after %ld retries", + (long)self.retryCountForDefaultToken); + [self performDefaultTokenHandlerWithToken:nil error:error]; + } + } else { + // If somebody updated IID with APNS token while our initial request did not have it + // set we need to update it on the server. + NSData *deviceTokenInRequest = instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSKey]; + BOOL isSandboxInRequest = + [instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey] boolValue]; + // Note that APNSTupleStringInRequest will be nil if deviceTokenInRequest is nil + NSString *APNSTupleStringInRequest = FIRInstanceIDAPNSTupleStringForTokenAndServerType( + deviceTokenInRequest, isSandboxInRequest); + // If the APNs value either remained nil, or was the same non-nil value, the APNs value + // did not change. + BOOL APNSRemainedSameDuringFetch = + (self.APNSTupleString == nil && APNSTupleStringInRequest == nil) || + ([self.APNSTupleString isEqualToString:APNSTupleStringInRequest]); + if (!APNSRemainedSameDuringFetch && hasFirebaseMessaging) { + // APNs value did change mid-fetch, so the token should be re-fetched with the current APNs + // value. + [self retryGetDefaultTokenAfter:0]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeRefetchingTokenForAPNS, + @"Received APNS token while fetching default token. " + @"Refetching default token."); + // Do not notify and handle completion handler since this is a retry. + // Simply return. + return; + } else { + FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeInstanceID010, + @"Successfully fetched default token."); + } + // Post the required notifications if somebody is waiting. + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID008, @"Got default token %@", + token); + // Update default FCM token, this method also triggers sending notification if token has + // changed. + self.defaultFCMToken = token; + + [self performDefaultTokenHandlerWithToken:token error:nil]; + } + }; + + [self tokenWithAuthorizedEntity:self.fcmSenderID + scope:kFIRInstanceIDDefaultTokenScope + options:instanceIDOptions + handler:newHandler]; +} + +/** + * + */ +- (void)performDefaultTokenHandlerWithToken:(NSString *)token error:(NSError *)error { + if (!self.defaultTokenFetchHandler) { + return; + } + + [self.defaultTokenFetchHandler combinedHandler](token, error); + self.defaultTokenFetchHandler = nil; +} + +- (void)retryGetDefaultTokenAfter:(NSTimeInterval)retryInterval { + FIRInstanceID_WEAKIFY(self); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(retryInterval * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRInstanceID_STRONGIFY(self); + // Pass nil: no new handlers to be added, currently existing handlers + // will be called + [self defaultTokenWithRetry:YES handler:nil]; + }); +} + +#pragma mark - APNS Token +// This should only be triggered from FCM. +- (void)notifyAPNSTokenIsSet:(NSNotification *)notification { + NSData *token = notification.object; + if (!token || ![token isKindOfClass:[NSData class]]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal002, @"Invalid APNS token type %@", + NSStringFromClass([notification.object class])); + return; + } + NSInteger type = [notification.userInfo[kFIRInstanceIDAPNSTokenType] integerValue]; + + // The APNS token is being added, or has changed (rare) + if ([self.apnsTokenData isEqualToData:token]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID011, + @"Trying to reset APNS token to the same value. Will return"); + return; + } + // Use this token type for when we have to automatically fetch tokens in the future + self.apnsTokenType = type; + BOOL isSandboxApp = (type == FIRInstanceIDAPNSTokenTypeSandbox); + if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) { + isSandboxApp = [self isSandboxApp]; + } + self.apnsTokenData = [token copy]; + self.APNSTupleString = FIRInstanceIDAPNSTupleStringForTokenAndServerType(token, isSandboxApp); + + // Pro-actively invalidate the default token, if the APNs change makes it + // invalid. Previously, we invalidated just before fetching the token. + NSArray<FIRInstanceIDTokenInfo *> *invalidatedTokens = + [self.tokenManager updateTokensToAPNSDeviceToken:self.apnsTokenData isSandbox:isSandboxApp]; + + // Re-fetch any invalidated tokens automatically, this time with the current APNs token, so that + // they are up-to-date. + if (invalidatedTokens.count > 0) { + FIRInstanceID_WEAKIFY(self); + + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (self == nil) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID017, + @"Instance ID shut down during token reset. Aborting"); + return; + } + if (self.apnsTokenData == nil) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID018, + @"apnsTokenData was set to nil during token reset. Aborting"); + return; + } + + NSMutableDictionary *tokenOptions = [@{ + kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData, + kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp) + } mutableCopy]; + if (self.firebaseAppID) { + tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID; + } + + for (FIRInstanceIDTokenInfo *tokenInfo in invalidatedTokens) { + if ([tokenInfo.token isEqualToString:self.defaultFCMToken]) { + // We will perform a special fetch for the default FCM token, so that the delegate + // methods are called. For all others, we will do an internal re-fetch. + [self defaultTokenWithHandler:nil]; + } else { + [self.tokenManager fetchNewTokenWithAuthorizedEntity:tokenInfo.authorizedEntity + scope:tokenInfo.scope + instanceID:identifier + options:tokenOptions + handler:^(NSString *_Nullable token, + NSError *_Nullable error){ + + }]; + } + } + }]; + } +} + +- (BOOL)isSandboxApp { + static BOOL isSandboxApp = YES; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + isSandboxApp = ![self isProductionApp]; + }); + return isSandboxApp; +} + +- (BOOL)isProductionApp { + const BOOL defaultAppTypeProd = YES; + + NSError *error = nil; + if ([GULAppEnvironmentUtil isSimulator]) { + [self logAPNSConfigurationError:@"Running InstanceID on a simulator doesn't have APNS. " + @"Use prod profile by default."]; + return defaultAppTypeProd; + } + + if ([GULAppEnvironmentUtil isFromAppStore]) { + // Apps distributed via AppStore or TestFlight use the Production APNS certificates. + return defaultAppTypeProd; + } +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST + NSString *path = [[[[NSBundle mainBundle] resourcePath] stringByDeletingLastPathComponent] + stringByAppendingPathComponent:@"embedded.provisionprofile"]; +#elif TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + NSString *path = [[[NSBundle mainBundle] bundlePath] + stringByAppendingPathComponent:@"embedded.mobileprovision"]; +#endif + + if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox] && !path.length) { + // Distributed via TestFlight + return defaultAppTypeProd; + } + + NSMutableData *profileData = [NSMutableData dataWithContentsOfFile:path options:0 error:&error]; + + if (!profileData.length || error) { + NSString *errorString = + [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + + // The "embedded.mobileprovision" sometimes contains characters with value 0, which signals the + // end of a c-string and halts the ASCII parser, or with value > 127, which violates strict 7-bit + // ASCII. Replace any 0s or invalid characters in the input. + uint8_t *profileBytes = (uint8_t *)profileData.bytes; + for (int i = 0; i < profileData.length; i++) { + uint8_t currentByte = profileBytes[i]; + if (!currentByte || currentByte > 127) { + profileBytes[i] = '.'; + } + } + + NSString *embeddedProfile = [[NSString alloc] initWithBytesNoCopy:profileBytes + length:profileData.length + encoding:NSASCIIStringEncoding + freeWhenDone:NO]; + + if (error || !embeddedProfile.length) { + NSString *errorString = + [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + + NSScanner *scanner = [NSScanner scannerWithString:embeddedProfile]; + NSString *plistContents; + if ([scanner scanUpToString:@"<plist" intoString:nil]) { + if ([scanner scanUpToString:@"</plist>" intoString:&plistContents]) { + plistContents = [plistContents stringByAppendingString:@"</plist>"]; + } + } + + if (!plistContents.length) { + return defaultAppTypeProd; + } + + NSData *data = [plistContents dataUsingEncoding:NSUTF8StringEncoding]; + if (!data.length) { + [self logAPNSConfigurationError:@"Couldn't read plist fetched from embedded mobileprovision"]; + return defaultAppTypeProd; + } + + NSError *plistMapError; + id plistData = [NSPropertyListSerialization propertyListWithData:data + options:NSPropertyListImmutable + format:nil + error:&plistMapError]; + if (plistMapError || ![plistData isKindOfClass:[NSDictionary class]]) { + NSString *errorString = + [NSString stringWithFormat:@"Error while converting assumed plist to dict %@", + plistMapError.localizedDescription]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + NSDictionary *plistMap = (NSDictionary *)plistData; + + if ([plistMap valueForKeyPath:@"ProvisionedDevices"]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID012, + @"Provisioning profile has specifically provisioned devices, " + @"most likely a Dev profile."); + } + + NSString *apsEnvironment = [plistMap valueForKeyPath:kEntitlementsAPSEnvironmentKey]; + NSString *debugString __unused = + [NSString stringWithFormat:@"APNS Environment in profile: %@", apsEnvironment]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID013, @"%@", debugString); + + // No aps-environment in the profile. + if (!apsEnvironment.length) { + [self logAPNSConfigurationError:@"No aps-environment set. If testing on a device APNS is not " + @"correctly configured. Please recheck your provisioning " + @"profiles. If testing on a simulator this is fine since APNS " + @"doesn't work on the simulator."]; + return defaultAppTypeProd; + } + + if ([apsEnvironment isEqualToString:kAPSEnvironmentDevelopmentValue]) { + return NO; + } + + return defaultAppTypeProd; +} + +/// Log error messages only when Messaging exists in the pod. +- (void)logAPNSConfigurationError:(NSString *)errorString { + BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil; + if (hasFirebaseMessaging) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID014, @"%@", errorString); + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID015, @"%@", errorString); + } +} + +#pragma mark - Sync InstanceID + +- (void)updateFirebaseInstallationID { + FIRInstanceID_WEAKIFY(self); + [self.installations + installationIDWithCompletion:^(NSString *_Nullable installationID, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + self.firebaseInstallationsID = installationID; + }]; +} + +- (void)installationIDDidChangeNotificationReceived:(NSNotification *)notification { + NSString *installationAppID = + notification.userInfo[kFIRInstallationIDDidChangeNotificationAppNameKey]; + if ([installationAppID isKindOfClass:[NSString class]] && + [installationAppID isEqual:self.firebaseAppID]) { + [self updateFirebaseInstallationID]; + } +} + +- (void)observeFirebaseInstallationIDChanges { + [[NSNotificationCenter defaultCenter] removeObserver:self + name:FIRInstallationIDDidChangeNotification + object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(installationIDDidChangeNotificationReceived:) + name:FIRInstallationIDDidChangeNotification + object:nil]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h new file mode 100644 index 00000000..92b2469b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents an APNS device token and whether its environment is for sandbox. + * It can read from and write to an NSDictionary for simple serialization. + */ +@interface FIRInstanceIDAPNSInfo : NSObject <NSCoding> + +/// The APNs device token, provided by the OS to the application delegate +@property(nonatomic, readonly, strong) NSData *deviceToken; +/// Represents whether or not this is deviceToken is for the sandbox +/// environment, or production. +@property(nonatomic, readonly, getter=isSandbox) BOOL sandbox; + +/** + * Initializes the receiver with an APNs device token, and boolean + * representing whether that token is for the sandbox environment. + * + * @param deviceToken The APNs device token typically provided by the + * operating system. + * @param isSandbox YES if the APNs device token is for the sandbox + * environment, or NO if it is for production. + * @return An instance of FIRInstanceIDAPNSInfo. + */ +- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox; + +/** + * Initializes the receiver from a token options dictionary containing data + * within the `kFIRInstanceIDTokenOptionsAPNSKey` and + * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey` keys. The token should be an + * NSData blob, and the sandbox value should be an NSNumber + * representing a boolean value. + * + * @param dictionary A dictionary containing values under the keys + * `kFIRInstanceIDTokenOptionsAPNSKey` and + * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey`. + * @return An instance of FIRInstanceIDAPNSInfo, or nil if the + * dictionary data was invalid or missing. + */ +- (nullable instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary; + +- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m new file mode 100644 index 00000000..d1f9d080 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m @@ -0,0 +1,79 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAPNSInfo.h" + +#import "FIRInstanceIDConstants.h" + +/// The key used to find the APNs device token in an archive. +NSString *const kFIRInstanceIDAPNSInfoTokenKey = @"device_token"; +/// The key used to find the sandbox value in an archive. +NSString *const kFIRInstanceIDAPNSInfoSandboxKey = @"sandbox"; + +@implementation FIRInstanceIDAPNSInfo + +- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox { + self = [super init]; + if (self) { + _deviceToken = [deviceToken copy]; + _sandbox = isSandbox; + } + return self; +} + +- (instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary { + id deviceToken = dictionary[kFIRInstanceIDTokenOptionsAPNSKey]; + if (![deviceToken isKindOfClass:[NSData class]]) { + return nil; + } + + id isSandbox = dictionary[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey]; + if (![isSandbox isKindOfClass:[NSNumber class]]) { + return nil; + } + self = [super init]; + if (self) { + _deviceToken = (NSData *)deviceToken; + _sandbox = ((NSNumber *)isSandbox).boolValue; + } + return self; +} + +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + id deviceToken = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoTokenKey]; + if (![deviceToken isKindOfClass:[NSData class]]) { + return nil; + } + BOOL isSandbox = [aDecoder decodeBoolForKey:kFIRInstanceIDAPNSInfoSandboxKey]; + return [self initWithDeviceToken:(NSData *)deviceToken isSandbox:isSandbox]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.deviceToken forKey:kFIRInstanceIDAPNSInfoTokenKey]; + [aCoder encodeBool:self.sandbox forKey:kFIRInstanceIDAPNSInfoSandboxKey]; +} + +- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo { + if ([super isEqual:otherInfo]) { + return YES; + } + return ([self.deviceToken isEqualToData:otherInfo.deviceToken] && + self.isSandbox == otherInfo.isSandbox); +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h new file mode 100644 index 00000000..8d453b8b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +extern NSString *__nonnull const kFIRInstanceIDKeychainWildcardIdentifier; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Wrapper around storing FCM auth data in iOS keychain. + */ +@interface FIRInstanceIDAuthKeychain : NSObject + +/** + * Designated Initializer. Init a generic `SecClassGenericPassword` keychain with `identifier` + * as the `kSecAttrGeneric`. + * + * @param identifier The generic attribute to be used by the keychain. + * + * @return A Keychain object with `kSecAttrGeneric` attribute set to identifier. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier; + +/** + * Get keychain items matching the given service and account. The service and/or account + * can be a wildcard (`kFIRInstanceIDKeychainWildcardIdentifier`), which case the query + * will include all items matching any services and/or accounts. + * + * @param service The kSecAttrService used to save the password. Can be wildcard. + * @param account The kSecAttrAccount used to save the password. Can be wildcard. + * + * @return An array of |NSData|s matching the provided inputs. + */ +- (NSArray<NSData *> *)itemsMatchingService:(NSString *)service account:(NSString *)account; + +/** + * Get keychain item for a given service and account. + * + * @param service The kSecAttrService used to save the password. + * @param account The kSecAttrAccount used to save the password. + * + * @return A cached keychain item for a given account and service, or nil if it was not + * found or could not be retrieved. + */ +- (NSData *)dataForService:(NSString *)service account:(NSString *)account; + +/** + * Remove the cached items from the keychain matching the service, account and access group. + * In case the items do not exist, YES is returned but with a valid error object with code + * `errSecItemNotFound`. + * + * @param service The kSecAttrService used to save the password. + * @param account The kSecAttrAccount used to save the password. + * @param handler The callback handler which is invoked when the remove operation is complete, with + * an error if there is any. + */ +- (void)removeItemsMatchingService:(NSString *)service + account:(NSString *)account + handler:(nullable void (^)(NSError *error))handler; + +/** + * Set the data for a given service and account. + * We use `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` which + * prevents backup and restore to iCloud, and works for app extension that can + * execute right after a device is restarted (and not unlocked). + * + * @param data The data to save. + * @param service The `kSecAttrService` used to save the password. + * @param account The `kSecAttrAccount` used to save the password. + * @param handler The callback handler which is invoked when the add operation is complete, + * with an error if there is any. + * + */ +- (void)setData:(NSData *)data + forService:(NSString *)service + account:(NSString *)account + handler:(nullable void (^)(NSError *))handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m new file mode 100644 index 00000000..dfce2f75 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m @@ -0,0 +1,216 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDKeychain.h" +#import "FIRInstanceIDLogger.h" + +/** + * The error type representing why we couldn't read data from the keychain. + */ +typedef NS_ENUM(int, FIRInstanceIDKeychainErrorType) { + kFIRInstanceIDKeychainErrorBadArguments = -1301, +}; + +NSString *const kFIRInstanceIDKeychainWildcardIdentifier = @"*"; + +@interface FIRInstanceIDAuthKeychain () + +@property(nonatomic, copy) NSString *generic; +// cachedKeychainData is keyed by service and account, the value is an array of NSData. +// It is used to cache the tokens per service, per account, as well as checkin data per service, +// per account inside the keychain. +@property(nonatomic) + NSMutableDictionary<NSString *, NSMutableDictionary<NSString *, NSArray<NSData *> *> *> + *cachedKeychainData; + +@end + +@implementation FIRInstanceIDAuthKeychain + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super init]; + if (self) { + _generic = [identifier copy]; + _cachedKeychainData = [[NSMutableDictionary alloc] init]; + } + return self; +} + ++ (NSMutableDictionary *)keychainQueryForService:(NSString *)service + account:(NSString *)account + generic:(NSString *)generic { + NSDictionary *query = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword}; + + NSMutableDictionary *finalQuery = [NSMutableDictionary dictionaryWithDictionary:query]; + if ([generic length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:generic]) { + finalQuery[(__bridge NSString *)kSecAttrGeneric] = generic; + } + if ([account length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:account]) { + finalQuery[(__bridge NSString *)kSecAttrAccount] = account; + } + if ([service length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:service]) { + finalQuery[(__bridge NSString *)kSecAttrService] = service; + } + return finalQuery; +} + +- (NSMutableDictionary *)keychainQueryForService:(NSString *)service account:(NSString *)account { + return [[self class] keychainQueryForService:service account:account generic:self.generic]; +} + +- (NSArray<NSData *> *)itemsMatchingService:(NSString *)service account:(NSString *)account { + // If query wildcard service, it asks for all the results, which always query from keychain. + if (![service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] && + ![account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] && + _cachedKeychainData[service][account]) { + // As long as service, account array exist, even it's empty, it means we've queried it before, + // returns the cache value. + return _cachedKeychainData[service][account]; + } + + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + NSMutableArray<NSData *> *results; + keychainQuery[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue; +#if TARGET_OS_IOS || TARGET_OS_TV + keychainQuery[(__bridge id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue; + keychainQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; + // FIRInstanceIDKeychain should only take a query and return a result, will handle the query here. + NSArray *passwordInfos = + CFBridgingRelease([[FIRInstanceIDKeychain sharedInstance] itemWithQuery:keychainQuery]); +#elif TARGET_OS_OSX || TARGET_OS_WATCH + keychainQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + NSData *passwordInfos = + CFBridgingRelease([[FIRInstanceIDKeychain sharedInstance] itemWithQuery:keychainQuery]); +#endif + + if (!passwordInfos) { + // Nothing was found, simply return from this sync block. + // Make sure to label the cache entry empty, signaling that we've queried this entry. + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Do not update cache if it's wildcard query. + return @[]; + } else if (_cachedKeychainData[service]) { + [_cachedKeychainData[service] setObject:@[] forKey:account]; + } else { + [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service]; + } + return @[]; + } + results = [[NSMutableArray alloc] init]; +#if TARGET_OS_IOS || TARGET_OS_TV + NSInteger numPasswords = passwordInfos.count; + for (NSUInteger i = 0; i < numPasswords; i++) { + NSDictionary *passwordInfo = [passwordInfos objectAtIndex:i]; + if (passwordInfo[(__bridge id)kSecValueData]) { + [results addObject:passwordInfo[(__bridge id)kSecValueData]]; + } + } +#elif TARGET_OS_OSX || TARGET_OS_WATCH + [results addObject:passwordInfos]; +#endif + // We query the keychain because it didn't exist in cache, now query is done, update the result in + // the cache. + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Do not update cache if it's wildcard query. + return [results copy]; + } else if (_cachedKeychainData[service]) { + [_cachedKeychainData[service] setObject:[results copy] forKey:account]; + } else { + NSMutableDictionary *entry = [@{account : [results copy]} mutableCopy]; + [_cachedKeychainData setObject:entry forKey:service]; + } + return [results copy]; +} + +- (NSData *)dataForService:(NSString *)service account:(NSString *)account { + NSArray<NSData *> *items = [self itemsMatchingService:service account:account]; + // If items is nil or empty, nil will be returned. + return items.firstObject; +} + +- (void)removeItemsMatchingService:(NSString *)service + account:(NSString *)account + handler:(void (^)(NSError *error))handler { + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Delete all keychain items. + _cachedKeychainData = [[NSMutableDictionary alloc] init]; + } else if ([account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Delete all entries under service, + if (_cachedKeychainData[service]) { + _cachedKeychainData[service] = [[NSMutableDictionary alloc] init]; + } + } else if (_cachedKeychainData[service]) { + // We should keep the service/account entry instead of nil so we know + // it's "empty entry" instead of "not query from keychain yet". + [_cachedKeychainData[service] setObject:@[] forKey:account]; + } else { + [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service]; + } + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:keychainQuery handler:handler]; +} + +- (void)setData:(NSData *)data + forService:(NSString *)service + account:(NSString *)account + handler:(void (^)(NSError *))handler { + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + if (handler) { + handler([NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:kFIRInstanceIDKeychainErrorBadArguments + userInfo:nil]); + } + return; + } + [self removeItemsMatchingService:service + account:account + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (data.length > 0) { + NSMutableDictionary *keychainQuery = + [self keychainQueryForService:service account:account]; + keychainQuery[(__bridge id)kSecValueData] = data; + + keychainQuery[(__bridge id)kSecAttrAccessible] = + (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + [[FIRInstanceIDKeychain sharedInstance] + addItemWithQuery:keychainQuery + handler:handler]; + } + }]; + // Set the cache value. This must happen after removeItemsMatchingService:account:handler was + // called, so the cache value was reset before setting a new value. + if (_cachedKeychainData[service]) { + if (_cachedKeychainData[service][account]) { + _cachedKeychainData[service][account] = @[ data ]; + } else { + [_cachedKeychainData[service] setObject:@[ data ] forKey:account]; + } + } else { + [_cachedKeychainData setObject:[@{account : @[ data ]} mutableCopy] forKey:service]; + } +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h new file mode 100644 index 00000000..1fb715e7 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> +#import "FIRInstanceIDCheckinService.h" + +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDStore; + +/** + * FIRInstanceIDAuthService is responsible for retrieving, caching, and supplying checkin info + * for the rest of Instance ID. A checkin can be scheduled, meaning that it will keep retrying the + * checkin request until it is successful. A checkin can also be requested directly, with a + * completion handler. + */ +@interface FIRInstanceIDAuthService : NSObject + +/** + * Used only for testing. In addition to taking a store (for locally caching the checkin info), it + * also takes a checkinService. + */ +- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService + store:(FIRInstanceIDStore *)store; + +/** + * Initializes the auth service given a store (which provides the local caching of checkin info). + * This initializer will create its own instance of FIRInstanceIDCheckinService. + */ +- (instancetype)initWithStore:(FIRInstanceIDStore *)store; + +#pragma mark - Checkin Service + +/** + * Checks if the current deviceID and secret are valid or not. + * + * @return YES if the checkin credentials are valid else NO. + */ +- (BOOL)hasValidCheckinInfo; + +/** + * Fetch checkin info from the server. This would usually refresh the existing + * checkin credentials for the current app. + * + * @param handler The completion handler to invoke once the checkin info has been + * refreshed. + */ +- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler; + +/** + * Schedule checkin. Will hit the network only if the currently loaded checkin + * preferences are stale. + * + * @param immediately YES if we want it to be scheduled immediately else NO. + */ +- (void)scheduleCheckin:(BOOL)immediately; + +/** + * Returns the checkin preferences currently loaded in memory. The Checkin preferences + * can be either valid or invalid. + * + * @return The checkin preferences loaded in memory. + */ +- (FIRInstanceIDCheckinPreferences *)checkinPreferences; + +/** + * Cancels any ongoing checkin fetch, if any. + */ +- (void)stopCheckinRequest; + +/** + * Resets the checkin information. + * + * @param handler The callback handler which is invoked when checkin reset is complete, + * with an error if there is any. + */ +- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m new file mode 100644 index 00000000..8c33c440 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m @@ -0,0 +1,302 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAuthService.h" + +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "NSError+FIRInstanceID.h" + +// Max time interval between checkin retry in seconds. +static const int64_t kMaxCheckinRetryIntervalInSeconds = 1 << 5; + +@interface FIRInstanceIDAuthService () + +// Used to retrieve and cache the checkin info to disk and Keychain. +@property(nonatomic, readwrite, strong) FIRInstanceIDStore *store; +// Used to perform single checkin fetches. +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinService *checkinService; +// The current checkin info. It will be compared to what is retrieved to determine whether it is +// different than what is in the cache. +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; + +// This array will track multiple handlers waiting for checkin to be performed. When a checkin +// request completes, all the handlers will be notified. +// Changes to the checkinHandlers array should happen in a thread-safe manner. +@property(nonatomic, readonly, strong) + NSMutableArray<FIRInstanceIDDeviceCheckinCompletion> *checkinHandlers; + +// This is set to true if there is a checkin request in-flight. +@property(atomic, readwrite, assign) BOOL isCheckinInProgress; +// This timer is used a perform checkin retries. It is cancellable. +@property(atomic, readwrite, strong) NSTimer *scheduledCheckinTimer; +// The number of times checkin has been retried during a scheduled checkin. +@property(atomic, readwrite, assign) int checkinRetryCount; + +@end + +@implementation FIRInstanceIDAuthService + +- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService + store:(FIRInstanceIDStore *)store { + self = [super init]; + if (self) { + _store = store; + _checkinPreferences = [_store cachedCheckinPreferences]; + _checkinService = checkinService; + _checkinHandlers = [NSMutableArray array]; + } + return self; +} + +- (void)dealloc { + [_scheduledCheckinTimer invalidate]; +} + +- (instancetype)initWithStore:(FIRInstanceIDStore *)store { + FIRInstanceIDCheckinService *checkinService = [[FIRInstanceIDCheckinService alloc] init]; + return [self initWithCheckinService:checkinService store:store]; +} + +#pragma mark - Schedule Checkin + +- (void)scheduleCheckin:(BOOL)immediately { + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + return; + } + + // Checkin is already scheduled, so this (non-immediate) request can be ignored. + if (!immediately && [self.scheduledCheckinTimer isValid]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService000, + @"Checkin sync already scheduled. Will not schedule."); + return; + } + + if (immediately) { + [self performScheduledCheckin]; + } else { + int64_t checkinRetryDuration = [self calculateNextCheckinRetryIntervalInSeconds]; + [self startCheckinTimerWithDuration:(NSTimeInterval)checkinRetryDuration]; + } +} + +- (void)startCheckinTimerWithDuration:(NSTimeInterval)timerDuration { + self.scheduledCheckinTimer = + [NSTimer scheduledTimerWithTimeInterval:timerDuration + target:self + selector:@selector(onScheduledCheckinTimerFired:) + userInfo:nil + repeats:NO]; + // Add some tolerance to the timer, to allow iOS to be more flexible with this timer + self.scheduledCheckinTimer.tolerance = 0.5; +} + +- (void)clearScheduledCheckinTimer { + [self.scheduledCheckinTimer invalidate]; + self.scheduledCheckinTimer = nil; +} + +- (void)onScheduledCheckinTimerFired:(NSTimer *)timer { + [self performScheduledCheckin]; +} + +- (void)performScheduledCheckin { + // No checkin scheduled as of now. + [self clearScheduledCheckinTimer]; + + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + return; + } + + FIRInstanceID_WEAKIFY(self); + [self + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + self.checkinRetryCount++; + + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService001, @"Checkin error %@.", + error); + + dispatch_async(dispatch_get_main_queue(), ^{ + // Schedule another checkin + [self scheduleCheckin:NO]; + }); + + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService002, @"Checkin success."); + } + }]; +} + +- (int64_t)calculateNextCheckinRetryIntervalInSeconds { + // persistent failures can lead to overflow prevent that. + if (self.checkinRetryCount >= 10) { + return kMaxCheckinRetryIntervalInSeconds; + } + return MIN(1 << self.checkinRetryCount, kMaxCheckinRetryIntervalInSeconds); +} + +#pragma mark - Checkin Service + +- (BOOL)hasValidCheckinInfo { + return [self.checkinPreferences hasValidCheckinInfo]; +} + +- (void)fetchCheckinInfoWithHandler:(nonnull FIRInstanceIDDeviceCheckinCompletion)handler { + // Perform any changes to self.checkinHandlers and _isCheckinInProgress in a thread-safe way. + @synchronized(self) { + [self.checkinHandlers addObject:handler]; + + if (_isCheckinInProgress) { + // Nothing more to do until our checkin request is done + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress, + @"Checkin is in progress\n"); + return; + } + } + + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + [self notifyCheckinHandlersWithCheckin:self.checkinPreferences error:nil]; + return; + } + + @synchronized(self) { + _isCheckinInProgress = YES; + } + [self.checkinService + checkinWithExistingCheckin:self.checkinPreferences + completion:^(FIRInstanceIDCheckinPreferences *checkinPreferences, + NSError *error) { + @synchronized(self) { + self->_isCheckinInProgress = NO; + } + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService003, + @"Failed to checkin device %@", error); + [self notifyCheckinHandlersWithCheckin:nil error:error]; + return; + } + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService004, + @"Successfully got checkin credentials"); + BOOL hasSameCachedPreferences = + [self cachedCheckinMatchesCheckin:checkinPreferences]; + checkinPreferences.hasPreCachedAuthCredentials = hasSameCachedPreferences; + + // Update to the most recent checkin preferences + self.checkinPreferences = checkinPreferences; + + // Save the checkin info to disk + // Keychain might not be accessible, so confirm that checkin preferences can + // be saved + [self.store + saveCheckinPreferences:checkinPreferences + handler:^(NSError *checkinSaveError) { + if (checkinSaveError && !hasSameCachedPreferences) { + // The checkin info was new, but it couldn't be + // written to the Keychain. Delete any stuff that was + // cached in memory. This doesn't delete any + // previously persisted preferences. + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeService004, + @"Unable to save checkin info, resetting " + @"checkin preferences " + "in memory."); + [checkinPreferences reset]; + [self + notifyCheckinHandlersWithCheckin:nil + error: + checkinSaveError]; + } else { + // The checkin is either new, or it was the same (and + // it couldn't be saved). Either way, report that the + // checkin preferences were received successfully. + [self notifyCheckinHandlersWithCheckin: + checkinPreferences + error:nil]; + if (!hasSameCachedPreferences) { + // Checkin is new. + // Notify any listeners that might be waiting for + // checkin to be fetched, such as Firebase + // Messaging (for its MCS connection). + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] + postNotificationName: + kFIRInstanceIDCheckinFetchedNotification + object:nil]; + }); + } + } + }]; + }]; +} + +- (FIRInstanceIDCheckinPreferences *)checkinPreferences { + return _checkinPreferences; +} + +- (void)stopCheckinRequest { + [self.checkinService stopFetching]; +} + +- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler { + [self.store removeCheckinPreferencesWithHandler:^(NSError *error) { + if (!error) { + self.checkinPreferences = nil; + } + if (handler) { + handler(error); + } + }]; +} + +#pragma mark - Private + +/** + * Goes through the current list of checkin handlers and fires them with the same checkin and/or + * error info. The checkin handlers will get cleared after. + */ +- (void)notifyCheckinHandlersWithCheckin:(nullable FIRInstanceIDCheckinPreferences *)checkin + error:(nullable NSError *)error { + @synchronized(self) { + for (FIRInstanceIDDeviceCheckinCompletion handler in self.checkinHandlers) { + handler(checkin, error); + } + [self.checkinHandlers removeAllObjects]; + } +} + +/** + * Given a |checkin|, it will compare it to the current checkinPreferences to see if the + * deviceID and secretToken are the same. + */ +- (BOOL)cachedCheckinMatchesCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + if (self.checkinPreferences && checkin) { + return ([self.checkinPreferences.deviceID isEqualToString:checkin.deviceID] && + [self.checkinPreferences.secretToken isEqualToString:checkin.secretToken]); + } + return NO; +} +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h new file mode 100644 index 00000000..bccaced8 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@interface FIRInstanceIDBackupExcludedPlist : NSObject + +/** + * Caches the plist contents in memory so we don't hit the disk each time we want + * to query something in the plist. This is loaded lazily i.e. if you write to the + * plist the contents you want to write will be stored here if the write was + * successful. The other case where it is loaded is if you read the plist contents + * by calling `contentAsDictionary`. + * + * In case you write to the plist and then try to read the file using + * `contentAsDictionary` we would just return the cachedPlistContents since it would + * represent the disk contents. + */ +@property(nonatomic, readonly, strong) NSDictionary *cachedPlistContents; + +/** + * Init a backup excluded plist file. + * + * @param fileName The filename for the plist file. + * @param subDirectory The subdirectory in Application Support to save the plist. + * + * @return Helper which allows to read write data to a backup excluded plist. + */ +- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory; + +/** + * Write dictionary data to the backup excluded plist file. If the file does not exist + * it would be created before writing to it. + * + * @param dict The data to be written to the plist. + * @param error The error object if any while writing the data. + * + * @return YES if the write was successful else NO. + */ +- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error; + +/** + * Delete the backup excluded plist created with the above filename. + * + * @param error The error object if any while deleting the file. + * + * @return YES If the delete was successful else NO. + */ +- (BOOL)deleteFile:(NSError **)error; + +/** + * The contents of the plist file. We also store the contents of the file in-memory. + * If the in-memory contents are valid we return the in-memory contents else we read + * the file from disk. + * + * @return A dictionary object that contains the contents of the plist file if the file + * exists else nil. + */ +- (NSDictionary *)contentAsDictionary; + +/** + * Check if the plist exists on the disk or not. + * + * @return YES if the file exists on the disk else NO. + */ +- (BOOL)doesFileExist; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m new file mode 100644 index 00000000..c1085cae --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m @@ -0,0 +1,117 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDBackupExcludedPlist.h" + +#import "FIRInstanceIDLogger.h" + +@interface FIRInstanceIDBackupExcludedPlist () + +@property(nonatomic, readwrite, copy) NSString *fileName; +@property(nonatomic, readwrite, copy) NSString *subDirectoryName; +@property(nonatomic, readwrite, strong) NSDictionary *cachedPlistContents; + +@end + +@implementation FIRInstanceIDBackupExcludedPlist + +- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory { + self = [super init]; + if (self) { + _fileName = [fileName copy]; + _subDirectoryName = [subDirectory copy]; + } + return self; +} + +- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error { + NSString *path = [self plistPathInDirectory]; + if (![dict writeToFile:path atomically:YES]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist000, + @"Failed to write to %@.plist", self.fileName); + return NO; + } + + // Successfully wrote contents -- change the in-memory contents + self.cachedPlistContents = [dict copy]; + + NSURL *URL = [NSURL fileURLWithPath:path]; + if (error) { + *error = nil; + } + + NSDictionary *preferences = [URL resourceValuesForKeys:@[ NSURLIsExcludedFromBackupKey ] + error:error]; + if ([preferences[NSURLIsExcludedFromBackupKey] boolValue]) { + return YES; + } + + BOOL success = [URL setResourceValue:@(YES) forKey:NSURLIsExcludedFromBackupKey error:error]; + if (!success) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist001, + @"Error excluding %@ from backup, %@", [URL lastPathComponent], + error ? *error : @""); + } + return success; +} + +- (BOOL)deleteFile:(NSError **)error { + BOOL success = YES; + NSString *path = [self plistPathInDirectory]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + success = [[NSFileManager defaultManager] removeItemAtPath:path error:error]; + } + // remove the in-memory contents + self.cachedPlistContents = nil; + return success; +} + +- (NSDictionary *)contentAsDictionary { + if (!self.cachedPlistContents) { + NSString *path = [self plistPathInDirectory]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + self.cachedPlistContents = [[NSDictionary alloc] initWithContentsOfFile:path]; + } + } + return self.cachedPlistContents; +} + +- (BOOL)doesFileExist { + NSString *path = [self plistPathInDirectory]; + return [[NSFileManager defaultManager] fileExistsAtPath:path]; +} + +#pragma mark - Private + +- (NSString *)plistPathInDirectory { + NSArray *directoryPaths; + NSString *plistNameWithExtension = [NSString stringWithFormat:@"%@.plist", self.fileName]; + directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSArray *components = @[ directoryPaths.lastObject, _subDirectoryName, plistNameWithExtension ]; + + return [NSString pathWithComponents:components]; +} + +- (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h new file mode 100644 index 00000000..d2f286d7 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <FirebaseInstanceID/FIRInstanceIDCheckinPreferences.h> + +@interface FIRInstanceIDCheckinPreferences (Internal) + +/** + * Parse the checkin auth credentials saved in the Keychain to initialize checkin + * preferences. + * + * @param keychainContent The checkin auth credentials saved in the Keychain. + * + * @return A valid checkin preferences object if the checkin auth credentials in the + * keychain can be parsed successfully else nil. + */ ++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent; + +/** + * Default initializer for InstanceID checkin preferences. + * + * @param deviceID The deviceID for the app. + * @param secretToken The secret token the app uses to authenticate with the server. + * + * @return A checkin preferences object with given deviceID and secretToken. + */ +- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken; + +/** + * Update checkin preferences from the preferences dict persisted as a plist. The dict contains + * all the checkin preferences retrieved from the server except the deviceID and secret which + * are stored in the Keychain. + * + * @param checkinPlistContent The checkin preferences saved in a plist on the disk. + */ +- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent; + +/** + * Reset the current checkin preferences object. + */ +- (void)reset; + +/** + * The string that contains the checkin auth credentials i.e. deviceID and secret. This + * needs to be stored in the Keychain. + * + * @return The checkin auth credential string containing the deviceID and secret. + */ +- (NSString *)checkinKeychainContent; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m new file mode 100644 index 00000000..88cc40a1 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m @@ -0,0 +1,112 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences+Internal.h" + +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDUtilities.h" + +static NSString *const kCheckinKeychainContentSeparatorString = @"|"; + +@interface FIRInstanceIDCheckinPreferences () + +@property(nonatomic, readwrite, copy) NSString *deviceID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, copy) NSString *digest; +@property(nonatomic, readwrite, copy) NSString *versionInfo; +@property(nonatomic, readwrite, copy) NSString *deviceDataVersion; + +@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis; + +@end + +@implementation FIRInstanceIDCheckinPreferences (Internal) + ++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent { + NSString *deviceID = [self checkinDeviceIDFromKeychainContent:keychainContent]; + NSString *secret = [self checkinSecretFromKeychainContent:keychainContent]; + if ([deviceID length] && [secret length]) { + return [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceID secretToken:secret]; + } else { + return nil; + } +} + +- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken { + self = [super init]; + if (self) { + self.deviceID = [deviceID copy]; + self.secretToken = [secretToken copy]; + } + return self; +} + +- (void)reset { + self.deviceID = nil; + self.secretToken = nil; + self.digest = nil; + self.versionInfo = nil; + self.gServicesData = nil; + self.deviceDataVersion = nil; + self.lastCheckinTimestampMillis = 0; +} + +- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent { + for (NSString *key in checkinPlistContent) { + if ([kFIRInstanceIDDigestStringKey isEqualToString:key]) { + self.digest = [checkinPlistContent[key] copy]; + } else if ([kFIRInstanceIDVersionInfoStringKey isEqualToString:key]) { + self.versionInfo = [checkinPlistContent[key] copy]; + } else if ([kFIRInstanceIDLastCheckinTimeKey isEqualToString:key]) { + self.lastCheckinTimestampMillis = [checkinPlistContent[key] longLongValue]; + } else if ([kFIRInstanceIDGServicesDictionaryKey isEqualToString:key]) { + self.gServicesData = [checkinPlistContent[key] mutableCopy]; + } else if ([kFIRInstanceIDDeviceDataVersionKey isEqualToString:key]) { + self.deviceDataVersion = [checkinPlistContent[key] copy]; + } + // Otherwise we have some keys we don't care about + } +} + +- (NSString *)checkinKeychainContent { + if ([self.deviceID length] && [self.secretToken length]) { + return [NSString stringWithFormat:@"%@%@%@", self.deviceID, + kCheckinKeychainContentSeparatorString, self.secretToken]; + } else { + return nil; + } +} + ++ (NSString *)checkinDeviceIDFromKeychainContent:(NSString *)keychainContent { + return [self checkinKeychainContent:keychainContent forIndex:0]; +} + ++ (NSString *)checkinSecretFromKeychainContent:(NSString *)keychainContent { + return [self checkinKeychainContent:keychainContent forIndex:1]; +} + ++ (NSString *)checkinKeychainContent:(NSString *)keychainContent forIndex:(int)index { + NSArray *keychainComponents = + [keychainContent componentsSeparatedByString:kCheckinKeychainContentSeparatorString]; + if (index >= 0 && index < 2 && [keychainComponents count] == 2) { + return keychainComponents[index]; + } else { + return nil; + } +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m new file mode 100644 index 00000000..965f4641 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences.h" + +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDUtilities.h" +#import "GoogleUtilities/UserDefaults/Private/GULUserDefaults.h" + +const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval = 7 * 24 * 60 * 60; // 7 days. + +@interface FIRInstanceIDCheckinPreferences () + +@property(nonatomic, readwrite, copy) NSString *deviceID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, copy) NSString *digest; +@property(nonatomic, readwrite, copy) NSString *versionInfo; +@property(nonatomic, readwrite, copy) NSString *deviceDataVersion; + +@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis; + +// This flag indicates that we have already saved the above deviceID and secret +// to our keychain and hence we don't need to save again. This is helpful since +// on checkin refresh we can avoid writing to the Keychain which can sometimes +// be very buggy. For info check this https://forums.developer.apple.com/thread/4743 +@property(nonatomic, readwrite, assign) BOOL hasPreCachedAuthCredentials; + +@end + +@implementation FIRInstanceIDCheckinPreferences + +- (NSDictionary *)checkinPlistContents { + NSMutableDictionary *checkinPlistContents = [NSMutableDictionary dictionary]; + checkinPlistContents[kFIRInstanceIDDigestStringKey] = self.digest ?: @""; + checkinPlistContents[kFIRInstanceIDVersionInfoStringKey] = self.versionInfo ?: @""; + checkinPlistContents[kFIRInstanceIDDeviceDataVersionKey] = self.deviceDataVersion ?: @""; + checkinPlistContents[kFIRInstanceIDLastCheckinTimeKey] = @(self.lastCheckinTimestampMillis); + checkinPlistContents[kFIRInstanceIDGServicesDictionaryKey] = + [self.gServicesData count] ? self.gServicesData : @{}; + return checkinPlistContents; +} + +- (BOOL)hasCheckinInfo { + return (self.deviceID.length && self.secretToken.length); +} + +- (BOOL)hasValidCheckinInfo { + int64_t currentTimestampInMillis = FIRInstanceIDCurrentTimestampInMilliseconds(); + int64_t timeSinceLastCheckinInMillis = currentTimestampInMillis - self.lastCheckinTimestampMillis; + + BOOL hasCheckinInfo = [self hasCheckinInfo]; + NSString *lastLocale = + [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale]; + // If it's app's first time open and checkin is already fetched and no locale information is + // stored, then checkin info is valid. We should not checkin again because locale is considered + // "changed". + if (hasCheckinInfo && !lastLocale) { + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + [[GULUserDefaults standardUserDefaults] setObject:currentLocale + forKey:kFIRInstanceIDUserDefaultsKeyLocale]; + return YES; + } + + // If locale has changed, checkin info is no longer valid. + // Also update locale information if changed. (Only do it here not in token refresh) + if (FIRInstanceIDHasLocaleChanged()) { + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + [[GULUserDefaults standardUserDefaults] setObject:currentLocale + forKey:kFIRInstanceIDUserDefaultsKeyLocale]; + return NO; + } + + return (hasCheckinInfo && + (timeSinceLastCheckinInMillis / 1000.0 < kFIRInstanceIDDefaultCheckinInterval)); +} + +- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials { + _hasPreCachedAuthCredentials = hasPreCachedAuthCredentials; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h new file mode 100644 index 00000000..9c5850ba --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <FirebaseInstanceID/FIRInstanceIDCheckinPreferences.h> + +/** Checkin refresh interval. **/ +FOUNDATION_EXPORT const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval; + +@interface FIRInstanceIDCheckinPreferences () + +- (BOOL)hasPreCachedAuthCredentials; +- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h new file mode 100644 index 00000000..e14b51cb --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h @@ -0,0 +1,68 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#import <FirebaseInstanceID/FIRInstanceID+Private.h> +#import "FIRInstanceIDUtilities.h" + +NS_ASSUME_NONNULL_BEGIN + +// keys in Checkin preferences +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceAuthIdKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDSecretTokenKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDigestStringKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDLastCheckinTimeKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDVersionInfoStringKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDGServicesDictionaryKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceDataVersionKey; + +@class FIRInstanceIDCheckinPreferences; + +/** + * Register the device with Checkin Service and get back the `authID`, `secret + * token` etc. for the client. Checkin results are cached in the + * `FIRInstanceIDCache` and periodically refreshed to prevent them from being stale. + * Each client needs to register with checkin before registering with InstanceID. + */ +@interface FIRInstanceIDCheckinService : NSObject + +/** + * Execute a device checkin request to obtain an deviceID, secret token, + * gService data. + * + * @param existingCheckin An existing checkin preference object, if available. + * @param completion Completion hander called on success or failure of device checkin. + */ +- (void)checkinWithExistingCheckin:(nullable FIRInstanceIDCheckinPreferences *)existingCheckin + completion:(FIRInstanceIDDeviceCheckinCompletion)completion; + +/** + * This would stop any request that the service made to the checkin backend and also + * release any callback handlers that it holds. + */ +- (void)stopFetching; + +/** + * Set test block for mock testing network requests. + * + * @param block The block to invoke as a mock response from the network. + */ ++ (void)setCheckinTestBlock:(nullable FIRInstanceIDURLRequestTestBlock)block; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m new file mode 100644 index 00000000..d3ace54e --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m @@ -0,0 +1,242 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinService.h" + +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +static NSString *const kDeviceCheckinURL = @"https://device-provisioning.googleapis.com/checkin"; + +// keys in Checkin preferences +NSString *const kFIRInstanceIDDeviceAuthIdKey = @"GMSInstanceIDDeviceAuthIdKey"; +NSString *const kFIRInstanceIDSecretTokenKey = @"GMSInstanceIDSecretTokenKey"; +NSString *const kFIRInstanceIDDigestStringKey = @"GMSInstanceIDDigestKey"; +NSString *const kFIRInstanceIDLastCheckinTimeKey = @"GMSInstanceIDLastCheckinTimestampKey"; +NSString *const kFIRInstanceIDVersionInfoStringKey = @"GMSInstanceIDVersionInfo"; +NSString *const kFIRInstanceIDGServicesDictionaryKey = @"GMSInstanceIDGServicesData"; +NSString *const kFIRInstanceIDDeviceDataVersionKey = @"GMSInstanceIDDeviceDataVersion"; + +static NSUInteger const kCheckinType = 2; // DeviceType IOS in l/w/a/_checkin.proto +static NSUInteger const kCheckinVersion = 2; +static NSUInteger const kFragment = 0; + +static FIRInstanceIDURLRequestTestBlock testBlock; + +@interface FIRInstanceIDCheckinService () + +@property(nonatomic, readwrite, strong) NSURLSession *session; + +@end + +@implementation FIRInstanceIDCheckinService +; + +- (instancetype)init { + self = [super init]; + if (self) { + // Create an URLSession once, even though checkin should happen about once a day + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + config.allowsCellularAccess = YES; + _session = [NSURLSession sessionWithConfiguration:config]; + _session.sessionDescription = @"com.google.iid-checkin"; + } + return self; +} + +- (void)dealloc { + testBlock = nil; + [self.session invalidateAndCancel]; +} + +- (void)checkinWithExistingCheckin:(FIRInstanceIDCheckinPreferences *)existingCheckin + completion:(FIRInstanceIDDeviceCheckinCompletion)completion { + if (self.session == nil) { + FIRInstanceIDLoggerError(kFIRInstanceIDInvalidNetworkSession, + @"Inconsistent state: NSURLSession has been invalidated"); + NSError *error = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]; + if (completion) { + completion(nil, error); + } + return; + } + + NSURL *url = [NSURL URLWithString:kDeviceCheckinURL]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + [request setValue:@"application/json" forHTTPHeaderField:@"content-type"]; + NSDictionary *checkinParameters = [self checkinParametersWithExistingCheckin:existingCheckin]; + NSData *checkinData = [NSJSONSerialization dataWithJSONObject:checkinParameters + options:0 + error:nil]; + request.HTTPMethod = @"POST"; + request.HTTPBody = checkinData; + + void (^handler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService000, + @"Device checkin HTTP fetch error. Error Code: %ld", + (long)error.code); + if (completion) { + completion(nil, error); + } + return; + } + + NSError *serializationError; + NSDictionary *dataResponse = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&serializationError]; + if (serializationError) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService001, + @"Error serializing json object. Error Code: %ld", + _FIRInstanceID_L(serializationError.code)); + if (completion) { + completion(nil, serializationError); + } + return; + } + + NSString *deviceAuthID = [dataResponse[@"android_id"] stringValue]; + NSString *secretToken = [dataResponse[@"security_token"] stringValue]; + if ([deviceAuthID length] == 0) { + NSError *error = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidRequest]; + if (completion) { + completion(nil, error); + } + return; + } + + int64_t lastCheckinTimestampMillis = [dataResponse[@"time_msec"] longLongValue]; + int64_t currentTimestampMillis = FIRInstanceIDCurrentTimestampInMilliseconds(); + // Somehow the server clock gets out of sync with the device clock. + // Reset the last checkin timestamp in case this happens. + if (lastCheckinTimestampMillis > currentTimestampMillis) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeService002, @"Invalid last checkin timestamp %@ in future.", + [NSDate dateWithTimeIntervalSince1970:lastCheckinTimestampMillis / 1000.0]); + lastCheckinTimestampMillis = currentTimestampMillis; + } + + NSString *deviceDataVersionInfo = dataResponse[@"device_data_version_info"] ?: @""; + NSString *digest = dataResponse[@"digest"] ?: @""; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService003, + @"Checkin successful with authId: %@, " + @"digest: %@, " + @"lastCheckinTimestamp: %lld", + deviceAuthID, digest, lastCheckinTimestampMillis); + + NSString *versionInfo = dataResponse[@"version_info"] ?: @""; + NSMutableDictionary *gservicesData = [NSMutableDictionary dictionary]; + + // Read gServices data. + NSArray *flatSettings = dataResponse[@"setting"]; + for (NSDictionary *dict in flatSettings) { + if (dict[@"name"] && dict[@"value"]) { + gservicesData[dict[@"name"]] = dict[@"value"]; + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDInvalidSettingResponse, + @"Invalid setting in checkin response: (%@: %@)", + dict[@"name"], dict[@"value"]); + } + } + + FIRInstanceIDCheckinPreferences *checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceAuthID + secretToken:secretToken]; + NSDictionary *preferences = @{ + kFIRInstanceIDDigestStringKey : digest, + kFIRInstanceIDVersionInfoStringKey : versionInfo, + kFIRInstanceIDLastCheckinTimeKey : @(lastCheckinTimestampMillis), + kFIRInstanceIDGServicesDictionaryKey : gservicesData, + kFIRInstanceIDDeviceDataVersionKey : deviceDataVersionInfo, + }; + [checkinPreferences updateWithCheckinPlistContents:preferences]; + if (completion) { + completion(checkinPreferences, nil); + } + }; + // Test block + if (testBlock) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService005, + @"Test block set, will not hit the server"); + testBlock(request, handler); + return; + } + + NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:handler]; + [task resume]; +} + +- (void)stopFetching { + [self.session invalidateAndCancel]; + // The session cannot be reused after invalidation. Dispose it to prevent accident reusing. + self.session = nil; +} + +#pragma mark - Private + +- (NSDictionary *)checkinParametersWithExistingCheckin: + (nullable FIRInstanceIDCheckinPreferences *)checkinPreferences { + NSString *deviceModel = FIRInstanceIDDeviceModel(); + NSString *systemVersion = FIRInstanceIDOperatingSystemVersion(); + NSString *osVersion = [NSString stringWithFormat:@"IOS_%@", systemVersion]; + + // Get locale from GCM if GCM exists else use system API. + NSString *locale = FIRInstanceIDCurrentLocale(); + + NSInteger userNumber = 0; // Multi Profile may change this. + NSInteger userSerialNumber = 0; // Multi Profile may change this + + NSString *timeZone = [NSTimeZone localTimeZone].name; + int64_t lastCheckingTimestampMillis = checkinPreferences.lastCheckinTimestampMillis; + + NSDictionary *checkinParameters = @{ + @"checkin" : @{ + @"iosbuild" : @{@"model" : deviceModel, @"os_version" : osVersion}, + @"type" : @(kCheckinType), + @"user_number" : @(userNumber), + @"last_checkin_msec" : @(lastCheckingTimestampMillis), + }, + @"fragment" : @(kFragment), + @"locale" : locale, + @"version" : @(kCheckinVersion), + @"digest" : checkinPreferences.digest ?: @"", + @"time_zone" : timeZone, + @"user_serial_number" : @(userSerialNumber), + @"id" : @([checkinPreferences.deviceID longLongValue]), + @"security_token" : @([checkinPreferences.secretToken longLongValue]), + }; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService006, @"Checkin parameters: %@", + checkinParameters); + return checkinParameters; +} + ++ (void)setCheckinTestBlock:(FIRInstanceIDURLRequestTestBlock)block { + testBlock = [block copy]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h new file mode 100644 index 00000000..a7307a7d --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h @@ -0,0 +1,96 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@class FIRInstanceIDAuthKeychain; +@class FIRInstanceIDBackupExcludedPlist; +@class FIRInstanceIDCheckinPreferences; + +// These values exposed for testing +extern NSString *const kFIRInstanceIDCheckinKeychainService; + +/** + * Checkin preferences backing store. + */ +@interface FIRInstanceIDCheckinStore : NSObject + +/** + * Designated Initializer. Initialize a checkin store with the given backup excluded + * plist filename. + * + * @param checkinFilename The backup excluded plist filename to persist checkin + * preferences. + * + * @param subDirectoryName Sub-directory in standard directory where we write + * InstanceID plist. + * + * @return Store to persist checkin preferences. + */ +- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename + subDirectoryName:(NSString *)subDirectoryName; + +/** + * Initialize a checkin store with the given backup excluded plist and keychain. + * + * @param plist The backup excluded plist to persist checkin preferences. + * @param keychain The keychain used to persist checkin auth preferences. + * + * @return Store to persist checkin preferences. + */ +- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist + keychain:(FIRInstanceIDAuthKeychain *)keychain; + +/** + * Checks whether the backup excluded checkin preferences are present on the disk or not. + * + * @return YES if the backup excluded checkin plist exists on the disks else NO. + */ +- (BOOL)hasCheckinPlist; + +#pragma mark - Save + +/** + * Save the checkin preferences to backing store. + * + * @param preferences Checkin preferences to save. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler; + +#pragma mark - Delete + +/** + * Remove the cached checkin preferences. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler; + +#pragma mark - Get + +/** + * Get the cached device secret. If we cannot access it for some reason we + * return the appropriate error object. + * + * @return The cached checkin preferences if present else nil. + */ +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m new file mode 100644 index 00000000..b3bd3535 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m @@ -0,0 +1,194 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinStore.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDBackupExcludedPlist.h" +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" +#import "FIRInstanceIDVersionUtilities.h" +#import "NSError+FIRInstanceID.h" + +static NSString *const kFIRInstanceIDCheckinKeychainGeneric = @"com.google.iid"; + +NSString *const kFIRInstanceIDCheckinKeychainService = @"com.google.iid.checkin"; + +@interface FIRInstanceIDCheckinStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *plist; +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain; +// Checkin will store items under +// Keychain account: <app bundle id>, +// Keychain service: |kFIRInstanceIDCheckinKeychainService| +@property(nonatomic, readonly) NSString *bundleIdentifierForKeychainAccount; + +@end + +@implementation FIRInstanceIDCheckinStore + +- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename + subDirectoryName:(NSString *)subDirectoryName { + FIRInstanceIDBackupExcludedPlist *plist = + [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:checkinFilename + subDirectory:subDirectoryName]; + + FIRInstanceIDAuthKeychain *keychain = + [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDCheckinKeychainGeneric]; + return [self initWithCheckinPlist:plist keychain:keychain]; +} + +- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist + keychain:(FIRInstanceIDAuthKeychain *)keychain { + self = [super init]; + if (self) { + _plist = plist; + _keychain = keychain; + } + return self; +} + +- (BOOL)hasCheckinPlist { + return [self.plist doesFileExist]; +} + +- (NSString *)bundleIdentifierForKeychainAccount { + static NSString *bundleIdentifier; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + bundleIdentifier = FIRInstanceIDAppIdentifier(); + }); + return bundleIdentifier; +} + +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler { + NSDictionary *checkinPlistContents = [preferences checkinPlistContents]; + NSString *checkinKeychainContent = [preferences checkinKeychainContent]; + + if (![checkinKeychainContent length]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore000, + @"Failed to get checkin keychain content from memory."); + if (handler) { + handler([NSError + errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]); + } + return; + } + if (![checkinPlistContents count]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore001, + @"Failed to get checkin plist contents from memory."); + if (handler) { + handler([NSError + errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]); + } + return; + } + + // Save all other checkin preferences in a plist + NSError *error; + if (![self.plist writeDictionary:checkinPlistContents error:&error]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore003, + @"Failed to save checkin plist contents." + @"Will delete auth credentials"); + [self.keychain removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:nil]; + if (handler) { + handler(error); + } + return; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved, + @"Checkin plist file is saved"); + + // Save the deviceID and secret in the Keychain + if (!preferences.hasPreCachedAuthCredentials) { + NSData *data = [checkinKeychainContent dataUsingEncoding:NSUTF8StringEncoding]; + [self.keychain setData:data + forService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (handler) { + handler(nil); + } + }]; + } else { + handler(nil); + } +} + +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler { + // Delete the checkin preferences plist first to avoid delay. + NSError *deletePlistError; + if (![self.plist deleteFile:&deletePlistError]) { + handler(deletePlistError); + return; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted, + @"Deleted checkin plist file."); + // Remove deviceID and secret from Keychain + [self.keychain removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:^(NSError *error) { + handler(error); + }]; +} + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + // Query the keychain for deviceID and secret + NSData *item = [self.keychain dataForService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount]; + + // Check info found in keychain + NSString *checkinKeychainContent = [[NSString alloc] initWithData:item + encoding:NSUTF8StringEncoding]; + FIRInstanceIDCheckinPreferences *checkinPreferences = + [FIRInstanceIDCheckinPreferences preferencesFromKeychainContents:checkinKeychainContent]; + + NSDictionary *checkinPlistContents = [self.plist contentAsDictionary]; + + NSString *plistDeviceAuthID = checkinPlistContents[kFIRInstanceIDDeviceAuthIdKey]; + NSString *plistSecretToken = checkinPlistContents[kFIRInstanceIDSecretTokenKey]; + + // If deviceID and secret not found in the keychain verify that we don't have them in the + // checkin preferences plist. + if (![checkinPreferences.deviceID length] && ![checkinPreferences.secretToken length]) { + if ([plistDeviceAuthID length] && [plistSecretToken length]) { + // Couldn't find checkin credentials in keychain but found them in the plist. + checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID + secretToken:plistSecretToken]; + } else { + // Couldn't find checkin credentials in keychain nor plist + return nil; + } + } + + [checkinPreferences updateWithCheckinPlistContents:checkinPlistContents]; + return checkinPreferences; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h new file mode 100644 index 00000000..dcb5429b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * A generic class to combine several handler blocks into a single block in a thread-safe manner + */ +@interface FIRInstanceIDCombinedHandler<ResultType> : NSObject + +- (void)addHandler:(void (^)(ResultType _Nullable result, NSError* _Nullable error))handler; +- (void (^)(ResultType _Nullable result, NSError* _Nullable error))combinedHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m new file mode 100644 index 00000000..bc6be6c1 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCombinedHandler.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^FIRInstanseIDHandler)(id _Nullable result, NSError *_Nullable error); + +@interface FIRInstanceIDCombinedHandler <ResultType>() +@property(atomic, readonly, strong) NSMutableArray<FIRInstanseIDHandler> *handlers; +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRInstanceIDCombinedHandler + +- (instancetype)init { + self = [super init]; + if (self) { + _handlers = [NSMutableArray array]; + } + return self; +} + +- (void)addHandler:(FIRInstanseIDHandler)handler { + if (!handler) { + return; + } + + @synchronized(self) { + [self.handlers addObject:handler]; + } +} + +- (FIRInstanseIDHandler)combinedHandler { + FIRInstanseIDHandler combinedHandler = nil; + + @synchronized(self) { + NSArray<FIRInstanseIDHandler> *handlers = [self.handlers copy]; + combinedHandler = ^(id result, NSError *error) { + for (FIRInstanseIDHandler handler in handlers) { + handler(result, error); + } + }; + } + + return combinedHandler; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h new file mode 100644 index 00000000..501039dc --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h @@ -0,0 +1,65 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#pragma mark - Commands + +/** + * Value included in a structured response or GCM message from IID, indicating + * an identity reset. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceID_CMD_RST; + +#pragma mark - Notifications + +/// Notification used to deliver GCM messages for InstanceID. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDCheckinFetchedNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAPNSTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification; + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDIdentityInvalidatedNotification; + +#pragma mark - Miscellaneous + +/// The scope used to save the IID "*" scope token. This is used for saving the +/// IID auth token that we receive from the server. This feature was never +/// implemented on the server side. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAllScopeIdentifier; +/// The scope used to save the IID "*" scope token. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultTokenScope; + +/// Subdirectory in search path directory to store InstanceID preferences. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDSubDirectoryName; + +/// The key for APNS token in options dictionary. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSKey; + +/// The key for APNS token environment type in options dictionary. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey; + +/// The key for GMP AppID sent in registration requests. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey; + +/// The key to enable auto-register by swizzling AppDelegate's methods. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey; + +/// The key for InstallationID or InstanceID in token request. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDParamInstanceID; + +/// Error code for missing entitlements in Keychain. iOS Keychain error +/// https://forums.developer.apple.com/thread/4743 +FOUNDATION_EXPORT const int kFIRInstanceIDSecMissingEntitlementErrorCode; diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m new file mode 100644 index 00000000..5eda1712 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDConstants.h" + +// Commands +NSString *const kFIRInstanceID_CMD_RST = @"RST"; + +// NOTIFICATIONS +NSString *const kFIRInstanceIDCheckinFetchedNotification = @"com.google.gcm.notif-checkin-fetched"; +NSString *const kFIRInstanceIDAPNSTokenNotification = @"com.firebase.iid.notif.apns-token"; +NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification = + @"com.firebase.iid.notif.fcm-token-fail"; + +NSString *const kFIRInstanceIDIdentityInvalidatedNotification = @"com.google.iid.identity-invalid"; + +// Miscellaneous +NSString *const kFIRInstanceIDAllScopeIdentifier = @"iid-all"; +NSString *const kFIRInstanceIDDefaultTokenScope = @"*"; +NSString *const kFIRInstanceIDSubDirectoryName = @"Google/FirebaseInstanceID"; + +// Registration Options +NSString *const kFIRInstanceIDTokenOptionsAPNSKey = @"apns_token"; +NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey = @"apns_sandbox"; +NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey = @"gmp_app_id"; +NSString *const kFIRInstanceIDParamInstanceID = @"appid"; + +NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +// iOS Keychain error https://forums.developer.apple.com/thread/4743 +// An undocumented error code hence need to be redeclared. +const int kFIRInstanceIDSecMissingEntitlementErrorCode = -34018; diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h new file mode 100644 index 00000000..ccc25b3d --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h @@ -0,0 +1,47 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRInstanceIDLib_FIRInstanceIDDefines_h +#define FIRInstanceIDLib_FIRInstanceIDDefines_h + +#define _FIRInstanceID_VERBOSE_LOGGING 1 + +// Verbose Logging +#if (_FIRInstanceID_VERBOSE_LOGGING) +#define FIRInstanceID_DEV_VERBOSE_LOG(...) NSLog(__VA_ARGS__) +#else +#define FIRInstanceID_DEV_VERBOSE_LOG(...) \ + do { \ + } while (0) +#endif // VERBOSE_LOGGING + +// WEAKIFY & STRONGIFY +// Helper macro. +#define _FIRInstanceID_WEAKNAME(VAR) VAR##_weak_ + +#define FIRInstanceID_WEAKIFY(VAR) __weak __typeof__(VAR) _FIRInstanceID_WEAKNAME(VAR) = (VAR); + +#define FIRInstanceID_STRONGIFY(VAR) \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\"") \ + __strong __typeof__(VAR) VAR = _FIRInstanceID_WEAKNAME(VAR); \ + _Pragma("clang diagnostic pop") + +// Type Conversions (used for NSInteger etc) +#ifndef _FIRInstanceID_L +#define _FIRInstanceID_L(v) (long)(v) +#endif + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h new file mode 100644 index 00000000..1c80d8e3 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +/* The Keychain error domain */ +extern NSString *const kFIRInstanceIDKeychainErrorDomain; + +/* + * Wrapping the keychain operations in a serialize queue. This is to avoid keychain operation + * blocking main queue. + */ +@interface FIRInstanceIDKeychain : NSObject + +/** + * FIRInstanceIDKeychain. + * + * @return A shared instance of FIRInstanceIDKeychain. + */ ++ (instancetype)sharedInstance; + +/** + * Get keychain items matching the given a query. + * + * @param keychainQuery The keychain query. + * + * @return An CFTypeRef result matching the provided inputs. + */ +- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery; + +/** + * Remove the cached items from the keychain matching the query. + * + * @param keychainQuery The keychain query. + * @param handler The callback handler which is invoked when the remove operation is + * complete, with an error if there is any. + */ +- (void)removeItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *error))handler; + +/** + * Add the item with a given query. + * + * @param keychainQuery The keychain query. + * @param handler The callback handler which is invoked when the add operation is + * complete, with an error if there is any. + */ +- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m new file mode 100644 index 00000000..df1b4f76 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m @@ -0,0 +1,114 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeychain.h" + +#import "FIRInstanceIDLogger.h" + +NSString *const kFIRInstanceIDKeychainErrorDomain = @"com.google.iid"; + +@interface FIRInstanceIDKeychain () { + dispatch_queue_t _keychainOperationQueue; +} + +@end + +@implementation FIRInstanceIDKeychain + ++ (instancetype)sharedInstance { + static FIRInstanceIDKeychain *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRInstanceIDKeychain alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _keychainOperationQueue = + dispatch_queue_create("com.google.FirebaseInstanceID.Keychain", DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery { + __block SecKeyRef keyRef = NULL; + dispatch_sync(_keychainOperationQueue, ^{ + OSStatus status = + SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyRef); + + if (status != noErr) { + if (keyRef) { + CFRelease(keyRef); + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDKeychainReadItemError, + @"Info is not found in Keychain. OSStatus: %d. Keychain query: %@", + (int)status, keychainQuery); + } + }); + return keyRef; +} + +- (void)removeItemWithQuery:(NSDictionary *)keychainQuery + handler:(void (^)(NSError *error))handler { + dispatch_async(_keychainOperationQueue, ^{ + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)keychainQuery); + if (status != noErr) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDKeychainDeleteItemError, + @"Couldn't delete item from Keychain OSStatus: %d with the keychain query %@", + (int)status, keychainQuery); + } + + if (handler) { + NSError *error; + // When item is not found, it should NOT be considered as an error. The operation should + // continue. + if (status != noErr && status != errSecItemNotFound) { + error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:status + userInfo:nil]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }); +} + +- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler { + dispatch_async(_keychainOperationQueue, ^{ + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL); + + if (handler) { + NSError *error; + if (status != noErr) { + FIRInstanceIDLoggerWarning(kFIRInstanceIDKeychainAddItemError, + @"Couldn't add item to Keychain OSStatus: %d", (int)status); + error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:status + userInfo:nil]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }); +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h new file mode 100644 index 00000000..ab93976c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h @@ -0,0 +1,66 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRIMessageCode.h" + +// The convenience macros are only defined if they haven't already been defined. +#ifndef FIRInstanceIDLoggerInfo + +// Convenience macros that log to the shared GTMLogger instance. These macros +// are how users should typically log to FIRInstanceIDLogger. +#define FIRInstanceIDLoggerDebug(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncDebug:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerInfo(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncInfo:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerNotice(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncNotice:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerWarning(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncWarning:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerError(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncError:__func__ messageCode:code msg:__VA_ARGS__] + +#endif // !defined(FIRInstanceIDLoggerInfo) + +@interface FIRInstanceIDLogger : NSObject + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncError:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +@end + +/** + * Instantiates and/or returns a shared GTMLogger used exclusively + * for InstanceID log messages. + * @return the shared GTMLogger instance + */ +FIRInstanceIDLogger *FIRInstanceIDSharedLogger(void); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m new file mode 100644 index 00000000..489939da --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m @@ -0,0 +1,92 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDLogger.h" + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +// Re-definition of FIRLogger service, as it is not included in :FIRAppHeaders target +NSString *const kFIRInstanceIDLoggerService = @"[Firebase/InstanceID]"; + +@implementation FIRInstanceIDLogger + +#pragma mark - Log Helpers + ++ (NSString *)formatMessageCode:(FIRInstanceIDMessageCode)messageCode { + return [NSString stringWithFormat:@"I-IID%06ld", (long)messageCode]; +} + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelDebug, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelInfo, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelNotice, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelWarning, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncError:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelError, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +@end + +FIRInstanceIDLogger *FIRInstanceIDSharedLogger() { + static dispatch_once_t onceToken; + static FIRInstanceIDLogger *logger; + dispatch_once(&onceToken, ^{ + logger = [[FIRInstanceIDLogger alloc] init]; + }); + + return logger; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h new file mode 100644 index 00000000..d1f26348 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h @@ -0,0 +1,183 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDBackupExcludedPlist; +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDCheckinStore; +@class FIRInstanceIDTokenInfo; +@class FIRInstanceIDTokenStore; + +@class FIRInstanceIDStore; +@protocol FIRInstanceIDStoreDelegate <NSObject> + +/** + * This is called when the store has decided to invalide its tokens associated with the + * previous checkin credentials. After deleting the tokens locally, it calls this method + * to notify the delegate of the change. If possible, the delegate should use this time + * to request the invalidation of the tokens on the server as well. + */ +- (void)store:(FIRInstanceIDStore *)store + didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin; + +@end + +/** + * Used to persist the InstanceID tokens. This is also used to cache the Checkin + * credentials. The store also checks for stale entries in the store and + * let's us know if things in the store are stale or not. It does not however + * acts on stale entries in anyway. + */ +@interface FIRInstanceIDStore : NSObject + +/** + * The delegate set in the initializer which is notified of changes in the store. + */ +@property(nonatomic, readonly, weak) NSObject<FIRInstanceIDStoreDelegate> *delegate; + +- (instancetype)init __attribute__((unavailable("Use initWithDelegate: instead."))); + +/** + * Initialize a default store to persist InstanceID tokens and options. + * + * @param delegate The delegate with which to be notified of changes in the store. + * @return Store to persist InstanceID tokens. + */ +- (instancetype)initWithDelegate:(NSObject<FIRInstanceIDStoreDelegate> *)delegate; + +/** + * Initialize a store with the token store used to persist tokens, and a checkin store. + * Used for testing. + * + * @param checkinStore Persistent store that persists checkin preferences. + * @param tokenStore Persistent store that persists tokens. + * + * @return Store to persist InstanceID tokens and options. + */ +- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore + tokenStore:(FIRInstanceIDTokenStore *)tokenStore + delegate:(NSObject<FIRInstanceIDStoreDelegate> *)delegate + NS_DESIGNATED_INITIALIZER; + +#pragma mark - Save +/** + * Save the instanceID token info to the store. + * + * @param tokenInfo The token info to store. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo handler:(void (^)(NSError *))handler; + +#pragma mark - Get + +/** + * Get the cached token info. + * + * @param authorizedEntity The authorized entity for which we want the token. + * @param scope The scope for which we want the token. + * + * @return The cached token info if any for the given authorizedEntity and scope else + * returns nil. + */ +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; +/** + * Return all cached token infos from the Keychain. + * + * @return The cached token infos, if any, that are stored in the Keychain. + */ +- (NSArray<FIRInstanceIDTokenInfo *> *)cachedTokenInfos; + +#pragma mark - Delete + +/** + * Remove the cached token for a given authorizedEntity and scope. If the token was never + * cached or deleted from the cache before this is a no-op. + * + * @param authorizedEntity The authorizedEntity for the cached token. + * @param scope The scope for the cached token + */ +- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope; + +/** + * Removes all cached tokens from the persistent store. In case deleting the cached tokens + * fails we try to delete the backup excluded plist that stores the tokens. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + * + */ +- (void)removeAllCachedTokensWithHandler:(nullable void (^)(NSError *error))handler; + +#pragma mark - Persisting Checkin Preferences + +/** + * Save the checkin preferences + * + * @param preferences Checkin preferences to save. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(nullable void (^)(NSError *error))handler; + +/** + * Return the cached checkin preferences. + * + * @return Checkin preferences. + */ +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Remove the cached checkin preferences from the store. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)removeCheckinPreferencesWithHandler:(nullable void (^)(NSError *error))handler; + +#pragma mark - Standard Directory sub-directory + +/** + * Check if supported directory has InstanceID subdirectory + * + * @return YES if the Application Support directory has InstanceID subdirectory else NO. + */ ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName; + +/** + * Create InstanceID subdirectory in Application support directory. + * + * @return YES if the subdirectory was created successfully else NO. + */ ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName; + +/** + * Removes Application Support subdirectory for InstanceID. + * + * @param error The error object if any while trying to delete the sub-directory. + * + * @return YES if the deletion was successful else NO. + */ ++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m new file mode 100644 index 00000000..ba68f968 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m @@ -0,0 +1,240 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDStore.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCheckinStore.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenStore.h" +#import "FIRInstanceIDVersionUtilities.h" + +// NOTE: These values should be in sync with what InstanceID saves in as. +static NSString *const kCheckinFileName = @"g-checkin"; + +// APNS token (use the old key value i.e. with prefix GMS) +static NSString *const kFIRInstanceIDLibraryVersion = @"GMSInstanceID-version"; + +@interface FIRInstanceIDStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinStore *checkinStore; +@property(nonatomic, readwrite, strong) FIRInstanceIDTokenStore *tokenStore; + +@end + +@implementation FIRInstanceIDStore + +- (instancetype)initWithDelegate:(NSObject<FIRInstanceIDStoreDelegate> *)delegate { + FIRInstanceIDCheckinStore *checkinStore = [[FIRInstanceIDCheckinStore alloc] + initWithCheckinPlistFileName:kCheckinFileName + subDirectoryName:kFIRInstanceIDSubDirectoryName]; + + FIRInstanceIDTokenStore *tokenStore = [FIRInstanceIDTokenStore defaultStore]; + + return [self initWithCheckinStore:checkinStore tokenStore:tokenStore delegate:delegate]; +} + +- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore + tokenStore:(FIRInstanceIDTokenStore *)tokenStore + delegate:(NSObject<FIRInstanceIDStoreDelegate> *)delegate { + self = [super init]; + if (self) { + _checkinStore = checkinStore; + _tokenStore = tokenStore; + _delegate = delegate; + [self resetCredentialsIfNeeded]; + } + return self; +} + +#pragma mark - Upgrades + ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL isDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return NO; + } else if (!isDirectory) { + return NO; + } + return YES; +} + ++ (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + ++ (NSString *)pathForSupportSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSString *dirPath = directoryPaths.lastObject; + NSArray *components = @[ dirPath, subDirectoryName ]; + return [NSString pathWithComponents:components]; +} + ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL hasSubDirectory; + + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:subDirectoryPath + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore000, + @"Cannot create directory %@, error: %@", subDirectoryPath, error); + return NO; + } + } else { + if (!hasSubDirectory) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore001, + @"Found file instead of directory at %@", subDirectoryPath); + return NO; + } + } + return YES; +} + ++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error { + if ([self hasSubDirectory:subDirectoryName]) { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL isDirectory; + if ([[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return [[NSFileManager defaultManager] removeItemAtPath:subDirectoryPath error:error]; + } + } + return YES; +} + +/** + * Reset the keychain preferences if the app had been deleted earlier and then reinstalled. + * Keychain preferences are not cleared in the above scenario so explicitly clear them. + * + * In case of an iCloud backup and restore the Keychain preferences should already be empty + * since the Keychain items are marked with `*BackupThisDeviceOnly`. + */ +- (void)resetCredentialsIfNeeded { + BOOL checkinPlistExists = [self.checkinStore hasCheckinPlist]; + // Checkin info existed in backup excluded plist. Should not be a fresh install. + if (checkinPlistExists) { + return; + } + + // Resets checkin in keychain if a fresh install. + // Keychain can still exist even if app is uninstalled. + FIRInstanceIDCheckinPreferences *oldCheckinPreferences = + [self.checkinStore cachedCheckinPreferences]; + + if (oldCheckinPreferences) { + [self.checkinStore removeCheckinPreferencesWithHandler:^(NSError *error) { + if (!error) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeStore002, + @"Removed cached checkin preferences from Keychain because this is a fresh install."); + } else { + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeStore003, + @"Couldn't remove cached checkin preferences for a fresh install. Error: %@", error); + } + if (oldCheckinPreferences.deviceID.length && oldCheckinPreferences.secretToken.length) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeStore006, + @"App reset detected. Will delete server registrations."); + // We don't really need to delete old FCM tokens created via IID auth tokens since + // those tokens are already hashed by APNS token as the has so creating a new + // token should automatically delete the old-token. + [self.delegate store:self didDeleteFCMScopedTokensForCheckin:oldCheckinPreferences]; + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeStore009, + @"App reset detected but no valid checkin auth preferences found." + @" Will not delete server registrations."); + } + }]; + } +} + +#pragma mark - Get + +- (FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + // TODO(chliangGoogle): If we don't have the token plist we should delete all the tokens from + // the keychain. This is because not having the plist signifies a backup and restore operation. + // In case the keychain has any tokens these would now be stale and therefore should be + // deleted. + if (![authorizedEntity length] || ![scope length]) { + return nil; + } + FIRInstanceIDTokenInfo *info = [self.tokenStore tokenInfoWithAuthorizedEntity:authorizedEntity + scope:scope]; + return info; +} + +- (NSArray<FIRInstanceIDTokenInfo *> *)cachedTokenInfos { + return [self.tokenStore cachedTokenInfos]; +} + +#pragma mark - Save + +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(void (^)(NSError *error))handler { + [self.tokenStore saveTokenInfo:tokenInfo handler:handler]; +} + +#pragma mark - Delete + +- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + if (![authorizedEntity length] || ![scope length]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore012, + @"Will not delete token with invalid entity: %@, scope: %@", + authorizedEntity, scope); + return; + } + [self.tokenStore removeTokenWithAuthorizedEntity:authorizedEntity scope:scope]; +} + +- (void)removeAllCachedTokensWithHandler:(void (^)(NSError *error))handler { + [self.tokenStore removeAllTokensWithHandler:handler]; +} + +#pragma mark - FIRInstanceIDCheckinCache protocol + +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler { + [self.checkinStore saveCheckinPreferences:preferences handler:handler]; +} + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + return [self.checkinStore cachedCheckinPreferences]; +} + +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *))handler { + [self.checkinStore removeCheckinPreferencesWithHandler:^(NSError *error) { + if (handler) { + handler(error); + } + }]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h new file mode 100644 index 00000000..b6723fda --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstanceIDTokenDeleteOperation : FIRInstanceIDTokenOperation + +- (instancetype)initWithAuthorizedEntity:(nullable NSString *)authorizedEntity + scope:(nullable NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(nullable NSString *)instanceID + action:(FIRInstanceIDTokenAction)action; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m new file mode 100644 index 00000000..64039091 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m @@ -0,0 +1,119 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenDeleteOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenOperation+Private.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +@implementation FIRInstanceIDTokenDeleteOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID + action:(FIRInstanceIDTokenAction)action { + self = [super initWithAction:action + forAuthorizedEntity:authorizedEntity + scope:scope + options:nil + checkinPreferences:checkinPreferences + instanceID:instanceID]; + if (self) { + } + return self; +} + +- (void)performTokenOperation { + NSMutableURLRequest *request = [self tokenRequest]; + + // Build form-encoded body + NSString *deviceAuthID = self.checkinPreferences.deviceID; + NSMutableArray<NSURLQueryItem *> *queryItems = + [FIRInstanceIDTokenOperation standardQueryItemsWithDeviceID:deviceAuthID scope:self.scope]; + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"delete" value:@"true"]]; + if (self.action == FIRInstanceIDTokenActionDeleteTokenAndIID) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"iid-operation" value:@"delete"]]; + } + if (self.authorizedEntity) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"sender" value:self.authorizedEntity]]; + } + // Typically we include our public key-signed url items, but in some cases (like deleting all FCM + // tokens), we don't. + if (self.instanceID.length > 0) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:kFIRInstanceIDParamInstanceID + value:self.instanceID]]; + } + + NSURLComponents *components = [[NSURLComponents alloc] init]; + components.queryItems = queryItems; + NSString *content = components.query; + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest, + @"Unregister request to %@ content: %@", FIRInstanceIDRegisterServer(), + content); + + FIRInstanceID_WEAKIFY(self); + void (^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + FIRInstanceID_STRONGIFY(self); + [self handleResponseWithData:data response:response error:error]; + }; + + // Test block + if (self.testBlock) { + self.testBlock(request, requestHandler); + return; + } + + NSURLSession *session = [FIRInstanceIDTokenOperation sharedURLSession]; + self.dataTask = [session dataTaskWithRequest:request completionHandler:requestHandler]; + [self.dataTask resume]; +} + +- (void)handleResponseWithData:(NSData *)data + response:(NSURLResponse *)response + error:(NSError *)error { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError, + @"Device unregister HTTP fetch error. Error code: %ld", + _FIRInstanceID_L(error.code)); + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + + NSString *dataResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (dataResponse.length == 0) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + + if (![dataResponse hasPrefix:@"deleted="] && ![dataResponse hasPrefix:@"token="]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse, + @"Invalid unregister response %@", response); + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + [self finishWithResult:FIRInstanceIDTokenOperationSucceeded token:nil error:nil]; +} +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h new file mode 100644 index 00000000..6fa800ef --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFirebaseUserAgentKey; + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFirebaseHeartbeatKey; + +@interface FIRInstanceIDTokenFetchOperation : FIRInstanceIDTokenOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary<NSString *, NSString *> *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID; + +@end +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m new file mode 100644 index 00000000..96ac2793 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m @@ -0,0 +1,207 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenFetchOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenOperation+Private.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +// We can have a static int since this error should theoretically only +// happen once (for the first time). If it repeats there is something +// else that is wrong. +static int phoneRegistrationErrorRetryCount = 0; +static const int kMaxPhoneRegistrationErrorRetryCount = 10; +NSString *const kFIRInstanceIDFirebaseUserAgentKey = @"X-firebase-client"; +NSString *const kFIRInstanceIDFirebaseHeartbeatKey = @"X-firebase-client-log-type"; +NSString *const kFIRInstanceIDHeartbeatTag = @"fire-iid"; + +@implementation FIRInstanceIDTokenFetchOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary<NSString *, NSString *> *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID { + self = [super initWithAction:FIRInstanceIDTokenActionFetch + forAuthorizedEntity:authorizedEntity + scope:scope + options:options + checkinPreferences:checkinPreferences + instanceID:instanceID]; + if (self) { + } + return self; +} + +- (void)performTokenOperation { + NSMutableURLRequest *request = [self tokenRequest]; + NSString *checkinVersionInfo = self.checkinPreferences.versionInfo; + [request setValue:checkinVersionInfo forHTTPHeaderField:@"info"]; + [request setValue:[FIRApp firebaseUserAgent] + forHTTPHeaderField:kFIRInstanceIDFirebaseUserAgentKey]; + [request setValue:@([FIRHeartbeatInfo heartbeatCodeForTag:kFIRInstanceIDHeartbeatTag]).stringValue + forHTTPHeaderField:kFIRInstanceIDFirebaseHeartbeatKey]; + + // Build form-encoded body + NSString *deviceAuthID = self.checkinPreferences.deviceID; + NSMutableArray<NSURLQueryItem *> *queryItems = + [[self class] standardQueryItemsWithDeviceID:deviceAuthID scope:self.scope]; + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"sender" value:self.authorizedEntity]]; + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"X-subtype" + value:self.authorizedEntity]]; + + if (self.instanceID.length > 0) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:kFIRInstanceIDParamInstanceID + value:self.instanceID]]; + } + // Create query items from passed-in options + id apnsTokenData = self.options[kFIRInstanceIDTokenOptionsAPNSKey]; + id apnsSandboxValue = self.options[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey]; + if ([apnsTokenData isKindOfClass:[NSData class]] && + [apnsSandboxValue isKindOfClass:[NSNumber class]]) { + NSString *APNSString = FIRInstanceIDAPNSTupleStringForTokenAndServerType( + apnsTokenData, ((NSNumber *)apnsSandboxValue).boolValue); + // The name of the query item happens to be the same as the dictionary key + NSURLQueryItem *item = [NSURLQueryItem queryItemWithName:kFIRInstanceIDTokenOptionsAPNSKey + value:APNSString]; + [queryItems addObject:item]; + } + id firebaseAppID = self.options[kFIRInstanceIDTokenOptionsFirebaseAppIDKey]; + if ([firebaseAppID isKindOfClass:[NSString class]]) { + // The name of the query item happens to be the same as the dictionary key + NSURLQueryItem *item = + [NSURLQueryItem queryItemWithName:kFIRInstanceIDTokenOptionsFirebaseAppIDKey + value:(NSString *)firebaseAppID]; + [queryItems addObject:item]; + } + + NSURLComponents *components = [[NSURLComponents alloc] init]; + components.queryItems = queryItems; + NSString *content = components.query; + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest, + @"Register request to %@ content: %@", FIRInstanceIDRegisterServer(), + content); + + FIRInstanceID_WEAKIFY(self); + void (^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + FIRInstanceID_STRONGIFY(self); + [self handleResponseWithData:data response:response error:error]; + }; + + // Test block + if (self.testBlock) { + self.testBlock(request, requestHandler); + return; + } + + NSURLSession *session = [FIRInstanceIDTokenOperation sharedURLSession]; + self.dataTask = [session dataTaskWithRequest:request completionHandler:requestHandler]; + [self.dataTask resume]; +} + +#pragma mark - Request Handling + +- (void)handleResponseWithData:(NSData *)data + response:(NSURLResponse *)response + error:(NSError *)error { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationRequestError, + @"Token fetch HTTP error. Error Code: %ld", (long)error.code); + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + NSString *dataResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + + if (dataResponse.length == 0) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + NSDictionary *parsedResponse = [self parseFetchTokenResponse:dataResponse]; + + if ([parsedResponse[@"token"] length]) { + [self finishWithResult:FIRInstanceIDTokenOperationSucceeded + token:parsedResponse[@"token"] + error:nil]; + return; + } + + NSString *errorValue = parsedResponse[@"Error"]; + NSError *responseError; + if (errorValue.length) { + NSArray *errorComponents = [errorValue componentsSeparatedByString:@":"]; + // HACK (Kansas replication delay), PHONE_REGISTRATION_ERROR on App + // uninstall and reinstall. + if ([errorComponents containsObject:@"PHONE_REGISTRATION_ERROR"]) { + // Encountered issue http://b/27043795 + // Retry register until successful or another error encountered or a + // certain number of tries are over. + + if (phoneRegistrationErrorRetryCount < kMaxPhoneRegistrationErrorRetryCount) { + const int nextRetryInterval = 1 << phoneRegistrationErrorRetryCount; + FIRInstanceID_WEAKIFY(self); + + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, (int64_t)(nextRetryInterval * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRInstanceID_STRONGIFY(self); + phoneRegistrationErrorRetryCount++; + [self performTokenOperation]; + }); + return; + } + } else if ([errorComponents containsObject:kFIRInstanceID_CMD_RST]) { + // Server detected the identity we use is no longer valid. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center postNotificationName:kFIRInstanceIDIdentityInvalidatedNotification object:nil]; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal001, + @"Identity is invalid. Server request identity reset."); + responseError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidIdentity]; + } + } + if (!responseError) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse, + @"Invalid fetch response, expected 'token' or 'Error' key"); + responseError = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + } + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:responseError]; +} + +// expect a response e.g. "token=<reg id>\nGOOG.ttl=123" +- (NSDictionary *)parseFetchTokenResponse:(NSString *)response { + NSArray *lines = [response componentsSeparatedByString:@"\n"]; + NSMutableDictionary *parsedResponse = [NSMutableDictionary dictionary]; + for (NSString *line in lines) { + NSArray *keyAndValue = [line componentsSeparatedByString:@"="]; + if ([keyAndValue count] > 1) { + parsedResponse[keyAndValue[0]] = keyAndValue[1]; + } + } + return parsedResponse; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h new file mode 100644 index 00000000..3b752a3a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h @@ -0,0 +1,92 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#import "FIRInstanceIDAPNSInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents an Instance ID token, and all of the relevant information + * associated with it. It can read from and write to an NSDictionary object, for + * simple serialization. + */ +@interface FIRInstanceIDTokenInfo : NSObject <NSCoding> + +/// The authorized entity (also known as Sender ID), associated with the token. +@property(nonatomic, readonly, copy) NSString *authorizedEntity; +/// The scope associated with the token. This is an arbitrary string, typically "*". +@property(nonatomic, readonly, copy) NSString *scope; +/// The token value itself, with which all other properties are associated. +@property(nonatomic, readonly, copy) NSString *token; + +// These properties are nullable because they might not exist for tokens fetched from +// legacy storage formats. + +/// The app version that this token represents. +@property(nonatomic, readonly, copy, nullable) NSString *appVersion; +/// The Firebase app ID (also known as GMP App ID), that this token is associated with. +@property(nonatomic, readonly, copy, nullable) NSString *firebaseAppID; + +/// Tokens may not always be associated with an APNs token, and may be associated after +/// being created. +@property(nonatomic, strong, nullable) FIRInstanceIDAPNSInfo *APNSInfo; +/// The time that this token info was updated. The cache time is writeable, since in +/// some cases the token info may be refreshed from the server. In those situations, +/// the cacheTime would be updated. +@property(nonatomic, copy, nullable) NSDate *cacheTime; + +/** + * Initializes a FIRInstanceIDTokenInfo object with the required parameters. These + * parameters represent all the relevant associated data with a token. + * + * @param authorizedEntity The authorized entity (also known as Sender ID). + * @param scope The scope of the token, typically "*" meaning + * it's a "default scope". + * @param token The token value itself. + * @param appVersion The application version that this token is associated with. + * @param firebaseAppID The Firebase app ID which this token is associated with. + * @return An instance of FIRInstanceIDTokenInfo. + */ +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + token:(NSString *)token + appVersion:(nullable NSString *)appVersion + firebaseAppID:(nullable NSString *)firebaseAppID; + +/** + * Check whether the token is still fresh based on: + * 1. Last fetch token is within the 7 days. + * 2. Language setting is not changed. + * 3. App version is current. + * 4. GMP App ID is current. + * 5. token is consistent with the current IID. + * 6. APNS info has changed. + * @param IID The app identifiier that is used to check if token is prefixed with. + * @return If token is fresh. + * + */ +- (BOOL)isFreshWithIID:(NSString *)IID; + +/* + * Check whether the token is default token. + */ +- (BOOL)isDefaultToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m new file mode 100644 index 00000000..59b0e924 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m @@ -0,0 +1,212 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenInfo.h" + +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" + +/** + * @enum Token Info Dictionary Key Constants + * @discussion The keys that are checked when a token info is + * created from a dictionary. The same keys are used + * when decoding/encoding an archive. + */ +/// Specifies a dictonary key whose value represents the authorized entity, or +/// Sender ID for the token. +static NSString *const kFIRInstanceIDAuthorizedEntityKey = @"authorized_entity"; +/// Specifies a dictionary key whose value represents the scope of the token, +/// typically "*". +static NSString *const kFIRInstanceIDScopeKey = @"scope"; +/// Specifies a dictionary key which represents the token value itself. +static NSString *const kFIRInstanceIDTokenKey = @"token"; +/// Specifies a dictionary key which represents the app version associated +/// with the token. +static NSString *const kFIRInstanceIDAppVersionKey = @"app_version"; +/// Specifies a dictionary key which represents the GMP App ID associated with +/// the token. +static NSString *const kFIRInstanceIDFirebaseAppIDKey = @"firebase_app_id"; +/// Specifies a dictionary key representing an archive for a +/// `FIRInstanceIDAPNSInfo` object. +static NSString *const kFIRInstanceIDAPNSInfoKey = @"apns_info"; +/// Specifies a dictionary key representing the "last cached" time for the token. +static NSString *const kFIRInstanceIDCacheTimeKey = @"cache_time"; +/// Default interval that token stays fresh. +const NSTimeInterval kDefaultFetchTokenInterval = 7 * 24 * 60 * 60; // 7 days. + +@implementation FIRInstanceIDTokenInfo + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + token:(NSString *)token + appVersion:(NSString *)appVersion + firebaseAppID:(NSString *)firebaseAppID { + self = [super init]; + if (self) { + _authorizedEntity = [authorizedEntity copy]; + _scope = [scope copy]; + _token = [token copy]; + _appVersion = [appVersion copy]; + _firebaseAppID = [firebaseAppID copy]; + } + return self; +} + +- (BOOL)isFreshWithIID:(NSString *)IID { + // Last fetch token cache time could be null if token is from legacy storage format. Then token is + // considered not fresh and should be refreshed and overwrite with the latest storage format. + if (!IID) { + return NO; + } + if (!_cacheTime) { + return NO; + } + + // Check if it's consistent with IID + if (![self.token hasPrefix:IID]) { + return NO; + } + + // Check if app has just been updated to a new version. + NSString *currentAppVersion = FIRInstanceIDCurrentAppVersion(); + if (!_appVersion || ![_appVersion isEqualToString:currentAppVersion]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager004, + @"Invalidating cached token for %@ (%@) due to app version change.", + _authorizedEntity, _scope); + return NO; + } + + // Check if GMP App ID has changed + NSString *currentFirebaseAppID = FIRInstanceIDFirebaseAppID(); + if (!_firebaseAppID || ![_firebaseAppID isEqualToString:currentFirebaseAppID]) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged, + @"Invalidating cached token due to Firebase App IID change from %@ to %@", _firebaseAppID, + currentFirebaseAppID); + return NO; + } + + // Check whether locale has changed, if yes, token needs to be updated with server for locale + // information. + if (FIRInstanceIDHasLocaleChanged()) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenInfoLocaleChanged, + @"Invalidating cached token due to locale change"); + return NO; + } + + // Locale is not changed, check whether token has been fetched within 7 days. + NSTimeInterval lastFetchTokenTimestamp = [_cacheTime timeIntervalSince1970]; + NSTimeInterval currentTimestamp = FIRInstanceIDCurrentTimestampInSeconds(); + NSTimeInterval timeSinceLastFetchToken = currentTimestamp - lastFetchTokenTimestamp; + return (timeSinceLastFetchToken < kDefaultFetchTokenInterval); +} + +- (BOOL)isDefaultToken { + return [self.scope isEqualToString:kFIRInstanceIDDefaultTokenScope]; +} + +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + // These value cannot be nil + + id authorizedEntity = [aDecoder decodeObjectForKey:kFIRInstanceIDAuthorizedEntityKey]; + if (![authorizedEntity isKindOfClass:[NSString class]]) { + return nil; + } + + id scope = [aDecoder decodeObjectForKey:kFIRInstanceIDScopeKey]; + if (![scope isKindOfClass:[NSString class]]) { + return nil; + } + + id token = [aDecoder decodeObjectForKey:kFIRInstanceIDTokenKey]; + if (![token isKindOfClass:[NSString class]]) { + return nil; + } + + // These values are nullable, so only fail the decode if the type does not match + + id appVersion = [aDecoder decodeObjectForKey:kFIRInstanceIDAppVersionKey]; + if (appVersion && ![appVersion isKindOfClass:[NSString class]]) { + return nil; + } + + id firebaseAppID = [aDecoder decodeObjectForKey:kFIRInstanceIDFirebaseAppIDKey]; + if (firebaseAppID && ![firebaseAppID isKindOfClass:[NSString class]]) { + return nil; + } + + id rawAPNSInfo = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoKey]; + if (rawAPNSInfo && ![rawAPNSInfo isKindOfClass:[NSData class]]) { + return nil; + } + + FIRInstanceIDAPNSInfo *APNSInfo = nil; + if (rawAPNSInfo) { + // TODO(chliangGoogle: Use the new API and secureCoding protocol. + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + APNSInfo = [NSKeyedUnarchiver unarchiveObjectWithData:rawAPNSInfo]; +#pragma clang diagnostic pop + } @catch (NSException *exception) { + FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo, + @"Could not parse raw APNS Info while parsing archived token info."); + APNSInfo = nil; + } @finally { + } + } + + id cacheTime = [aDecoder decodeObjectForKey:kFIRInstanceIDCacheTimeKey]; + if (cacheTime && ![cacheTime isKindOfClass:[NSDate class]]) { + return nil; + } + + self = [super init]; + if (self) { + _authorizedEntity = authorizedEntity; + _scope = scope; + _token = token; + _appVersion = appVersion; + _firebaseAppID = firebaseAppID; + _APNSInfo = APNSInfo; + _cacheTime = cacheTime; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.authorizedEntity forKey:kFIRInstanceIDAuthorizedEntityKey]; + [aCoder encodeObject:self.scope forKey:kFIRInstanceIDScopeKey]; + [aCoder encodeObject:self.token forKey:kFIRInstanceIDTokenKey]; + [aCoder encodeObject:self.appVersion forKey:kFIRInstanceIDAppVersionKey]; + [aCoder encodeObject:self.firebaseAppID forKey:kFIRInstanceIDFirebaseAppIDKey]; + NSData *rawAPNSInfo; + if (self.APNSInfo) { + // TODO(chliangGoogle: Use the new API and secureCoding protocol. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + rawAPNSInfo = [NSKeyedArchiver archivedDataWithRootObject:self.APNSInfo]; +#pragma clang diagnostic pop + + [aCoder encodeObject:rawAPNSInfo forKey:kFIRInstanceIDAPNSInfoKey]; + } + [aCoder encodeObject:self.cacheTime forKey:kFIRInstanceIDCacheTimeKey]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h new file mode 100644 index 00000000..46e1ac88 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h @@ -0,0 +1,149 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +@class FIRInstanceIDAuthService; +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDTokenInfo; +@class FIRInstanceIDStore; + +typedef NS_OPTIONS(NSUInteger, FIRInstanceIDInvalidTokenReason) { + FIRInstanceIDInvalidTokenReasonNone = 0, // 0 + FIRInstanceIDInvalidTokenReasonAppVersion = (1 << 0), // 0...00001 + FIRInstanceIDInvalidTokenReasonAPNSToken = (1 << 1), // 0...00010 +}; + +/** + * Manager for the InstanceID token requests i.e `newToken` and `deleteToken`. This + * manages the overall interaction of the `InstanceIDStore`, the token register + * service and the callbacks associated with `GCMInstanceID`. + */ +@interface FIRInstanceIDTokenManager : NSObject + +/// Expose the auth service, so it can be used by others +@property(nonatomic, readonly, strong) FIRInstanceIDAuthService *authService; + +/** + * Fetch new token for the given authorizedEntity and scope. This makes an + * asynchronous request to the InstanceID backend to create a new token for + * the service and returns it. This will replace any old token for the given + * authorizedEntity and scope that has been cached before. + * + * @param authorizedEntity The authorized entity for the token, should not be nil. + * @param scope The scope for the token, should not be nil. + * @param instanceID The unique string identifying the app instance. + * @param options The options to be added to the fetch request. + * @param handler The handler to be invoked once we have the token or the + * fetch request to InstanceID backend results in an error. Also + * since it's a public handler it should always be called + * asynchronously. This should be non-nil. + */ +- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler; + +/** + * Return the cached token info, if one exists, for the given authorizedEntity and scope. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + * @return The cached token info, if available, matching the parameters. + */ +- (FIRInstanceIDTokenInfo *)cachedTokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; + +/** + * Delete the token for the given authorizedEntity and scope. If the token has + * been cached, it will be deleted from the store. It will also make an + * asynchronous request to the InstanceID backend to invalidate the token. + * + * @param authorizedEntity The authorized entity for the token, should not be nil. + * @param scope The scope for the token, should not be nil. + * @param instanceID The unique string identifying the app instance. + * @param handler The handler to be invoked once the delete request to + * InstanceID backend has returned. If the request was + * successful we invoke the handler with a nil error; + * otherwise we call it with an appropriate error. Also since + * it's a public handler it should always be called + * asynchronously. This should be non-nil. + */ +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteTokenHandler)handler; + +/** + * Deletes all cached tokens from the persistent store. This method should only be triggered + * when InstanceID is deleted + * + * @param instanceID The unique string identifying the app instance. + * @param handler The handler to be invoked once the delete request to InstanceID backend + * has returned. If the request was successful we invoke the handler with + * a nil error; else we pass in an appropriate error. This should be non-nil + * and be called asynchronously. + */ +- (void)deleteAllTokensWithInstanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteHandler)handler; + +/** + * Deletes all cached tokens from the persistent store. + * @param handler The callback handler which is invoked when tokens deletion is complete, + * with an error if there is any. + * + */ +- (void)deleteAllTokensLocallyWithHandler:(void (^)(NSError *error))handler; + +/** + * Stop any ongoing token operations. + */ +- (void)stopAllTokenOperations; + +#pragma mark - Invalidating Cached Tokens + +/** + * Invalidate any cached tokens, if the app version has changed since last launch or if the token + * is cached for more than 7 days. + * @param IID The cached instanceID, check if token is prefixed by such IID. + * + * @return Whether we should fetch default token from server. + * + * @discussion This should safely be called prior to any tokens being retrieved from + * the cache or being fetched from the network. + */ +- (BOOL)checkTokenRefreshPolicyWithIID:(NSString *)IID; + +/** + * Upon being provided with different APNs or sandbox, any locally cached tokens + * should be deleted, and the new APNs token should be cached. + * + * @discussion It is possible for this method to be called while token operations are + * in-progress or queued. In this case, the in-flight token operations will have stale + * APNs information. The default token is checked for being out-of-date by Instance ID, + * and re-fetched. Custom tokens are not currently checked. + * + * @param deviceToken The APNS device token, provided by the operating system. + * @param isSandbox YES if the device token is for the sandbox environment, NO otherwise. + * + * @return The array of FIRInstanceIDTokenInfo objects which were invalidated. + */ +- (NSArray<FIRInstanceIDTokenInfo *> *)updateTokensToAPNSDeviceToken:(NSData *)deviceToken + isSandbox:(BOOL)isSandbox; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m new file mode 100644 index 00000000..0ebcfc88 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m @@ -0,0 +1,340 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenManager.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDTokenDeleteOperation.h" +#import "FIRInstanceIDTokenFetchOperation.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDTokenOperation.h" +#import "NSError+FIRInstanceID.h" + +@interface FIRInstanceIDTokenManager () <FIRInstanceIDStoreDelegate> + +@property(nonatomic, readwrite, strong) FIRInstanceIDStore *instanceIDStore; +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthService *authService; +@property(nonatomic, readonly, strong) NSOperationQueue *tokenOperations; + +@property(nonatomic, readwrite, strong) FIRInstanceIDAPNSInfo *currentAPNSInfo; + +@end + +@implementation FIRInstanceIDTokenManager + +- (instancetype)init { + self = [super init]; + if (self) { + _instanceIDStore = [[FIRInstanceIDStore alloc] initWithDelegate:self]; + _authService = [[FIRInstanceIDAuthService alloc] initWithStore:_instanceIDStore]; + [self configureTokenOperations]; + } + return self; +} + +- (void)dealloc { + [self stopAllTokenOperations]; +} + +- (void)configureTokenOperations { + _tokenOperations = [[NSOperationQueue alloc] init]; + _tokenOperations.name = @"com.google.iid-token-operations"; + // For now, restrict the operations to be serial, because in some cases (like if the + // authorized entity and scope are the same), order matters. + // If we have to deal with several different token requests simultaneously, it would be a good + // idea to add some better intelligence around this (performing unrelated token operations + // simultaneously, etc.). + _tokenOperations.maxConcurrentOperationCount = 1; + if ([_tokenOperations respondsToSelector:@selector(qualityOfService)]) { + _tokenOperations.qualityOfService = NSOperationQualityOfServiceUtility; + } +} + +- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager000, + @"Fetch new token for authorizedEntity: %@, scope: %@", authorizedEntity, + scope); + FIRInstanceIDTokenFetchOperation *operation = + [self createFetchOperationWithAuthorizedEntity:authorizedEntity + scope:scope + options:options + instanceID:instanceID]; + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDTokenOperationCompletion completion = + ^(FIRInstanceIDTokenOperationResult result, NSString *_Nullable token, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + handler(nil, error); + return; + } + NSString *firebaseAppID = options[kFIRInstanceIDTokenOptionsFirebaseAppIDKey]; + FIRInstanceIDTokenInfo *tokenInfo = [[FIRInstanceIDTokenInfo alloc] + initWithAuthorizedEntity:authorizedEntity + scope:scope + token:token + appVersion:FIRInstanceIDCurrentAppVersion() + firebaseAppID:firebaseAppID]; + tokenInfo.APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:options]; + + [self.instanceIDStore + saveTokenInfo:tokenInfo + handler:^(NSError *error) { + if (!error) { + // Do not send the token back in case the save was unsuccessful. Since with + // the new asychronous fetch mechanism this can lead to infinite loops, for + // example, we will return a valid token even though we weren't able to store + // it in our cache. The first token will lead to a onTokenRefresh callback + // wherein the user again calls `getToken` but since we weren't able to save + // it we won't hit the cache but hit the server again leading to an infinite + // loop. + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenManager001, + @"Token fetch successful, token: %@, authorizedEntity: %@, scope:%@", + token, authorizedEntity, scope); + + if (handler) { + handler(token, nil); + } + } else { + if (handler) { + handler(nil, error); + } + } + }]; + }; + // Add completion handler, and ensure it's called on the main queue + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(result, token, error); + }); + }]; + [self.tokenOperations addOperation:operation]; +} + +- (FIRInstanceIDTokenInfo *)cachedTokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + return [self.instanceIDStore tokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]; +} + +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteTokenHandler)handler { + if ([self.instanceIDStore tokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]) { + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:authorizedEntity scope:scope]; + } + // Does not matter if we cannot find it in the cache. Still make an effort to unregister + // from the server. + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:authorizedEntity + scope:scope + checkinPreferences:checkinPreferences + instanceID:instanceID + action:FIRInstanceIDTokenActionDeleteToken]; + + if (handler) { + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }]; + } + [self.tokenOperations addOperation:operation]; +} + +- (void)deleteAllTokensWithInstanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteHandler)handler { + // delete all tokens + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + if (!checkinPreferences) { + // The checkin is already deleted. No need to trigger the token delete operation as client no + // longer has the checkin information for server to delete. + dispatch_async(dispatch_get_main_queue(), ^{ + handler(nil); + }); + return; + } + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:kFIRInstanceIDKeychainWildcardIdentifier + scope:kFIRInstanceIDKeychainWildcardIdentifier + checkinPreferences:checkinPreferences + instanceID:instanceID + action:FIRInstanceIDTokenActionDeleteTokenAndIID]; + if (handler) { + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }]; + } + [self.tokenOperations addOperation:operation]; +} + +- (void)deleteAllTokensLocallyWithHandler:(void (^)(NSError *error))handler { + [self.instanceIDStore removeAllCachedTokensWithHandler:handler]; +} + +- (void)stopAllTokenOperations { + [self.authService stopCheckinRequest]; + [self.tokenOperations cancelAllOperations]; +} + +#pragma mark - FIRInstanceIDStoreDelegate + +- (void)store:(FIRInstanceIDStore *)store + didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + // Make a best effort try to delete the old client related state on the FCM server. This is + // required to delete old pubusb registrations which weren't cleared when the app was deleted. + // + // This is only a one time effort. If this call fails the client would still receive duplicate + // pubsub notifications if he is again subscribed to the same topic. + // + // The client state should be cleared on the server for the provided checkin preferences. + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:nil + scope:nil + checkinPreferences:checkin + instanceID:nil + action:FIRInstanceIDTokenActionDeleteToken]; + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + if (error) { + FIRInstanceIDMessageCode code = + kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset; + FIRInstanceIDLoggerDebug(code, @"Failed to delete GCM server registrations on app reset."); + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset, + @"Successfully deleted GCM server registrations on app reset"); + } + }]; + + [self.tokenOperations addOperation:operation]; +} + +#pragma mark - Unit Testing Stub Helpers +// We really have this method so that we can more easily stub it out for unit testing +- (FIRInstanceIDTokenFetchOperation *) + createFetchOperationWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary<NSString *, NSString *> *)options + instanceID:(NSString *)instanceID { + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + FIRInstanceIDTokenFetchOperation *operation = + [[FIRInstanceIDTokenFetchOperation alloc] initWithAuthorizedEntity:authorizedEntity + scope:scope + options:options + checkinPreferences:checkinPreferences + instanceID:instanceID]; + return operation; +} + +// We really have this method so that we can more easily stub it out for unit testing +- (FIRInstanceIDTokenDeleteOperation *) + createDeleteOperationWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID + action:(FIRInstanceIDTokenAction)action { + FIRInstanceIDTokenDeleteOperation *operation = + [[FIRInstanceIDTokenDeleteOperation alloc] initWithAuthorizedEntity:authorizedEntity + scope:scope + checkinPreferences:checkinPreferences + instanceID:instanceID + action:action]; + return operation; +} + +#pragma mark - Invalidating Cached Tokens +- (BOOL)checkTokenRefreshPolicyWithIID:(NSString *)IID { + // We know at least one cached token exists. + BOOL shouldFetchDefaultToken = NO; + NSArray<FIRInstanceIDTokenInfo *> *tokenInfos = [self.instanceIDStore cachedTokenInfos]; + + NSMutableArray<FIRInstanceIDTokenInfo *> *tokenInfosToDelete = + [NSMutableArray arrayWithCapacity:tokenInfos.count]; + for (FIRInstanceIDTokenInfo *tokenInfo in tokenInfos) { + if ([tokenInfo isFreshWithIID:IID]) { + // Token is fresh and in right format, do nothing + continue; + } + if ([tokenInfo isDefaultToken]) { + // Default token is expired, do not mark for deletion. Fetch directly from server to + // replace the current one. + shouldFetchDefaultToken = YES; + } else { + // Non-default token is expired, mark for deletion. + [tokenInfosToDelete addObject:tokenInfo]; + } + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken, + @"Invalidating cached token for %@ (%@) due to token is no longer fresh.", + tokenInfo.authorizedEntity, tokenInfo.scope); + } + for (FIRInstanceIDTokenInfo *tokenInfoToDelete in tokenInfosToDelete) { + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:tokenInfoToDelete.authorizedEntity + scope:tokenInfoToDelete.scope]; + } + return shouldFetchDefaultToken; +} + +- (NSArray<FIRInstanceIDTokenInfo *> *)updateTokensToAPNSDeviceToken:(NSData *)deviceToken + isSandbox:(BOOL)isSandbox { + // Each cached IID token that is missing an APNSInfo, or has an APNSInfo associated should be + // checked and invalidated if needed. + FIRInstanceIDAPNSInfo *APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithDeviceToken:deviceToken + isSandbox:isSandbox]; + if ([self.currentAPNSInfo isEqualToAPNSInfo:APNSInfo]) { + return @[]; + } + self.currentAPNSInfo = APNSInfo; + + NSArray<FIRInstanceIDTokenInfo *> *tokenInfos = [self.instanceIDStore cachedTokenInfos]; + NSMutableArray<FIRInstanceIDTokenInfo *> *tokenInfosToDelete = + [NSMutableArray arrayWithCapacity:tokenInfos.count]; + for (FIRInstanceIDTokenInfo *cachedTokenInfo in tokenInfos) { + // Check if the cached APNSInfo is nil, or if it is an old APNSInfo. + if (!cachedTokenInfo.APNSInfo || + ![cachedTokenInfo.APNSInfo isEqualToAPNSInfo:self.currentAPNSInfo]) { + // Mark for invalidation. + [tokenInfosToDelete addObject:cachedTokenInfo]; + } + } + for (FIRInstanceIDTokenInfo *tokenInfoToDelete in tokenInfosToDelete) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated, + @"Invalidating cached token for %@ (%@) due to APNs token change.", + tokenInfoToDelete.authorizedEntity, tokenInfoToDelete.scope); + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:tokenInfoToDelete.authorizedEntity + scope:tokenInfoToDelete.scope]; + } + return tokenInfosToDelete; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h new file mode 100644 index 00000000..c430f11f --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h @@ -0,0 +1,66 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +#import "FIRInstanceIDUtilities.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstanceIDTokenOperation (Private) + +@property(atomic, strong) NSURLSessionDataTask *dataTask; +@property(readonly, strong) + NSMutableArray<FIRInstanceIDTokenOperationCompletion> *completionHandlers; + +// For testing only +@property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock; + ++ (NSURLSession *)sharedURLSession; + +#pragma mark - Initialization +- (instancetype)initWithAction:(FIRInstanceIDTokenAction)action + forAuthorizedEntity:(nullable NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary<NSString *, NSString *> *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID; + +#pragma mark - Request Construction ++ (NSMutableArray<NSURLQueryItem *> *)standardQueryItemsWithDeviceID:(NSString *)deviceID + scope:(NSString *)scope; +- (NSMutableURLRequest *)tokenRequest; + +#pragma mark - HTTP Headers +/** + * Given a valid checkin preferences object, it will return a string that can be used + * in the "Authorization" HTTP header to authenticate this request. + * + * @param checkin The valid checkin preferences object, with a deviceID and secretToken. + */ ++ (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin; + +#pragma mark - Result +- (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result + token:(nullable NSString *)token + error:(nullable NSError *)error; + +#pragma mark - Methods to override +- (void)performTokenOperation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h new file mode 100644 index 00000000..fa8ad085 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h @@ -0,0 +1,72 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@class FIRInstanceIDCheckinPreferences; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents the action taken on an FCM token. + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDTokenAction) { + FIRInstanceIDTokenActionFetch, + FIRInstanceIDTokenActionDeleteToken, + FIRInstanceIDTokenActionDeleteTokenAndIID, +}; + +/** + * Represents the possible results of a token operation. + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDTokenOperationResult) { + FIRInstanceIDTokenOperationSucceeded, + FIRInstanceIDTokenOperationError, + FIRInstanceIDTokenOperationCancelled, +}; + +/** + * Callback to invoke once the HTTP call to FIRMessaging backend for updating + * subscription finishes. + * + * @param result The result of the operation. + * @param token If the action for fetching a token and the request was successful, this will hold + * the value of the token. Otherwise nil. + * @param error The error which occurred while performing the token operation. This will be nil + * in case the operation was successful, or if the operation was cancelled. + */ +typedef void (^FIRInstanceIDTokenOperationCompletion)(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, + NSError *_Nullable error); + +@interface FIRInstanceIDTokenOperation : NSOperation + +@property(nonatomic, readonly) FIRInstanceIDTokenAction action; +@property(nonatomic, readonly, nullable) NSString *authorizedEntity; +@property(nonatomic, readonly, nullable) NSString *scope; +@property(nonatomic, readonly, nullable) NSDictionary<NSString *, NSString *> *options; +@property(nonatomic, readonly, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; +@property(nonatomic, readonly, strong) NSString *instanceID; + +@property(nonatomic, readonly) FIRInstanceIDTokenOperationResult result; + +- (instancetype)init NS_UNAVAILABLE; + +- (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m new file mode 100644 index 00000000..e5d725a7 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m @@ -0,0 +1,249 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +#import "FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +static const NSInteger kFIRInstanceIDPlatformVersionIOS = 2; + +// Scope parameter that defines the service using the token +static NSString *const kFIRInstanceIDParamScope = @"X-scope"; +// Defines the SDK version +static NSString *const kFIRInstanceIDParamFCMLibVersion = @"X-cliv"; + +@interface FIRInstanceIDTokenOperation () { + BOOL _isFinished; + BOOL _isExecuting; +} + +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; +@property(nonatomic, readwrite, strong) NSString *instanceID; + +@property(atomic, strong) NSURLSessionDataTask *dataTask; +@property(readonly, strong) + NSMutableArray<FIRInstanceIDTokenOperationCompletion> *completionHandlers; + +@property(atomic, strong, nullable) NSString *FISAuthToken; + +// For testing only +@property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock; + +@end + +@implementation FIRInstanceIDTokenOperation + ++ (NSURLSession *)sharedURLSession { + static NSURLSession *tokenOperationSharedSession; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + tokenOperationSharedSession = [NSURLSession sessionWithConfiguration:config]; + tokenOperationSharedSession.sessionDescription = @"com.google.iid.tokens.session"; + }); + return tokenOperationSharedSession; +} + +- (instancetype)initWithAction:(FIRInstanceIDTokenAction)action + forAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary<NSString *, NSString *> *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID { + self = [super init]; + if (self) { + _action = action; + _authorizedEntity = [authorizedEntity copy]; + _scope = [scope copy]; + _options = [options copy]; + _checkinPreferences = checkinPreferences; + _instanceID = instanceID; + _completionHandlers = [NSMutableArray array]; + + _isExecuting = NO; + _isFinished = NO; + } + return self; +} + +- (void)dealloc { + _testBlock = nil; + _authorizedEntity = nil; + _scope = nil; + _options = nil; + _checkinPreferences = nil; + _instanceID = nil; + [_completionHandlers removeAllObjects]; + _completionHandlers = nil; +} + +- (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler { + [self.completionHandlers addObject:handler]; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + return _isExecuting; +} + +- (void)setExecuting:(BOOL)executing { + [self willChangeValueForKey:@"isExecuting"]; + _isExecuting = executing; + [self didChangeValueForKey:@"isExecuting"]; +} + +- (BOOL)isFinished { + return _isFinished; +} + +- (void)setFinished:(BOOL)finished { + [self willChangeValueForKey:@"isFinished"]; + _isFinished = finished; + [self didChangeValueForKey:@"isFinished"]; +} + +- (void)start { + if (self.isCancelled) { + [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil]; + return; + } + + // Quickly validate whether or not the operation has all it needs to begin + BOOL checkinfoAvailable = [self.checkinPreferences hasCheckinInfo]; + if (!checkinfoAvailable) { + FIRInstanceIDErrorCode errorCode = kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn; + [self finishWithResult:FIRInstanceIDTokenOperationError + token:nil + error:[NSError errorWithFIRInstanceIDErrorCode:errorCode]]; + return; + } + + [self setExecuting:YES]; + + [[FIRInstallations installations] + authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult, + NSError *_Nullable error) { + if (tokenResult.authToken.length > 0) { + self.FISAuthToken = tokenResult.authToken; + [self performTokenOperation]; + } else { + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + } + }]; +} + +- (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result + token:(nullable NSString *)token + error:(nullable NSError *)error { + // Add a check to prevent this finish from being called more than once. + if (self.isFinished) { + return; + } + self.dataTask = nil; + _result = result; + // TODO(chliangGoogle): Call these in the main thread? + for (FIRInstanceIDTokenOperationCompletion completionHandler in self.completionHandlers) { + completionHandler(result, token, error); + } + + [self setExecuting:NO]; + [self setFinished:YES]; +} + +- (void)cancel { + [super cancel]; + [self.dataTask cancel]; + [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil]; +} + +- (void)performTokenOperation { +} + +- (NSMutableURLRequest *)tokenRequest { + NSString *authHeader = + [FIRInstanceIDTokenOperation HTTPAuthHeaderFromCheckin:self.checkinPreferences]; + return [[self class] requestWithAuthHeader:authHeader FISAuthToken:self.FISAuthToken]; +} + +#pragma mark - Request Construction ++ (NSMutableURLRequest *)requestWithAuthHeader:(NSString *)authHeaderString + FISAuthToken:(NSString *)FISAuthToken { + NSURL *url = [NSURL URLWithString:FIRInstanceIDRegisterServer()]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + + // Add HTTP headers + [request setValue:authHeaderString forHTTPHeaderField:@"Authorization"]; + [request setValue:FIRInstanceIDAppIdentifier() forHTTPHeaderField:@"app"]; + if (FISAuthToken) { + [request setValue:FISAuthToken forHTTPHeaderField:@"x-goog-firebase-installations-auth"]; + } + request.HTTPMethod = @"POST"; + return request; +} + ++ (NSMutableArray<NSURLQueryItem *> *)standardQueryItemsWithDeviceID:(NSString *)deviceID + scope:(NSString *)scope { + NSMutableArray<NSURLQueryItem *> *queryItems = [NSMutableArray arrayWithCapacity:8]; + + // E.g. X-osv=10.2.1 + NSString *systemVersion = FIRInstanceIDOperatingSystemVersion(); + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"X-osv" value:systemVersion]]; + // E.g. device= + if (deviceID) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"device" value:deviceID]]; + } + // E.g. X-scope=fcm + if (scope) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:kFIRInstanceIDParamScope value:scope]]; + } + // E.g. plat=2 + NSString *platform = [NSString stringWithFormat:@"%ld", (long)kFIRInstanceIDPlatformVersionIOS]; + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"plat" value:platform]]; + // E.g. app=com.myapp.foo + NSString *appIdentifier = FIRInstanceIDAppIdentifier(); + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"app" value:appIdentifier]]; + // E.g. app_ver=1.5 + NSString *appVersion = FIRInstanceIDCurrentAppVersion(); + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"app_ver" value:appVersion]]; + // E.g. X-cliv=fiid-1.2.3 + NSString *fcmLibraryVersion = + [NSString stringWithFormat:@"fiid-%@", FIRInstanceIDCurrentGCMVersion()]; + if (fcmLibraryVersion.length) { + NSURLQueryItem *gcmLibVersion = + [NSURLQueryItem queryItemWithName:kFIRInstanceIDParamFCMLibVersion value:fcmLibraryVersion]; + [queryItems addObject:gcmLibVersion]; + } + + return queryItems; +} + +#pragma mark - HTTP Header + ++ (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + NSString *deviceID = checkin.deviceID; + NSString *secret = checkin.secretToken; + return [NSString stringWithFormat:@"AidLogin %@:%@", deviceID, secret]; +} +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h new file mode 100644 index 00000000..861c87b9 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h @@ -0,0 +1,106 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@class FIRInstanceIDAPNSInfo; +@class FIRInstanceIDAuthKeychain; +@class FIRInstanceIDTokenInfo; + +/** + * This class is responsible for retrieving and saving `FIRInstanceIDTokenInfo` objects from the + * keychain. The keychain keys that are used are: + * Account: <Main App Bundle ID> (e.g. com.mycompany.myapp) + * Service: <Sender ID>:<Scope> (e.g. 1234567890:*) + */ +@interface FIRInstanceIDTokenStore : NSObject + +NS_ASSUME_NONNULL_BEGIN + +/** + * Create a default InstanceID token store. Uses a valid Keychain object as it's + * persistent backing store. + * + * @return A valid token store object. + */ ++ (instancetype)defaultStore; + +- (instancetype)init __attribute__((unavailable("Use -initWithKeychain: instead."))); + +/** + * Initialize a token store object with a Keychain object. Used for testing. + * + * @param keychain The Keychain object to use as the backing store for tokens. + * + * @return A valid token store object with the given Keychain as backing store. + */ +- (instancetype)initWithKeychain:(FIRInstanceIDAuthKeychain *)keychain; + +#pragma mark - Get + +/** + * Get the cached token from the Keychain. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + * @return The cached token info if any for the given authorizedEntity and scope else + * nil. + */ +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; + +/** + * Return all cached token infos from the Keychain. + * + * @return The cached token infos, if any, that are stored in the Keychain. + */ +- (NSArray<FIRInstanceIDTokenInfo *> *)cachedTokenInfos; + +#pragma mark - Save + +/** + * Save the instanceID token info to the persistent store. + * + * @param tokenInfo The token info to store. + * @param handler The callback handler which is invoked when token saving is complete, + * with an error if there is any. + */ +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(nullable void (^)(NSError *))handler; + +#pragma mark - Delete + +/** + * Remove the cached token from Keychain. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + */ +- (void)removeTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope; + +/** + * Remove all the cached tokens from the Keychain. + * @param handler The callback handler which is invoked when tokens deletion is complete, + * with an error if there is any. + * + */ +- (void)removeAllTokensWithHandler:(nullable void (^)(NSError *))handler; + +NS_ASSUME_NONNULL_END + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m new file mode 100644 index 00000000..f97f9321 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m @@ -0,0 +1,143 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenStore.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDUtilities.h" + +static NSString *const kFIRInstanceIDTokenKeychainId = @"com.google.iid-tokens"; + +@interface FIRInstanceIDTokenStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain; + +@end + +@implementation FIRInstanceIDTokenStore + ++ (instancetype)defaultStore { + FIRInstanceIDAuthKeychain *tokenKeychain = + [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDTokenKeychainId]; + return [[FIRInstanceIDTokenStore alloc] initWithKeychain:tokenKeychain]; +} + +- (instancetype)initWithKeychain:(FIRInstanceIDAuthKeychain *)keychain { + self = [super init]; + if (self) { + _keychain = keychain; + } + return self; +} + +#pragma mark - Get + ++ (NSString *)serviceKeyForAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + return [NSString stringWithFormat:@"%@:%@", authorizedEntity, scope]; +} + +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope]; + NSData *item = [self.keychain dataForService:service account:account]; + if (!item) { + return nil; + } + // Token infos created from legacy storage don't have appVersion, firebaseAppID, or APNSInfo. + FIRInstanceIDTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item]; + return tokenInfo; +} + +- (NSArray<FIRInstanceIDTokenInfo *> *)cachedTokenInfos { + NSString *account = FIRInstanceIDAppIdentifier(); + NSArray<NSData *> *items = + [self.keychain itemsMatchingService:kFIRInstanceIDKeychainWildcardIdentifier account:account]; + NSMutableArray<FIRInstanceIDTokenInfo *> *tokenInfos = + [NSMutableArray arrayWithCapacity:items.count]; + for (NSData *item in items) { + FIRInstanceIDTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item]; + if (tokenInfo) { + [tokenInfos addObject:tokenInfo]; + } + } + return tokenInfos; +} + ++ (nullable FIRInstanceIDTokenInfo *)tokenInfoFromKeychainItem:(NSData *)item { + // Check if it is saved as an archived FIRInstanceIDTokenInfo, otherwise return nil. + FIRInstanceIDTokenInfo *tokenInfo = nil; + // NOTE: Passing in nil to unarchiveObjectWithData will result in an iOS error logged + // in the console on iOS 10 and below. Avoid by checking item.data's existence. + if (item) { + // TODO(chliangGoogle: Use the new API and secureCoding protocol. + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + tokenInfo = [NSKeyedUnarchiver unarchiveObjectWithData:item]; +#pragma clang diagnostic pop + + } @catch (NSException *exception) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo, + @"Unable to parse token info from Keychain item; item was in an " + @"invalid format"); + tokenInfo = nil; + } @finally { + } + } + return tokenInfo; +} + +#pragma mark - Save +// Token Infos will be saved under these Keychain keys: +// Account: <Main App Bundle ID> (e.g. com.mycompany.myapp) +// Service: <Sender ID>:<Scope> (e.g. 1234567890:*) +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(void (^)(NSError *))handler { // Keep the cachetime up-to-date. + tokenInfo.cacheTime = [NSDate date]; + // Always write to the Keychain, so that the cacheTime is up-to-date. + NSData *tokenInfoData; + // TODO(chliangGoogle: Use the new API and secureCoding protocol. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + tokenInfoData = [NSKeyedArchiver archivedDataWithRootObject:tokenInfo]; +#pragma clang diagnostic pop + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:tokenInfo.authorizedEntity + scope:tokenInfo.scope]; + [self.keychain setData:tokenInfoData forService:service account:account handler:handler]; +} + +#pragma mark - Delete + +- (void)removeTokenWithAuthorizedEntity:(nonnull NSString *)authorizedEntity + scope:(nonnull NSString *)scope { + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope]; + [self.keychain removeItemsMatchingService:service account:account handler:nil]; +} + +- (void)removeAllTokensWithHandler:(void (^)(NSError *error))handler { + NSString *account = FIRInstanceIDAppIdentifier(); + [self.keychain removeItemsMatchingService:kFIRInstanceIDKeychainWildcardIdentifier + account:account + handler:handler]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h new file mode 100644 index 00000000..da6ebad3 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h @@ -0,0 +1,85 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the required method. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFCMSDKClassString; + +/// locale key stored in GULUserDefaults +FOUNDATION_EXPORT NSString *const kFIRInstanceIDUserDefaultsKeyLocale; + +#pragma mark - Test Blocks + +/** + * Response block for mock registration requests made during tests. + * + * @param data The data as returned by the mock request. + * @param response The response as returned by the mock request. + * @param error The error if any as returned by the mock request. + */ +typedef void (^FIRInstanceIDURLRequestTestResponseBlock)(NSData *data, + NSURLResponse *response, + NSError *error); + +/** + * Test block to mock registration requests response. + * + * @param request The request to mock response for. + * @param response The response block for the mocked request. + */ +typedef void (^FIRInstanceIDURLRequestTestBlock)(NSURLRequest *request, + FIRInstanceIDURLRequestTestResponseBlock response); + +#pragma mark - URL Helpers + +FOUNDATION_EXPORT NSString *FIRInstanceIDRegisterServer(void); + +#pragma mark - Time + +FOUNDATION_EXPORT int64_t FIRInstanceIDCurrentTimestampInSeconds(void); +FOUNDATION_EXPORT int64_t FIRInstanceIDCurrentTimestampInMilliseconds(void); + +#pragma mark - App Info + +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentAppVersion(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDAppIdentifier(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDFirebaseAppID(void); + +#pragma mark - Device Info + +FOUNDATION_EXPORT NSString *FIRInstanceIDDeviceModel(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDOperatingSystemVersion(void); +FOUNDATION_EXPORT BOOL FIRInstanceIDHasLocaleChanged(void); + +#pragma mark - Helpers + +FOUNDATION_EXPORT BOOL FIRInstanceIDIsValidGCMScope(NSString *scope); +FOUNDATION_EXPORT NSString *FIRInstanceIDStringForAPNSDeviceToken(NSData *deviceToken); +FOUNDATION_EXPORT NSString *FIRInstanceIDAPNSTupleStringForTokenAndServerType(NSData *deviceToken, + BOOL isSandbox); + +#pragma mark - GCM Helpers +/// Returns the current GCM version if GCM library is found else returns nil. +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentGCMVersion(void); + +/// Returns the current locale. If GCM is present it queries GCM for a +/// Context Manager specific locale. Otherwise, it returns the system's first +/// preferred language (which may be set independently from locale). If the +/// system returns no preferred languages, this method returns the most common +/// language for the user's given locale. Guaranteed to return a nonnull value. +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentLocale(void); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m new file mode 100644 index 00000000..25d1b972 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m @@ -0,0 +1,208 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDUtilities.h" + +#if TARGET_OS_IOS || TARGET_OS_TV +#import <UIKit/UIKit.h> +#endif +#import <sys/utsname.h> + +#import "FIRInstanceID.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "GoogleUtilities/UserDefaults/Private/GULUserDefaults.h" + +// Convert the macro to a string +#define STR_EXPAND(x) #x +#define STR(x) STR_EXPAND(x) + +static NSString *const kFIRInstanceIDAPNSSandboxPrefix = @"s_"; +static NSString *const kFIRInstanceIDAPNSProdPrefix = @"p_"; + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the required method. +NSString *const kFIRInstanceIDFCMSDKClassString = @"FIRMessaging"; + +/// FIRMessaging selector that returns the current FIRMessaging library version. +static NSString *const kFIRInstanceIDFCMSDKVersionSelectorString = @"FIRMessagingSDKVersion"; + +/// FIRMessaging selector that returns the current device locale. +static NSString *const kFIRInstanceIDFCMSDKLocaleSelectorString = @"FIRMessagingSDKCurrentLocale"; + +NSString *const kFIRInstanceIDUserDefaultsKeyLocale = + @"com.firebase.instanceid.user_defaults.locale"; // locale key stored in GULUserDefaults + +/// Static values which will be populated once retrieved using +/// |FIRInstanceIDRetrieveEnvironmentInfoFromFirebaseCore|. +static NSString *operatingSystemVersion; +static NSString *hardwareDeviceModel; + +#pragma mark - URL Helpers + +NSString *FIRInstanceIDRegisterServer() { + return @"https://fcmtoken.googleapis.com/register"; +} + +#pragma mark - Time + +int64_t FIRInstanceIDCurrentTimestampInSeconds() { + return (int64_t)[[NSDate date] timeIntervalSince1970]; +} + +int64_t FIRInstanceIDCurrentTimestampInMilliseconds() { + return (int64_t)(FIRInstanceIDCurrentTimestampInSeconds() * 1000.0); +} + +#pragma mark - App Info + +NSString *FIRInstanceIDCurrentAppVersion() { + NSString *version = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"]; + if (![version length]) { + return @""; + } + return version; +} + +NSString *FIRInstanceIDBundleIDByRemovingLastPartFrom(NSString *bundleID) { + NSString *bundleIDComponentsSeparator = @"."; + + NSMutableArray<NSString *> *bundleIDComponents = + [[bundleID componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy]; + [bundleIDComponents removeLastObject]; + + return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator]; +} + +NSString *FIRInstanceIDAppIdentifier() { + NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; + if (!bundleID.length) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier, + @"The mainBundle's bundleIdentifier returned '%@'. Bundle identifier " + @"expected to be non-empty.", + bundleID); + return @""; + } +#if TARGET_OS_WATCH + return FIRInstanceIDBundleIDByRemovingLastPartFrom(bundleID); +#endif + return bundleID; +} + +NSString *FIRInstanceIDFirebaseAppID() { + return [FIROptions defaultOptions].googleAppID; +} + +#pragma mark - Device Info +// Get the device model from Firebase Core's App Environment Util +NSString *FIRInstanceIDDeviceModel() { + static dispatch_once_t once; + dispatch_once(&once, ^{ + struct utsname systemInfo; + if (uname(&systemInfo) == 0) { + hardwareDeviceModel = [NSString stringWithUTF8String:systemInfo.machine]; + } + }); + return hardwareDeviceModel; +} + +// Get the system version from Firebase Core's App Environment Util +NSString *FIRInstanceIDOperatingSystemVersion() { +#if TARGET_OS_IOS || TARGET_OS_TV + return [UIDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX || TARGET_OS_WATCH + return [NSProcessInfo processInfo].operatingSystemVersionString; +#endif +} + +BOOL FIRInstanceIDHasLocaleChanged() { + NSString *lastLocale = + [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale]; + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + if (lastLocale) { + if ([currentLocale isEqualToString:lastLocale]) { + return NO; + } + } + return YES; +} + +#pragma mark - Helpers + +BOOL FIRInstanceIDIsValidGCMScope(NSString *scope) { + return [scope compare:kFIRInstanceIDScopeFirebaseMessaging + options:NSCaseInsensitiveSearch] == NSOrderedSame; +} + +NSString *FIRInstanceIDStringForAPNSDeviceToken(NSData *deviceToken) { + NSMutableString *APNSToken = [NSMutableString string]; + unsigned char *bytes = (unsigned char *)[deviceToken bytes]; + for (int i = 0; i < (int)deviceToken.length; i++) { + [APNSToken appendFormat:@"%02x", bytes[i]]; + } + return APNSToken; +} + +NSString *FIRInstanceIDAPNSTupleStringForTokenAndServerType(NSData *deviceToken, BOOL isSandbox) { + if (deviceToken == nil) { + // A nil deviceToken leads to an invalid tuple string, so return nil. + return nil; + } + NSString *prefix = isSandbox ? kFIRInstanceIDAPNSSandboxPrefix : kFIRInstanceIDAPNSProdPrefix; + NSString *APNSString = FIRInstanceIDStringForAPNSDeviceToken(deviceToken); + NSString *APNSTupleString = [NSString stringWithFormat:@"%@%@", prefix, APNSString]; + + return APNSTupleString; +} + +#pragma mark - GCM Helpers + +NSString *FIRInstanceIDCurrentGCMVersion() { + Class versionClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + SEL versionSelector = NSSelectorFromString(kFIRInstanceIDFCMSDKVersionSelectorString); + if ([versionClass respondsToSelector:versionSelector]) { + IMP getVersionIMP = [versionClass methodForSelector:versionSelector]; + NSString *(*getVersion)(id, SEL) = (void *)getVersionIMP; + return getVersion(versionClass, versionSelector); + } + return nil; +} + +NSString *FIRInstanceIDCurrentLocale() { + Class localeClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + SEL localeSelector = NSSelectorFromString(kFIRInstanceIDFCMSDKLocaleSelectorString); + + if ([localeClass respondsToSelector:localeSelector]) { + IMP getLocaleIMP = [localeClass methodForSelector:localeSelector]; + NSString *(*getLocale)(id, SEL) = (void *)getLocaleIMP; + NSString *fcmLocale = getLocale(localeClass, localeSelector); + if (fcmLocale != nil) { + return fcmLocale; + } + } + + NSString *systemLanguage = [[NSLocale preferredLanguages] firstObject]; + if (systemLanguage != nil) { + return systemLanguage; + } + + if (@available(macOS 10.12, iOS 10.0, *)) { + return [NSLocale currentLocale].languageCode; + } else { + return nil; + } +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h new file mode 100644 index 00000000..ec5a76c5 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +/** + * Parsing utility for InstanceID Library versions. InstanceID lib follows semantic versioning. + * This provides utilities to parse the library versions to enable features and do + * updates based on appropriate library versions. + * + * Some example semantic versions are 1.0.1, 2.1.0, 2.1.1, 2.2.0-alpha1, 2.2.1-beta1 + */ + +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentLibraryVersion(void); +/// Returns the current Major version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionMajor(void); +/// Returns the current Minor version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionMinor(void); +/// Returns the current Patch version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionPatch(void); +/// Returns YES if current library version is `beta` else NO. +FOUNDATION_EXPORT BOOL FIRInstanceIDCurrentLibraryVersionIsBeta(void); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m new file mode 100644 index 00000000..c2e532a7 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m @@ -0,0 +1,85 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDVersionUtilities.h" + +// Convert the macro to a string +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +static NSString *const kSemanticVersioningSeparator = @"."; +static NSString *const kBetaVersionPrefix = @"-beta"; + +static NSString *libraryVersion; + +static int majorVersion; +static int minorVersion; +static int patchVersion; +static int betaVersion; + +void FIRInstanceIDParseCurrentLibraryVersion() { + static NSArray *allVersions; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableString *daylightVersion = + [NSMutableString stringWithUTF8String:STR(FIRInstanceID_LIB_VERSION)]; + // Parse versions + // major, minor, patch[-beta#] + allVersions = [daylightVersion componentsSeparatedByString:kSemanticVersioningSeparator]; + if (allVersions.count == 3) { + majorVersion = [allVersions[0] intValue]; + minorVersion = [allVersions[1] intValue]; + + // Parse patch and beta versions + NSArray *patchAndBetaVersion = + [allVersions[2] componentsSeparatedByString:kBetaVersionPrefix]; + if (patchAndBetaVersion.count == 2) { + patchVersion = [patchAndBetaVersion[0] intValue]; + betaVersion = [patchAndBetaVersion[1] intValue]; + } else if (patchAndBetaVersion.count == 1) { + patchVersion = [patchAndBetaVersion[0] intValue]; + } + } + + // Copy library version + libraryVersion = [daylightVersion copy]; + }); +} + +NSString *FIRInstanceIDCurrentLibraryVersion() { + FIRInstanceIDParseCurrentLibraryVersion(); + return libraryVersion; +} + +int FIRInstanceIDCurrentLibraryVersionMajor() { + FIRInstanceIDParseCurrentLibraryVersion(); + return majorVersion; +} + +int FIRInstanceIDCurrentLibraryVersionMinor() { + FIRInstanceIDParseCurrentLibraryVersion(); + return minorVersion; +} + +int FIRInstanceIDCurrentLibraryVersionPatch() { + FIRInstanceIDParseCurrentLibraryVersion(); + return patchVersion; +} + +BOOL FIRInstanceIDCurrentLibraryVersionIsBeta() { + FIRInstanceIDParseCurrentLibraryVersion(); + return betaVersion > 0; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h new file mode 100644 index 00000000..b533dc4a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDomain; + +typedef NS_ENUM(NSUInteger, FIRInstanceIDErrorCode) { + // Unknown error. + kFIRInstanceIDErrorCodeUnknown = 0, + + // Http related errors. + kFIRInstanceIDErrorCodeAuthentication = 1, + kFIRInstanceIDErrorCodeNoAccess = 2, + kFIRInstanceIDErrorCodeTimeout = 3, + kFIRInstanceIDErrorCodeNetwork = 4, + + // Another operation is in progress. + kFIRInstanceIDErrorCodeOperationInProgress = 5, + + // Failed to perform device check in. + kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn = 6, + + kFIRInstanceIDErrorCodeInvalidRequest = 7, + + // InstanceID generic errors + kFIRInstanceIDErrorCodeMissingDeviceID = 501, + + // InstanceID Token specific errors + kFIRInstanceIDErrorCodeMissingAPNSToken = 1001, + kFIRInstanceIDErrorCodeMissingAPNSServerType = 1002, + kFIRInstanceIDErrorCodeInvalidAuthorizedEntity = 1003, + kFIRInstanceIDErrorCodeInvalidScope = 1004, + kFIRInstanceIDErrorCodeInvalidStart = 1005, + kFIRInstanceIDErrorCodeInvalidKeyPair = 1006, + + // InstanceID Identity specific errors + // Generic InstanceID keypair error + kFIRInstanceIDErrorCodeMissingKeyPair = 2001, + kFIRInstanceIDErrorCodeInvalidKeyPairTags = 2002, + kFIRInstanceIDErrorCodeInvalidKeyPairCreationTime = 2005, + kFIRInstanceIDErrorCodeInvalidIdentity = 2006, + +}; + +@interface NSError (FIRInstanceID) + +@property(nonatomic, readonly) FIRInstanceIDErrorCode instanceIDErrorCode; + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode; + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode + userInfo:(NSDictionary *)userInfo; + ++ (NSError *)FIRInstanceIDErrorMissingCheckin; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m new file mode 100644 index 00000000..560a5df0 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "NSError+FIRInstanceID.h" + +NSString *const kFIRInstanceIDDomain = @"com.firebase.iid"; + +@implementation NSError (FIRInstanceID) + +- (FIRInstanceIDErrorCode)instanceIDErrorCode { + return (FIRInstanceIDErrorCode)self.code; +} + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode { + return [NSError errorWithFIRInstanceIDErrorCode:errorCode userInfo:nil]; +} + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode + userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:kFIRInstanceIDDomain code:errorCode userInfo:userInfo]; +} + ++ (NSError *)FIRInstanceIDErrorMissingCheckin { + NSDictionary *userInfo = @{@"msg" : @"Missing device credentials. Retry later."}; + + return [NSError errorWithDomain:kFIRInstanceIDDomain + code:kFIRInstanceIDErrorCodeMissingDeviceID + userInfo:userInfo]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID+Private.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID+Private.h new file mode 100644 index 00000000..632e21bc --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID+Private.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <FirebaseInstanceID/FIRInstanceID.h> +#import <FirebaseInstanceID/FIRInstanceIDCheckinPreferences.h> + +/** + * @related FIRInstanceIDCheckinService + * + * The completion handler invoked once the fetch from Checkin server finishes. + * For successful fetches we returned checkin information by the checkin service + * and `nil` error, else we return the appropriate error object as reported by the + * Checkin Service. + * + * @param checkinPreferences The checkin preferences as fetched from the server. + * @param error The error object which fetching GServices data. + */ +typedef void (^FIRInstanceIDDeviceCheckinCompletion)( + FIRInstanceIDCheckinPreferences *_Nullable checkinPreferences, NSError *_Nullable error); + +/** + * Private API used by Firebase SDK teams by calling in reflection or internal teams. + */ +@interface FIRInstanceID (Private) + +/** + * Fetches checkin info for the app. If the app has valid cached checkin preferences + * they are returned instead of making a network request. + * + * @param handler The completion handler to invoke once the request has completed. + */ +- (void)fetchCheckinInfoWithHandler:(nullable FIRInstanceIDDeviceCheckinCompletion)handler; + +/** + * Get the InstanceID for the app. If an ID was created before and cached + * successfully we will return that ID. If no cached ID exists we create + * a new ID, cache it and return that. + * + * This is a blocking call and should not really be called on the main thread. + * + * @param error The error object that represents the error while trying to + * retrieve the instance id. + * + * @return The InstanceID for the app. + */ +- (nullable NSString *)appInstanceID:(NSError *_Nullable *_Nullable)error + DEPRECATED_MSG_ATTRIBUTE("Please use getID(handler:) for Swift or " + "getIDWithHandler: for Objective-C instead."); + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h new file mode 100644 index 00000000..be3ec572 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +/** + * The preferences InstanceID loads from checkin server. The deviceID and secret that checkin + * provides is used to authenticate all future requests to the server. Besides the deviceID + * and secret the other information that checkin provides is stored in a plist on the device. + * The deviceID and secret are persisted in the device keychain. + */ +@interface FIRInstanceIDCheckinPreferences : NSObject + +/** + * DeviceID and secretToken are the checkin auth credentials and are stored in the Keychain. + */ +@property(nonatomic, readonly, copy) NSString *deviceID; +@property(nonatomic, readonly, copy) NSString *secretToken; + +/** + * All the other checkin preferences other than deviceID and secret are stored in a plist. + */ +@property(nonatomic, readonly, copy) NSString *deviceDataVersion; +@property(nonatomic, readonly, copy) NSString *digest; +@property(nonatomic, readonly, copy) NSString *versionInfo; +@property(nonatomic, readonly, assign) int64_t lastCheckinTimestampMillis; + +/** + * The content retrieved from checkin server that should be persisted in a plist. This + * doesn't contain the deviceID and secret which are stored in the Keychain since they + * should be more private. + * + * @return The checkin preferences that should be persisted in a plist. + */ +- (NSDictionary *)checkinPlistContents; + +/** + * Return whether checkin info exists, valid or not. + */ +- (BOOL)hasCheckinInfo; + +/** + * Verify if checkin preferences are valid or not. + * + * @return YES if valid checkin preferences else NO. + */ +- (BOOL)hasValidCheckinInfo; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h new file mode 100644 index 00000000..c343f88d --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h @@ -0,0 +1,74 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <FirebaseInstanceID/FIRInstanceID.h> + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDCheckinPreferences; +@class FIRInstallations; + +/** + * Private API used by other Firebase SDKs. + */ +@interface FIRInstanceID () + +@property(nonatomic, readonly, strong) NSString *deviceAuthID; +@property(nonatomic, readonly, strong) NSString *secretToken; +@property(nonatomic, readonly, strong) NSString *versionInfo; + +@property(nonatomic, readonly, strong) FIRInstallations *installations; + +/// A cached value of FID. Should be used only for `-[FIRInstanceID appInstanceID:]`. +@property(atomic, readonly, copy, nullable) NSString *firebaseInstallationsID; + +/** + * Private initializer. + */ +- (instancetype)initPrivately; + +/** + * Returns a Firebase Messaging scoped token for the firebase app. + * + * @return Returns the stored token if the device has registered with Firebase Messaging, otherwise + * returns nil. + */ +- (nullable NSString *)token; + +/** + * Verify if valid checkin preferences have been loaded in memory. + * + * @return YES if valid checkin preferences exist in memory else NO. + */ +- (BOOL)hasValidCheckinInfo; + +/** + * Try to load prefetched checkin preferences from the cache. This supports the use case where + * InstanceID library has already obtained a valid checkin and we should be using that. + * + * This should be used as a last gasp effort to retreive any cached checkin preferences before + * hitting the FIRMessaging backend to retrieve new preferences. + * + * Note this is only required because InstanceID and FIRMessaging both require checkin preferences + * which need to be synced with each other. + * + * @return YES if successfully loaded cached checkin preferences into memory else NO. + */ +- (BOOL)tryToLoadValidCheckinInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h new file mode 100644 index 00000000..0f96d910 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h @@ -0,0 +1,312 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDResult; +/** + * @memberof FIRInstanceID + * + * The scope to be used when fetching/deleting a token for Firebase Messaging. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceIDScopeFirebaseMessaging + NS_SWIFT_NAME(InstanceIDScopeFirebaseMessaging); + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +/** + * Called when the system determines that tokens need to be refreshed. + * This method is also called if Instance ID has been reset in which + * case, tokens and FCM topic subscriptions also need to be refreshed. + * + * Instance ID service will throttle the refresh event across all devices + * to control the rate of token updates on application servers. + */ +FOUNDATION_EXPORT const NSNotificationName kFIRInstanceIDTokenRefreshNotification + NS_SWIFT_NAME(InstanceIDTokenRefresh); +#else +/** + * Called when the system determines that tokens need to be refreshed. + * This method is also called if Instance ID has been reset in which + * case, tokens and FCM topic subscriptions also need to be refreshed. + * + * Instance ID service will throttle the refresh event across all devices + * to control the rate of token updates on application servers. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenRefreshNotification + NS_SWIFT_NAME(InstanceIDTokenRefreshNotification); +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the InstanceID token returns. If + * the call fails we return the appropriate `error code` as described below. + * + * @param token The valid token as returned by InstanceID backend. + * + * @param error The error describing why generating a new token + * failed. See the error codes below for a more detailed + * description. + */ +typedef void (^FIRInstanceIDTokenHandler)(NSString *__nullable token, NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDTokenHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the InstanceID `deleteToken` returns. If + * the call fails we return the appropriate `error code` as described below + * + * @param error The error describing why deleting the token failed. + * See the error codes below for a more detailed description. + */ +typedef void (^FIRInstanceIDDeleteTokenHandler)(NSError *error) + NS_SWIFT_NAME(InstanceIDDeleteTokenHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity is created. If the + * identity wasn't created for some reason we return the appropriate error code. + * + * @param identity A valid identity for the app instance, nil if there was an error + * while creating an identity. + * @param error The error if fetching the identity fails else nil. + */ +typedef void (^FIRInstanceIDHandler)(NSString *__nullable identity, NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity and all the tokens associated + * with it are deleted. Returns a valid error object in case of failure else nil. + * + * @param error The error if deleting the identity and all the tokens associated with + * it fails else nil. + */ +typedef void (^FIRInstanceIDDeleteHandler)(NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDDeleteHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity and token are fetched. If the + * identity wasn't created for some reason we return the appropriate error code. + * + * @param result The result containing an identity for the app instance and a valid token, + * nil if there was an error while creating the result. + * @param error The error if fetching the identity or token fails else nil. + */ +typedef void (^FIRInstanceIDResultHandler)(FIRInstanceIDResult *__nullable result, + NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDResultHandler); + +/** + * Public errors produced by InstanceID. + */ +typedef NS_ENUM(NSUInteger, FIRInstanceIDError) { + // Http related errors. + + /// Unknown error. + FIRInstanceIDErrorUnknown = 0, + + /// Auth Error -- GCM couldn't validate request from this client. + FIRInstanceIDErrorAuthentication = 1, + + /// NoAccess -- InstanceID service cannot be accessed. + FIRInstanceIDErrorNoAccess = 2, + + /// Timeout -- Request to InstanceID backend timed out. + FIRInstanceIDErrorTimeout = 3, + + /// Network -- No network available to reach the servers. + FIRInstanceIDErrorNetwork = 4, + + /// OperationInProgress -- Another similar operation in progress, + /// bailing this one. + FIRInstanceIDErrorOperationInProgress = 5, + + /// InvalidRequest -- Some parameters of the request were invalid. + FIRInstanceIDErrorInvalidRequest = 7, +} NS_SWIFT_NAME(InstanceIDError); + +/** + * A class contains the results of InstanceID and token query. + */ +NS_SWIFT_NAME(InstanceIDResult) +@interface FIRInstanceIDResult : NSObject <NSCopying> + +/** + * An instanceID uniquely identifies the app instance. + */ +@property(nonatomic, readonly, copy) NSString *instanceID; + +/* + * Returns a Firebase Messaging scoped token for the firebase app. + */ +@property(nonatomic, readonly, copy) NSString *token; + +@end + +/** + * Instance ID provides a unique identifier for each app instance and a mechanism + * to authenticate and authorize actions (for example, sending an FCM message). + * + * Once an InstanceID is generated, the library periodically sends information about the + * application and the device where it's running to the Firebase backend. To stop this. see + * `[FIRInstanceID deleteIDWithHandler:]`. + * + * Instance ID is long lived but, may be reset if the device is not used for + * a long time or the Instance ID service detects a problem. + * If Instance ID is reset, the app will be notified via + * `kFIRInstanceIDTokenRefreshNotification`. + * + * If the Instance ID has become invalid, the app can request a new one and + * send it to the app server. + * To prove ownership of Instance ID and to allow servers to access data or + * services associated with the app, call + * `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`. + */ +NS_SWIFT_NAME(InstanceID) +@interface FIRInstanceID : NSObject + +/** + * FIRInstanceID. + * + * @return A shared instance of FIRInstanceID. + */ ++ (instancetype)instanceID NS_SWIFT_NAME(instanceID()); + +/** + * Unavailable. Use +instanceID instead. + */ +- (instancetype)init __attribute__((unavailable("Use +instanceID instead."))); + +#pragma mark - Tokens + +/** + * Returns a result of app instance identifier InstanceID and a Firebase Messaging scoped token. + * param handler The callback handler invoked when an app instanceID and a default token + * are generated and returned. If instanceID and token fetching fail for some + * reason the callback is invoked with nil `result` and the appropriate error. + */ +- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler; + +/** + * Returns a token that authorizes an Entity (example: cloud service) to perform + * an action on behalf of the application identified by Instance ID. + * + * This is similar to an OAuth2 token except, it applies to the + * application instance instead of a user. + * + * This is an asynchronous call. If the token fetching fails for some reason + * we invoke the completion callback with nil `token` and the appropriate + * error. + * + * This generates an Instance ID if it does not exist yet, which starts periodically sending + * information to the Firebase backend (see `[FIRInstanceID getIDWithHandler:]`). + * + * Note, you can only have one `token` or `deleteToken` call for a given + * authorizedEntity and scope at any point of time. Making another such call with the + * same authorizedEntity and scope before the last one finishes will result in an + * error with code `OperationInProgress`. + * + * @see FIRInstanceID deleteTokenWithAuthorizedEntity:scope:handler: + * + * @param authorizedEntity Entity authorized by the token. + * @param scope Action authorized for authorizedEntity. + * @param options The extra options to be sent with your token request. The + * value for the `apns_token` should be the NSData object + * passed to the UIApplicationDelegate's + * `didRegisterForRemoteNotificationsWithDeviceToken` method. + * The value for `apns_sandbox` should be a boolean (or an + * NSNumber representing a BOOL in Objective-C) set to true if + * your app is a debug build, which means that the APNs + * device token is for the sandbox environment. It should be + * set to false otherwise. If the `apns_sandbox` key is not + * provided, an automatically-detected value shall be used. + * @param handler The callback handler which is invoked when the token is + * successfully fetched. In case of success a valid `token` and + * `nil` error are returned. In case of any error the `token` + * is nil and a valid `error` is returned. The valid error + * codes have been documented above. + */ +- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler; + +/** + * Revokes access to a scope (action) for an entity previously + * authorized by `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`. + * + * This is an asynchronous call. Call this on the main thread since InstanceID lib + * is not thread safe. In case token deletion fails for some reason we invoke the + * `handler` callback passed in with the appropriate error code. + * + * Note, you can only have one `token` or `deleteToken` call for a given + * authorizedEntity and scope at a point of time. Making another such call with the + * same authorizedEntity and scope before the last one finishes will result in an error + * with code `OperationInProgress`. + * + * @param authorizedEntity Entity that must no longer have access. + * @param scope Action that entity is no longer authorized to perform. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of error an appropriate error object is returned + * else error is nil. + */ +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + handler:(FIRInstanceIDDeleteTokenHandler)handler; + +#pragma mark - Identity + +/** + * Asynchronously fetch a stable identifier that uniquely identifies the app + * instance. If the identifier has been revoked or has expired, this method will + * return a new identifier. + * + * Once an InstanceID is generated, the library periodically sends information about the + * application and the device where it's running to the Firebase backend. To stop this. see + * `[FIRInstanceID deleteIDWithHandler:]`. + * + * @param handler The handler to invoke once the identifier has been fetched. + * In case of error an appropriate error object is returned else + * a valid identifier is returned and a valid identifier for the + * application instance. + */ +- (void)getIDWithHandler:(FIRInstanceIDHandler)handler NS_SWIFT_NAME(getID(handler:)); + +/** + * Resets Instance ID and revokes all tokens. + * + * This method also triggers a request to fetch a new Instance ID and Firebase Messaging scope + * token. Please listen to kFIRInstanceIDTokenRefreshNotification when the new ID and token are + * ready. + * + * This stops the periodic sending of data to the Firebase backend that began when the Instance ID + * was generated. No more data is sent until another library calls Instance ID internally again + * (like FCM, RemoteConfig or Analytics) or user explicitly calls Instance ID APIs to get an + * Instance ID and token again. + */ +- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler NS_SWIFT_NAME(deleteID(handler:)); + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h new file mode 100644 index 00000000..78c9ef16 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h @@ -0,0 +1,17 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" |
