123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- /*
- * 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 "FIRInstanceIDCheckinPreferences.h"
- #import "FIRInstanceIDKeyPair.h"
- #import "FIRInstanceIDKeyPairUtilities.h"
- #import "FIRInstanceIDLogger.h"
- #import "FIRInstanceIDURLQueryItem.h"
- #import "FIRInstanceIDUtilities.h"
- #import "NSError+FIRInstanceID.h"
-
- static const NSInteger kFIRInstanceIDPlatformVersionIOS = 2;
-
- static NSString *const kFIRInstanceIDParamInstanceID = @"appid";
- // 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) FIRInstanceIDKeyPair *keyPair;
-
- @property(atomic, strong) NSURLSessionDataTask *dataTask;
- @property(readonly, strong)
- NSMutableArray<FIRInstanceIDTokenOperationCompletion> *completionHandlers;
-
- // 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
- keyPair:(FIRInstanceIDKeyPair *)keyPair {
- self = [super init];
- if (self) {
- _action = action;
- _authorizedEntity = [authorizedEntity copy];
- _scope = [scope copy];
- _options = [options copy];
- _checkinPreferences = checkinPreferences;
- _keyPair = keyPair;
- _completionHandlers = [NSMutableArray array];
-
- _isExecuting = NO;
- _isFinished = NO;
- }
- return self;
- }
-
- - (void)dealloc {
- _testBlock = nil;
- _authorizedEntity = nil;
- _scope = nil;
- _options = nil;
- _checkinPreferences = nil;
- _keyPair = 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];
-
- [self performTokenOperation];
- }
-
- - (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 {
- }
-
- #pragma mark - Request Construction
- + (NSMutableURLRequest *)requestWithAuthHeader:(NSString *)authHeaderString {
- NSURL *url = [NSURL URLWithString:FIRInstanceIDRegisterServer()];
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
-
- // Add HTTP headers
- [request setValue:authHeaderString forHTTPHeaderField:@"Authorization"];
- [request setValue:FIRInstanceIDAppIdentifier() forHTTPHeaderField:@"app"];
- request.HTTPMethod = @"POST";
- return request;
- }
-
- + (NSMutableArray<FIRInstanceIDURLQueryItem *> *)standardQueryItemsWithDeviceID:(NSString *)deviceID
- scope:(NSString *)scope {
- NSMutableArray<FIRInstanceIDURLQueryItem *> *queryItems = [NSMutableArray arrayWithCapacity:8];
-
- // E.g. X-osv=10.2.1
- NSString *systemVersion = FIRInstanceIDOperatingSystemVersion();
- [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"X-osv" value:systemVersion]];
- // E.g. device=
- if (deviceID) {
- [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"device" value:deviceID]];
- }
- // E.g. X-scope=fcm
- if (scope) {
- [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamScope
- value:scope]];
- }
- // E.g. plat=2
- NSString *platform = [NSString stringWithFormat:@"%ld", (long)kFIRInstanceIDPlatformVersionIOS];
- [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"plat" value:platform]];
- // E.g. app=com.myapp.foo
- NSString *appIdentifier = FIRInstanceIDAppIdentifier();
- [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app" value:appIdentifier]];
- // E.g. app_ver=1.5
- NSString *appVersion = FIRInstanceIDCurrentAppVersion();
- [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app_ver" value:appVersion]];
- // E.g. X-cliv=fiid-1.2.3
- NSString *fcmLibraryVersion =
- [NSString stringWithFormat:@"fiid-%@", FIRInstanceIDCurrentGCMVersion()];
- if (fcmLibraryVersion.length) {
- FIRInstanceIDURLQueryItem *gcmLibVersion =
- [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamFCMLibVersion
- value:fcmLibraryVersion];
- [queryItems addObject:gcmLibVersion];
- }
-
- return queryItems;
- }
-
- - (NSArray<FIRInstanceIDURLQueryItem *> *)queryItemsWithKeyPair:(FIRInstanceIDKeyPair *)keyPair {
- NSMutableArray<FIRInstanceIDURLQueryItem *> *items = [NSMutableArray arrayWithCapacity:3];
- // appid=
- NSString *instanceID = FIRInstanceIDAppIdentity(keyPair);
- [items addObject:[FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamInstanceID
- value:instanceID]];
- return items;
- }
-
- #pragma mark - HTTP Header
-
- + (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin {
- NSString *deviceID = checkin.deviceID;
- NSString *secret = checkin.secretToken;
- return [NSString stringWithFormat:@"AidLogin %@:%@", deviceID, secret];
- }
- @end
|