AutorÃa | Ultima modificación | Ver Log |
/** Copyright 2017 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 <TargetConditionals.h>#if TARGET_OS_IOS || TARGET_OS_TV#import <UIKit/UIKit.h>#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"#import "FirebaseInAppMessaging/Sources/FIRCore+InAppMessaging.h"#import "FirebaseInAppMessaging/Sources/Private/Flows/FIRIAMActivityLogger.h"@implementation FIRIAMActivityRecordstatic NSString *const kActiveTypeArchiveKey = @"type";static NSString *const kIsSuccessArchiveKey = @"is_success";static NSString *const kTimeStampArchiveKey = @"timestamp";static NSString *const kDetailArchiveKey = @"detail";- (id)initWithCoder:(NSCoder *)decoder {self = [super init];if (self != nil) {_activityType = [decoder decodeIntegerForKey:kActiveTypeArchiveKey];_timestamp = [decoder decodeObjectForKey:kTimeStampArchiveKey];_success = [decoder decodeBoolForKey:kIsSuccessArchiveKey];_detail = [decoder decodeObjectForKey:kDetailArchiveKey];}return self;}- (void)encodeWithCoder:(NSCoder *)encoder {[encoder encodeInteger:self.activityType forKey:kActiveTypeArchiveKey];[encoder encodeObject:self.timestamp forKey:kTimeStampArchiveKey];[encoder encodeBool:self.success forKey:kIsSuccessArchiveKey];[encoder encodeObject:self.detail forKey:kDetailArchiveKey];}- (instancetype)initWithActivityType:(FIRIAMActivityType)typeisSuccessful:(BOOL)isSuccessfulwithDetail:(NSString *)detailtimestamp:(nullable NSDate *)timestamp {if (self = [super init]) {_activityType = type;_success = isSuccessful;_detail = detail;_timestamp = timestamp ? timestamp : [[NSDate alloc] init];}return self;}- (NSString *)displayStringForActivityType {switch (self.activityType) {case FIRIAMActivityTypeFetchMessage:return @"Message Fetching";case FIRIAMActivityTypeRenderMessage:return @"Message Rendering";case FIRIAMActivityTypeDismissMessage:return @"Message Dismiss";case FIRIAMActivityTypeCheckForOnOpenMessage:return @"OnOpen Msg Check";case FIRIAMActivityTypeCheckForAnalyticsEventMessage:return @"Analytic Msg Check";case FIRIAMActivityTypeCheckForFetch:return @"Fetch Check";}}@end@interface FIRIAMActivityLogger ()@property(nonatomic) BOOL isDirty;// always insert at the head of this array so that they are always in anti-chronological order@property(nonatomic, nonnull) NSMutableArray<FIRIAMActivityRecord *> *activityRecords;// When we see the number of log records goes beyond maxRecordCountBeforeReduce, we would trigger// a reduction action which would bring the array length to be the size as defined by// newSizeAfterReduce@property(nonatomic, readonly) NSInteger maxRecordCountBeforeReduce;@property(nonatomic, readonly) NSInteger newSizeAfterReduce;@end@implementation FIRIAMActivityLogger- (instancetype)initWithMaxCountBeforeReduce:(NSInteger)maxBeforeReducewithSizeAfterReduce:(NSInteger)sizeAfterReduceverboseMode:(BOOL)verboseModeloadFromCache:(BOOL)loadFromCache {if (self = [super init]) {_maxRecordCountBeforeReduce = maxBeforeReduce;_newSizeAfterReduce = sizeAfterReduce;_activityRecords = [[NSMutableArray alloc] init];_verboseMode = verboseMode;_isDirty = NO;[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(appWillBecomeInactive:)name:UIApplicationWillResignActiveNotificationobject:nil];#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000if (@available(iOS 13.0, tvOS 13.0, *)) {[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(appWillBecomeInactive:)name:UISceneWillDeactivateNotificationobject:nil];}#endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000if (loadFromCache) {@try {[self loadFromCachePath:nil];} @catch (NSException *exception) {FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM310003",@"Non-fatal exception in loading persisted activity log records: %@.",exception);}}}return self;}- (void)dealloc {[[NSNotificationCenter defaultCenter] removeObserver:self];}+ (NSString *)determineCacheFilePath {static NSString *logCachePath;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{NSString *cacheDirPath =NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];logCachePath = [NSString stringWithFormat:@"%@/firebase-iam-activity-log-cache", cacheDirPath];FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM310001",@"Persistent file path for activity log data is %@", logCachePath);});return logCachePath;}- (void)loadFromCachePath:(NSString *)cacheFilePath {NSString *filePath = cacheFilePath == nil ? [self.class determineCacheFilePath] : cacheFilePath;#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wdeprecated-declarations"id fetchedActivityRecords = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];#pragma clang diagnostic popif (fetchedActivityRecords) {@synchronized(self) {self.activityRecords = (NSMutableArray<FIRIAMActivityRecord *> *)fetchedActivityRecords;self.isDirty = NO;}}}- (BOOL)saveIntoCacheWithPath:(NSString *)cacheFilePath {NSString *filePath = cacheFilePath == nil ? [self.class determineCacheFilePath] : cacheFilePath;@synchronized(self) {#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wdeprecated-declarations"BOOL result = [NSKeyedArchiver archiveRootObject:self.activityRecords toFile:filePath];#pragma clang diagnostic popif (result) {self.isDirty = NO;}return result;}}- (void)appWillBecomeInactive:(NSNotification *)notification {FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM310004",@"App will become inactive, save"" activity logs");if (self.isDirty) {dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{if ([self saveIntoCacheWithPath:nil]) {FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM310002",@"Persisting activity log data is was successful");} else {FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM310005",@"Persisting activity log data has failed");}});}}// Helper function to determine if a given activity type should be recorded under// non verbose type.+ (BOOL)isMandatoryType:(FIRIAMActivityType)type {switch (type) {case FIRIAMActivityTypeFetchMessage:case FIRIAMActivityTypeRenderMessage:case FIRIAMActivityTypeDismissMessage:return YES;default:return NO;}}- (void)addLogRecord:(FIRIAMActivityRecord *)newRecord {if (self.verboseMode || [FIRIAMActivityLogger isMandatoryType:newRecord.activityType]) {@synchronized(self) {[self.activityRecords insertObject:newRecord atIndex:0];if (self.activityRecords.count >= self.maxRecordCountBeforeReduce) {NSRange removeRange;removeRange.location = self.newSizeAfterReduce;removeRange.length = self.maxRecordCountBeforeReduce - self.newSizeAfterReduce;[self.activityRecords removeObjectsInRange:removeRange];}self.isDirty = YES;}}}- (NSArray<FIRIAMActivityRecord *> *)readRecords {return [self.activityRecords copy];}@end#endif // TARGET_OS_IOS || TARGET_OS_TV