Sin descripción

FIRInstanceIDTokenOperation.m 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. * Copyright 2019 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "FIRInstanceIDTokenOperation.h"
  17. #import "FIRInstanceIDCheckinPreferences.h"
  18. #import "FIRInstanceIDDefines.h"
  19. #import "FIRInstanceIDKeyPair.h"
  20. #import "FIRInstanceIDKeyPairUtilities.h"
  21. #import "FIRInstanceIDLogger.h"
  22. #import "FIRInstanceIDURLQueryItem.h"
  23. #import "FIRInstanceIDUtilities.h"
  24. #import "NSError+FIRInstanceID.h"
  25. static const NSInteger kFIRInstanceIDPlatformVersionIOS = 2;
  26. static NSString *const kFIRInstanceIDParamInstanceID = @"appid";
  27. // Scope parameter that defines the service using the token
  28. static NSString *const kFIRInstanceIDParamScope = @"X-scope";
  29. // Defines the SDK version
  30. static NSString *const kFIRInstanceIDParamFCMLibVersion = @"X-cliv";
  31. @interface FIRInstanceIDTokenOperation () {
  32. BOOL _isFinished;
  33. BOOL _isExecuting;
  34. }
  35. @property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences;
  36. @property(nonatomic, readwrite, strong) FIRInstanceIDKeyPair *keyPair;
  37. @property(atomic, strong) NSURLSessionDataTask *dataTask;
  38. @property(readonly, strong)
  39. NSMutableArray<FIRInstanceIDTokenOperationCompletion> *completionHandlers;
  40. // For testing only
  41. @property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock;
  42. @end
  43. @implementation FIRInstanceIDTokenOperation
  44. + (NSURLSession *)sharedURLSession {
  45. static NSURLSession *tokenOperationSharedSession;
  46. static dispatch_once_t onceToken;
  47. dispatch_once(&onceToken, ^{
  48. NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
  49. config.timeoutIntervalForResource = 60.0f; // 1 minute
  50. tokenOperationSharedSession = [NSURLSession sessionWithConfiguration:config];
  51. tokenOperationSharedSession.sessionDescription = @"com.google.iid.tokens.session";
  52. });
  53. return tokenOperationSharedSession;
  54. }
  55. - (instancetype)initWithAction:(FIRInstanceIDTokenAction)action
  56. forAuthorizedEntity:(NSString *)authorizedEntity
  57. scope:(NSString *)scope
  58. options:(NSDictionary<NSString *, NSString *> *)options
  59. checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences
  60. keyPair:(FIRInstanceIDKeyPair *)keyPair {
  61. self = [super init];
  62. if (self) {
  63. _action = action;
  64. _authorizedEntity = [authorizedEntity copy];
  65. _scope = [scope copy];
  66. _options = [options copy];
  67. _checkinPreferences = checkinPreferences;
  68. _keyPair = keyPair;
  69. _completionHandlers = [NSMutableArray array];
  70. _isExecuting = NO;
  71. _isFinished = NO;
  72. }
  73. return self;
  74. }
  75. - (void)dealloc {
  76. _testBlock = nil;
  77. _authorizedEntity = nil;
  78. _scope = nil;
  79. _options = nil;
  80. _checkinPreferences = nil;
  81. _keyPair = nil;
  82. [_completionHandlers removeAllObjects];
  83. _completionHandlers = nil;
  84. }
  85. - (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler {
  86. [self.completionHandlers addObject:handler];
  87. }
  88. - (BOOL)isAsynchronous {
  89. return YES;
  90. }
  91. - (BOOL)isExecuting {
  92. return _isExecuting;
  93. }
  94. - (void)setExecuting:(BOOL)executing {
  95. [self willChangeValueForKey:@"isExecuting"];
  96. _isExecuting = executing;
  97. [self didChangeValueForKey:@"isExecuting"];
  98. }
  99. - (BOOL)isFinished {
  100. return _isFinished;
  101. }
  102. - (void)setFinished:(BOOL)finished {
  103. [self willChangeValueForKey:@"isFinished"];
  104. _isFinished = finished;
  105. [self didChangeValueForKey:@"isFinished"];
  106. }
  107. - (void)start {
  108. if (self.isCancelled) {
  109. [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil];
  110. return;
  111. }
  112. // Quickly validate whether or not the operation has all it needs to begin
  113. BOOL checkinfoAvailable = [self.checkinPreferences hasCheckinInfo];
  114. _FIRInstanceIDDevAssert(checkinfoAvailable, @"Cannot fetch token invalid checkin state");
  115. if (!checkinfoAvailable) {
  116. FIRInstanceIDErrorCode errorCode = kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn;
  117. [self finishWithResult:FIRInstanceIDTokenOperationError
  118. token:nil
  119. error:[NSError errorWithFIRInstanceIDErrorCode:errorCode]];
  120. return;
  121. }
  122. [self setExecuting:YES];
  123. [self performTokenOperation];
  124. }
  125. - (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result
  126. token:(nullable NSString *)token
  127. error:(nullable NSError *)error {
  128. // Add a check to prevent this finish from being called more than once.
  129. if (self.isFinished) {
  130. return;
  131. }
  132. self.dataTask = nil;
  133. _result = result;
  134. // TODO(chliangGoogle): Call these in the main thread?
  135. for (FIRInstanceIDTokenOperationCompletion completionHandler in self.completionHandlers) {
  136. completionHandler(result, token, error);
  137. }
  138. [self setExecuting:NO];
  139. [self setFinished:YES];
  140. }
  141. - (void)cancel {
  142. [super cancel];
  143. [self.dataTask cancel];
  144. [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil];
  145. }
  146. - (void)performTokenOperation {
  147. }
  148. #pragma mark - Request Construction
  149. + (NSMutableURLRequest *)requestWithAuthHeader:(NSString *)authHeaderString {
  150. NSURL *url = [NSURL URLWithString:FIRInstanceIDRegisterServer()];
  151. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  152. // Add HTTP headers
  153. [request setValue:authHeaderString forHTTPHeaderField:@"Authorization"];
  154. [request setValue:FIRInstanceIDAppIdentifier() forHTTPHeaderField:@"app"];
  155. request.HTTPMethod = @"POST";
  156. return request;
  157. }
  158. + (NSMutableArray<FIRInstanceIDURLQueryItem *> *)standardQueryItemsWithDeviceID:(NSString *)deviceID
  159. scope:(NSString *)scope {
  160. NSMutableArray<FIRInstanceIDURLQueryItem *> *queryItems = [NSMutableArray arrayWithCapacity:8];
  161. // E.g. X-osv=10.2.1
  162. NSString *systemVersion = FIRInstanceIDOperatingSystemVersion();
  163. [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"X-osv" value:systemVersion]];
  164. // E.g. device=
  165. if (deviceID) {
  166. [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"device" value:deviceID]];
  167. }
  168. // E.g. X-scope=fcm
  169. if (scope) {
  170. [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamScope
  171. value:scope]];
  172. }
  173. // E.g. plat=2
  174. NSString *platform = [NSString stringWithFormat:@"%ld", (long)kFIRInstanceIDPlatformVersionIOS];
  175. [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"plat" value:platform]];
  176. // E.g. app=com.myapp.foo
  177. NSString *appIdentifier = FIRInstanceIDAppIdentifier();
  178. [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app" value:appIdentifier]];
  179. // E.g. app_ver=1.5
  180. NSString *appVersion = FIRInstanceIDCurrentAppVersion();
  181. [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app_ver" value:appVersion]];
  182. // E.g. X-cliv=fiid-1.2.3
  183. NSString *fcmLibraryVersion =
  184. [NSString stringWithFormat:@"fiid-%@", FIRInstanceIDCurrentGCMVersion()];
  185. if (fcmLibraryVersion.length) {
  186. FIRInstanceIDURLQueryItem *gcmLibVersion =
  187. [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamFCMLibVersion
  188. value:fcmLibraryVersion];
  189. [queryItems addObject:gcmLibVersion];
  190. }
  191. return queryItems;
  192. }
  193. - (NSArray<FIRInstanceIDURLQueryItem *> *)queryItemsWithKeyPair:(FIRInstanceIDKeyPair *)keyPair {
  194. NSMutableArray<FIRInstanceIDURLQueryItem *> *items = [NSMutableArray arrayWithCapacity:3];
  195. // appid=
  196. NSString *instanceID = FIRInstanceIDAppIdentity(keyPair);
  197. [items addObject:[FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamInstanceID
  198. value:instanceID]];
  199. return items;
  200. }
  201. #pragma mark - HTTP Header
  202. + (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin {
  203. NSString *deviceID = checkin.deviceID;
  204. NSString *secret = checkin.secretToken;
  205. return [NSString stringWithFormat:@"AidLogin %@:%@", deviceID, secret];
  206. }
  207. @end