| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /*
- * 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 "FirebaseMessaging/Sources/Token/FIRMessagingTokenOperation.h"
- #import <GoogleUtilities/GULAppEnvironmentUtil.h>
- #import "FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h"
- #import "FirebaseMessaging/Sources/FIRMessagingLogger.h"
- #import "FirebaseMessaging/Sources/FIRMessagingUtilities.h"
- #import "FirebaseMessaging/Sources/FIRMessaging_Private.h"
- #import "FirebaseMessaging/Sources/NSError+FIRMessaging.h"
- #import "FirebaseMessaging/Sources/Token/FIRMessagingCheckinPreferences.h"
- static const NSInteger kFIRMessagingPlatformVersionIOS = 2;
- // Scope parameter that defines the service using the token
- static NSString *const kFIRMessagingParamScope = @"X-scope";
- // Defines the SDK version
- static NSString *const kFIRMessagingParamFCMLibVersion = @"X-cliv";
- @interface FIRMessagingTokenOperation () {
- BOOL _isFinished;
- BOOL _isExecuting;
- NSMutableArray<FIRMessagingTokenOperationCompletion> *_completionHandlers;
- FIRMessagingCheckinPreferences *_checkinPreferences;
- }
- @property(nonatomic, readwrite, strong) NSString *instanceID;
- @property(atomic, strong, nullable) NSString *FISAuthToken;
- @end
- @implementation FIRMessagingTokenOperation
- - (instancetype)initWithAction:(FIRMessagingTokenAction)action
- forAuthorizedEntity:(NSString *)authorizedEntity
- scope:(NSString *)scope
- options:(NSDictionary<NSString *, NSString *> *)options
- checkinPreferences:(FIRMessagingCheckinPreferences *)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 alloc] init];
- _isExecuting = NO;
- _isFinished = NO;
- }
- return self;
- }
- - (void)dealloc {
- [_completionHandlers removeAllObjects];
- }
- - (void)addCompletionHandler:(FIRMessagingTokenOperationCompletion)handler {
- [_completionHandlers addObject:[handler copy]];
- }
- - (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:FIRMessagingTokenOperationCancelled 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) {
- FIRMessagingErrorCode errorCode = kFIRMessagingErrorCodeRegistrarFailedToCheckIn;
- [self finishWithResult:FIRMessagingTokenOperationError
- token:nil
- error:[NSError messagingErrorWithCode:errorCode
- failureReason:
- @"Failed to checkin before token registration."]];
- 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:FIRMessagingTokenOperationError token:nil error:error];
- }
- }];
- }
- - (void)finishWithResult:(FIRMessagingTokenOperationResult)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;
- for (FIRMessagingTokenOperationCompletion completionHandler in _completionHandlers) {
- completionHandler(result, token, error);
- }
- [self setExecuting:NO];
- [self setFinished:YES];
- }
- - (void)cancel {
- [super cancel];
- [self.dataTask cancel];
- [self finishWithResult:FIRMessagingTokenOperationCancelled token:nil error:nil];
- }
- - (void)performTokenOperation {
- }
- - (NSMutableURLRequest *)tokenRequest {
- NSString *authHeader =
- [FIRMessagingTokenOperation 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:FIRMessagingTokenRegisterServer()];
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
- // Add HTTP headers
- [request setValue:authHeaderString forHTTPHeaderField:@"Authorization"];
- [request setValue:FIRMessagingAppIdentifier() 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 = [GULAppEnvironmentUtil systemVersion];
- [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:kFIRMessagingParamScope value:scope]];
- }
- // E.g. plat=2
- NSString *platform = [NSString stringWithFormat:@"%ld", (long)kFIRMessagingPlatformVersionIOS];
- [queryItems addObject:[NSURLQueryItem queryItemWithName:@"plat" value:platform]];
- // E.g. app=com.myapp.foo
- NSString *appIdentifier = FIRMessagingAppIdentifier();
- [queryItems addObject:[NSURLQueryItem queryItemWithName:@"app" value:appIdentifier]];
- // E.g. app_ver=1.5
- NSString *appVersion = FIRMessagingCurrentAppVersion();
- [queryItems addObject:[NSURLQueryItem queryItemWithName:@"app_ver" value:appVersion]];
- // E.g. X-cliv=fiid-1.2.3
- NSString *fcmLibraryVersion =
- [NSString stringWithFormat:@"fiid-%@", [FIRMessaging FIRMessagingSDKVersion]];
- if (fcmLibraryVersion.length) {
- NSURLQueryItem *gcmLibVersion =
- [NSURLQueryItem queryItemWithName:kFIRMessagingParamFCMLibVersion value:fcmLibraryVersion];
- [queryItems addObject:gcmLibVersion];
- }
- return queryItems;
- }
- #pragma mark - Header
- + (NSString *)HTTPAuthHeaderFromCheckin:(FIRMessagingCheckinPreferences *)checkin {
- NSString *deviceID = checkin.deviceID;
- NSString *secret = checkin.secretToken;
- return [NSString stringWithFormat:@"AidLogin %@:%@", deviceID, secret];
- }
- @end
|