AutorÃa | Ultima modificación | Ver Log |
/** 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/FIRMessagingCheckinStore.h"#import "FirebaseMessaging/Sources/FIRMessagingCode.h"#import "FirebaseMessaging/Sources/FIRMessagingConstants.h"#import "FirebaseMessaging/Sources/FIRMessagingLogger.h"#import "FirebaseMessaging/Sources/FIRMessagingUtilities.h"#import "FirebaseMessaging/Sources/NSError+FIRMessaging.h"#import "FirebaseMessaging/Sources/Token/FIRMessagingAuthKeychain.h"#import "FirebaseMessaging/Sources/Token/FIRMessagingBackupExcludedPlist.h"#import "FirebaseMessaging/Sources/Token/FIRMessagingCheckinPreferences.h"#import "FirebaseMessaging/Sources/Token/FIRMessagingCheckinService.h"// NOTE: These values should be in sync with what InstanceID saves in as.static NSString *const kCheckinFileName = @"g-checkin";static NSString *const kFIRMessagingCheckinKeychainGeneric = @"com.google.iid";NSString *const kFIRMessagingCheckinKeychainService = @"com.google.iid.checkin";@interface FIRMessagingCheckinStore ()@property(nonatomic, readwrite, strong) FIRMessagingBackupExcludedPlist *plist;@property(nonatomic, readwrite, strong) FIRMessagingAuthKeychain *keychain;// Checkin will store items under// Keychain account: <app bundle id>,// Keychain service: |kFIRMessagingCheckinKeychainService|@property(nonatomic, readonly) NSString *bundleIdentifierForKeychainAccount;@end@implementation FIRMessagingCheckinStore- (instancetype)init {self = [super init];if (self) {_plist = [[FIRMessagingBackupExcludedPlist alloc]initWithFileName:kCheckinFileNamesubDirectory:kFIRMessagingInstanceIDSubDirectoryName];_keychain =[[FIRMessagingAuthKeychain alloc] initWithIdentifier:kFIRMessagingCheckinKeychainGeneric];}return self;}- (BOOL)hasCheckinPlist {return [self.plist doesFileExist];}- (NSString *)bundleIdentifierForKeychainAccount {static NSString *bundleIdentifier;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{bundleIdentifier = FIRMessagingAppIdentifier();});return bundleIdentifier;}- (void)saveCheckinPreferences:(FIRMessagingCheckinPreferences *)preferenceshandler:(void (^)(NSError *error))handler {NSDictionary *checkinPlistContents = [preferences checkinPlistContents];NSString *checkinKeychainContent = [preferences checkinKeychainContent];if (![checkinKeychainContent length]) {NSString *failureReason = @"Failed to get checkin keychain content from memory.";FIRMessagingLoggerDebug(kFIRMessagingMessageCodeCheckinStore000, @"%@", failureReason);if (handler) {handler([NSError messagingErrorWithCode:kFIRMessagingErrorCodeRegistrarFailedToCheckInfailureReason:failureReason]);}return;}if (![checkinPlistContents count]) {NSString *failureReason = @"Failed to get checkin plist contents from memory.";FIRMessagingLoggerDebug(kFIRMessagingMessageCodeCheckinStore001, @"%@", failureReason);if (handler) {handler([NSError messagingErrorWithCode:kFIRMessagingErrorCodeRegistrarFailedToCheckInfailureReason:failureReason]);}return;}// Save all other checkin preferences in a plistNSError *error;if (![self.plist writeDictionary:checkinPlistContents error:&error]) {FIRMessagingLoggerDebug(kFIRMessagingMessageCodeCheckinStore003,@"Failed to save checkin plist contents."@"Will delete auth credentials");[self.keychain removeItemsMatchingService:kFIRMessagingCheckinKeychainServiceaccount:self.bundleIdentifierForKeychainAccounthandler:nil];if (handler) {handler(error);}return;}FIRMessagingLoggerDebug(kFIRMessagingMessageCodeCheckinStoreCheckinPlistSaved,@"Checkin plist file is saved");// Save the deviceID and secret in the Keychainif (!preferences.hasPreCachedAuthCredentials) {NSData *data = [checkinKeychainContent dataUsingEncoding:NSUTF8StringEncoding];[self.keychain setData:dataforService:kFIRMessagingCheckinKeychainServiceaccount:self.bundleIdentifierForKeychainAccounthandler:^(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;}FIRMessagingLoggerDebug(kFIRMessagingMessageCodeCheckinStoreCheckinPlistDeleted,@"Deleted checkin plist file.");// Remove deviceID and secret from Keychain[self.keychain removeItemsMatchingService:kFIRMessagingCheckinKeychainServiceaccount:self.bundleIdentifierForKeychainAccounthandler:^(NSError *error) {handler(error);}];}- (FIRMessagingCheckinPreferences *)cachedCheckinPreferences {// Query the keychain for deviceID and secretNSData *item = [self.keychain dataForService:kFIRMessagingCheckinKeychainServiceaccount:self.bundleIdentifierForKeychainAccount];// Check info found in keychainNSString *checkinKeychainContent = [[NSString alloc] initWithData:itemencoding:NSUTF8StringEncoding];FIRMessagingCheckinPreferences *checkinPreferences = [FIRMessagingCheckinPreferencespreferencesFromKeychainContents:[checkinKeychainContent copy]];NSDictionary *checkinPlistContents = [self.plist contentAsDictionary];NSString *plistDeviceAuthID = checkinPlistContents[kFIRMessagingDeviceAuthIdKey];NSString *plistSecretToken = checkinPlistContents[kFIRMessagingSecretTokenKey];// 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 =[[FIRMessagingCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthIDsecretToken:plistSecretToken];} else {// Couldn't find checkin credentials in keychain nor plistreturn nil;}}[checkinPreferences updateWithCheckinPlistContents:checkinPlistContents];return checkinPreferences;}@end