diff options
Diffstat (limited to 'StoneIsland/platforms/ios/Pods/GoogleDataTransport')
50 files changed, 6750 insertions, 0 deletions
diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTCompressionHelper.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTCompressionHelper.m new file mode 100644 index 00000000..18cd41b2 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTCompressionHelper.m @@ -0,0 +1,95 @@ +/* + * Copyright 2020 Google LLC + * + * 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 "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h" + +#import <zlib.h> + +@implementation GDTCCTCompressionHelper + ++ (nullable NSData *)gzippedData:(NSData *)data { +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (data.length > UINT_MAX) { + return nil; + } +#endif + + const uint kChunkSize = 1024; + + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + + int level = Z_DEFAULT_COMPRESSION; + if (!bytes || !length) { + return nil; + } + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + int memLevel = 8; // Default. + int windowBits = 15 + 16; // Enable gzip header instead of zlib header. + + int retCode; + if (deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, Z_DEFAULT_STRATEGY) != Z_OK) { + return nil; + } + + // Hint the size at 1/4 the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)]; + unsigned char output[kChunkSize]; + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + // Collect the data. + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = deflate(&strm, Z_FINISH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + deflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // If the loop exits, it used all input and the stream ended. + NSAssert(strm.avail_in == 0, + @"Should have finished deflating without using all input, %u bytes left", strm.avail_in); + NSAssert(retCode == Z_STREAM_END, + @"thought we finished deflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + deflateEnd(&strm); + + return result; +} + ++ (BOOL)isGzipped:(NSData *)data { + const UInt8 *bytes = (const UInt8 *)data.bytes; + return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b); +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTNanopbHelpers.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTNanopbHelpers.m new file mode 100644 index 00000000..b13da862 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTNanopbHelpers.m @@ -0,0 +1,270 @@ +/* + * 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 "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h" + +#if TARGET_OS_IOS || TARGET_OS_TV +#import <UIKit/UIKit.h> +#elif TARGET_OS_OSX +#import <AppKit/AppKit.h> +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORPlatform.h" + +#import <nanopb/pb.h> +#import <nanopb/pb_decode.h> +#import <nanopb/pb_encode.h> + +#import "GoogleDataTransport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h" + +#pragma mark - General purpose encoders + +pb_bytes_array_t *GDTCCTEncodeString(NSString *string) { + NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding]; + return GDTCCTEncodeData(stringBytes); +} + +pb_bytes_array_t *GDTCCTEncodeData(NSData *data) { + pb_bytes_array_t *pbBytesArray = calloc(1, PB_BYTES_ARRAY_T_ALLOCSIZE(data.length)); + if (pbBytesArray != NULL) { + [data getBytes:pbBytesArray->bytes length:data.length]; + pbBytesArray->size = (pb_size_t)data.length; + } + return pbBytesArray; +} + +#pragma mark - CCT object constructors + +NSData *_Nullable GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest) { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + // Encode 1 time to determine the size. + if (!pb_encode(&sizestream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) { + GDTCORLogError(GDTCORMCEGeneralError, @"Error in nanopb encoding for size: %s", + PB_GET_ERROR(&sizestream)); + } + + // Encode a 2nd time to actually get the bytes from it. + size_t bufferSize = sizestream.bytes_written; + CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize); + CFDataSetLength(dataRef, bufferSize); + pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize); + if (!pb_encode(&ostream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) { + GDTCORLogError(GDTCORMCEGeneralError, @"Error in nanopb encoding for bytes: %s", + PB_GET_ERROR(&ostream)); + } + + return CFBridgingRelease(dataRef); +} + +gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest( + NSDictionary<NSString *, NSSet<GDTCOREvent *> *> *logMappingIDToLogSet) { + gdt_cct_BatchedLogRequest batchedLogRequest = gdt_cct_BatchedLogRequest_init_default; + NSUInteger numberOfLogRequests = logMappingIDToLogSet.count; + gdt_cct_LogRequest *logRequests = calloc(numberOfLogRequests, sizeof(gdt_cct_LogRequest)); + if (logRequests == NULL) { + return batchedLogRequest; + } + + __block int i = 0; + [logMappingIDToLogSet enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull logMappingID, + NSSet<GDTCOREvent *> *_Nonnull logSet, + BOOL *_Nonnull stop) { + int32_t logSource = [logMappingID intValue]; + gdt_cct_LogRequest logRequest = GDTCCTConstructLogRequest(logSource, logSet); + logRequests[i] = logRequest; + i++; + }]; + + batchedLogRequest.log_request = logRequests; + batchedLogRequest.log_request_count = (pb_size_t)numberOfLogRequests; + return batchedLogRequest; +} + +gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, + NSSet<GDTCOREvent *> *_Nonnull logSet) { + if (logSet.count == 0) { + GDTCORLogError(GDTCORMCEGeneralError, @"%@", + @"An empty event set can't be serialized to proto."); + gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default; + return logRequest; + } + gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default; + logRequest.log_source = logSource; + logRequest.has_log_source = 1; + logRequest.client_info = GDTCCTConstructClientInfo(); + logRequest.has_client_info = 1; + logRequest.log_event = calloc(logSet.count, sizeof(gdt_cct_LogEvent)); + if (logRequest.log_event == NULL) { + return logRequest; + } + int i = 0; + for (GDTCOREvent *log in logSet) { + gdt_cct_LogEvent logEvent = GDTCCTConstructLogEvent(log); + logRequest.log_event[i] = logEvent; + i++; + } + logRequest.log_event_count = (pb_size_t)logSet.count; + + GDTCORClock *currentTime = [GDTCORClock snapshot]; + logRequest.request_time_ms = currentTime.timeMillis; + logRequest.has_request_time_ms = 1; + logRequest.request_uptime_ms = [currentTime uptimeMilliseconds]; + logRequest.has_request_uptime_ms = 1; + + return logRequest; +} + +gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCOREvent *event) { + gdt_cct_LogEvent logEvent = gdt_cct_LogEvent_init_default; + logEvent.event_time_ms = event.clockSnapshot.timeMillis; + logEvent.has_event_time_ms = 1; + logEvent.event_uptime_ms = [event.clockSnapshot uptimeMilliseconds]; + logEvent.has_event_uptime_ms = 1; + logEvent.timezone_offset_seconds = event.clockSnapshot.timezoneOffsetSeconds; + logEvent.has_timezone_offset_seconds = 1; + if (event.customBytes) { + NSData *networkConnectionInfoData = event.networkConnectionInfoData; + if (networkConnectionInfoData) { + [networkConnectionInfoData getBytes:&logEvent.network_connection_info + length:networkConnectionInfoData.length]; + logEvent.has_network_connection_info = 1; + } + NSNumber *eventCode = event.eventCode; + if (eventCode != nil) { + logEvent.has_event_code = 1; + logEvent.event_code = [eventCode intValue]; + } + } + NSError *error; + NSData *extensionBytes; + extensionBytes = event.serializedDataObjectBytes; + if (error) { + GDTCORLogWarning(GDTCORMCWFileReadError, + @"There was an error reading extension bytes from disk: %@", error); + return logEvent; + } + logEvent.source_extension = GDTCCTEncodeData(extensionBytes); // read bytes from the file. + return logEvent; +} + +gdt_cct_ClientInfo GDTCCTConstructClientInfo() { + gdt_cct_ClientInfo clientInfo = gdt_cct_ClientInfo_init_default; + clientInfo.client_type = gdt_cct_ClientInfo_ClientType_IOS_FIREBASE; + clientInfo.has_client_type = 1; +#if TARGET_OS_IOS || TARGET_OS_TV + clientInfo.ios_client_info = GDTCCTConstructiOSClientInfo(); + clientInfo.has_ios_client_info = 1; +#elif TARGET_OS_OSX + // TODO(mikehaney24): Expand the proto to include macOS client info. +#endif + return clientInfo; +} + +gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo() { + gdt_cct_IosClientInfo iOSClientInfo = gdt_cct_IosClientInfo_init_default; +#if TARGET_OS_IOS || TARGET_OS_TV + UIDevice *device = [UIDevice currentDevice]; + NSBundle *bundle = [NSBundle mainBundle]; + NSLocale *locale = [NSLocale currentLocale]; + iOSClientInfo.os_full_version = GDTCCTEncodeString(device.systemVersion); + NSArray *versionComponents = [device.systemVersion componentsSeparatedByString:@"."]; + iOSClientInfo.os_major_version = GDTCCTEncodeString(versionComponents[0]); + NSString *version = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]; + if (version) { + iOSClientInfo.application_build = GDTCCTEncodeString(version); + } + NSString *countryCode = [locale objectForKey:NSLocaleCountryCode]; + if (countryCode) { + iOSClientInfo.country = GDTCCTEncodeString([locale objectForKey:NSLocaleCountryCode]); + } + iOSClientInfo.model = GDTCCTEncodeString(GDTCORDeviceModel()); + NSString *languageCode = bundle.preferredLocalizations.firstObject; + iOSClientInfo.language_code = + languageCode ? GDTCCTEncodeString(languageCode) : GDTCCTEncodeString(@"en"); + iOSClientInfo.application_bundle_id = GDTCCTEncodeString(bundle.bundleIdentifier); +#endif + return iOSClientInfo; +} + +NSData *GDTCCTConstructNetworkConnectionInfoData() { + gdt_cct_NetworkConnectionInfo networkConnectionInfo = gdt_cct_NetworkConnectionInfo_init_default; + NSInteger currentNetworkType = GDTCORNetworkTypeMessage(); + if (currentNetworkType) { + networkConnectionInfo.has_network_type = 1; + if (currentNetworkType == GDTCORNetworkTypeMobile) { + networkConnectionInfo.network_type = gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE; + networkConnectionInfo.mobile_subtype = GDTCCTNetworkConnectionInfoNetworkMobileSubtype(); + if (networkConnectionInfo.mobile_subtype != + gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE) { + networkConnectionInfo.has_mobile_subtype = 1; + } + } else { + networkConnectionInfo.network_type = gdt_cct_NetworkConnectionInfo_NetworkType_WIFI; + } + } + NSData *networkConnectionInfoData = [NSData dataWithBytes:&networkConnectionInfo + length:sizeof(networkConnectionInfo)]; + return networkConnectionInfoData; +} + +gdt_cct_NetworkConnectionInfo_MobileSubtype GDTCCTNetworkConnectionInfoNetworkMobileSubtype() { + NSNumber *networkMobileSubtypeMessage = @(GDTCORNetworkMobileSubTypeMessage()); + if (!networkMobileSubtypeMessage.intValue) { + return gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE; + } + static NSDictionary<NSNumber *, NSNumber *> *MessageToNetworkSubTypeMessage; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + MessageToNetworkSubTypeMessage = @{ + @(GDTCORNetworkMobileSubtypeGPRS) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_GPRS), + @(GDTCORNetworkMobileSubtypeEdge) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EDGE), + @(GDTCORNetworkMobileSubtypeWCDMA) : + @(gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE), + @(GDTCORNetworkMobileSubtypeHSDPA) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_HSDPA), + @(GDTCORNetworkMobileSubtypeHSUPA) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_HSUPA), + @(GDTCORNetworkMobileSubtypeCDMA1x) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_CDMA), + @(GDTCORNetworkMobileSubtypeCDMAEVDORev0) : + @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_0), + @(GDTCORNetworkMobileSubtypeCDMAEVDORevA) : + @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_A), + @(GDTCORNetworkMobileSubtypeCDMAEVDORevB) : + @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_B), + @(GDTCORNetworkMobileSubtypeHRPD) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EHRPD), + @(GDTCORNetworkMobileSubtypeLTE) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE), + }; + }); + NSNumber *networkMobileSubtype = MessageToNetworkSubTypeMessage[networkMobileSubtypeMessage]; + return networkMobileSubtype.intValue; +} + +#pragma mark - CCT Object decoders + +gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error) { + gdt_cct_LogResponse response = gdt_cct_LogResponse_init_default; + pb_istream_t istream = pb_istream_from_buffer([data bytes], [data length]); + if (!pb_decode(&istream, gdt_cct_LogResponse_fields, &response)) { + NSString *nanopb_error = [NSString stringWithFormat:@"%s", PB_GET_ERROR(&istream)]; + NSDictionary *userInfo = @{@"nanopb error:" : nanopb_error}; + if (error != NULL) { + *error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:userInfo]; + } + response = (gdt_cct_LogResponse)gdt_cct_LogResponse_init_default; + } + return response; +} diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTUploader.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTUploader.m new file mode 100644 index 00000000..b088c559 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTUploader.m @@ -0,0 +1,693 @@ +/* + * 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 "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploader.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORPlatform.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORRegistrar.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageProtocol.h" + +#import <nanopb/pb.h> +#import <nanopb/pb_decode.h> +#import <nanopb/pb_encode.h> + +#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h" +#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h" + +#import "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h" + +NS_ASSUME_NONNULL_BEGIN + +#ifdef GDTCOR_VERSION +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +static NSString *const kGDTCCTSupportSDKVersion = @STR(GDTCOR_VERSION); +#else +static NSString *const kGDTCCTSupportSDKVersion = @"UNKNOWN"; +#endif // GDTCOR_VERSION + +/** */ +static NSInteger kWeekday; + +/** */ +static NSString *const kLibraryDataCCTNextUploadTimeKey = @"GDTCCTUploaderFLLNextUploadTimeKey"; + +/** */ +static NSString *const kLibraryDataFLLNextUploadTimeKey = @"GDTCCTUploaderFLLNextUploadTimeKey"; + +#if !NDEBUG +NSNotificationName const GDTCCTUploadCompleteNotification = @"com.GDTCCTUploader.UploadComplete"; +#endif // #if !NDEBUG + +typedef void (^GDTCCTUploaderURLTaskCompletion)(NSNumber *batchID, + NSSet<GDTCOREvent *> *_Nullable events, + NSData *_Nullable data, + NSURLResponse *_Nullable response, + NSError *_Nullable error); + +typedef void (^GDTCCTUploaderEventBatchBlock)(NSNumber *_Nullable batchID, + NSSet<GDTCOREvent *> *_Nullable events); + +@interface GDTCCTUploader () <NSURLSessionDelegate> + +/// Redeclared as readwrite. +@property(nullable, nonatomic, readwrite) NSURLSessionUploadTask *currentTask; + +/// A flag indicating if there is an ongoing upload. The current implementation supports only a +/// single upload operation. If `uploadTarget` method is called when `isCurrentlyUploading == YES` +/// then no new uploads will be started. +@property(atomic) BOOL isCurrentlyUploading; + +@end + +@implementation GDTCCTUploader + ++ (void)load { + GDTCCTUploader *uploader = [GDTCCTUploader sharedInstance]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCCT]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetFLL]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCSH]; +} + ++ (instancetype)sharedInstance { + static GDTCCTUploader *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCCTUploader alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _uploaderQueue = dispatch_queue_create("com.google.GDTCCTUploader", DISPATCH_QUEUE_SERIAL); + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + _uploaderSession = [NSURLSession sessionWithConfiguration:config + delegate:self + delegateQueue:nil]; + } + return self; +} + +/** + * + */ +- (nullable NSURL *)serverURLForTarget:(GDTCORTarget)target { + // These strings should be interleaved to construct the real URL. This is just to (hopefully) + // fool github URL scanning bots. + static NSURL *CCTServerURL; + static dispatch_once_t CCTOnceToken; + dispatch_once(&CCTOnceToken, ^{ + const char *p1 = "hts/frbslgiggolai.o/0clgbth"; + const char *p2 = "tp:/ieaeogn.ogepscmvc/o/ac"; + const char URL[54] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], '\0'}; + CCTServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + + static NSURL *FLLServerURL; + static dispatch_once_t FLLOnceToken; + dispatch_once(&FLLOnceToken, ^{ + const char *p1 = "hts/frbslgigp.ogepscmv/ieo/eaybtho"; + const char *p2 = "tp:/ieaeogn-agolai.o/1frlglgc/aclg"; + const char URL[69] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], p2[26], + p1[27], p2[27], p1[28], p2[28], p1[29], p2[29], p1[30], p2[30], p1[31], + p2[31], p1[32], p2[32], p1[33], p2[33], '\0'}; + FLLServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + + static NSURL *CSHServerURL; + static dispatch_once_t CSHOnceToken; + dispatch_once(&CSHOnceToken, ^{ + // These strings should be interleaved to construct the real URL. This is just to (hopefully) + // fool github URL scanning bots. + const char *p1 = "hts/cahyiseot-agolai.o/1frlglgc/aclg"; + const char *p2 = "tp:/rsltcrprsp.ogepscmv/ieo/eaybtho"; + const char URL[72] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], p2[26], + p1[27], p2[27], p1[28], p2[28], p1[29], p2[29], p1[30], p2[30], p1[31], + p2[31], p1[32], p2[32], p1[33], p2[33], p1[34], p2[34], p1[35], '\0'}; + CSHServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + +#if !NDEBUG + if (_testServerURL) { + return _testServerURL; + } +#endif // !NDEBUG + + switch (target) { + case kGDTCORTargetCCT: + return CCTServerURL; + + case kGDTCORTargetFLL: + return FLLServerURL; + + case kGDTCORTargetCSH: + return CSHServerURL; + + default: + GDTCORLogDebug(@"GDTCCTUploader doesn't support target %ld", (long)target); + return nil; + break; + } +} + +- (NSString *)FLLAndCSHAPIKey { + static NSString *defaultServerKey; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // These strings should be interleaved to construct the real key. + const char *p1 = "AzSBG0honD6A-PxV5nBc"; + const char *p2 = "Iay44Iwtu2vV0AOrz1C"; + const char defaultKey[40] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], + p1[4], p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], + p1[8], p2[8], p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], + p1[12], p2[12], p1[13], p2[13], p1[14], p2[14], p1[15], p2[15], + p1[16], p2[16], p1[17], p2[17], p1[18], p2[18], p1[19], '\0'}; + defaultServerKey = [NSString stringWithUTF8String:defaultKey]; + }); + return defaultServerKey; +} + +# + +- (void)uploadTarget:(GDTCORTarget)target withConditions:(GDTCORUploadConditions)conditions { + __block GDTCORBackgroundIdentifier backgroundTaskID = GDTCORBackgroundIdentifierInvalid; + + dispatch_block_t backgroundTaskCompletion = ^{ + // End the background task if there was one. + if (backgroundTaskID != GDTCORBackgroundIdentifierInvalid) { + [[GDTCORApplication sharedApplication] endBackgroundTask:backgroundTaskID]; + backgroundTaskID = GDTCORBackgroundIdentifierInvalid; + } + }; + + backgroundTaskID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTCCTUploader-upload" + expirationHandler:^{ + if (backgroundTaskID != GDTCORBackgroundIdentifierInvalid) { + // Cancel the upload and complete delivery. + [self.currentTask cancel]; + + // End the background task. + backgroundTaskCompletion(); + } + }]; + + dispatch_async(_uploaderQueue, ^{ + id<GDTCORStorageProtocol> storage = GDTCORStorageInstanceForTarget(target); + + // 1. Fetch events to upload. + [self batchToUploadForTarget:target + storage:storage + conditions:conditions + completion:^(NSNumber *_Nullable batchID, + NSSet<GDTCOREvent *> *_Nullable events) { + // 2. Check if there are events to upload. + if (!events || events.count == 0) { + dispatch_async(self.uploaderQueue, ^{ + GDTCORLogDebug(@"Target %ld reported as ready for upload, but no " + @"events were selected", + (long)target); + self.isCurrentlyUploading = NO; + backgroundTaskCompletion(); + }); + + return; + } + // 3. Upload events. + [self uploadBatchWithID:batchID + events:events + target:target + storage:storage + completion:^{ + backgroundTaskCompletion(); + }]; + }]; + }); +} + +#pragma mark - Upload implementation details + +/** Performs URL request, handles the result and updates the uploader state. */ +- (void)uploadBatchWithID:(nullable NSNumber *)batchID + events:(nullable NSSet<GDTCOREvent *> *)events + target:(GDTCORTarget)target + storage:(id<GDTCORStorageProtocol>)storage + completion:(dispatch_block_t)completion { + [self + sendURLRequestForBatchWithID:batchID + events:events + target:target + completionHandler:^(NSNumber *_Nonnull batchID, + NSSet<GDTCOREvent *> *_Nullable events, NSData *_Nullable data, + NSURLResponse *_Nullable response, NSError *_Nullable error) { + dispatch_async(self.uploaderQueue, ^{ + [self handleURLResponse:response + data:data + error:error + target:target + storage:storage + batchID:batchID]; +#if !NDEBUG + // Post a notification when in DEBUG mode to state how many packages + // were uploaded. Useful for validation during tests. + [[NSNotificationCenter defaultCenter] + postNotificationName:GDTCCTUploadCompleteNotification + object:@(events.count)]; +#endif // #if !NDEBUG + self.isCurrentlyUploading = NO; + completion(); + }); + }]; +} + +/** Validates events and sends URL request and calls completion with the result. Modifies uploading + * state in the case of the failure.*/ +- (void)sendURLRequestForBatchWithID:(nullable NSNumber *)batchID + events:(nullable NSSet<GDTCOREvent *> *)events + target:(GDTCORTarget)target + completionHandler:(GDTCCTUploaderURLTaskCompletion)completionHandler { + dispatch_async(self.uploaderQueue, ^{ + NSData *requestProtoData = [self constructRequestProtoWithEvents:events]; + NSData *gzippedData = [GDTCCTCompressionHelper gzippedData:requestProtoData]; + BOOL usingGzipData = gzippedData != nil && gzippedData.length < requestProtoData.length; + NSData *dataToSend = usingGzipData ? gzippedData : requestProtoData; + NSURLRequest *request = [self constructRequestForTarget:target data:dataToSend]; + GDTCORLogDebug(@"CTT: request containing %lu events created: %@", (unsigned long)events.count, + request); + NSSet<GDTCOREvent *> *eventsForDebug; +#if !NDEBUG + eventsForDebug = events; +#endif + self.currentTask = [self.uploaderSession + uploadTaskWithRequest:request + fromData:dataToSend + completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, + NSError *_Nullable error) { + completionHandler(batchID, eventsForDebug, data, response, error); + }]; + GDTCORLogDebug(@"%@", @"CCT: The upload task is about to begin."); + [self.currentTask resume]; + }); +} + +/** Handles URL request response. */ +- (void)handleURLResponse:(nullable NSURLResponse *)response + data:(nullable NSData *)data + error:(nullable NSError *)error + target:(GDTCORTarget)target + storage:(id<GDTCORStorageProtocol>)storage + batchID:(NSNumber *)batchID { + GDTCORLogDebug(@"%@", @"CCT: request completed"); + if (error) { + GDTCORLogWarning(GDTCORMCWUploadFailed, @"There was an error uploading events: %@", error); + } + NSError *decodingError; + GDTCORClock *futureUploadTime; + if (data) { + gdt_cct_LogResponse logResponse = GDTCCTDecodeLogResponse(data, &decodingError); + if (!decodingError && logResponse.has_next_request_wait_millis) { + GDTCORLogDebug(@"CCT: The backend responded asking to not upload for %lld millis from now.", + logResponse.next_request_wait_millis); + futureUploadTime = + [GDTCORClock clockSnapshotInTheFuture:logResponse.next_request_wait_millis]; + } else if (decodingError) { + GDTCORLogDebug(@"There was a response decoding error: %@", decodingError); + } + pb_release(gdt_cct_LogResponse_fields, &logResponse); + } + if (!futureUploadTime) { + GDTCORLogDebug(@"%@", @"CCT: The backend response failed to parse, so the next request " + @"won't occur until 15 minutes from now"); + // 15 minutes from now. + futureUploadTime = [GDTCORClock clockSnapshotInTheFuture:15 * 60 * 1000]; + } + switch (target) { + case kGDTCORTargetCCT: + self->_CCTNextUploadTime = futureUploadTime; + break; + + case kGDTCORTargetFLL: + // Falls through. + case kGDTCORTargetCSH: + self->_FLLNextUploadTime = futureUploadTime; + break; + default: + break; + } + + // Only retry if one of these codes is returned, or there was an error. + if (error || ((NSHTTPURLResponse *)response).statusCode == 429 || + ((NSHTTPURLResponse *)response).statusCode == 503) { + // Move the events back to the main storage to be uploaded on the next attempt. + [storage removeBatchWithID:batchID deleteEvents:NO onComplete:nil]; + } else { + GDTCORLogDebug(@"%@", @"CCT: package delivered"); + [storage removeBatchWithID:batchID deleteEvents:YES onComplete:nil]; + } + + self.currentTask = nil; +} + +#pragma mark - Stored events upload + +/** Fetches a batch of pending events for the specified target and conditions. Passes `nil` to + * completion if there are no suitable events to upload. */ +- (void)batchToUploadForTarget:(GDTCORTarget)target + storage:(id<GDTCORStorageProtocol>)storage + conditions:(GDTCORUploadConditions)conditions + completion:(GDTCCTUploaderEventBatchBlock)completion { + // 1. Check if the conditions for the target are suitable. + if (![self readyToUploadTarget:target conditions:conditions]) { + completion(nil, nil); + return; + } + + // 2. Remove previously attempted batches + [self removeBatchesForTarget:target + storage:storage + onComplete:^{ + // There may be a big amount of events stored, so creating a batch may be an + // expensive operation. + + // 3. Do a lightweight check if there are any events for the target first to + // finish early if there are no. + [storage hasEventsForTarget:target + onComplete:^(BOOL hasEvents) { + // 4. Proceed with fetching the events. + [self batchToUploadForTarget:target + storage:storage + conditions:conditions + hasEvents:hasEvents + completion:completion]; + }]; + }]; +} + +/** Makes final checks before and makes */ +- (void)batchToUploadForTarget:(GDTCORTarget)target + storage:(id<GDTCORStorageProtocol>)storage + conditions:(GDTCORUploadConditions)conditions + hasEvents:(BOOL)hasEvents + completion:(GDTCCTUploaderEventBatchBlock)completion { + dispatch_async(self.uploaderQueue, ^{ + if (!hasEvents) { + // No events to upload. + completion(nil, nil); + return; + } + + // Check if the conditions are still met before starting upload. + if (![self readyToUploadTarget:target conditions:conditions]) { + completion(nil, nil); + return; + } + + // All conditions have been checked and met. Lock uploader for this target to prevent other + // targets upload attempts. + self.isCurrentlyUploading = YES; + + // Fetch a batch to upload and pass along. + GDTCORStorageEventSelector *eventSelector = [self eventSelectorTarget:target + withConditions:conditions]; + [storage batchWithEventSelector:eventSelector + batchExpiration:[NSDate dateWithTimeIntervalSinceNow:600] + onComplete:completion]; + }); +} + +- (void)removeBatchesForTarget:(GDTCORTarget)target + storage:(id<GDTCORStorageProtocol>)storage + onComplete:(dispatch_block_t)onComplete { + [storage batchIDsForTarget:target + onComplete:^(NSSet<NSNumber *> *_Nullable batchIDs) { + // No stored batches, no need to remove anything. + if (batchIDs.count < 1) { + onComplete(); + return; + } + + dispatch_group_t dispatchGroup = dispatch_group_create(); + for (NSNumber *batchID in batchIDs) { + dispatch_group_enter(dispatchGroup); + + // Remove batches and moves events back to the storage. + [storage removeBatchWithID:batchID + deleteEvents:NO + onComplete:^{ + dispatch_group_leave(dispatchGroup); + }]; + } + + // Wait until all batches are removed and call completion handler. + dispatch_group_notify(dispatchGroup, self.uploaderQueue, ^{ + onComplete(); + }); + }]; +} + +#pragma mark - Private helper methods + +/** */ +- (BOOL)readyToUploadTarget:(GDTCORTarget)target conditions:(GDTCORUploadConditions)conditions { + if (self.isCurrentlyUploading) { + GDTCORLogDebug(@"%@", @"CCT: Wait until previous upload finishes. The current version supports " + @"only a single batch uploading at the time."); + return NO; + } + + // Not ready to upload with no network connection. + // TODO: Reconsider using reachability to prevent an upload attempt. + // See https://developer.apple.com/videos/play/wwdc2019/712/ (49:40) for more details. + if (conditions & GDTCORUploadConditionNoNetwork) { + GDTCORLogDebug(@"%@", @"CCT: Not ready to upload without a network connection."); + return NO; + } + + // Upload events when there are with no additional conditions for kGDTCORTargetCSH. + if (target == kGDTCORTargetCSH) { + GDTCORLogDebug(@"%@", + @"CCT: kGDTCORTargetCSH events are allowed to be uploaded straight away."); + return YES; + } + + // Upload events with no additional conditions if high priority. + if ((conditions & GDTCORUploadConditionHighPriority) == GDTCORUploadConditionHighPriority) { + GDTCORLogDebug(@"%@", @"CCT: a high priority event is allowing an upload"); + return YES; + } + + // Check next upload time for the target. + BOOL isAfterNextUploadTime = YES; + switch (target) { + case kGDTCORTargetCCT: + if (self->_CCTNextUploadTime) { + isAfterNextUploadTime = [[GDTCORClock snapshot] isAfter:self->_CCTNextUploadTime]; + } + break; + + case kGDTCORTargetFLL: + if (self->_FLLNextUploadTime) { + isAfterNextUploadTime = [[GDTCORClock snapshot] isAfter:self->_FLLNextUploadTime]; + } + break; + + default: + // The CSH backend should be handled above. + break; + } + + if (isAfterNextUploadTime) { + GDTCORLogDebug(@"CCT: can upload to target %ld because the request wait time has transpired", + (long)target); + } else { + GDTCORLogDebug(@"CCT: can't upload to target %ld because the backend asked to wait", + (long)target); + } + + return isAfterNextUploadTime; +} + +/** Constructs data given an upload package. + * + * @param events The events used to construct the request proto bytes. + * @return Proto bytes representing a gdt_cct_LogRequest object. + */ +- (nonnull NSData *)constructRequestProtoWithEvents:(NSSet<GDTCOREvent *> *)events { + // Segment the log events by log type. + NSMutableDictionary<NSString *, NSMutableSet<GDTCOREvent *> *> *logMappingIDToLogSet = + [[NSMutableDictionary alloc] init]; + [events enumerateObjectsUsingBlock:^(GDTCOREvent *_Nonnull event, BOOL *_Nonnull stop) { + NSMutableSet *logSet = logMappingIDToLogSet[event.mappingID]; + logSet = logSet ? logSet : [[NSMutableSet alloc] init]; + [logSet addObject:event]; + logMappingIDToLogSet[event.mappingID] = logSet; + }]; + + gdt_cct_BatchedLogRequest batchedLogRequest = + GDTCCTConstructBatchedLogRequest(logMappingIDToLogSet); + + NSData *data = GDTCCTEncodeBatchedLogRequest(&batchedLogRequest); + pb_release(gdt_cct_BatchedLogRequest_fields, &batchedLogRequest); + return data ? data : [[NSData alloc] init]; +} + +/** Constructs a request to FLL given a URL and request body data. + * + * @param target The target backend to send the request to. + * @param data The request body data. + * @return A new NSURLRequest ready to be sent to FLL. + */ +- (nullable NSURLRequest *)constructRequestForTarget:(GDTCORTarget)target data:(NSData *)data { + if (data == nil || data.length == 0) { + GDTCORLogDebug(@"There was no data to construct a request for target %ld.", (long)target); + return nil; + } + NSURL *URL = [self serverURLForTarget:target]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; + NSString *targetString; + switch (target) { + case kGDTCORTargetCCT: + targetString = @"cct"; + break; + + case kGDTCORTargetFLL: + targetString = @"fll"; + break; + + case kGDTCORTargetCSH: + targetString = @"csh"; + break; + + default: + targetString = @"unknown"; + break; + } + NSString *userAgent = + [NSString stringWithFormat:@"datatransport/%@ %@support/%@ apple/", kGDTCORVersion, + targetString, kGDTCCTSupportSDKVersion]; + if (target == kGDTCORTargetFLL || target == kGDTCORTargetCSH) { + [request setValue:[self FLLAndCSHAPIKey] forHTTPHeaderField:@"X-Goog-Api-Key"]; + } + if ([GDTCCTCompressionHelper isGzipped:data]) { + [request setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"]; + } + [request setValue:@"application/x-protobuf" forHTTPHeaderField:@"Content-Type"]; + [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; + [request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + request.HTTPMethod = @"POST"; + [request setHTTPBody:data]; + return request; +} + +/** */ +- (nullable GDTCORStorageEventSelector *)eventSelectorTarget:(GDTCORTarget)target + withConditions:(GDTCORUploadConditions)conditions { + id<GDTCORStorageProtocol> storage = GDTCORStorageInstanceForTarget(target); + if ((conditions & GDTCORUploadConditionHighPriority) == GDTCORUploadConditionHighPriority) { + return [GDTCORStorageEventSelector eventSelectorForTarget:target]; + } + NSMutableSet<NSNumber *> *qosTiers = [[NSMutableSet alloc] init]; + if (conditions & GDTCORUploadConditionWifiData) { + [qosTiers addObjectsFromArray:@[ + @(GDTCOREventQoSFast), @(GDTCOREventQoSWifiOnly), @(GDTCOREventQosDefault), + @(GDTCOREventQoSTelemetry), @(GDTCOREventQoSUnknown) + ]]; + } + if (conditions & GDTCORUploadConditionMobileData) { + [qosTiers addObjectsFromArray:@[ @(GDTCOREventQoSFast), @(GDTCOREventQosDefault) ]]; + } + + __block NSInteger lastDayOfDailyUpload; + NSString *lastDailyUploadDataKey = [NSString + stringWithFormat:@"%@LastDailyUpload-%ld", NSStringFromClass([self class]), (long)target]; + [storage libraryDataForKey:lastDailyUploadDataKey + onFetchComplete:^(NSData *_Nullable data, NSError *_Nullable error) { + [data getBytes:&lastDayOfDailyUpload length:sizeof(NSInteger)]; + } + setNewValue:^NSData *_Nullable { + if (lastDayOfDailyUpload != kWeekday) { + return [NSData dataWithBytes:&lastDayOfDailyUpload length:sizeof(NSInteger)]; + } + return nil; + }]; + + return [[GDTCORStorageEventSelector alloc] initWithTarget:target + eventIDs:nil + mappingIDs:nil + qosTiers:qosTiers]; +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillForeground:(GDTCORApplication *)app { + dispatch_async(_uploaderQueue, ^{ + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + NSCalendar *gregorianCalendar = + [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; + NSDate *date = [gregorianCalendar dateFromComponents:dateComponents]; + kWeekday = [gregorianCalendar component:NSCalendarUnitWeekday fromDate:date]; + }); +} + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_uploaderQueue, ^{ + [self.currentTask cancel]; + }); +} + +#pragma mark - NSURLSessionDelegate + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *_Nullable))completionHandler { + if (!completionHandler) { + return; + } + if (response.statusCode == 302 || response.statusCode == 301) { + if ([request.URL isEqual:[self serverURLForTarget:kGDTCORTargetFLL]]) { + NSURLRequest *newRequest = [self constructRequestForTarget:kGDTCORTargetCCT + data:task.originalRequest.HTTPBody]; + completionHandler(newRequest); + } + } else { + completionHandler(request); + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m new file mode 100644 index 00000000..00a0f1b4 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m @@ -0,0 +1,236 @@ +/* + * Copyright 2020 Google LLC + * + * 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 "GoogleDataTransport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" + +NSString *const GDTCCTNeedsNetworkConnectionInfo = @"needs_network_connection_info"; + +NSString *const GDTCCTNetworkConnectionInfo = @"network_connection_info"; + +NSString *const GDTCCTEventCodeInfo = @"event_code_info"; + +@implementation GDTCOREvent (GDTCCTSupport) + +- (void)setNeedsNetworkConnectionInfoPopulated:(BOOL)needsNetworkConnectionInfoPopulated { + if (!needsNetworkConnectionInfoPopulated) { + if (!self.customBytes) { + return; + } + + // Make sure we don't destroy the eventCode data, if any is present. + @try { + NSError *error; + NSMutableDictionary *bytesDict = + [[NSJSONSerialization JSONObjectWithData:self.customBytes options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + NSNumber *eventCode = bytesDict[GDTCCTEventCodeInfo]; + if (eventCode != nil) { + self.customBytes = + [NSJSONSerialization dataWithJSONObject:@{GDTCCTEventCodeInfo : eventCode} + options:0 + error:&error]; + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@", + exception); + } + } else { + @try { + NSError *error; + NSMutableDictionary *bytesDict; + if (self.customBytes) { + bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an even'ts event_code: %@", error); + return; + } + } else { + bytesDict = [[NSMutableDictionary alloc] init]; + } + [bytesDict setObject:@YES forKey:GDTCCTNeedsNetworkConnectionInfo]; + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@", + exception); + } + } +} + +- (BOOL)needsNetworkConnectionInfoPopulated { + if (self.customBytes) { + @try { + NSError *error; + NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error]; + return bytesDict && !error && [bytesDict[GDTCCTNeedsNetworkConnectionInfo] boolValue]; + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when checking the event for needs_network_connection_info: %@", + exception); + } + } + return NO; +} + +- (void)setNetworkConnectionInfoData:(NSData *)networkConnectionInfoData { + @try { + NSError *error; + NSString *dataString = [networkConnectionInfoData base64EncodedStringWithOptions:0]; + if (dataString != nil) { + NSMutableDictionary *bytesDict; + if (self.customBytes) { + bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an even'ts event_code: %@", error); + return; + } + } else { + bytesDict = [[NSMutableDictionary alloc] init]; + } + [bytesDict setObject:dataString forKey:GDTCCTNetworkConnectionInfo]; + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + if (error) { + self.customBytes = nil; + GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error); + } + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", exception); + } +} + +- (nullable NSData *)networkConnectionInfoData { + if (self.customBytes) { + @try { + NSError *error; + NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error]; + NSString *base64Data = bytesDict[GDTCCTNetworkConnectionInfo]; + NSData *networkConnectionInfoData = [[NSData alloc] initWithBase64EncodedString:base64Data + options:0]; + if (error) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error); + return nil; + } else { + return networkConnectionInfoData; + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception); + } + } + return nil; +} + +- (NSNumber *)eventCode { + if (self.customBytes) { + @try { + NSError *error; + NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error]; + NSString *eventCodeString = bytesDict[GDTCCTEventCodeInfo]; + + if (!eventCodeString) { + return nil; + } + + NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; + formatter.numberStyle = NSNumberFormatterDecimalStyle; + NSNumber *eventCode = [formatter numberFromString:eventCodeString]; + + if (error) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error); + return nil; + } else { + return eventCode; + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when getting an event's event_code: %@", exception); + } + } + return nil; +} + +- (void)setEventCode:(NSNumber *)eventCode { + if (eventCode == nil) { + if (!self.customBytes) { + return; + } + + NSError *error; + NSMutableDictionary *bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + + [bytesDict removeObjectForKey:GDTCCTEventCodeInfo]; + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + if (error) { + self.customBytes = nil; + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + return; + } + + @try { + NSMutableDictionary *bytesDict; + NSError *error; + if (self.customBytes) { + bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + } else { + bytesDict = [[NSMutableDictionary alloc] init]; + } + + NSString *eventCodeString = [eventCode stringValue]; + if (eventCodeString == nil) { + return; + } + + [bytesDict setObject:eventCodeString forKey:GDTCCTEventCodeInfo]; + + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + if (error) { + self.customBytes = nil; + GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error); + return; + } + + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception); + } +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h new file mode 100644 index 00000000..b53dd5fa --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Google LLC + * + * 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 <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** A class with methods to help with gzipped data. */ +@interface GDTCCTCompressionHelper : NSObject + +/** Compresses the given data and returns a new data object. + * + * @note Reduced version from GULNSData+zlib.m of GoogleUtilities. + * @return Compressed data, or nil if there was an error. + */ ++ (nullable NSData *)gzippedData:(NSData *)data; + +/** Returns YES if the data looks like it was gzip compressed by checking for the gzip magic number. + * + * @note: From https://en.wikipedia.org/wiki/Gzip, gzip's magic number is 1f 8b. + * @return YES if the data appears gzipped, NO otherwise. + */ ++ (BOOL)isGzipped:(NSData *)data; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h new file mode 100644 index 00000000..f83a982c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h @@ -0,0 +1,128 @@ +/* + * 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 <Foundation/Foundation.h> + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORReachability.h" + +#import "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h" + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - General purpose encoders + +/** Converts an NSString* to a pb_bytes_array_t*. + * + * @note calloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param string The string to convert. + * @return A newly allocated array of bytes representing the UTF8 encoding of the string. + */ +pb_bytes_array_t *GDTCCTEncodeString(NSString *string); + +/** Converts an NSData to a pb_bytes_array_t*. + * + * @note calloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param data The data to convert. + * @return A newly allocated array of bytes with [data bytes] copied into it. + */ +pb_bytes_array_t *GDTCCTEncodeData(NSData *data); + +#pragma mark - CCT object constructors + +/** Encodes a batched log request. + * + * @note Ensure that pb_release is called on the batchedLogRequest param. + * + * @param batchedLogRequest A pointer to the log batch to encode to bytes. + * @return An NSData object representing the bytes of the log request batch. + */ +FOUNDATION_EXPORT +NSData *GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest); + +/** Constructs a gdt_cct_BatchedLogRequest given sets of events segemented by mapping ID. + * + * @note calloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param logMappingIDToLogSet A map of mapping IDs to sets of events to convert into a batch. + * @return A newly created gdt_cct_BatchedLogRequest. + */ +FOUNDATION_EXPORT +gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest( + NSDictionary<NSString *, NSSet<GDTCOREvent *> *> *logMappingIDToLogSet); + +/** Constructs a log request given a log source and a set of events. + * + * @note calloc is called in this method. Ensure that pb_release is called on this or the parent. + * @param logSource The CCT log source to put into the log request. + * @param logSet The set of events to send in this log request. + */ +FOUNDATION_EXPORT +gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, NSSet<GDTCOREvent *> *logSet); + +/** Constructs a gdt_cct_LogEvent given a GDTCOREvent*. + * + * @param event The GDTCOREvent to convert. + * @return The new gdt_cct_LogEvent object. + */ +FOUNDATION_EXPORT +gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCOREvent *event); + +/** Constructs a gdt_cct_ClientInfo representing the client device. + * + * @return The new gdt_cct_ClientInfo object. + */ +FOUNDATION_EXPORT +gdt_cct_ClientInfo GDTCCTConstructClientInfo(void); + +/** Constructs a gdt_cct_IosClientInfo representing the client device. + * + * @return The new gdt_cct_IosClientInfo object. + */ +FOUNDATION_EXPORT +gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo(void); + +/** Constructs the data of a gdt_cct_NetworkConnectionInfo representing the client nework connection + * information. + * + * @return The data of a gdt_cct_NetworkConnectionInfo object. + */ +FOUNDATION_EXPORT +NSData *GDTCCTConstructNetworkConnectionInfoData(void); + +/** Return a gdt_cct_NetworkConnectionInfo_MobileSubtype representing the client + * + * @return The gdt_cct_NetworkConnectionInfo_MobileSubtype. + */ +FOUNDATION_EXPORT +gdt_cct_NetworkConnectionInfo_MobileSubtype GDTCCTNetworkConnectionInfoNetworkMobileSubtype(void); + +#pragma mark - CCT object decoders + +/** Decodes a gdt_cct_LogResponse given proto bytes. + * + * @note calloc is called in this method. Ensure that pb_release is called on the return value. + * + * @param data The proto bytes of the gdt_cct_LogResponse. + * @param error An error that will be populated if something went wrong during decoding. + * @return A newly allocated gdt_cct_LogResponse from the data, if the bytes decoded properly. + */ +FOUNDATION_EXPORT +gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error); + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploader.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploader.h new file mode 100644 index 00000000..c5c1b678 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploader.h @@ -0,0 +1,60 @@ +/* + * 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 <Foundation/Foundation.h> + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORUploader.h" + +NS_ASSUME_NONNULL_BEGIN + +#if !NDEBUG +/** A notification fired when uploading is complete, detailing the number of events uploaded. */ +extern NSNotificationName const GDTCCTUploadCompleteNotification; +#endif // #if !NDEBUG + +/** Class capable of uploading events to the CCT backend. */ +@interface GDTCCTUploader : NSObject <GDTCORUploader> + +/** The queue on which all CCT uploading will occur. */ +@property(nonatomic, readonly) dispatch_queue_t uploaderQueue; + +/** The URL session that will attempt upload. */ +@property(nonatomic, readonly) NSURLSession *uploaderSession; + +/** The current upload task. */ +@property(nullable, nonatomic, readonly) NSURLSessionUploadTask *currentTask; + +/** The next upload time for the CCT target. */ +@property(nullable, nonatomic) GDTCORClock *CCTNextUploadTime; + +/** The next upload time for the FLL target. */ +@property(nullable, nonatomic) GDTCORClock *FLLNextUploadTime; + +#if !NDEBUG +/** An upload URL used across all targets. For testing only. */ +@property(nullable, nonatomic) NSURL *testServerURL; + +#endif // !NDEBUG + +/** Creates and/or returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c new file mode 100644 index 00000000..36875724 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c @@ -0,0 +1,128 @@ +/* + * 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. + */ + +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.5 */ + +#include "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default = gdt_cct_NetworkConnectionInfo_NetworkType_NONE; +const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default = gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE; +const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default = gdt_cct_QosTierConfiguration_QosTier_DEFAULT; +const int32_t gdt_cct_QosTierConfiguration_log_source_default = 0; + + +const pb_field_t gdt_cct_LogEvent_fields[7] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogEvent, event_time_ms, event_time_ms, 0), + PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_LogEvent, source_extension, event_time_ms, 0), + PB_FIELD( 11, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_code, source_extension, 0), + PB_FIELD( 15, SINT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, timezone_offset_seconds, event_code, 0), + PB_FIELD( 17, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_uptime_ms, timezone_offset_seconds, 0), + PB_FIELD( 23, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, network_connection_info, event_uptime_ms, &gdt_cct_NetworkConnectionInfo_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3] = { + PB_FIELD( 1, ENUM , OPTIONAL, STATIC , FIRST, gdt_cct_NetworkConnectionInfo, network_type, network_type, &gdt_cct_NetworkConnectionInfo_network_type_default), + PB_FIELD( 2, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_NetworkConnectionInfo, mobile_subtype, network_type, &gdt_cct_NetworkConnectionInfo_mobile_subtype_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_IosClientInfo_fields[8] = { + PB_FIELD( 3, BYTES , OPTIONAL, POINTER , FIRST, gdt_cct_IosClientInfo, os_major_version, os_major_version, 0), + PB_FIELD( 4, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, os_full_version, os_major_version, 0), + PB_FIELD( 5, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_build, os_full_version, 0), + PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, country, application_build, 0), + PB_FIELD( 7, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, model, country, 0), + PB_FIELD( 8, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, language_code, model, 0), + PB_FIELD( 11, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_bundle_id, language_code, 0), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_ClientInfo_fields[3] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_ClientInfo, client_type, client_type, 0), + PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_ClientInfo, ios_client_info, client_type, &gdt_cct_IosClientInfo_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_BatchedLogRequest_fields[2] = { + PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_BatchedLogRequest, log_request, log_request, &gdt_cct_LogRequest_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_LogRequest_fields[7] = { + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, gdt_cct_LogRequest, client_info, client_info, &gdt_cct_ClientInfo_fields), + PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, log_source, client_info, 0), + PB_FIELD( 3, MESSAGE , REPEATED, POINTER , OTHER, gdt_cct_LogRequest, log_event, log_source, &gdt_cct_LogEvent_fields), + PB_FIELD( 4, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_time_ms, log_event, 0), + PB_FIELD( 8, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_uptime_ms, request_time_ms, 0), + PB_FIELD( 9, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, qos_tier, request_uptime_ms, &gdt_cct_LogRequest_qos_tier_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_QosTierConfiguration_fields[3] = { + PB_FIELD( 2, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_QosTierConfiguration, qos_tier, qos_tier, 0), + PB_FIELD( 3, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTierConfiguration, log_source, qos_tier, &gdt_cct_QosTierConfiguration_log_source_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_QosTiersOverride_fields[3] = { + PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_QosTiersOverride, qos_tier_configuration, qos_tier_configuration, &gdt_cct_QosTierConfiguration_fields), + PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTiersOverride, qos_tier_fingerprint, qos_tier_configuration, 0), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_LogResponse_fields[3] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogResponse, next_request_wait_millis, next_request_wait_millis, 0), + PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogResponse, qos_tier, next_request_wait_millis, &gdt_cct_QosTiersOverride_fields), + PB_LAST_FIELD +}; + + + + + + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 65536 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 65536 && pb_membersize(gdt_cct_LogRequest, client_info) < 65536 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 256 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 256 && pb_membersize(gdt_cct_LogRequest, client_info) < 256 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse) +#endif + + +/* @@protoc_insertion_point(eof) */ diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h new file mode 100644 index 00000000..e9d9a12c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h @@ -0,0 +1,281 @@ +/* + * 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. + */ + +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.5 */ + +#ifndef PB_GDT_CCT_CCT_NANOPB_H_INCLUDED +#define PB_GDT_CCT_CCT_NANOPB_H_INCLUDED +#include <nanopb/pb.h> + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + +/* Enum definitions */ +typedef enum _gdt_cct_NetworkConnectionInfo_NetworkType { + gdt_cct_NetworkConnectionInfo_NetworkType_NONE = -1, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE = 0, + gdt_cct_NetworkConnectionInfo_NetworkType_WIFI = 1, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_MMS = 2, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_SUPL = 3, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_DUN = 4, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_HIPRI = 5, + gdt_cct_NetworkConnectionInfo_NetworkType_WIMAX = 6, + gdt_cct_NetworkConnectionInfo_NetworkType_BLUETOOTH = 7, + gdt_cct_NetworkConnectionInfo_NetworkType_DUMMY = 8, + gdt_cct_NetworkConnectionInfo_NetworkType_ETHERNET = 9, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_FOTA = 10, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IMS = 11, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_CBS = 12, + gdt_cct_NetworkConnectionInfo_NetworkType_WIFI_P2P = 13, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IA = 14, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_EMERGENCY = 15, + gdt_cct_NetworkConnectionInfo_NetworkType_PROXY = 16, + gdt_cct_NetworkConnectionInfo_NetworkType_VPN = 17 +} gdt_cct_NetworkConnectionInfo_NetworkType; +#define _gdt_cct_NetworkConnectionInfo_NetworkType_MIN gdt_cct_NetworkConnectionInfo_NetworkType_NONE +#define _gdt_cct_NetworkConnectionInfo_NetworkType_MAX gdt_cct_NetworkConnectionInfo_NetworkType_VPN +#define _gdt_cct_NetworkConnectionInfo_NetworkType_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_NetworkType)(gdt_cct_NetworkConnectionInfo_NetworkType_VPN+1)) + +typedef enum _gdt_cct_NetworkConnectionInfo_MobileSubtype { + gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE = 0, + gdt_cct_NetworkConnectionInfo_MobileSubtype_GPRS = 1, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EDGE = 2, + gdt_cct_NetworkConnectionInfo_MobileSubtype_UMTS = 3, + gdt_cct_NetworkConnectionInfo_MobileSubtype_CDMA = 4, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_0 = 5, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_A = 6, + gdt_cct_NetworkConnectionInfo_MobileSubtype_RTT = 7, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSDPA = 8, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSUPA = 9, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPA = 10, + gdt_cct_NetworkConnectionInfo_MobileSubtype_IDEN = 11, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_B = 12, + gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE = 13, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EHRPD = 14, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPAP = 15, + gdt_cct_NetworkConnectionInfo_MobileSubtype_GSM = 16, + gdt_cct_NetworkConnectionInfo_MobileSubtype_TD_SCDMA = 17, + gdt_cct_NetworkConnectionInfo_MobileSubtype_IWLAN = 18, + gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE_CA = 19, + gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED = 100 +} gdt_cct_NetworkConnectionInfo_MobileSubtype; +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MAX gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_MobileSubtype)(gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED+1)) + +typedef enum _gdt_cct_ClientInfo_ClientType { + gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN = 0, + gdt_cct_ClientInfo_ClientType_IOS_FIREBASE = 15 +} gdt_cct_ClientInfo_ClientType; +#define _gdt_cct_ClientInfo_ClientType_MIN gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN +#define _gdt_cct_ClientInfo_ClientType_MAX gdt_cct_ClientInfo_ClientType_IOS_FIREBASE +#define _gdt_cct_ClientInfo_ClientType_ARRAYSIZE ((gdt_cct_ClientInfo_ClientType)(gdt_cct_ClientInfo_ClientType_IOS_FIREBASE+1)) + +typedef enum _gdt_cct_QosTierConfiguration_QosTier { + gdt_cct_QosTierConfiguration_QosTier_DEFAULT = 0, + gdt_cct_QosTierConfiguration_QosTier_UNMETERED_ONLY = 1, + gdt_cct_QosTierConfiguration_QosTier_UNMETERED_OR_DAILY = 2, + gdt_cct_QosTierConfiguration_QosTier_FAST_IF_RADIO_AWAKE = 3, + gdt_cct_QosTierConfiguration_QosTier_NEVER = 4 +} gdt_cct_QosTierConfiguration_QosTier; +#define _gdt_cct_QosTierConfiguration_QosTier_MIN gdt_cct_QosTierConfiguration_QosTier_DEFAULT +#define _gdt_cct_QosTierConfiguration_QosTier_MAX gdt_cct_QosTierConfiguration_QosTier_NEVER +#define _gdt_cct_QosTierConfiguration_QosTier_ARRAYSIZE ((gdt_cct_QosTierConfiguration_QosTier)(gdt_cct_QosTierConfiguration_QosTier_NEVER+1)) + +/* Struct definitions */ +typedef struct _gdt_cct_BatchedLogRequest { + pb_size_t log_request_count; + struct _gdt_cct_LogRequest *log_request; +/* @@protoc_insertion_point(struct:gdt_cct_BatchedLogRequest) */ +} gdt_cct_BatchedLogRequest; + +typedef struct _gdt_cct_IosClientInfo { + pb_bytes_array_t *os_major_version; + pb_bytes_array_t *os_full_version; + pb_bytes_array_t *application_build; + pb_bytes_array_t *country; + pb_bytes_array_t *model; + pb_bytes_array_t *language_code; + pb_bytes_array_t *application_bundle_id; +/* @@protoc_insertion_point(struct:gdt_cct_IosClientInfo) */ +} gdt_cct_IosClientInfo; + +typedef struct _gdt_cct_ClientInfo { + bool has_client_type; + gdt_cct_ClientInfo_ClientType client_type; + bool has_ios_client_info; + gdt_cct_IosClientInfo ios_client_info; +/* @@protoc_insertion_point(struct:gdt_cct_ClientInfo) */ +} gdt_cct_ClientInfo; + +typedef struct _gdt_cct_NetworkConnectionInfo { + bool has_network_type; + gdt_cct_NetworkConnectionInfo_NetworkType network_type; + bool has_mobile_subtype; + gdt_cct_NetworkConnectionInfo_MobileSubtype mobile_subtype; +/* @@protoc_insertion_point(struct:gdt_cct_NetworkConnectionInfo) */ +} gdt_cct_NetworkConnectionInfo; + +typedef struct _gdt_cct_QosTierConfiguration { + bool has_qos_tier; + gdt_cct_QosTierConfiguration_QosTier qos_tier; + bool has_log_source; + int32_t log_source; +/* @@protoc_insertion_point(struct:gdt_cct_QosTierConfiguration) */ +} gdt_cct_QosTierConfiguration; + +typedef struct _gdt_cct_QosTiersOverride { + pb_size_t qos_tier_configuration_count; + struct _gdt_cct_QosTierConfiguration *qos_tier_configuration; + bool has_qos_tier_fingerprint; + int64_t qos_tier_fingerprint; +/* @@protoc_insertion_point(struct:gdt_cct_QosTiersOverride) */ +} gdt_cct_QosTiersOverride; + +typedef struct _gdt_cct_LogEvent { + bool has_event_time_ms; + int64_t event_time_ms; + pb_bytes_array_t *source_extension; + bool has_event_code; + int32_t event_code; + bool has_timezone_offset_seconds; + int64_t timezone_offset_seconds; + bool has_event_uptime_ms; + int64_t event_uptime_ms; + bool has_network_connection_info; + gdt_cct_NetworkConnectionInfo network_connection_info; +/* @@protoc_insertion_point(struct:gdt_cct_LogEvent) */ +} gdt_cct_LogEvent; + +typedef struct _gdt_cct_LogRequest { + bool has_client_info; + gdt_cct_ClientInfo client_info; + bool has_log_source; + int32_t log_source; + pb_size_t log_event_count; + struct _gdt_cct_LogEvent *log_event; + bool has_request_time_ms; + int64_t request_time_ms; + bool has_request_uptime_ms; + int64_t request_uptime_ms; + bool has_qos_tier; + gdt_cct_QosTierConfiguration_QosTier qos_tier; +/* @@protoc_insertion_point(struct:gdt_cct_LogRequest) */ +} gdt_cct_LogRequest; + +typedef struct _gdt_cct_LogResponse { + bool has_next_request_wait_millis; + int64_t next_request_wait_millis; + bool has_qos_tier; + gdt_cct_QosTiersOverride qos_tier; +/* @@protoc_insertion_point(struct:gdt_cct_LogResponse) */ +} gdt_cct_LogResponse; + +/* Default values for struct fields */ +extern const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default; +extern const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default; +extern const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default; +extern const int32_t gdt_cct_QosTierConfiguration_log_source_default; + +/* Initializer values for message structs */ +#define gdt_cct_LogEvent_init_default {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_default} +#define gdt_cct_NetworkConnectionInfo_init_default {false, gdt_cct_NetworkConnectionInfo_NetworkType_NONE, false, gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE} +#define gdt_cct_IosClientInfo_init_default {NULL, NULL, NULL, NULL, NULL, NULL, NULL} +#define gdt_cct_ClientInfo_init_default {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_default} +#define gdt_cct_BatchedLogRequest_init_default {0, NULL} +#define gdt_cct_LogRequest_init_default {false, gdt_cct_ClientInfo_init_default, false, 0, 0, NULL, false, 0, false, 0, false, gdt_cct_QosTierConfiguration_QosTier_DEFAULT} +#define gdt_cct_QosTierConfiguration_init_default {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0} +#define gdt_cct_QosTiersOverride_init_default {0, NULL, false, 0} +#define gdt_cct_LogResponse_init_default {false, 0, false, gdt_cct_QosTiersOverride_init_default} +#define gdt_cct_LogEvent_init_zero {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_zero} +#define gdt_cct_NetworkConnectionInfo_init_zero {false, _gdt_cct_NetworkConnectionInfo_NetworkType_MIN, false, _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN} +#define gdt_cct_IosClientInfo_init_zero {NULL, NULL, NULL, NULL, NULL, NULL, NULL} +#define gdt_cct_ClientInfo_init_zero {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_zero} +#define gdt_cct_BatchedLogRequest_init_zero {0, NULL} +#define gdt_cct_LogRequest_init_zero {false, gdt_cct_ClientInfo_init_zero, false, 0, 0, NULL, false, 0, false, 0, false, _gdt_cct_QosTierConfiguration_QosTier_MIN} +#define gdt_cct_QosTierConfiguration_init_zero {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0} +#define gdt_cct_QosTiersOverride_init_zero {0, NULL, false, 0} +#define gdt_cct_LogResponse_init_zero {false, 0, false, gdt_cct_QosTiersOverride_init_zero} + +/* Field tags (for use in manual encoding/decoding) */ +#define gdt_cct_BatchedLogRequest_log_request_tag 1 +#define gdt_cct_IosClientInfo_os_major_version_tag 3 +#define gdt_cct_IosClientInfo_os_full_version_tag 4 +#define gdt_cct_IosClientInfo_application_build_tag 5 +#define gdt_cct_IosClientInfo_country_tag 6 +#define gdt_cct_IosClientInfo_model_tag 7 +#define gdt_cct_IosClientInfo_language_code_tag 8 +#define gdt_cct_IosClientInfo_application_bundle_id_tag 11 +#define gdt_cct_ClientInfo_client_type_tag 1 +#define gdt_cct_ClientInfo_ios_client_info_tag 4 +#define gdt_cct_NetworkConnectionInfo_network_type_tag 1 +#define gdt_cct_NetworkConnectionInfo_mobile_subtype_tag 2 +#define gdt_cct_QosTierConfiguration_qos_tier_tag 2 +#define gdt_cct_QosTierConfiguration_log_source_tag 3 +#define gdt_cct_QosTiersOverride_qos_tier_configuration_tag 1 +#define gdt_cct_QosTiersOverride_qos_tier_fingerprint_tag 2 +#define gdt_cct_LogEvent_event_time_ms_tag 1 +#define gdt_cct_LogEvent_event_code_tag 11 +#define gdt_cct_LogEvent_event_uptime_ms_tag 17 +#define gdt_cct_LogEvent_source_extension_tag 6 +#define gdt_cct_LogEvent_timezone_offset_seconds_tag 15 +#define gdt_cct_LogEvent_network_connection_info_tag 23 +#define gdt_cct_LogRequest_request_time_ms_tag 4 +#define gdt_cct_LogRequest_request_uptime_ms_tag 8 +#define gdt_cct_LogRequest_client_info_tag 1 +#define gdt_cct_LogRequest_log_source_tag 2 +#define gdt_cct_LogRequest_log_event_tag 3 +#define gdt_cct_LogRequest_qos_tier_tag 9 +#define gdt_cct_LogResponse_next_request_wait_millis_tag 1 +#define gdt_cct_LogResponse_qos_tier_tag 3 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t gdt_cct_LogEvent_fields[7]; +extern const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3]; +extern const pb_field_t gdt_cct_IosClientInfo_fields[8]; +extern const pb_field_t gdt_cct_ClientInfo_fields[3]; +extern const pb_field_t gdt_cct_BatchedLogRequest_fields[2]; +extern const pb_field_t gdt_cct_LogRequest_fields[7]; +extern const pb_field_t gdt_cct_QosTierConfiguration_fields[3]; +extern const pb_field_t gdt_cct_QosTiersOverride_fields[3]; +extern const pb_field_t gdt_cct_LogResponse_fields[3]; + +/* Maximum encoded size of messages (where known) */ +/* gdt_cct_LogEvent_size depends on runtime parameters */ +#define gdt_cct_NetworkConnectionInfo_size 13 +/* gdt_cct_IosClientInfo_size depends on runtime parameters */ +/* gdt_cct_ClientInfo_size depends on runtime parameters */ +/* gdt_cct_BatchedLogRequest_size depends on runtime parameters */ +/* gdt_cct_LogRequest_size depends on runtime parameters */ +#define gdt_cct_QosTierConfiguration_size 13 +/* gdt_cct_QosTiersOverride_size depends on runtime parameters */ +/* gdt_cct_LogResponse_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define CCT_MESSAGES \ + + +#endif + +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h new file mode 100644 index 00000000..295e6f87 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h @@ -0,0 +1,51 @@ +/* + * Copyright 2020 Google LLC + * + * 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h" + +NS_ASSUME_NONNULL_BEGIN + +/** A string sets in customBytes as a key paired to @YES if current event needs to + * populate network connection info data, @NO otherwise. + */ +FOUNDATION_EXPORT NSString *const GDTCCTNeedsNetworkConnectionInfo; + +/** A string sets in customBytes as a key paired to the network connection info data + * of current event. + */ +FOUNDATION_EXPORT NSString *const GDTCCTNetworkConnectionInfo; + +/** A category that uses the customBytes property of a GDTCOREvent to store network connection info. + */ +@interface GDTCOREvent (GDTCCTSupport) + +/** If YES, needs the network connection info field set during prioritization. + * @note Uses the GDTCOREvent customBytes property. + */ +@property(nonatomic) BOOL needsNetworkConnectionInfoPopulated; + +/** The network connection info as collected at the time of the event. + * @note Uses the GDTCOREvent customBytes property. + */ +@property(nullable, nonatomic) NSData *networkConnectionInfoData; + +/** Code that identifies the event to be sent to the CCT backend. + */ +@property(nullable, nonatomic) NSNumber *eventCode; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m new file mode 100644 index 00000000..e191699a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m @@ -0,0 +1,36 @@ +/* + * 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORAssert.h" + +GDTCORAssertionBlock GDTCORAssertionBlockToRunInstead(void) { + // This class is only compiled in by unit tests, and this should fail quickly in optimized builds. + Class GDTCORAssertClass = NSClassFromString(@"GDTCORAssertHelper"); + if (__builtin_expect(!!GDTCORAssertClass, 0)) { + SEL assertionBlockSEL = NSSelectorFromString(@"assertionBlock"); + if (assertionBlockSEL) { + IMP assertionBlockIMP = [GDTCORAssertClass methodForSelector:assertionBlockSEL]; + if (assertionBlockIMP) { + GDTCORAssertionBlock assertionBlock = ((GDTCORAssertionBlock(*)(id, SEL))assertionBlockIMP)( + GDTCORAssertClass, assertionBlockSEL); + if (assertionBlock) { + return assertionBlock; + } + } + } + } + return NULL; +} diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m new file mode 100644 index 00000000..75eed40e --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m @@ -0,0 +1,180 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h" + +#import <sys/sysctl.h> + +// Using a monotonic clock is necessary because CFAbsoluteTimeGetCurrent(), NSDate, and related all +// are subject to drift. That it to say, multiple consecutive calls do not always result in a +// time that is in the future. Clocks may be adjusted by the user, NTP, or any number of external +// factors. This class attempts to determine the wall-clock time at the time of the event by +// capturing the kernel start and time since boot to determine a wallclock time in UTC. +// +// Timezone offsets at the time of a snapshot are also captured in order to provide local-time +// details. Other classes in this library depend on comparing times at some time in the future to +// a time captured in the past, and this class needs to provide a mechanism to do that. +// +// TL;DR: This class attempts to accomplish two things: 1. Provide accurate event times. 2. Provide +// a monotonic clock mechanism to accurately check if some clock snapshot was before or after +// by using a shared reference point (kernel boot time). +// +// Note: Much of the mach time stuff doesn't work properly in the simulator. So this class can be +// difficult to unit test. + +/** Returns the kernel boottime property from sysctl. + * + * Inspired by https://stackoverflow.com/a/40497811 + * + * @return The KERN_BOOTTIME property from sysctl, in nanoseconds. + */ +static int64_t KernelBootTimeInNanoseconds() { + // Caching the result is not possible because clock drift would not be accounted for. + struct timeval boottime; + int mib[2] = {CTL_KERN, KERN_BOOTTIME}; + size_t size = sizeof(boottime); + int rc = sysctl(mib, 2, &boottime, &size, NULL, 0); + if (rc != 0) { + return 0; + } + return (int64_t)boottime.tv_sec * NSEC_PER_SEC + (int64_t)boottime.tv_usec * NSEC_PER_USEC; +} + +/** Returns value of gettimeofday, in nanoseconds. + * + * Inspired by https://stackoverflow.com/a/40497811 + * + * @return The value of gettimeofday, in nanoseconds. + */ +static int64_t UptimeInNanoseconds() { + int64_t before_now_nsec; + int64_t after_now_nsec; + struct timeval now; + + before_now_nsec = KernelBootTimeInNanoseconds(); + // Addresses a race condition in which the system time has updated, but the boottime has not. + do { + gettimeofday(&now, NULL); + after_now_nsec = KernelBootTimeInNanoseconds(); + } while (after_now_nsec != before_now_nsec); + return (int64_t)now.tv_sec * NSEC_PER_SEC + (int64_t)now.tv_usec * NSEC_PER_USEC - + before_now_nsec; +} + +// TODO: Consider adding a 'trustedTime' property that can be populated by the response from a BE. +@implementation GDTCORClock + +- (instancetype)init { + self = [super init]; + if (self) { + _kernelBootTimeNanoseconds = KernelBootTimeInNanoseconds(); + _uptimeNanoseconds = UptimeInNanoseconds(); + _timeMillis = + (int64_t)((CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) * NSEC_PER_USEC); + CFTimeZoneRef timeZoneRef = CFTimeZoneCopySystem(); + _timezoneOffsetSeconds = CFTimeZoneGetSecondsFromGMT(timeZoneRef, 0); + CFRelease(timeZoneRef); + } + return self; +} + ++ (GDTCORClock *)snapshot { + return [[GDTCORClock alloc] init]; +} + ++ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture { + GDTCORClock *snapshot = [self snapshot]; + snapshot->_timeMillis += millisInTheFuture; + return snapshot; +} + +- (BOOL)isAfter:(GDTCORClock *)otherClock { + // These clocks are trivially comparable when they share a kernel boot time. + if (_kernelBootTimeNanoseconds == otherClock->_kernelBootTimeNanoseconds) { + int64_t timeDiff = (_timeMillis + _timezoneOffsetSeconds) - + (otherClock->_timeMillis + otherClock->_timezoneOffsetSeconds); + return timeDiff > 0; + } else { + int64_t kernelBootTimeDiff = + otherClock->_kernelBootTimeNanoseconds - _kernelBootTimeNanoseconds; + // This isn't a great solution, but essentially, if the other clock's boot time is 'later', NO + // is returned. This can be altered by changing the system time and rebooting. + return kernelBootTimeDiff < 0 ? YES : NO; + } +} + +- (int64_t)uptimeMilliseconds { + return self.uptimeNanoseconds / NSEC_PER_MSEC; +} + +- (NSUInteger)hash { + return [@(_kernelBootTimeNanoseconds) hash] ^ [@(_uptimeNanoseconds) hash] ^ + [@(_timeMillis) hash] ^ [@(_timezoneOffsetSeconds) hash]; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +#pragma mark - NSSecureCoding + +/** NSKeyedCoder key for timeMillis property. */ +static NSString *const kGDTCORClockTimeMillisKey = @"GDTCORClockTimeMillis"; + +/** NSKeyedCoder key for timezoneOffsetMillis property. */ +static NSString *const kGDTCORClockTimezoneOffsetSeconds = @"GDTCORClockTimezoneOffsetSeconds"; + +/** NSKeyedCoder key for _kernelBootTime ivar. */ +static NSString *const kGDTCORClockKernelBootTime = @"GDTCORClockKernelBootTime"; + +/** NSKeyedCoder key for _uptimeNanoseconds ivar. */ +static NSString *const kGDTCORClockUptime = @"GDTCORClockUptime"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + // TODO: If the kernelBootTimeNanoseconds is more recent, we need to change the kernel boot time + // and uptimeMillis ivars + _timeMillis = [aDecoder decodeInt64ForKey:kGDTCORClockTimeMillisKey]; + _timezoneOffsetSeconds = [aDecoder decodeInt64ForKey:kGDTCORClockTimezoneOffsetSeconds]; + _kernelBootTimeNanoseconds = [aDecoder decodeInt64ForKey:kGDTCORClockKernelBootTime]; + _uptimeNanoseconds = [aDecoder decodeInt64ForKey:kGDTCORClockUptime]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInt64:_timeMillis forKey:kGDTCORClockTimeMillisKey]; + [aCoder encodeInt64:_timezoneOffsetSeconds forKey:kGDTCORClockTimezoneOffsetSeconds]; + [aCoder encodeInt64:_kernelBootTimeNanoseconds forKey:kGDTCORClockKernelBootTime]; + [aCoder encodeInt64:_uptimeNanoseconds forKey:kGDTCORClockUptime]; +} + +#pragma mark - Deprecated properties + +- (int64_t)kernelBootTime { + return self.kernelBootTimeNanoseconds; +} + +- (int64_t)uptime { + return self.uptimeNanoseconds; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m new file mode 100644 index 00000000..5eaee924 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m @@ -0,0 +1,55 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" + +volatile NSInteger GDTCORConsoleLoggerLoggingLevel = GDTCORLoggingLevelErrors; + +/** The console logger prefix. */ +static NSString *kGDTCORConsoleLogger = @"[GoogleDataTransport]"; + +NSString *GDTCORMessageCodeEnumToString(GDTCORMessageCode code) { + return [[NSString alloc] initWithFormat:@"I-GDTCOR%06ld", (long)code]; +} + +void GDTCORLog(GDTCORMessageCode code, GDTCORLoggingLevel logLevel, NSString *format, ...) { +// Don't log anything in not debug builds. +#if !NDEBUG + if (logLevel >= GDTCORConsoleLoggerLoggingLevel) { + NSString *logFormat = [NSString stringWithFormat:@"%@[%@] %@", kGDTCORConsoleLogger, + GDTCORMessageCodeEnumToString(code), format]; + va_list args; + va_start(args, format); + NSLogv(logFormat, args); + va_end(args); + } +#endif // !NDEBUG +} + +void GDTCORLogAssert( + BOOL wasFatal, NSString *_Nonnull file, NSInteger line, NSString *_Nullable format, ...) { +// Don't log anything in not debug builds. +#if !NDEBUG + GDTCORMessageCode code = wasFatal ? GDTCORMCEFatalAssertion : GDTCORMCEGeneralError; + NSString *logFormat = + [NSString stringWithFormat:@"%@[%@] (%@:%ld) : %@", kGDTCORConsoleLogger, + GDTCORMessageCodeEnumToString(code), file, (long)line, format]; + va_list args; + va_start(args, format); + NSLogv(logFormat, args); + va_end(args); +#endif // !NDEBUG +} diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m new file mode 100644 index 00000000..5f14ec90 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m @@ -0,0 +1,156 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORAssert.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORPlatform.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageProtocol.h" + +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h" + +@implementation GDTCOREvent + ++ (NSString *)nextEventID { + // TODO: Consider a way to make the eventIDs incremental without introducing a storage dependency + // to the object. + // + // Replace special non-alphanumeric characters to avoid potential conflicts with storage logic. + return [[NSUUID UUID].UUIDString stringByReplacingOccurrencesOfString:@"-" withString:@""]; +} + +- (nullable instancetype)initWithMappingID:(NSString *)mappingID target:(GDTCORTarget)target { + GDTCORAssert(mappingID.length > 0, @"Please give a valid mapping ID"); + GDTCORAssert(target > 0, @"A target cannot be negative or 0"); + if (mappingID.length == 0 || target <= 0) { + return nil; + } + self = [super init]; + if (self) { + _eventID = [GDTCOREvent nextEventID]; + _mappingID = mappingID; + _target = target; + _qosTier = GDTCOREventQosDefault; + _expirationDate = [NSDate dateWithTimeIntervalSinceNow:604800]; // 7 days. + + GDTCORLogDebug(@"Event %@ created. ID:%@ mappingID: %@ target:%ld", self, _eventID, mappingID, + (long)target); + } + + return self; +} + +- (instancetype)copy { + GDTCOREvent *copy = [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target]; + copy->_eventID = _eventID; + copy.dataObject = _dataObject; + copy.qosTier = _qosTier; + copy.clockSnapshot = _clockSnapshot; + copy.customBytes = _customBytes; + GDTCORLogDebug(@"Copying event %@ to event %@", self, copy); + return copy; +} + +- (NSUInteger)hash { + // This loses some precision, but it's probably fine. + NSUInteger eventIDHash = [_eventID hash]; + NSUInteger mappingIDHash = [_mappingID hash]; + NSUInteger timeHash = [_clockSnapshot hash]; + NSInteger serializedBytesHash = [_serializedDataObjectBytes hash]; + + return eventIDHash ^ mappingIDHash ^ _target ^ _qosTier ^ timeHash ^ serializedBytesHash; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +#pragma mark - Property overrides + +- (void)setDataObject:(id<GDTCOREventDataObject>)dataObject { + // If you're looking here because of a performance issue in -transportBytes slowing the assignment + // of -dataObject, one way to address this is to add a queue to this class, + // dispatch_(barrier_ if concurrent)async here, and implement the getter with a dispatch_sync. + if (dataObject != _dataObject) { + _dataObject = dataObject; + } + self->_serializedDataObjectBytes = [dataObject transportBytes]; +} + +#pragma mark - NSSecureCoding and NSCoding Protocols + +/** NSCoding key for eventID property. */ +static NSString *kEventIDKey = @"GDTCOREventEventIDKey"; + +/** NSCoding key for mappingID property. */ +static NSString *kMappingIDKey = @"GDTCOREventMappingIDKey"; + +/** NSCoding key for target property. */ +static NSString *kTargetKey = @"GDTCOREventTargetKey"; + +/** NSCoding key for qosTier property. */ +static NSString *kQoSTierKey = @"GDTCOREventQoSTierKey"; + +/** NSCoding key for clockSnapshot property. */ +static NSString *kClockSnapshotKey = @"GDTCOREventClockSnapshotKey"; + +/** NSCoding key for expirationDate property. */ +static NSString *kExpirationDateKey = @"GDTCOREventExpirationDateKey"; + +/** NSCoding key for serializedDataObjectBytes property. */ +static NSString *kSerializedDataObjectBytes = @"GDTCOREventSerializedDataObjectBytesKey"; + +/** NSCoding key for customData property. */ +static NSString *kCustomDataKey = @"GDTCOREventCustomDataKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [self init]; + if (self) { + _mappingID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kMappingIDKey]; + _target = [aDecoder decodeIntegerForKey:kTargetKey]; + _eventID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kEventIDKey] + ?: [GDTCOREvent nextEventID]; + _qosTier = [aDecoder decodeIntegerForKey:kQoSTierKey]; + _clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kClockSnapshotKey]; + _customBytes = [aDecoder decodeObjectOfClass:[NSData class] forKey:kCustomDataKey]; + _expirationDate = [aDecoder decodeObjectOfClass:[NSDate class] forKey:kExpirationDateKey]; + _serializedDataObjectBytes = [aDecoder decodeObjectOfClass:[NSData class] + forKey:kSerializedDataObjectBytes]; + if (!_serializedDataObjectBytes) { + return nil; + } + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_eventID forKey:kEventIDKey]; + [aCoder encodeObject:_mappingID forKey:kMappingIDKey]; + [aCoder encodeInteger:_target forKey:kTargetKey]; + [aCoder encodeInteger:_qosTier forKey:kQoSTierKey]; + [aCoder encodeObject:_clockSnapshot forKey:kClockSnapshotKey]; + [aCoder encodeObject:_customBytes forKey:kCustomDataKey]; + [aCoder encodeObject:_expirationDate forKey:kExpirationDateKey]; + [aCoder encodeObject:self.serializedDataObjectBytes forKey:kSerializedDataObjectBytes]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m new file mode 100644 index 00000000..3dee4d45 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m @@ -0,0 +1,777 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORAssert.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORLifecycle.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORPlatform.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageEventSelector.h" + +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h" +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +NS_ASSUME_NONNULL_BEGIN + +/** A library data key this class uses to track batchIDs. */ +static NSString *const gBatchIDCounterKey = @"GDTCORFlatFileStorageBatchIDCounter"; + +/** The separator used between metadata elements in filenames. */ +static NSString *const kMetadataSeparator = @"-"; + +NSString *const kGDTCOREventComponentsEventIDKey = @"GDTCOREventComponentsEventIDKey"; + +NSString *const kGDTCOREventComponentsQoSTierKey = @"GDTCOREventComponentsQoSTierKey"; + +NSString *const kGDTCOREventComponentsMappingIDKey = @"GDTCOREventComponentsMappingIDKey"; + +NSString *const kGDTCOREventComponentsExpirationKey = @"GDTCOREventComponentsExpirationKey"; + +NSString *const kGDTCORBatchComponentsTargetKey = @"GDTCORBatchComponentsTargetKey"; + +NSString *const kGDTCORBatchComponentsBatchIDKey = @"GDTCORBatchComponentsBatchIDKey"; + +NSString *const kGDTCORBatchComponentsExpirationKey = @"GDTCORBatchComponentsExpirationKey"; + +@implementation GDTCORFlatFileStorage + ++ (void)load { +#if !NDEBUG + [[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetTest]; +#endif // !NDEBUG + [[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetCCT]; + [[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetFLL]; + [[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetCSH]; + + // Sets a global translation mapping to decode GDTCORStoredEvent objects encoded as instances of + // GDTCOREvent instead. Then we do the same thing with GDTCORStorage. This must be done in load + // because there are no direct references to this class and the NSCoding methods won't be called + // unless the class name is mapped early. + [NSKeyedUnarchiver setClass:[GDTCOREvent class] forClassName:@"GDTCORStoredEvent"]; + [NSKeyedUnarchiver setClass:[GDTCORFlatFileStorage class] forClassName:@"GDTCORStorage"]; +} + ++ (instancetype)sharedInstance { + static GDTCORFlatFileStorage *sharedStorage; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedStorage = [[GDTCORFlatFileStorage alloc] init]; + }); + return sharedStorage; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _storageQueue = + dispatch_queue_create("com.google.GDTCORFlatFileStorage", DISPATCH_QUEUE_SERIAL); + _uploadCoordinator = [GDTCORUploadCoordinator sharedInstance]; + } + return self; +} + +#pragma mark - GDTCORStorageProtocol + +- (void)storeEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion { + GDTCORLogDebug(@"Saving event: %@", event); + if (event == nil || event.serializedDataObjectBytes == nil) { + GDTCORLogDebug(@"%@", @"The event was nil, so it was not saved."); + if (completion) { + completion(NO, [NSError errorWithDomain:NSInternalInconsistencyException + code:-1 + userInfo:nil]); + } + return; + } + if (!completion) { + completion = ^(BOOL wasWritten, NSError *_Nullable error) { + GDTCORLogDebug(@"event %@ stored. success:%@ error:%@", event, wasWritten ? @"YES" : @"NO", + error); + }; + } + + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTStorage" + expirationHandler:^{ + // End the background task if it's still valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + + dispatch_async(_storageQueue, ^{ + // Check that a backend implementation is available for this target. + GDTCORTarget target = event.target; + NSString *filePath = [GDTCORFlatFileStorage pathForTarget:target + eventID:event.eventID + qosTier:@(event.qosTier) + expirationDate:event.expirationDate + mappingID:event.mappingID]; + NSError *error; + GDTCOREncodeArchive(event, filePath, &error); + if (error) { + completion(NO, error); + return; + } else { + completion(YES, nil); + } + + // Check the QoS, if it's high priority, notify the target that it has a high priority event. + if (event.qosTier == GDTCOREventQoSFast) { + // TODO: Remove a direct dependency on the upload coordinator. + [self.uploadCoordinator forceUploadForTarget:target]; + } + + // Cancel or end the associated background task if it's still valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }); +} + +- (void)batchWithEventSelector:(nonnull GDTCORStorageEventSelector *)eventSelector + batchExpiration:(nonnull NSDate *)expiration + onComplete: + (nonnull void (^)(NSNumber *_Nullable batchID, + NSSet<GDTCOREvent *> *_Nullable events))onComplete { + dispatch_queue_t queue = _storageQueue; + void (^onPathsForTargetComplete)(NSNumber *, NSSet<NSString *> *_Nonnull) = ^( + NSNumber *batchID, NSSet<NSString *> *_Nonnull paths) { + dispatch_async(queue, ^{ + NSMutableSet<GDTCOREvent *> *events = [[NSMutableSet alloc] init]; + for (NSString *eventPath in paths) { + NSError *error; + GDTCOREvent *event = + (GDTCOREvent *)GDTCORDecodeArchive([GDTCOREvent class], eventPath, nil, &error); + if (event == nil || error) { + GDTCORLogDebug(@"Error deserializing event: %@", error); + [[NSFileManager defaultManager] removeItemAtPath:eventPath error:nil]; + continue; + } else { + NSString *fileName = [eventPath lastPathComponent]; + NSString *batchPath = + [GDTCORFlatFileStorage batchPathForTarget:eventSelector.selectedTarget + batchID:batchID + expirationDate:expiration]; + [[NSFileManager defaultManager] createDirectoryAtPath:batchPath + withIntermediateDirectories:YES + attributes:nil + error:nil]; + NSString *destinationPath = [batchPath stringByAppendingPathComponent:fileName]; + error = nil; + [[NSFileManager defaultManager] moveItemAtPath:eventPath + toPath:destinationPath + error:&error]; + if (error) { + GDTCORLogDebug(@"An event file wasn't moveable into the batch directory: %@", error); + } + [events addObject:event]; + } + } + if (onComplete) { + if (events.count == 0) { + onComplete(nil, nil); + } else { + onComplete(batchID, events); + } + } + }); + }; + + void (^onBatchIDFetchComplete)(NSNumber *) = ^(NSNumber *batchID) { + dispatch_async(queue, ^{ + if (batchID == nil) { + if (onComplete) { + onComplete(nil, nil); + return; + } + } + [self pathsForTarget:eventSelector.selectedTarget + eventIDs:eventSelector.selectedEventIDs + qosTiers:eventSelector.selectedQosTiers + mappingIDs:eventSelector.selectedMappingIDs + onComplete:^(NSSet<NSString *> *_Nonnull paths) { + onPathsForTargetComplete(batchID, paths); + }]; + }); + }; + + [self nextBatchID:^(NSNumber *_Nullable batchID) { + if (batchID == nil) { + if (onComplete) { + onComplete(nil, nil); + } + } else { + onBatchIDFetchComplete(batchID); + } + }]; +} + +- (void)removeBatchWithID:(nonnull NSNumber *)batchID + deleteEvents:(BOOL)deleteEvents + onComplete:(void (^_Nullable)(void))onComplete { + dispatch_async(_storageQueue, ^{ + [self syncThreadUnsafeRemoveBatchWithID:batchID deleteEvents:deleteEvents]; + + if (onComplete) { + onComplete(); + } + }); +} + +- (void)batchIDsForTarget:(GDTCORTarget)target + onComplete:(nonnull void (^)(NSSet<NSNumber *> *_Nullable))onComplete { + dispatch_async(_storageQueue, ^{ + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error; + NSArray<NSString *> *batchPaths = + [fileManager contentsOfDirectoryAtPath:[GDTCORFlatFileStorage batchDataStoragePath] + error:&error]; + if (error || batchPaths.count == 0) { + if (onComplete) { + onComplete(nil); + } + return; + } + NSMutableSet<NSNumber *> *batchIDs = [[NSMutableSet alloc] init]; + for (NSString *path in batchPaths) { + NSDictionary<NSString *, id> *components = [self batchComponentsFromFilename:path]; + NSNumber *targetNumber = components[kGDTCORBatchComponentsTargetKey]; + NSNumber *batchID = components[kGDTCORBatchComponentsBatchIDKey]; + if (targetNumber.intValue == target) { + [batchIDs addObject:batchID]; + } + } + if (onComplete) { + onComplete(batchIDs); + } + }); +} + +- (void)libraryDataForKey:(nonnull NSString *)key + onFetchComplete:(nonnull void (^)(NSData *_Nullable, NSError *_Nullable))onFetchComplete + setNewValue:(NSData *_Nullable (^_Nullable)(void))setValueBlock { + dispatch_async(_storageQueue, ^{ + NSString *dataPath = [[[self class] libraryDataStoragePath] stringByAppendingPathComponent:key]; + NSError *error; + NSData *data = [NSData dataWithContentsOfFile:dataPath options:0 error:&error]; + if (onFetchComplete) { + onFetchComplete(data, error); + } + if (setValueBlock) { + NSData *newValue = setValueBlock(); + // The -isKindOfClass check is necessary because without an explicit 'return nil' in the block + // the implicit return value will be the block itself. The compiler doesn't detect this. + if (newValue != nil && [newValue isKindOfClass:[NSData class]] && newValue.length) { + NSError *newValueError; + [newValue writeToFile:dataPath options:NSDataWritingAtomic error:&newValueError]; + if (newValueError) { + GDTCORLogDebug(@"Error writing new value in libraryDataForKey: %@", newValueError); + } + } + } + }); +} + +- (void)storeLibraryData:(NSData *)data + forKey:(nonnull NSString *)key + onComplete:(nullable void (^)(NSError *_Nullable error))onComplete { + if (!data || data.length <= 0) { + if (onComplete) { + onComplete([NSError errorWithDomain:NSInternalInconsistencyException code:-1 userInfo:nil]); + } + return; + } + dispatch_async(_storageQueue, ^{ + NSError *error; + NSString *dataPath = [[[self class] libraryDataStoragePath] stringByAppendingPathComponent:key]; + [data writeToFile:dataPath options:NSDataWritingAtomic error:&error]; + if (onComplete) { + onComplete(error); + } + }); +} + +- (void)removeLibraryDataForKey:(nonnull NSString *)key + onComplete:(nonnull void (^)(NSError *_Nullable error))onComplete { + dispatch_async(_storageQueue, ^{ + NSError *error; + NSString *dataPath = [[[self class] libraryDataStoragePath] stringByAppendingPathComponent:key]; + if ([[NSFileManager defaultManager] fileExistsAtPath:dataPath]) { + [[NSFileManager defaultManager] removeItemAtPath:dataPath error:&error]; + if (onComplete) { + onComplete(error); + } + } + }); +} + +- (void)hasEventsForTarget:(GDTCORTarget)target onComplete:(void (^)(BOOL hasEvents))onComplete { + dispatch_async(_storageQueue, ^{ + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *targetPath = [NSString + stringWithFormat:@"%@/%ld", [GDTCORFlatFileStorage eventDataStoragePath], (long)target]; + [fileManager createDirectoryAtPath:targetPath + withIntermediateDirectories:YES + attributes:nil + error:nil]; + NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:targetPath]; + BOOL hasEventAtLeastOneEvent = [enumerator nextObject] != nil; + if (onComplete) { + onComplete(hasEventAtLeastOneEvent); + } + }); +} + +- (void)checkForExpirations { + dispatch_async(_storageQueue, ^{ + GDTCORLogDebug(@"%@", @"Checking for expired events and batches"); + NSTimeInterval now = [NSDate date].timeIntervalSince1970; + NSFileManager *fileManager = [NSFileManager defaultManager]; + + // TODO: Storage may not have enough context to remove batches because a batch may be being + // uploaded but the storage has not context of it. + + // Find expired batches and move their events back to the main storage. + // If a batch contains expired events they are expected to be removed further in the method + // together with other expired events in the main storage. + NSString *batchDataPath = [GDTCORFlatFileStorage batchDataStoragePath]; + NSArray<NSString *> *batchDataPaths = [fileManager contentsOfDirectoryAtPath:batchDataPath + error:nil]; + for (NSString *path in batchDataPaths) { + NSString *fileName = [path lastPathComponent]; + NSDictionary<NSString *, id> *batchComponents = [self batchComponentsFromFilename:fileName]; + NSDate *expirationDate = batchComponents[kGDTCORBatchComponentsExpirationKey]; + NSNumber *batchID = batchComponents[kGDTCORBatchComponentsBatchIDKey]; + if (expirationDate != nil && expirationDate.timeIntervalSince1970 < now && batchID != nil) { + NSNumber *batchID = batchComponents[kGDTCORBatchComponentsBatchIDKey]; + // Move all events from the expired batch back to the main storage. + [self syncThreadUnsafeRemoveBatchWithID:batchID deleteEvents:NO]; + } + } + + // Find expired events and remove them from the storage. + NSString *eventDataPath = [GDTCORFlatFileStorage eventDataStoragePath]; + NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:eventDataPath]; + NSString *path; + while ((path = [enumerator nextObject])) { + NSString *fileName = [path lastPathComponent]; + NSDictionary<NSString *, id> *eventComponents = [self eventComponentsFromFilename:fileName]; + NSDate *expirationDate = eventComponents[kGDTCOREventComponentsExpirationKey]; + if (expirationDate != nil && expirationDate.timeIntervalSince1970 < now) { + NSString *pathToDelete = [eventDataPath stringByAppendingPathComponent:path]; + NSError *error; + [fileManager removeItemAtPath:pathToDelete error:&error]; + if (error != nil) { + GDTCORLogDebug(@"There was an error deleting an expired item: %@", error); + } else { + GDTCORLogDebug(@"Item deleted because it expired: %@", pathToDelete); + } + } + } + }); +} + +- (void)storageSizeWithCallback:(void (^)(uint64_t storageSize))onComplete { + dispatch_async(_storageQueue, ^{ + unsigned long long totalBytes = 0; + NSString *eventDataPath = [GDTCORFlatFileStorage eventDataStoragePath]; + NSString *libraryDataPath = [GDTCORFlatFileStorage libraryDataStoragePath]; + NSString *batchDataPath = [GDTCORFlatFileStorage batchDataStoragePath]; + NSDirectoryEnumerator *enumerator = + [[NSFileManager defaultManager] enumeratorAtPath:eventDataPath]; + while ([enumerator nextObject]) { + NSFileAttributeType fileType = enumerator.fileAttributes[NSFileType]; + if ([fileType isEqual:NSFileTypeRegular]) { + NSNumber *fileSize = enumerator.fileAttributes[NSFileSize]; + totalBytes += fileSize.unsignedLongLongValue; + } + } + enumerator = [[NSFileManager defaultManager] enumeratorAtPath:libraryDataPath]; + while ([enumerator nextObject]) { + NSFileAttributeType fileType = enumerator.fileAttributes[NSFileType]; + if ([fileType isEqual:NSFileTypeRegular]) { + NSNumber *fileSize = enumerator.fileAttributes[NSFileSize]; + totalBytes += fileSize.unsignedLongLongValue; + } + } + enumerator = [[NSFileManager defaultManager] enumeratorAtPath:batchDataPath]; + while ([enumerator nextObject]) { + NSFileAttributeType fileType = enumerator.fileAttributes[NSFileType]; + if ([fileType isEqual:NSFileTypeRegular]) { + NSNumber *fileSize = enumerator.fileAttributes[NSFileSize]; + totalBytes += fileSize.unsignedLongLongValue; + } + } + if (onComplete) { + onComplete(totalBytes); + } + }); +} + +#pragma mark - Private not thread safe methods +/** Looks for directory paths containing events for a batch with the specified ID. + * @param batchID A batch ID. + * @param outError A pointer to `NSError *` to assign as possible error to. + * @return An array of an array of paths to directories for event batches with a specified batch ID + * or `nil` in the case of an error. Usually returns a single path but potentially return more in + * cases when the app is terminated while uploading a batch. + */ +- (nullable NSArray<NSString *> *)batchDirPathsForBatchID:(NSNumber *)batchID + error:(NSError **)outError { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error; + NSArray<NSString *> *batches = + [fileManager contentsOfDirectoryAtPath:[GDTCORFlatFileStorage batchDataStoragePath] + error:&error]; + if (batches == nil) { + *outError = error; + GDTCORLogDebug(@"Failed to find event file paths for batchID: %@, error: %@", batchID, error); + return nil; + } + + NSMutableArray<NSString *> *batchDirPaths = [NSMutableArray array]; + for (NSString *path in batches) { + NSDictionary<NSString *, id> *components = [self batchComponentsFromFilename:path]; + NSNumber *pathBatchID = components[kGDTCORBatchComponentsBatchIDKey]; + if ([pathBatchID isEqual:batchID]) { + NSString *batchDirPath = + [[GDTCORFlatFileStorage batchDataStoragePath] stringByAppendingPathComponent:path]; + [batchDirPaths addObject:batchDirPath]; + } + } + + return [batchDirPaths copy]; +} + +/** Makes a copy of the contents of a directory to a directory at the specified path.*/ +- (BOOL)moveContentsOfDirectoryAtPath:(NSString *)sourcePath + to:(NSString *)destinationPath + error:(NSError **)outError { + NSFileManager *fileManager = [NSFileManager defaultManager]; + + NSError *error; + NSArray<NSString *> *contentsPaths = [fileManager contentsOfDirectoryAtPath:sourcePath + error:&error]; + if (contentsPaths == nil) { + *outError = error; + return NO; + } + + NSMutableArray<NSError *> *errors = [NSMutableArray array]; + for (NSString *path in contentsPaths) { + NSString *contentDestinationPath = [destinationPath stringByAppendingPathComponent:path]; + NSString *contentSourcePath = [sourcePath stringByAppendingPathComponent:path]; + + NSError *moveError; + if (![fileManager moveItemAtPath:contentSourcePath + toPath:contentDestinationPath + error:&moveError] && + moveError) { + [errors addObject:moveError]; + } + } + + if (errors.count == 0) { + return YES; + } else { + NSError *combinedError = [NSError errorWithDomain:@"GDTCORFlatFileStorage" + code:-1 + userInfo:@{NSUnderlyingErrorKey : errors}]; + *outError = combinedError; + return NO; + } +} + +- (void)syncThreadUnsafeRemoveBatchWithID:(nonnull NSNumber *)batchID + deleteEvents:(BOOL)deleteEvents { + NSError *error; + NSArray<NSString *> *batchDirPaths = [self batchDirPathsForBatchID:batchID error:&error]; + + if (batchDirPaths == nil) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + + void (^removeBatchDir)(NSString *batchDirPath) = ^(NSString *batchDirPath) { + NSError *error; + if ([fileManager removeItemAtPath:batchDirPath error:&error]) { + GDTCORLogDebug(@"Batch removed at path: %@", batchDirPath); + } else { + GDTCORLogDebug(@"Failed to remove batch at path: %@", batchDirPath); + } + }; + + for (NSString *batchDirPath in batchDirPaths) { + if (deleteEvents) { + removeBatchDir(batchDirPath); + } else { + NSString *batchDirName = [batchDirPath lastPathComponent]; + NSDictionary<NSString *, id> *components = [self batchComponentsFromFilename:batchDirName]; + NSNumber *target = components[kGDTCORBatchComponentsTargetKey]; + NSString *destinationPath = [[GDTCORFlatFileStorage eventDataStoragePath] + stringByAppendingPathComponent:target.stringValue]; + + // `- [NSFileManager moveItemAtPath:toPath:error:]` method fails if an item by the + // destination path already exists (which usually is the case for the current method). Move + // the events one by one instead. + if ([self moveContentsOfDirectoryAtPath:batchDirPath to:destinationPath error:&error]) { + GDTCORLogDebug(@"Batched events at path: %@ moved back to the storage: %@", batchDirPath, + destinationPath); + } else { + GDTCORLogDebug(@"Error encountered whilst moving events back: %@", error); + } + + // Even if not all events where moved back to the storage, there is not much can be done at + // this point, so cleanup batch directory now to avoid clattering. + removeBatchDir(batchDirPath); + } + } +} + +#pragma mark - Private helper methods + ++ (NSString *)eventDataStoragePath { + static NSString *eventDataPath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + eventDataPath = [NSString stringWithFormat:@"%@/%@/gdt_event_data", GDTCORRootDirectory().path, + NSStringFromClass([self class])]; + }); + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:eventDataPath + withIntermediateDirectories:YES + attributes:0 + error:&error]; + GDTCORAssert(error == nil, @"Creating the library data path failed: %@", error); + return eventDataPath; +} + ++ (NSString *)batchDataStoragePath { + static NSString *batchDataPath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + batchDataPath = [NSString stringWithFormat:@"%@/%@/gdt_batch_data", GDTCORRootDirectory().path, + NSStringFromClass([self class])]; + }); + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:batchDataPath + withIntermediateDirectories:YES + attributes:0 + error:&error]; + GDTCORAssert(error == nil, @"Creating the batch data path failed: %@", error); + return batchDataPath; +} + ++ (NSString *)libraryDataStoragePath { + static NSString *libraryDataPath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + libraryDataPath = + [NSString stringWithFormat:@"%@/%@/gdt_library_data", GDTCORRootDirectory().path, + NSStringFromClass([self class])]; + }); + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:libraryDataPath + withIntermediateDirectories:YES + attributes:0 + error:&error]; + GDTCORAssert(error == nil, @"Creating the library data path failed: %@", error); + return libraryDataPath; +} + ++ (NSString *)batchPathForTarget:(GDTCORTarget)target + batchID:(NSNumber *)batchID + expirationDate:(NSDate *)expirationDate { + return + [NSString stringWithFormat:@"%@/%ld%@%@%@%llu", [GDTCORFlatFileStorage batchDataStoragePath], + (long)target, kMetadataSeparator, batchID, kMetadataSeparator, + ((uint64_t)expirationDate.timeIntervalSince1970)]; +} + ++ (NSString *)pathForTarget:(GDTCORTarget)target + eventID:(NSString *)eventID + qosTier:(NSNumber *)qosTier + expirationDate:(NSDate *)expirationDate + mappingID:(NSString *)mappingID { + NSMutableCharacterSet *allowedChars = [[NSCharacterSet alphanumericCharacterSet] mutableCopy]; + [allowedChars addCharactersInString:kMetadataSeparator]; + mappingID = [mappingID stringByAddingPercentEncodingWithAllowedCharacters:allowedChars]; + return [NSString stringWithFormat:@"%@/%ld/%@%@%@%@%llu%@%@", + [GDTCORFlatFileStorage eventDataStoragePath], (long)target, + eventID, kMetadataSeparator, qosTier, kMetadataSeparator, + ((uint64_t)expirationDate.timeIntervalSince1970), + kMetadataSeparator, mappingID]; +} + +- (void)pathsForTarget:(GDTCORTarget)target + eventIDs:(nullable NSSet<NSString *> *)eventIDs + qosTiers:(nullable NSSet<NSNumber *> *)qosTiers + mappingIDs:(nullable NSSet<NSString *> *)mappingIDs + onComplete:(void (^)(NSSet<NSString *> *paths))onComplete { + void (^completion)(NSSet<NSString *> *) = onComplete == nil ? ^(NSSet<NSString *> *paths){} : onComplete; + dispatch_async(_storageQueue, ^{ + NSMutableSet<NSString *> *paths = [[NSMutableSet alloc] init]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *targetPath = [NSString + stringWithFormat:@"%@/%ld", [GDTCORFlatFileStorage eventDataStoragePath], (long)target]; + [fileManager createDirectoryAtPath:targetPath + withIntermediateDirectories:YES + attributes:nil + error:nil]; + NSError *error; + NSArray<NSString *> *dirPaths = [fileManager contentsOfDirectoryAtPath:targetPath error:&error]; + if (error) { + GDTCORLogDebug(@"There was an error reading the contents of the target path: %@", error); + completion(paths); + return; + } + BOOL checkingIDs = eventIDs.count > 0; + BOOL checkingQosTiers = qosTiers.count > 0; + BOOL checkingMappingIDs = mappingIDs.count > 0; + BOOL checkingAnything = checkingIDs == NO && checkingQosTiers == NO && checkingMappingIDs == NO; + for (NSString *path in dirPaths) { + // Skip hidden files that are created as part of atomic file creation. + if ([path hasPrefix:@"."]) { + continue; + } + NSString *filePath = [targetPath stringByAppendingPathComponent:path]; + if (checkingAnything) { + [paths addObject:filePath]; + continue; + } + NSString *filename = [path lastPathComponent]; + NSDictionary<NSString *, id> *eventComponents = [self eventComponentsFromFilename:filename]; + if (!eventComponents) { + GDTCORLogDebug(@"There was an error reading the filename components: %@", eventComponents); + continue; + } + NSString *eventID = eventComponents[kGDTCOREventComponentsEventIDKey]; + NSNumber *qosTier = eventComponents[kGDTCOREventComponentsQoSTierKey]; + NSString *mappingID = eventComponents[kGDTCOREventComponentsMappingIDKey]; + + NSNumber *eventIDMatch = checkingIDs ? @([eventIDs containsObject:eventID]) : nil; + NSNumber *qosTierMatch = checkingQosTiers ? @([qosTiers containsObject:qosTier]) : nil; + NSNumber *mappingIDMatch = + checkingMappingIDs + ? @([mappingIDs containsObject:[mappingID stringByRemovingPercentEncoding]]) + : nil; + if ((eventIDMatch == nil || eventIDMatch.boolValue) && + (qosTierMatch == nil || qosTierMatch.boolValue) && + (mappingIDMatch == nil || mappingIDMatch.boolValue)) { + [paths addObject:filePath]; + } + } + completion(paths); + }); +} + +- (void)nextBatchID:(void (^)(NSNumber *_Nullable batchID))nextBatchID { + __block int32_t lastBatchID = -1; + [self libraryDataForKey:gBatchIDCounterKey + onFetchComplete:^(NSData *_Nullable data, NSError *_Nullable getValueError) { + if (!getValueError) { + [data getBytes:(void *)&lastBatchID length:sizeof(int32_t)]; + } + if (data == nil) { + lastBatchID = 0; + } + if (nextBatchID) { + nextBatchID(@(lastBatchID)); + } + } + setNewValue:^NSData *_Nullable(void) { + if (lastBatchID != -1) { + int32_t incrementedValue = lastBatchID + 1; + return [NSData dataWithBytes:&incrementedValue length:sizeof(int32_t)]; + } + return nil; + }]; +} + +- (nullable NSDictionary<NSString *, id> *)eventComponentsFromFilename:(NSString *)fileName { + NSArray<NSString *> *components = [fileName componentsSeparatedByString:kMetadataSeparator]; + if (components.count >= 4) { + NSString *eventID = components[0]; + NSNumber *qosTier = @(components[1].integerValue); + NSDate *expirationDate = [NSDate dateWithTimeIntervalSince1970:components[2].longLongValue]; + NSString *mappingID = [[components subarrayWithRange:NSMakeRange(3, components.count - 3)] + componentsJoinedByString:kMetadataSeparator]; + if (eventID == nil || qosTier == nil || mappingID == nil || expirationDate == nil) { + GDTCORLogDebug(@"There was an error parsing the event filename components: %@", components); + return nil; + } + return @{ + kGDTCOREventComponentsEventIDKey : eventID, + kGDTCOREventComponentsQoSTierKey : qosTier, + kGDTCOREventComponentsExpirationKey : expirationDate, + kGDTCOREventComponentsMappingIDKey : mappingID + }; + } + GDTCORLogDebug(@"The event filename could not be split: %@", fileName); + return nil; +} + +- (nullable NSDictionary<NSString *, id> *)batchComponentsFromFilename:(NSString *)fileName { + NSArray<NSString *> *components = [fileName componentsSeparatedByString:kMetadataSeparator]; + if (components.count == 3) { + NSNumber *target = @(components[0].integerValue); + NSNumber *batchID = @(components[1].integerValue); + NSDate *expirationDate = [NSDate dateWithTimeIntervalSince1970:components[2].doubleValue]; + if (target == nil || batchID == nil || expirationDate == nil) { + GDTCORLogDebug(@"There was an error parsing the batch filename components: %@", components); + return nil; + } + return @{ + kGDTCORBatchComponentsTargetKey : target, + kGDTCORBatchComponentsBatchIDKey : batchID, + kGDTCORBatchComponentsExpirationKey : expirationDate + }; + } + GDTCORLogDebug(@"The batch filename could not be split: %@", fileName); + return nil; +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillBackground:(GDTCORApplication *)app { + dispatch_async(_storageQueue, ^{ + // Immediately request a background task to run until the end of the current queue of work, + // and cancel it once the work is done. + __block GDTCORBackgroundIdentifier bgID = + [app beginBackgroundTaskWithName:@"GDTStorage" + expirationHandler:^{ + [app endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + // End the background task if it's still valid. + [app endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }); +} + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_storageQueue, ^{ + }); +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m new file mode 100644 index 00000000..4947984c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m @@ -0,0 +1,119 @@ +/* + * 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORLifecycle.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h" + +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h" +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +@implementation GDTCORLifecycle + ++ (void)load { + [self sharedInstance]; +} + +/** Creates/returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance { + static GDTCORLifecycle *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORLifecycle alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(applicationDidEnterBackground:) + name:kGDTCORApplicationDidEnterBackgroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(applicationWillEnterForeground:) + name:kGDTCORApplicationWillEnterForegroundNotification + object:nil]; + + NSString *name = kGDTCORApplicationWillTerminateNotification; + [notificationCenter addObserver:self + selector:@selector(applicationWillTerminate:) + name:name + object:nil]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)applicationDidEnterBackground:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORTransformer that the app is backgrounding."); + [[GDTCORTransformer sharedInstance] appWillBackground:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORUploadCoordinator that the app is backgrounding."); + [[GDTCORUploadCoordinator sharedInstance] appWillBackground:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORRegistrar that the app is backgrounding."); + [[GDTCORRegistrar sharedInstance] appWillBackground:application]; + } +} + +- (void)applicationWillEnterForeground:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORTransformer that the app is foregrounding."); + [[GDTCORTransformer sharedInstance] appWillForeground:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORUploadCoordinator that the app is foregrounding."); + [[GDTCORUploadCoordinator sharedInstance] appWillForeground:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORRegistrar that the app is foregrounding."); + [[GDTCORRegistrar sharedInstance] appWillForeground:application]; + } +} + +- (void)applicationWillTerminate:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORTransformer that the app is terminating."); + [[GDTCORTransformer sharedInstance] appWillTerminate:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORUploadCoordinator that the app is terminating."); + [[GDTCORUploadCoordinator sharedInstance] appWillTerminate:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORRegistrar that the app is terminating."); + [[GDTCORRegistrar sharedInstance] appWillTerminate:application]; + } +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m new file mode 100644 index 00000000..04f15806 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m @@ -0,0 +1,589 @@ +/* + * 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORPlatform.h" + +#import <sys/sysctl.h> + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORAssert.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORReachability.h" + +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +#ifdef GDTCOR_VERSION +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +NSString *const kGDTCORVersion = @STR(GDTCOR_VERSION); +#else +NSString *const kGDTCORVersion = @"Unknown"; +#endif // GDTCOR_VERSION + +const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid = 0; + +NSString *const kGDTCORApplicationDidEnterBackgroundNotification = + @"GDTCORApplicationDidEnterBackgroundNotification"; + +NSString *const kGDTCORApplicationWillEnterForegroundNotification = + @"GDTCORApplicationWillEnterForegroundNotification"; + +NSString *const kGDTCORApplicationWillTerminateNotification = + @"GDTCORApplicationWillTerminateNotification"; + +NSURL *GDTCORRootDirectory(void) { + static NSURL *GDTPath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *cachePath = + NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; + GDTPath = + [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/google-sdks-events", cachePath]]; + GDTCORLogDebug(@"GDT's state will be saved to: %@", GDTPath); + }); + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:GDTPath.path + withIntermediateDirectories:YES + attributes:nil + error:&error]; + GDTCORAssert(error == nil, @"There was an error creating GDT's path"); + return GDTPath; +} + +BOOL GDTCORReachabilityFlagsReachable(GDTCORNetworkReachabilityFlags flags) { +#if !TARGET_OS_WATCH + BOOL reachable = + (flags & kSCNetworkReachabilityFlagsReachable) == kSCNetworkReachabilityFlagsReachable; + BOOL connectionRequired = (flags & kSCNetworkReachabilityFlagsConnectionRequired) == + kSCNetworkReachabilityFlagsConnectionRequired; + return reachable && !connectionRequired; +#else + return (flags & kGDTCORNetworkReachabilityFlagsReachable) == + kGDTCORNetworkReachabilityFlagsReachable; +#endif +} + +BOOL GDTCORReachabilityFlagsContainWWAN(GDTCORNetworkReachabilityFlags flags) { +#if TARGET_OS_IOS + return (flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN; +#else + // Assume network connection not WWAN on macOS, tvOS, watchOS. + return NO; +#endif // TARGET_OS_IOS +} + +GDTCORNetworkType GDTCORNetworkTypeMessage() { +#if !TARGET_OS_WATCH + SCNetworkReachabilityFlags reachabilityFlags = [GDTCORReachability currentFlags]; + if ((reachabilityFlags & kSCNetworkReachabilityFlagsReachable) == + kSCNetworkReachabilityFlagsReachable) { + if (GDTCORReachabilityFlagsContainWWAN(reachabilityFlags)) { + return GDTCORNetworkTypeMobile; + } else { + return GDTCORNetworkTypeWIFI; + } + } +#endif + return GDTCORNetworkTypeUNKNOWN; +} + +GDTCORNetworkMobileSubtype GDTCORNetworkMobileSubTypeMessage() { +#if TARGET_OS_IOS + static NSDictionary<NSString *, NSNumber *> *CTRadioAccessTechnologyToNetworkSubTypeMessage; + static CTTelephonyNetworkInfo *networkInfo; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + CTRadioAccessTechnologyToNetworkSubTypeMessage = @{ + CTRadioAccessTechnologyGPRS : @(GDTCORNetworkMobileSubtypeGPRS), + CTRadioAccessTechnologyEdge : @(GDTCORNetworkMobileSubtypeEdge), + CTRadioAccessTechnologyWCDMA : @(GDTCORNetworkMobileSubtypeWCDMA), + CTRadioAccessTechnologyHSDPA : @(GDTCORNetworkMobileSubtypeHSDPA), + CTRadioAccessTechnologyHSUPA : @(GDTCORNetworkMobileSubtypeHSUPA), + CTRadioAccessTechnologyCDMA1x : @(GDTCORNetworkMobileSubtypeCDMA1x), + CTRadioAccessTechnologyCDMAEVDORev0 : @(GDTCORNetworkMobileSubtypeCDMAEVDORev0), + CTRadioAccessTechnologyCDMAEVDORevA : @(GDTCORNetworkMobileSubtypeCDMAEVDORevA), + CTRadioAccessTechnologyCDMAEVDORevB : @(GDTCORNetworkMobileSubtypeCDMAEVDORevB), + CTRadioAccessTechnologyeHRPD : @(GDTCORNetworkMobileSubtypeHRPD), + CTRadioAccessTechnologyLTE : @(GDTCORNetworkMobileSubtypeLTE), + }; + networkInfo = [[CTTelephonyNetworkInfo alloc] init]; + }); + NSString *networkCurrentRadioAccessTechnology; +#if TARGET_OS_MACCATALYST + NSDictionary<NSString *, NSString *> *networkCurrentRadioAccessTechnologyDict = + networkInfo.serviceCurrentRadioAccessTechnology; + if (networkCurrentRadioAccessTechnologyDict.count) { + networkCurrentRadioAccessTechnology = networkCurrentRadioAccessTechnologyDict.allValues[0]; + } +#else // TARGET_OS_MACCATALYST +#if defined(__IPHONE_12_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000 + if (@available(iOS 12.0, *)) { + NSDictionary<NSString *, NSString *> *networkCurrentRadioAccessTechnologyDict = + networkInfo.serviceCurrentRadioAccessTechnology; + if (networkCurrentRadioAccessTechnologyDict.count) { + // In iOS 12, multiple radio technologies can be captured. We prefer not particular radio + // tech to another, so we'll just return the first value in the dictionary. + networkCurrentRadioAccessTechnology = networkCurrentRadioAccessTechnologyDict.allValues[0]; + } + } else { +#else // defined(__IPHONE_12_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000 + networkCurrentRadioAccessTechnology = networkInfo.currentRadioAccessTechnology; +#endif // // defined(__IPHONE_12_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000 + } +#endif // TARGET_OS_MACCATALYST + if (networkCurrentRadioAccessTechnology) { + NSNumber *networkMobileSubtype = + CTRadioAccessTechnologyToNetworkSubTypeMessage[networkCurrentRadioAccessTechnology]; + return networkMobileSubtype.intValue; + } else { + return GDTCORNetworkMobileSubtypeUNKNOWN; + } +#else + return GDTCORNetworkMobileSubtypeUNKNOWN; +#endif +} + +NSString *_Nonnull GDTCORDeviceModel() { + static NSString *deviceModel = @"Unknown"; + +#if TARGET_OS_IOS || TARGET_OS_TV + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + size_t size; + char *keyToExtract = "hw.machine"; + sysctlbyname(keyToExtract, NULL, &size, NULL, 0); + if (size > 0) { + char *machine = calloc(1, size); + sysctlbyname(keyToExtract, machine, &size, NULL, 0); + deviceModel = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding]; + free(machine); + } else { + deviceModel = [UIDevice currentDevice].model; + } + }); +#endif + + return deviceModel; +} + +NSData *_Nullable GDTCOREncodeArchive(id<NSSecureCoding> obj, + NSString *archivePath, + NSError *_Nullable *error) { + BOOL result = NO; + if (archivePath.length > 0) { + result = [[NSFileManager defaultManager] + createDirectoryAtPath:[archivePath stringByDeletingLastPathComponent] + withIntermediateDirectories:YES + attributes:nil + error:error]; + if (result == NO || *error) { + GDTCORLogDebug(@"Attempt to create directory failed: path:%@ error:%@", archivePath, *error); + return nil; + } + } + NSData *resultData; +#if (defined(__IPHONE_11_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || \ + (defined(__MAC_10_13) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101300) || \ + (defined(__TVOS_11_0) && __TV_OS_VERSION_MAX_ALLOWED >= 110000) || \ + (defined(__WATCHOS_4_0) && __WATCH_OS_VERSION_MAX_ALLOWED >= 040000) || \ + (defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST) + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4, *)) { + resultData = [NSKeyedArchiver archivedDataWithRootObject:obj + requiringSecureCoding:YES + error:error]; + if (resultData == nil || (error != NULL && *error != nil)) { + GDTCORLogDebug(@"Encoding an object failed: %@", *error); + return nil; + } + if (archivePath.length > 0) { + result = [resultData writeToFile:archivePath options:NSDataWritingAtomic error:error]; + if (result == NO || *error) { + GDTCORLogDebug(@"Attempt to write archive failed: path:%@ error:%@", archivePath, *error); + } else { + GDTCORLogDebug(@"Writing archive succeeded: %@", archivePath); + } + } + } else { +#endif + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + resultData = [NSKeyedArchiver archivedDataWithRootObject:obj]; +#pragma clang diagnostic pop + if (archivePath.length > 0) { + result = [resultData writeToFile:archivePath options:NSDataWritingAtomic error:error]; + if (result == NO || *error) { + GDTCORLogDebug(@"Attempt to write archive failed: URL:%@ error:%@", archivePath, *error); + } else { + GDTCORLogDebug(@"Writing archive succeeded: %@", archivePath); + } + } + } @catch (NSException *exception) { + NSString *errorString = + [NSString stringWithFormat:@"An exception was thrown during encoding: %@", exception]; + *error = [NSError errorWithDomain:NSCocoaErrorDomain + code:-1 + userInfo:@{NSLocalizedFailureReasonErrorKey : errorString}]; + } + GDTCORLogDebug(@"Attempt to write archive. successful:%@ URL:%@ error:%@", + result ? @"YES" : @"NO", archivePath, *error); + } + return resultData; +} + +id<NSSecureCoding> _Nullable GDTCORDecodeArchive(Class archiveClass, + NSString *_Nullable archivePath, + NSData *_Nullable archiveData, + NSError *_Nullable *error) { + id<NSSecureCoding> unarchivedObject = nil; +#if (defined(__IPHONE_11_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || \ + (defined(__MAC_10_13) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101300) || \ + (defined(__TVOS_11_0) && __TV_OS_VERSION_MAX_ALLOWED >= 110000) || \ + (defined(__WATCHOS_4_0) && __WATCH_OS_VERSION_MAX_ALLOWED >= 040000) || \ + (defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST) + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4, *)) { + NSData *data = archiveData ? archiveData : [NSData dataWithContentsOfFile:archivePath]; + if (data) { + unarchivedObject = [NSKeyedUnarchiver unarchivedObjectOfClass:archiveClass + fromData:data + error:error]; + } + } else { +#endif + @try { + NSData *archivedData = + archiveData ? archiveData : [NSData dataWithContentsOfFile:archivePath]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + unarchivedObject = [NSKeyedUnarchiver unarchiveObjectWithData:archivedData]; +#pragma clang diagnostic pop + } @catch (NSException *exception) { + NSString *errorString = + [NSString stringWithFormat:@"An exception was thrown during encoding: %@", exception]; + *error = [NSError errorWithDomain:NSCocoaErrorDomain + code:-1 + userInfo:@{NSLocalizedFailureReasonErrorKey : errorString}]; + } + } + return unarchivedObject; +} + +@interface GDTCORApplication () +/** + Private flag to match the existing `readonly` public flag. This will be accurate for all platforms, + since we handle each platform's lifecycle notifications separately. + */ +@property(atomic, readwrite) BOOL isRunningInBackground; + +@end + +@implementation GDTCORApplication + +#if TARGET_OS_WATCH +/** A dispatch queue on which all task semaphores will populate and remove from + * gBackgroundIdentifierToSemaphoreMap. + */ +static dispatch_queue_t gSemaphoreQueue; + +/** For mapping backgroundIdentifier to task semaphore. */ +static NSMutableDictionary<NSNumber *, dispatch_semaphore_t> *gBackgroundIdentifierToSemaphoreMap; +#endif + ++ (void)load { + GDTCORLogDebug( + @"%@", @"GDT is initializing. Please note that if you quit the app via the " + "debugger and not through a lifecycle event, event data will remain on disk but " + "storage won't have a reference to them since the singleton wasn't saved to disk."); +#if TARGET_OS_IOS || TARGET_OS_TV + // If this asserts, please file a bug at https://github.com/firebase/firebase-ios-sdk/issues. + GDTCORFatalAssert( + GDTCORBackgroundIdentifierInvalid == UIBackgroundTaskInvalid, + @"GDTCORBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same."); +#endif + [self sharedApplication]; +} + ++ (void)initialize { +#if TARGET_OS_WATCH + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gSemaphoreQueue = dispatch_queue_create("com.google.GDTCORApplication", DISPATCH_QUEUE_SERIAL); + GDTCORLogDebug( + @"%@", + @"GDTCORApplication is initializing on watchOS, gSemaphoreQueue has been initialized."); + gBackgroundIdentifierToSemaphoreMap = [[NSMutableDictionary alloc] init]; + GDTCORLogDebug(@"%@", @"GDTCORApplication is initializing on watchOS, " + @"gBackgroundIdentifierToSemaphoreMap has been initialized."); + }); +#endif +} + ++ (nullable GDTCORApplication *)sharedApplication { + static GDTCORApplication *application; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + application = [[GDTCORApplication alloc] init]; + }); + return application; +} + +- (instancetype)init { + self = [super init]; + if (self) { + // This class will be instantiated in the foreground. + _isRunningInBackground = NO; + +#if TARGET_OS_IOS || TARGET_OS_TV + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + + NSString *name = UIApplicationWillTerminateNotification; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillTerminate:) + name:name + object:nil]; + +#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + if (@available(iOS 13, tvOS 13.0, *)) { + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:UISceneWillEnterForegroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:UISceneWillDeactivateNotification + object:nil]; + } +#endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + +#elif TARGET_OS_OSX + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(macOSApplicationWillTerminate:) + name:NSApplicationWillTerminateNotification + object:nil]; + +#elif TARGET_OS_WATCH + // TODO: Notification on watchOS platform is currently posted by strings which are frangible. + // TODO: Needs improvements here. + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:@"UIApplicationDidEnterBackgroundNotification" + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:@"UIApplicationWillEnterForegroundNotification" + object:nil]; + + // Adds observers for app extension on watchOS platform + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:NSExtensionHostDidEnterBackgroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:NSExtensionHostWillEnterForegroundNotification + object:nil]; +#endif + } + return self; +} + +#if TARGET_OS_WATCH +/** Generates and maps a unique background identifier to the given semaphore. + * + * @param semaphore The semaphore to map. + * @return A unique GDTCORBackgroundIdentifier mapped to the given semaphore. + */ ++ (GDTCORBackgroundIdentifier)createAndMapBackgroundIdentifierToSemaphore: + (dispatch_semaphore_t)semaphore { + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + dispatch_queue_t queue = gSemaphoreQueue; + NSMutableDictionary<NSNumber *, dispatch_semaphore_t> *map = gBackgroundIdentifierToSemaphoreMap; + if (queue && map) { + dispatch_sync(queue, ^{ + bgID = arc4random(); + NSNumber *bgIDNumber = @(bgID); + while (bgID == GDTCORBackgroundIdentifierInvalid || map[bgIDNumber]) { + bgID = arc4random(); + bgIDNumber = @(bgID); + } + map[bgIDNumber] = semaphore; + }); + } + return bgID; +} + +/** Returns the semaphore mapped to given bgID and removes the value from the map. + * + * @param bgID The unique NSUInteger as GDTCORBackgroundIdentifier. + * @return The semaphore mapped by given bgID. + */ ++ (dispatch_semaphore_t)semaphoreForBackgroundIdentifier:(GDTCORBackgroundIdentifier)bgID { + __block dispatch_semaphore_t semaphore; + dispatch_queue_t queue = gSemaphoreQueue; + NSMutableDictionary<NSNumber *, dispatch_semaphore_t> *map = gBackgroundIdentifierToSemaphoreMap; + NSNumber *bgIDNumber = @(bgID); + if (queue && map) { + dispatch_sync(queue, ^{ + semaphore = map[bgIDNumber]; + [map removeObjectForKey:bgIDNumber]; + }); + } + return semaphore; +} +#endif + +- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name + expirationHandler:(void (^)(void))handler { + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; +#if !TARGET_OS_WATCH + bgID = [[self sharedApplicationForBackgroundTask] beginBackgroundTaskWithName:name + expirationHandler:handler]; +#if !NDEBUG + if (bgID != GDTCORBackgroundIdentifierInvalid) { + GDTCORLogDebug(@"Creating background task with name:%@ bgID:%ld", name, (long)bgID); + } +#endif // !NDEBUG +#elif TARGET_OS_WATCH + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + bgID = [GDTCORApplication createAndMapBackgroundIdentifierToSemaphore:semaphore]; + if (bgID != GDTCORBackgroundIdentifierInvalid) { + GDTCORLogDebug(@"Creating activity with name:%@ bgID:%ld on watchOS.", name, (long)bgID); + } + [[self sharedNSProcessInfoForBackgroundTask] + performExpiringActivityWithReason:name + usingBlock:^(BOOL expired) { + if (expired) { + if (handler) { + handler(); + } + dispatch_semaphore_signal(semaphore); + GDTCORLogDebug( + @"Activity with name:%@ bgID:%ld on watchOS is expiring.", + name, (long)bgID); + } else { + dispatch_semaphore_wait( + semaphore, + dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC)); + } + }]; +#endif + return bgID; +} + +- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID { +#if !TARGET_OS_WATCH + if (bgID != GDTCORBackgroundIdentifierInvalid) { + GDTCORLogDebug(@"Ending background task with ID:%ld was successful", (long)bgID); + [[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID]; + return; + } +#elif TARGET_OS_WATCH + if (bgID != GDTCORBackgroundIdentifierInvalid) { + dispatch_semaphore_t semaphore = [GDTCORApplication semaphoreForBackgroundIdentifier:bgID]; + GDTCORLogDebug(@"Ending activity with bgID:%ld on watchOS.", (long)bgID); + if (semaphore) { + dispatch_semaphore_signal(semaphore); + GDTCORLogDebug(@"Signaling semaphore with bgID:%ld on watchOS.", (long)bgID); + } else { + GDTCORLogDebug(@"Semaphore with bgID:%ld is nil on watchOS.", (long)bgID); + } + } +#endif // !TARGET_OS_WATCH +} + +#pragma mark - App environment helpers + +- (BOOL)isAppExtension { + BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + return appExtension; +} + +/** Returns a UIApplication or NSProcessInfo instance if on the appropriate platform. + * + * @return The shared UIApplication or NSProcessInfo if on the appropriate platform. + */ +#if TARGET_OS_IOS || TARGET_OS_TV +- (nullable UIApplication *)sharedApplicationForBackgroundTask { +#elif TARGET_OS_WATCH +- (nullable NSProcessInfo *)sharedNSProcessInfoForBackgroundTask { +#else +- (nullable id)sharedApplicationForBackgroundTask { +#endif + id sharedInstance = nil; +#if TARGET_OS_IOS || TARGET_OS_TV + if (![self isAppExtension]) { + Class uiApplicationClass = NSClassFromString(@"UIApplication"); + if (uiApplicationClass && + [uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) { + sharedInstance = [uiApplicationClass sharedApplication]; + } + } +#elif TARGET_OS_WATCH + sharedInstance = [NSProcessInfo processInfo]; +#endif + return sharedInstance; +} + +#pragma mark - UIApplicationDelegate and WKExtensionDelegate + +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH +- (void)iOSApplicationDidEnterBackground:(NSNotification *)notif { + _isRunningInBackground = YES; + + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is backgrounding."); + [notifCenter postNotificationName:kGDTCORApplicationDidEnterBackgroundNotification object:nil]; +} + +- (void)iOSApplicationWillEnterForeground:(NSNotification *)notif { + _isRunningInBackground = NO; + + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is foregrounding."); + [notifCenter postNotificationName:kGDTCORApplicationWillEnterForegroundNotification object:nil]; +} +#endif // TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + +#pragma mark - UIApplicationDelegate + +#if TARGET_OS_IOS || TARGET_OS_TV +- (void)iOSApplicationWillTerminate:(NSNotification *)notif { + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is terminating."); + [notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil]; +} +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#pragma mark - NSApplicationDelegate + +#if TARGET_OS_OSX +- (void)macOSApplicationWillTerminate:(NSNotification *)notif { + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is terminating."); + [notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil]; +} +#endif // TARGET_OS_OSX + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m new file mode 100644 index 00000000..2a24362d --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m @@ -0,0 +1,125 @@ +/* + * 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORReachability.h" +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" + +#import <netinet/in.h> + +/** Sets the _callbackFlag ivar whenever the network changes. + * + * @param reachability The reachability object calling back. + * @param flags The new flag values. + * @param info Any data that might be passed in by the callback. + */ +static void GDTCORReachabilityCallback(GDTCORNetworkReachabilityRef reachability, + GDTCORNetworkReachabilityFlags flags, + void *info); + +@implementation GDTCORReachability { + /** The reachability object. */ + GDTCORNetworkReachabilityRef _reachabilityRef; + + /** The queue on which callbacks and all work will occur. */ + dispatch_queue_t _reachabilityQueue; + + /** Flags specified by reachability callbacks. */ + GDTCORNetworkReachabilityFlags _callbackFlags; +} + ++ (void)initialize { + [self sharedInstance]; +} + ++ (instancetype)sharedInstance { + static GDTCORReachability *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORReachability alloc] init]; + }); + return sharedInstance; +} + ++ (GDTCORNetworkReachabilityFlags)currentFlags { + __block GDTCORNetworkReachabilityFlags currentFlags; +#if !TARGET_OS_WATCH + dispatch_sync([GDTCORReachability sharedInstance] -> _reachabilityQueue, ^{ + GDTCORReachability *reachability = [GDTCORReachability sharedInstance]; + currentFlags = + reachability->_callbackFlags ? reachability->_callbackFlags : reachability->_flags; + GDTCORLogDebug(@"Initial reachability flags determined: %d", currentFlags); + }); +#else + currentFlags = kGDTCORNetworkReachabilityFlagsReachable; +#endif + return currentFlags; +} + +- (instancetype)init { + self = [super init]; +#if !TARGET_OS_WATCH + if (self) { + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + _reachabilityQueue = + dispatch_queue_create("com.google.GDTCORReachability", DISPATCH_QUEUE_SERIAL); + _reachabilityRef = SCNetworkReachabilityCreateWithAddress( + kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress); + Boolean success = SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _reachabilityQueue); + if (!success) { + GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", @"The reachability queue wasn't set."); + } + success = SCNetworkReachabilitySetCallback(_reachabilityRef, GDTCORReachabilityCallback, NULL); + if (!success) { + GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", + @"The reachability callback wasn't set."); + } + + // Get the initial set of flags. + dispatch_async(_reachabilityQueue, ^{ + Boolean valid = SCNetworkReachabilityGetFlags(self->_reachabilityRef, &self->_flags); + if (!valid) { + GDTCORLogDebug(@"%@", @"Determining reachability failed."); + self->_flags = 0; + } + }); + } +#endif + return self; +} + +- (void)setCallbackFlags:(GDTCORNetworkReachabilityFlags)flags { + if (_callbackFlags != flags) { + self->_callbackFlags = flags; + } +} + +@end + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +static void GDTCORReachabilityCallback(GDTCORNetworkReachabilityRef reachability, + GDTCORNetworkReachabilityFlags flags, + void *info) { +#pragma clang diagnostic pop + GDTCORLogDebug(@"Reachability changed, new flags: %d", flags); + [[GDTCORReachability sharedInstance] setCallbackFlags:flags]; +} diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m new file mode 100644 index 00000000..63dd45dd --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m @@ -0,0 +1,146 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORRegistrar.h" +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" + +id<GDTCORStorageProtocol> _Nullable GDTCORStorageInstanceForTarget(GDTCORTarget target) { + return [GDTCORRegistrar sharedInstance].targetToStorage[@(target)]; +} + +@implementation GDTCORRegistrar { + /** Backing ivar for targetToUploader property. */ + NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *_targetToUploader; + + /** Backing ivar for targetToStorage property. */ + NSMutableDictionary<NSNumber *, id<GDTCORStorageProtocol>> *_targetToStorage; +} + ++ (instancetype)sharedInstance { + static GDTCORRegistrar *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORRegistrar alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _registrarQueue = dispatch_queue_create("com.google.GDTCORRegistrar", DISPATCH_QUEUE_SERIAL); + _targetToUploader = [[NSMutableDictionary alloc] init]; + _targetToStorage = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)registerUploader:(id<GDTCORUploader>)backend target:(GDTCORTarget)target { + __weak GDTCORRegistrar *weakSelf = self; + dispatch_async(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + GDTCORLogDebug(@"Registered an uploader: %@ for target:%ld", backend, (long)target); + strongSelf->_targetToUploader[@(target)] = backend; + } + }); +} + +- (void)registerStorage:(id<GDTCORStorageProtocol>)storage target:(GDTCORTarget)target { + __weak GDTCORRegistrar *weakSelf = self; + dispatch_async(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + GDTCORLogDebug(@"Registered storage: %@ for target:%ld", storage, (long)target); + strongSelf->_targetToStorage[@(target)] = storage; + } + }); +} + +- (NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *)targetToUploader { + __block NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *targetToUploader; + __weak GDTCORRegistrar *weakSelf = self; + dispatch_sync(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + targetToUploader = strongSelf->_targetToUploader; + } + }); + return targetToUploader; +} + +- (NSMutableDictionary<NSNumber *, id<GDTCORStorageProtocol>> *)targetToStorage { + __block NSMutableDictionary<NSNumber *, id<GDTCORStorageProtocol>> *targetToStorage; + __weak GDTCORRegistrar *weakSelf = self; + dispatch_sync(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + targetToStorage = strongSelf->_targetToStorage; + } + }); + return targetToStorage; +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillBackground:(nonnull GDTCORApplication *)app { + NSArray<id<GDTCORUploader>> *uploaders = [self.targetToUploader allValues]; + for (id<GDTCORUploader> uploader in uploaders) { + if ([uploader respondsToSelector:@selector(appWillBackground:)]) { + [uploader appWillBackground:app]; + } + } + NSArray<id<GDTCORStorageProtocol>> *storages = [self.targetToStorage allValues]; + for (id<GDTCORStorageProtocol> storage in storages) { + if ([storage respondsToSelector:@selector(appWillBackground:)]) { + [storage appWillBackground:app]; + } + } +} + +- (void)appWillForeground:(nonnull GDTCORApplication *)app { + NSArray<id<GDTCORUploader>> *uploaders = [self.targetToUploader allValues]; + for (id<GDTCORUploader> uploader in uploaders) { + if ([uploader respondsToSelector:@selector(appWillForeground:)]) { + [uploader appWillForeground:app]; + } + } + NSArray<id<GDTCORStorageProtocol>> *storages = [self.targetToStorage allValues]; + for (id<GDTCORStorageProtocol> storage in storages) { + if ([storage respondsToSelector:@selector(appWillForeground:)]) { + [storage appWillForeground:app]; + } + } +} + +- (void)appWillTerminate:(nonnull GDTCORApplication *)app { + NSArray<id<GDTCORUploader>> *uploaders = [self.targetToUploader allValues]; + for (id<GDTCORUploader> uploader in uploaders) { + if ([uploader respondsToSelector:@selector(appWillTerminate:)]) { + [uploader appWillTerminate:app]; + } + } + NSArray<id<GDTCORStorageProtocol>> *storages = [self.targetToStorage allValues]; + for (id<GDTCORStorageProtocol> storage in storages) { + if ([storage respondsToSelector:@selector(appWillTerminate:)]) { + [storage appWillTerminate:app]; + } + } +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorageEventSelector.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorageEventSelector.m new file mode 100644 index 00000000..416c42f2 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorageEventSelector.m @@ -0,0 +1,39 @@ +/* + * Copyright 2020 Google LLC + * + * 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageEventSelector.h" + +@implementation GDTCORStorageEventSelector + ++ (instancetype)eventSelectorForTarget:(GDTCORTarget)target { + return [[self alloc] initWithTarget:target eventIDs:nil mappingIDs:nil qosTiers:nil]; +} + +- (instancetype)initWithTarget:(GDTCORTarget)target + eventIDs:(nullable NSSet<NSString *> *)eventIDs + mappingIDs:(nullable NSSet<NSString *> *)mappingIDs + qosTiers:(nullable NSSet<NSNumber *> *)qosTiers { + self = [super init]; + if (self) { + _selectedTarget = target; + _selectedEventIDs = eventIDs; + _selectedMappingIDs = mappingIDs; + _selectedQosTiers = qosTiers; + } + return self; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m new file mode 100644 index 00000000..05c6f6e5 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m @@ -0,0 +1,104 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h" +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORAssert.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREventTransformer.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORLifecycle.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageProtocol.h" + +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h" +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +@implementation GDTCORTransformer + ++ (instancetype)sharedInstance { + static GDTCORTransformer *eventTransformer; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + eventTransformer = [[self alloc] init]; + }); + return eventTransformer; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _eventWritingQueue = + dispatch_queue_create("com.google.GDTCORTransformer", DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (void)transformEvent:(GDTCOREvent *)event + withTransformers:(NSArray<id<GDTCOREventTransformer>> *)transformers + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion { + GDTCORAssert(event, @"You can't write a nil event"); + BOOL hadOriginalCompletion = completion != nil; + if (!completion) { + completion = ^(BOOL wasWritten, NSError *_Nullable error) { + }; + } + + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTTransformer" + expirationHandler:^{ + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + dispatch_async(_eventWritingQueue, ^{ + GDTCOREvent *transformedEvent = event; + for (id<GDTCOREventTransformer> transformer in transformers) { + if ([transformer respondsToSelector:@selector(transform:)]) { + GDTCORLogDebug(@"Applying a transformer to event %@", event); + transformedEvent = [transformer transform:transformedEvent]; + if (!transformedEvent) { + completion(NO, nil); + return; + } + } else { + GDTCORLogError(GDTCORMCETransformerDoesntImplementTransform, + @"Transformer doesn't implement transform: %@", transformer); + completion(NO, nil); + return; + } + } + + id<GDTCORStorageProtocol> storage = + [GDTCORRegistrar sharedInstance].targetToStorage[@(event.target)]; + + [storage storeEvent:transformedEvent onComplete:hadOriginalCompletion ? completion : nil]; + + // The work is done, cancel the background task if it's valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }); +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillTerminate:(GDTCORApplication *)application { + // Flush the queue immediately. + dispatch_sync(_eventWritingQueue, ^{ + }); +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m new file mode 100644 index 00000000..be939a94 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m @@ -0,0 +1,92 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTransport.h" +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORAssert.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h" + +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h" + +@implementation GDTCORTransport + +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + transformers: + (nullable NSArray<id<GDTCOREventTransformer>> *)transformers + target:(GDTCORTarget)target { + GDTCORAssert(mappingID.length > 0, @"A mapping ID cannot be nil or empty"); + GDTCORAssert(target > 0, @"A target cannot be negative or 0"); + if (mappingID == nil || mappingID.length == 0 || target <= 0) { + return nil; + } + self = [super init]; + if (self) { + _mappingID = mappingID; + _transformers = transformers; + _target = target; + _transformerInstance = [GDTCORTransformer sharedInstance]; + } + GDTCORLogDebug(@"Transport object created. mappingID:%@ transformers:%@ target:%ld", mappingID, + transformers, (long)target); + return self; +} + +- (void)sendTelemetryEvent:(GDTCOREvent *)event + onComplete: + (void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion { + event.qosTier = GDTCOREventQoSTelemetry; + [self sendEvent:event onComplete:completion]; +} + +- (void)sendDataEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion { + GDTCORAssert(event.qosTier != GDTCOREventQoSTelemetry, @"Use -sendTelemetryEvent, please."); + [self sendEvent:event onComplete:completion]; +} + +- (void)sendTelemetryEvent:(GDTCOREvent *)event { + [self sendTelemetryEvent:event onComplete:nil]; +} + +- (void)sendDataEvent:(GDTCOREvent *)event { + [self sendDataEvent:event onComplete:nil]; +} + +- (GDTCOREvent *)eventForTransport { + return [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target]; +} + +#pragma mark - Private helper methods + +/** Sends the given event through the transport pipeline. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion { + // TODO: Determine if sending an event before registration is allowed. + GDTCORAssert(event, @"You can't send a nil event"); + GDTCOREvent *copiedEvent = [event copy]; + copiedEvent.clockSnapshot = [GDTCORClock snapshot]; + [self.transformerInstance transformEvent:copiedEvent + withTransformers:_transformers + onComplete:completion]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m new file mode 100644 index 00000000..7074374c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m @@ -0,0 +1,170 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORAssert.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORReachability.h" + +#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +@implementation GDTCORUploadCoordinator + ++ (instancetype)sharedInstance { + static GDTCORUploadCoordinator *sharedUploader; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedUploader = [[GDTCORUploadCoordinator alloc] init]; + [sharedUploader startTimer]; + }); + return sharedUploader; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _coordinationQueue = + dispatch_queue_create("com.google.GDTCORUploadCoordinator", DISPATCH_QUEUE_SERIAL); + _registrar = [GDTCORRegistrar sharedInstance]; + _timerInterval = 30 * NSEC_PER_SEC; + _timerLeeway = 5 * NSEC_PER_SEC; + } + return self; +} + +- (void)forceUploadForTarget:(GDTCORTarget)target { + dispatch_async(_coordinationQueue, ^{ + GDTCORLogDebug(@"Forcing an upload of target %ld", (long)target); + GDTCORUploadConditions conditions = [self uploadConditions]; + conditions |= GDTCORUploadConditionHighPriority; + [self uploadTargets:@[ @(target) ] conditions:conditions]; + }); +} + +#pragma mark - Private helper methods + +/** Starts a timer that checks whether or not events can be uploaded at regular intervals. It will + * check the next-upload clocks of all targets to determine if an upload attempt can be made. + */ +- (void)startTimer { + dispatch_async(_coordinationQueue, ^{ + if (self->_timer) { + // The timer has been already started. + return; + } + + self->_timer = + dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self->_coordinationQueue); + dispatch_source_set_timer(self->_timer, DISPATCH_TIME_NOW, self->_timerInterval, + self->_timerLeeway); + + dispatch_source_set_event_handler(self->_timer, ^{ + if (![[GDTCORApplication sharedApplication] isRunningInBackground]) { + GDTCORUploadConditions conditions = [self uploadConditions]; + GDTCORLogDebug(@"%@", @"Upload timer fired"); + [self uploadTargets:[self.registrar.targetToUploader allKeys] conditions:conditions]; + } + }); + GDTCORLogDebug(@"%@", @"Upload timer started"); + dispatch_resume(self->_timer); + }); +} + +/** Stops the currently running timer. */ +- (void)stopTimer { + if (_timer) { + dispatch_source_cancel(_timer); + _timer = nil; + } +} + +/** Triggers the uploader implementations for the given targets to upload. + * + * @param targets An array of targets to trigger. + * @param conditions The set of upload conditions. + */ +- (void)uploadTargets:(NSArray<NSNumber *> *)targets conditions:(GDTCORUploadConditions)conditions { + dispatch_async(_coordinationQueue, ^{ + // TODO: The reachability signal may be not reliable enough to prevent an upload attempt. + // See https://developer.apple.com/videos/play/wwdc2019/712/ (49:40) for more details. + if ((conditions & GDTCORUploadConditionNoNetwork) == GDTCORUploadConditionNoNetwork) { + return; + } + for (NSNumber *target in targets) { + id<GDTCORUploader> uploader = self->_registrar.targetToUploader[target]; + [uploader uploadTarget:target.intValue withConditions:conditions]; + } + }); +} + +- (void)signalToStoragesToCheckExpirations { + for (id<GDTCORStorageProtocol> storage in [_registrar.targetToStorage allValues]) { + [storage checkForExpirations]; + } +} + +/** Returns the registered storage for the given NSNumber wrapped GDTCORTarget. + * + * @param target The NSNumber wrapping of a GDTCORTarget to find the storage instance of. + * @return The storage instance for the given target. + */ +- (nullable id<GDTCORStorageProtocol>)storageForTarget:(NSNumber *)target { + id<GDTCORStorageProtocol> storage = [GDTCORRegistrar sharedInstance].targetToStorage[target]; + GDTCORAssert(storage, @"A storage must be registered for target %@", target); + return storage; +} + +/** Returns the current upload conditions after making determinations about the network connection. + * + * @return The current upload conditions. + */ +- (GDTCORUploadConditions)uploadConditions { + GDTCORNetworkReachabilityFlags currentFlags = [GDTCORReachability currentFlags]; + BOOL networkConnected = GDTCORReachabilityFlagsReachable(currentFlags); + if (!networkConnected) { + return GDTCORUploadConditionNoNetwork; + } + BOOL isWWAN = GDTCORReachabilityFlagsContainWWAN(currentFlags); + if (isWWAN) { + return GDTCORUploadConditionMobileData; + } else { + return GDTCORUploadConditionWifiData; + } +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillForeground:(GDTCORApplication *)app { + // -startTimer is thread-safe. + [self startTimer]; + [self signalToStoragesToCheckExpirations]; +} + +- (void)appWillBackground:(GDTCORApplication *)app { + dispatch_async(_coordinationQueue, ^{ + [self stopTimer]; + }); +} + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_coordinationQueue, ^{ + [self stopTimer]; + }); +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GoogleDataTransportInternal.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GoogleDataTransportInternal.h new file mode 100644 index 00000000..a002e5cd --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GoogleDataTransportInternal.h @@ -0,0 +1,18 @@ +// Copyright 2020 Google LLC +// +// 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. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#import <GoogleDataTransport/GoogleDataTransport.h> diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h new file mode 100644 index 00000000..e97eb31a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h @@ -0,0 +1,33 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h" + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCOREvent () + +/** The unique ID of the event. This property is for testing only. */ +@property(nonatomic, readwrite) NSString *eventID; + +/** Generates a unique event ID. */ ++ (NSString *)nextEventID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h new file mode 100644 index 00000000..b58ff68c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h @@ -0,0 +1,149 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORLifecycle.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageEventSelector.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageProtocol.h" + +@class GDTCOREvent; +@class GDTCORUploadCoordinator; + +NS_ASSUME_NONNULL_BEGIN + +/** The event components eventID dictionary key. */ +FOUNDATION_EXPORT NSString *const kGDTCOREventComponentsEventIDKey; + +/** The event components qosTier dictionary key. */ +FOUNDATION_EXPORT NSString *const kGDTCOREventComponentsQoSTierKey; + +/** The event components mappingID dictionary key. */ +FOUNDATION_EXPORT NSString *const kGDTCOREventComponentsMappingIDKey; + +/** The event components expirationDate dictionary key. */ +FOUNDATION_EXPORT NSString *const kGDTCOREventComponentsExpirationKey; + +/** The batch components target dictionary key. */ +FOUNDATION_EXPORT NSString *const kGDTCORBatchComponentsTargetKey; + +/** The batch components batchID dictionary key. */ +FOUNDATION_EXPORT NSString *const kGDTCORBatchComponentsBatchIDKey; + +/** The batch components expiration dictionary key. */ +FOUNDATION_EXPORT NSString *const kGDTCORBatchComponentsExpirationKey; + +/** Manages the storage of events. This class is thread-safe. + * + * Event files will be stored as follows: + * <app cache>/google-sdk-events/<classname>/gdt_event_data/<target>/<eventID>.<qosTier>.<mappingID> + * + * Library data will be stored as follows: + * <app cache>/google-sdk-events/<classname>/gdt_library_data/<libraryDataKey> + * + * Batch data will be stored as follows: + * <app + * cache>/google-sdk-events/<classname>/gdt_batch_data/<target>.<batchID>/<eventID>.<qosTier>.<mappingID> + */ +@interface GDTCORFlatFileStorage : NSObject <GDTCORStorageProtocol, GDTCORLifecycleProtocol> + +/** The queue on which all storage work will occur. */ +@property(nonatomic) dispatch_queue_t storageQueue; + +/** The upload coordinator instance used by this storage instance. */ +@property(nonatomic) GDTCORUploadCoordinator *uploadCoordinator; + +/** Creates and/or returns the storage singleton. + * + * @return The storage singleton. + */ ++ (instancetype)sharedInstance; + +/** Returns the base directory under which all events will be stored. + * + * @return The base directory under which all events will be stored. + */ ++ (NSString *)eventDataStoragePath; + +/** Returns the base directory under which all library data will be stored. + * + * @return The base directory under which all library data will be stored. + */ ++ (NSString *)libraryDataStoragePath; + +/** Returns the base directory under which all batch data will be stored. + * + * @return The base directory under which all batch data will be stored. + */ ++ (NSString *)batchDataStoragePath; + +/** */ ++ (NSString *)batchPathForTarget:(GDTCORTarget)target + batchID:(NSNumber *)batchID + expirationDate:(NSDate *)expirationDate; + +/** Returns a constructed storage path based on the given values. This path may not exist. + * + * @param target The target, which is necessary to be given a path. + * @param eventID The eventID. + * @param qosTier The qosTier. + * @param expirationDate The expirationDate as a 1970-relative time interval. + * @param mappingID The mappingID. + * @return The path representing the combination of the given parameters. + */ ++ (NSString *)pathForTarget:(GDTCORTarget)target + eventID:(NSString *)eventID + qosTier:(NSNumber *)qosTier + expirationDate:(NSDate *)expirationDate + mappingID:(NSString *)mappingID; + +/** Returns extant paths that match all of the given parameters. + * + * @param eventIDs The list of eventIDs to look for, or nil for any. + * @param qosTiers The list of qosTiers to look for, or nil for any. + * @param mappingIDs The list of mappingIDs to look for, or nil for any. + * @param onComplete The completion to call once the paths have been discovered. + */ +- (void)pathsForTarget:(GDTCORTarget)target + eventIDs:(nullable NSSet<NSString *> *)eventIDs + qosTiers:(nullable NSSet<NSNumber *> *)qosTiers + mappingIDs:(nullable NSSet<NSString *> *)mappingIDs + onComplete:(void (^)(NSSet<NSString *> *paths))onComplete; + +/** Fetches the current batchID counter value from library storage, increments it, and sets the new + * value. Returns nil if a batchID was not able to be created for some reason. + * + * @param onComplete A block to execute when creating the next batchID is complete. + */ +- (void)nextBatchID:(void (^)(NSNumber *_Nullable batchID))onComplete; + +/** Constructs a dictionary of event filename components. + * + * @param fileName The event filename to split. + * @return The dictionary of event component keys to their values. + */ +- (nullable NSDictionary<NSString *, id> *)eventComponentsFromFilename:(NSString *)fileName; + +/** Constructs a dictionary of batch filename components. + * + * @param fileName The batch folder name to split. + * @return The dictionary of batch component keys to their values. + */ +- (nullable NSDictionary<NSString *, id> *)batchComponentsFromFilename:(NSString *)fileName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h new file mode 100644 index 00000000..90487499 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h @@ -0,0 +1,30 @@ +/* + * 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORReachability.h" + +@interface GDTCORReachability () + +/** Allows manually setting the flags for testing purposes. */ +@property(nonatomic, readwrite) GDTCORNetworkReachabilityFlags flags; + +/** Creates/returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +@end diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h new file mode 100644 index 00000000..85584e6d --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORRegistrar.h" + +@interface GDTCORRegistrar () + +NS_ASSUME_NONNULL_BEGIN + +/** The concurrent queue on which all registration occurs. */ +@property(nonatomic, readonly) dispatch_queue_t registrarQueue; + +/** A map of targets to backend implementations. */ +@property(atomic, readonly) NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *targetToUploader; + +/** A map of targets to storage instances. */ +@property(atomic, readonly) + NSMutableDictionary<NSNumber *, id<GDTCORStorageProtocol>> *targetToStorage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h new file mode 100644 index 00000000..5a808cd2 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORLifecycle.h" + +@class GDTCOREvent; + +@protocol GDTCOREventTransformer; + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the transforming of events. It's desirable for this to be its own class + * because running all events through a single instance ensures that transformers are thread-safe. + * Having a per-transport queue to run on isn't sufficient because transformer objects could + * maintain state (or at least, there's nothing to stop them from doing that) and the same instances + * may be used across multiple instances. + */ +@interface GDTCORTransformer : NSObject <GDTCORLifecycleProtocol> + +/** Instantiates or returns the event transformer singleton. + * + * @return The singleton instance of the event transformer. + */ ++ (instancetype)sharedInstance; + +/** Writes the result of applying the given transformers' -transform method on the given event. + * + * @note If the app is suspended, a background task will be created to complete work in-progress, + * but this method will not send any further events until the app is resumed. + * + * @param event The event to apply transformers on. + * @param transformers The list of transformers to apply. + * @param completion A block to run when an event was written to disk or dropped. + */ +- (void)transformEvent:(GDTCOREvent *)event + withTransformers:(nullable NSArray<id<GDTCOREventTransformer>> *)transformers + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h new file mode 100644 index 00000000..c72019cc --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h @@ -0,0 +1,28 @@ +/* + * Copyright 2018 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 "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransformer () + +/** The queue on which all work will occur. */ +@property(nonatomic) dispatch_queue_t eventWritingQueue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h new file mode 100644 index 00000000..41a12248 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h @@ -0,0 +1,39 @@ +/* + * 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 "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTransport.h" + +@class GDTCORTransformer; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransport () + +/** The mapping identifier that the target backend will use to map the transport bytes to proto. */ +@property(nonatomic) NSString *mappingID; + +/** The transformers that will operate on events sent by this transport. */ +@property(nonatomic) NSArray<id<GDTCOREventTransformer>> *transformers; + +/** The target backend of this transport. */ +@property(nonatomic) NSInteger target; + +/** The transformer instance to used to transform events. Allows injecting a fake during testing. */ +@property(nonatomic) GDTCORTransformer *transformerInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h new file mode 100644 index 00000000..4426fd61 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h @@ -0,0 +1,68 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORLifecycle.h" +#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORRegistrar.h" + +@class GDTCORClock; + +NS_ASSUME_NONNULL_BEGIN + +/** This class connects storage and uploader implementations, providing events to an uploader + * and informing the storage what events were successfully uploaded or not. + */ +@interface GDTCORUploadCoordinator : NSObject <GDTCORLifecycleProtocol> + +/** The queue on which all upload coordination will occur. Also used by a dispatch timer. */ +/** Creates and/or returrns the singleton. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +/** The queue on which all upload coordination will occur. */ +@property(nonatomic, readonly) dispatch_queue_t coordinationQueue; + +/** A timer that will causes regular checks for events to upload. */ +@property(nonatomic, readonly, nullable) dispatch_source_t timer; + +/** The interval the timer will fire. */ +@property(nonatomic, readonly) uint64_t timerInterval; + +/** Some leeway given to libdispatch for the timer interval event. */ +@property(nonatomic, readonly) uint64_t timerLeeway; + +/** The registrar object the coordinator will use. Generally used for testing. */ +@property(nonatomic) GDTCORRegistrar *registrar; + +/** Forces the backend specified by the target to upload the provided set of events. This should + * only ever happen when the QoS tier of an event requires it. + * + * @param target The target that should force an upload. + */ +- (void)forceUploadForTarget:(GDTCORTarget)target; + +/** Starts the upload timer. */ +- (void)startTimer; + +/** Stops the upload timer from running. */ +- (void)stopTimer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORAssert.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORAssert.h new file mode 100644 index 00000000..d920f54b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORAssert.h @@ -0,0 +1,95 @@ +/* + * 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 <Foundation/Foundation.h> + +#import "GDTCORConsoleLogger.h" + +NS_ASSUME_NONNULL_BEGIN + +/** A block type that could be run instead of normal assertion logging. No return type, no params. + */ +typedef void (^GDTCORAssertionBlock)(void); + +/** Returns the result of executing a soft-linked method present in unit tests that allows a block + * to be run instead of normal assertion logging. This helps ameliorate issues with catching + * exceptions that occur on a dispatch_queue. + * + * @return A block that can be run instead of normal assert printing. + */ +FOUNDATION_EXPORT GDTCORAssertionBlock _Nullable GDTCORAssertionBlockToRunInstead(void); + +#if defined(NS_BLOCK_ASSERTIONS) + +#define GDTCORAssert(condition, ...) \ + do { \ + } while (0); + +#define GDTCORFatalAssert(condition, ...) \ + do { \ + } while (0); + +#else // defined(NS_BLOCK_ASSERTIONS) + +/** Asserts using a console log, unless a block was specified to be run instead. + * + * @param condition The condition you'd expect to be YES. + */ +#define GDTCORAssert(condition, format, ...) \ + do { \ + __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ + if (__builtin_expect(!(condition), 0)) { \ + GDTCORAssertionBlock assertionBlock = GDTCORAssertionBlockToRunInstead(); \ + if (assertionBlock) { \ + assertionBlock(); \ + } else { \ + NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \ + __assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; \ + GDTCORLogAssert(NO, __assert_file__, __LINE__, format, ##__VA_ARGS__); \ + __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ + } \ + } \ + } while (0); + +/** Asserts by logging to the console and throwing an exception if NS_BLOCK_ASSERTIONS is not + * defined. + * + * @param condition The condition you'd expect to be YES. + */ +#define GDTCORFatalAssert(condition, format, ...) \ + do { \ + __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ + if (__builtin_expect(!(condition), 0)) { \ + GDTCORAssertionBlock assertionBlock = GDTCORAssertionBlockToRunInstead(); \ + if (assertionBlock) { \ + assertionBlock(); \ + } else { \ + NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \ + __assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; \ + GDTCORLogAssert(YES, __assert_file__, __LINE__, format, ##__VA_ARGS__); \ + [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \ + object:self \ + file:__assert_file__ \ + lineNumber:__LINE__ \ + description:format, ##__VA_ARGS__]; \ + __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ + } \ + } \ + } while (0); + +#endif // defined(NS_BLOCK_ASSERTIONS) + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h new file mode 100644 index 00000000..8c75b50e --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h @@ -0,0 +1,66 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** This class manages the device clock and produces snapshots of the current time. */ +@interface GDTCORClock : NSObject <NSSecureCoding> + +/** The wallclock time, UTC, in milliseconds. */ +@property(nonatomic, readonly) int64_t timeMillis; + +/** The offset from UTC in seconds. */ +@property(nonatomic, readonly) int64_t timezoneOffsetSeconds; + +/** The kernel boot time when this clock was created in nanoseconds. */ +@property(nonatomic, readonly) int64_t kernelBootTimeNanoseconds; + +/** The device uptime when this clock was created in nanoseconds. */ +@property(nonatomic, readonly) int64_t uptimeNanoseconds; + +@property(nonatomic, readonly) int64_t kernelBootTime DEPRECATED_MSG_ATTRIBUTE( + "Please use `kernelBootTimeNanoseconds` instead"); + +@property(nonatomic, readonly) + int64_t uptime DEPRECATED_MSG_ATTRIBUTE("Please use `uptimeNanoseconds` instead"); + +/** Creates a GDTCORClock object using the current time and offsets. + * + * @return A new GDTCORClock object representing the current time state. + */ ++ (instancetype)snapshot; + +/** Creates a GDTCORClock object representing a time in the future, relative to now. + * + * @param millisInTheFuture The millis in the future from now this clock should represent. + * @return An instance representing a future time. + */ ++ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture; + +/** Compares one clock with another, returns YES if the caller is after the parameter. + * + * @return YES if the calling clock's time is after the given clock's time. + */ +- (BOOL)isAfter:(GDTCORClock *)otherClock; + +/** Returns value of `uptime` property in milliseconds. */ +- (int64_t)uptimeMilliseconds; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h new file mode 100644 index 00000000..d306f182 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h @@ -0,0 +1,143 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +/** The current logging level. This value and higher will be printed. Declared as volatile to make + * getting and setting atomic. + */ +FOUNDATION_EXPORT volatile NSInteger GDTCORConsoleLoggerLoggingLevel; + +/** A list of logging levels that GDT supports. */ +typedef NS_ENUM(NSInteger, GDTCORLoggingLevel) { + + /** Causes all logs to be printed. */ + GDTCORLoggingLevelDebug = 1, + + /** Causes all non-debug logs to be printed. */ + GDTCORLoggingLevelVerbose = 2, + + /** Causes warnings and errors to be printed. */ + GDTCORLoggingLevelWarnings = 3, + + /** Causes errors to be printed. This is the default value. */ + GDTCORLoggingLevelErrors = 4 +}; + +/** A list of message codes to print in the logger that help to correspond printed messages with + * code locations. + * + * Prefixes: + * - MCD => MessageCodeDebug + * - MCW => MessageCodeWarning + * - MCE => MessageCodeError + */ +typedef NS_ENUM(NSInteger, GDTCORMessageCode) { + + /** For debug logs. */ + GDTCORMCDDebugLog = 0, + + /** For warning messages concerning transportBytes: not being implemented by a data object. */ + GDTCORMCWDataObjectMissingBytesImpl = 1, + + /** For warning messages concerning a failed event upload. */ + GDTCORMCWUploadFailed = 2, + + /** For warning messages concerning a forced event upload. */ + GDTCORMCWForcedUpload = 3, + + /** For warning messages concerning a failed reachability call. */ + GDTCORMCWReachabilityFailed = 4, + + /** For warning messages concerning a database warning. */ + GDTCORMCWDatabaseWarning = 5, + + /** For warning messages concerning the reading of a event file. */ + GDTCORMCWFileReadError = 6, + + /** For error messages concerning transform: not being implemented by an event transformer. */ + GDTCORMCETransformerDoesntImplementTransform = 1000, + + /** For error messages concerning the creation of a directory failing. */ + GDTCORMCEDirectoryCreationError = 1001, + + /** For error messages concerning the writing of a event file. */ + GDTCORMCEFileWriteError = 1002, + + /** For error messages concerning the lack of a prioritizer for a given backend. */ + GDTCORMCEPrioritizerError = 1003, + + /** For error messages concerning a package delivery API violation. */ + GDTCORMCEDeliverTwice = 1004, + + /** For error messages concerning an error in an implementation of -transportBytes. */ + GDTCORMCETransportBytesError = 1005, + + /** For general purpose error messages in a dependency. */ + GDTCORMCEGeneralError = 1006, + + /** For fatal errors. Please go to https://github.com/firebase/firebase-ios-sdk/issues and open + * an issue if you encounter an error with this code. + */ + GDTCORMCEFatalAssertion = 1007, + + /** For error messages concerning the reading of a event file. */ + GDTCORMCEFileReadError = 1008, + + /** For errors related to running sqlite. */ + GDTCORMCEDatabaseError = 1009, +}; + +/** Prints the given code and format string to the console. + * + * @param code The message code describing the nature of the log. + * @param logLevel The log level of this log. + * @param format The format string. + */ +FOUNDATION_EXPORT +void GDTCORLog(GDTCORMessageCode code, GDTCORLoggingLevel logLevel, NSString *_Nonnull format, ...) + NS_FORMAT_FUNCTION(3, 4); + +/** Prints an assert log to the console. + * + * @param wasFatal Send YES if the assertion should be fatal, NO otherwise. + * @param file The file in which the failure occurred. + * @param line The line number of the failure. + * @param format The format string. + */ +FOUNDATION_EXPORT void GDTCORLogAssert(BOOL wasFatal, + NSString *_Nonnull file, + NSInteger line, + NSString *_Nullable format, + ...) NS_FORMAT_FUNCTION(4, 5); + +/** Returns the string that represents some message code. + * + * @param code The code to convert to a string. + * @return The string representing the message code. + */ +FOUNDATION_EXPORT NSString *_Nonnull GDTCORMessageCodeEnumToString(GDTCORMessageCode code); + +#define GDTCORLogDebug(MESSAGE_FORMAT, ...) \ + GDTCORLog(GDTCORMCDDebugLog, GDTCORLoggingLevelDebug, MESSAGE_FORMAT, __VA_ARGS__); + +// A define to wrap GULLogWarning with slightly more convenient usage. +#define GDTCORLogWarning(MESSAGE_CODE, MESSAGE_FORMAT, ...) \ + GDTCORLog(MESSAGE_CODE, GDTCORLoggingLevelWarnings, MESSAGE_FORMAT, __VA_ARGS__); + +// A define to wrap GULLogError with slightly more convenient usage and a failing assert. +#define GDTCORLogError(MESSAGE_CODE, MESSAGE_FORMAT, ...) \ + GDTCORLog(MESSAGE_CODE, GDTCORLoggingLevelErrors, MESSAGE_FORMAT, __VA_ARGS__); diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h new file mode 100644 index 00000000..52c2384e --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h @@ -0,0 +1,87 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +#import "GDTCOREventDataObject.h" +#import "GDTCORTargets.h" + +@class GDTCORClock; + +NS_ASSUME_NONNULL_BEGIN + +/** The different possible quality of service specifiers. High values indicate high priority. */ +typedef NS_ENUM(NSInteger, GDTCOREventQoS) { + /** The QoS tier wasn't set, and won't ever be sent. */ + GDTCOREventQoSUnknown = 0, + + /** This event is internal telemetry data that should not be sent on its own if possible. */ + GDTCOREventQoSTelemetry = 1, + + /** This event should be sent, but in a batch only roughly once per day. */ + GDTCOREventQoSDaily = 2, + + /** This event should be sent when requested by the uploader. */ + GDTCOREventQosDefault = 3, + + /** This event should be sent immediately along with any other data that can be batched. */ + GDTCOREventQoSFast = 4, + + /** This event should only be uploaded on wifi. */ + GDTCOREventQoSWifiOnly = 5, +}; + +@interface GDTCOREvent : NSObject <NSSecureCoding> + +/** The unique ID of the event. */ +@property(readonly, nonatomic) NSString *eventID; + +/** The mapping identifier, to allow backends to map the transport bytes to a proto. */ +@property(nullable, readonly, nonatomic) NSString *mappingID; + +/** The identifier for the backend this event will eventually be sent to. */ +@property(readonly, nonatomic) GDTCORTarget target; + +/** The data object encapsulated in the transport of your choice, as long as it implements + * the GDTCOREventDataObject protocol. */ +@property(nullable, nonatomic) id<GDTCOREventDataObject> dataObject; + +/** The serialized bytes from calling [dataObject transportBytes]. */ +@property(nullable, readonly, nonatomic) NSData *serializedDataObjectBytes; + +/** The quality of service tier this event belongs to. */ +@property(nonatomic) GDTCOREventQoS qosTier; + +/** The clock snapshot at the time of the event. */ +@property(nonatomic) GDTCORClock *clockSnapshot; + +/** The expiration date of the event. Default is 604800 seconds (7 days) from creation. */ +@property(nonatomic) NSDate *expirationDate; + +/** Bytes that can be used by an uploader later on. */ +@property(nullable, nonatomic) NSData *customBytes; + +/** Initializes an instance using the given mappingID. + * + * @param mappingID The mapping identifier. + * @param target The event's target identifier. + * @return An instance of this class. + */ +- (nullable instancetype)initWithMappingID:(NSString *)mappingID target:(GDTCORTarget)target; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREventDataObject.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREventDataObject.h new file mode 100644 index 00000000..34ef6242 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREventDataObject.h @@ -0,0 +1,36 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** This protocol defines the common interface that event protos should implement regardless of the + * underlying transport technology (protobuf, nanopb, etc). + */ +@protocol GDTCOREventDataObject <NSObject> + +@required + +/** Returns the serialized proto bytes of the implementing event proto. + * + * @return the serialized proto bytes of the implementing event proto. + */ +- (NSData *)transportBytes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREventTransformer.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREventTransformer.h new file mode 100644 index 00000000..29f95924 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREventTransformer.h @@ -0,0 +1,38 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +/** Defines the API that event transformers must adopt. */ +@protocol GDTCOREventTransformer <NSObject> + +@required + +/** Transforms an event by applying some logic to it. Events returned can be nil, for example, in + * instances where the event should be sampled. + * + * @param event The event to transform. + * @return A transformed event, or nil if the transformation dropped the event. + */ +- (nullable GDTCOREvent *)transform:(GDTCOREvent *)event; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORLifecycle.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORLifecycle.h new file mode 100644 index 00000000..ac04fd64 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORLifecycle.h @@ -0,0 +1,63 @@ +/* + * 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 <Foundation/Foundation.h> + +#import "GDTCORPlatform.h" + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +/** A protocol defining the lifecycle events objects in the library must respond to immediately. */ +@protocol GDTCORLifecycleProtocol <NSObject> + +@optional + +/** Indicates an imminent app termination in the rare occurrence when -applicationWillTerminate: has + * been called. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillTerminate:(GDTCORApplication *)app; + +/** Indicates that the app is moving to background and eventual suspension or the current UIScene is + * deactivating. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillBackground:(GDTCORApplication *)app; + +/** Indicates that the app is resuming operation or a UIScene is activating. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillForeground:(GDTCORApplication *)app; + +@end + +/** This class manages the library's response to app lifecycle events. + * + * When backgrounding, the library doesn't stop processing events, it's just that several background + * tasks will end up being created for every event that's sent, and the stateful objects of the + * library (GDTCORStorage and GDTCORUploadCoordinator instances) will deserialize themselves from + * and to disk before and after every operation, respectively. + */ +@interface GDTCORLifecycle : NSObject <GDTCORApplicationDelegate> + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORPlatform.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORPlatform.h new file mode 100644 index 00000000..951204b6 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORPlatform.h @@ -0,0 +1,210 @@ +/* + * 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 <Foundation/Foundation.h> + +#if !TARGET_OS_WATCH +#import <SystemConfiguration/SystemConfiguration.h> +#endif + +#if TARGET_OS_IOS || TARGET_OS_TV +#import <UIKit/UIKit.h> +#elif TARGET_OS_OSX +#import <AppKit/AppKit.h> +#elif TARGET_OS_WATCH +#import <WatchKit/WatchKit.h> +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#if TARGET_OS_IOS +#import <CoreTelephony/CTTelephonyNetworkInfo.h> +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** The GoogleDataTransport library version. */ +FOUNDATION_EXPORT NSString *const kGDTCORVersion; + +/** A notification sent out if the app is backgrounding. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationDidEnterBackgroundNotification; + +/** A notification sent out if the app is foregrounding. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillEnterForegroundNotification; + +/** A notification sent out if the app is terminating. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillTerminateNotification; + +/** The different possible network connection type. */ +typedef NS_ENUM(NSInteger, GDTCORNetworkType) { + GDTCORNetworkTypeUNKNOWN = 0, + GDTCORNetworkTypeWIFI = 1, + GDTCORNetworkTypeMobile = 2, +}; + +/** The different possible network connection mobile subtype. */ +typedef NS_ENUM(NSInteger, GDTCORNetworkMobileSubtype) { + GDTCORNetworkMobileSubtypeUNKNOWN = 0, + GDTCORNetworkMobileSubtypeGPRS = 1, + GDTCORNetworkMobileSubtypeEdge = 2, + GDTCORNetworkMobileSubtypeWCDMA = 3, + GDTCORNetworkMobileSubtypeHSDPA = 4, + GDTCORNetworkMobileSubtypeHSUPA = 5, + GDTCORNetworkMobileSubtypeCDMA1x = 6, + GDTCORNetworkMobileSubtypeCDMAEVDORev0 = 7, + GDTCORNetworkMobileSubtypeCDMAEVDORevA = 8, + GDTCORNetworkMobileSubtypeCDMAEVDORevB = 9, + GDTCORNetworkMobileSubtypeHRPD = 10, + GDTCORNetworkMobileSubtypeLTE = 11, +}; + +#if !TARGET_OS_WATCH +/** Define SCNetworkReachabilityFlags as GDTCORNetworkReachabilityFlags on non-watchOS. */ +typedef SCNetworkReachabilityFlags GDTCORNetworkReachabilityFlags; + +/** Define SCNetworkReachabilityRef as GDTCORNetworkReachabilityRef on non-watchOS. */ +typedef SCNetworkReachabilityRef GDTCORNetworkReachabilityRef; + +#else +/** The different possible reachabilityFlags option on watchOS. */ +typedef NS_OPTIONS(uint32_t, GDTCORNetworkReachabilityFlags) { + kGDTCORNetworkReachabilityFlagsReachable = 1 << 1, + // TODO(doudounan): Add more options on watchOS if watchOS network connection information relative + // APIs available in the future. +}; + +/** Define a struct as GDTCORNetworkReachabilityRef on watchOS to store network connection + * information. */ +typedef struct { + // TODO(doudounan): Store network connection information on watchOS if watchOS network connection + // information relative APIs available in the future. +} GDTCORNetworkReachabilityRef; +#endif + +/** Returns a URL to the root directory under which all GDT-associated data must be saved. + * + * @return A URL to the root directory under which all GDT-associated data must be saved. + */ +NSURL *GDTCORRootDirectory(void); + +/** Compares flags with the reachable flag (on non-watchos with both reachable and + * connectionRequired flags), if available, and returns YES if network reachable. + * + * @param flags The set of reachability flags. + * @return YES if the network is reachable, NO otherwise. + */ +BOOL GDTCORReachabilityFlagsReachable(GDTCORNetworkReachabilityFlags flags); + +/** Compares flags with the WWAN reachability flag, if available, and returns YES if present. + * + * @param flags The set of reachability flags. + * @return YES if the WWAN flag is set, NO otherwise. + */ +BOOL GDTCORReachabilityFlagsContainWWAN(GDTCORNetworkReachabilityFlags flags); + +/** Generates an enum message GDTCORNetworkType representing network connection type. + * + * @return A GDTCORNetworkType representing network connection type. + */ +GDTCORNetworkType GDTCORNetworkTypeMessage(void); + +/** Generates an enum message GDTCORNetworkMobileSubtype representing network connection mobile + * subtype. + * + * @return A GDTCORNetworkMobileSubtype representing network connection mobile subtype. + */ +GDTCORNetworkMobileSubtype GDTCORNetworkMobileSubTypeMessage(void); + +/** Identifies the model of the device on which the library is currently working on. + * + * @return A NSString representing the device model. + */ +NSString *_Nonnull GDTCORDeviceModel(void); + +/** Writes the given object to the given fileURL and populates the given error if it fails. + * + * @param obj The object to encode. + * @param filePath The path to write the object to. Can be nil if you just need the data. + * @param error The error to populate if something goes wrong. + * @return The data of the archive. If error is nil, it's been written to disk. + */ +NSData *_Nullable GDTCOREncodeArchive(id<NSSecureCoding> obj, + NSString *_Nullable filePath, + NSError *_Nullable *error); + +/** Decodes an object of the given class from the given archive path or data and populates the given + * error if it fails. + * + * @param archiveClass The class of the archive's root object. + * @param archivePath The path to the archived data. Don't use with the archiveData param. + * @param archiveData The data to decode. Don't use with the archivePath param. + * @param error The error to populate if something goes wrong. + */ +id<NSSecureCoding> _Nullable GDTCORDecodeArchive(Class archiveClass, + NSString *_Nullable archivePath, + NSData *_Nullable archiveData, + NSError *_Nullable *error); + +/** A typedef identify background identifiers. */ +typedef volatile NSUInteger GDTCORBackgroundIdentifier; + +/** A background task's invalid sentinel value. */ +FOUNDATION_EXPORT const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid; + +#if TARGET_OS_IOS || TARGET_OS_TV +/** A protocol that wraps UIApplicationDelegate, WKExtensionDelegate or NSObject protocol, depending + * on the platform. + */ +@protocol GDTCORApplicationDelegate <UIApplicationDelegate> +#elif TARGET_OS_OSX +@protocol GDTCORApplicationDelegate <NSApplicationDelegate> +#elif TARGET_OS_WATCH +@protocol GDTCORApplicationDelegate <WKExtensionDelegate> +#else +@protocol GDTCORApplicationDelegate <NSObject> +#endif // TARGET_OS_IOS || TARGET_OS_TV + +@end + +/** A cross-platform application class. */ +@interface GDTCORApplication : NSObject <GDTCORApplicationDelegate> + +/** Flag to determine if the application is running in the background. */ +@property(atomic, readonly) BOOL isRunningInBackground; + +/** Creates and/or returns the shared application instance. + * + * @return The shared application instance. + */ ++ (nullable GDTCORApplication *)sharedApplication; + +/** Creates a background task with the returned identifier if on a suitable platform. + * + * @name name The name of the task, useful for debugging which background tasks are running. + * @param handler The handler block that is called if the background task expires. + * @return An identifier for the background task, or GDTCORBackgroundIdentifierInvalid if one + * couldn't be created. + */ +- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name + expirationHandler:(void (^__nullable)(void))handler; + +/** Ends the background task if the identifier is valid. + * + * @param bgID The background task to end. + */ +- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORReachability.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORReachability.h new file mode 100644 index 00000000..840f02a7 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORReachability.h @@ -0,0 +1,31 @@ +/* + * 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 <Foundation/Foundation.h> + +#import "GDTCORPlatform.h" + +NS_ASSUME_NONNULL_BEGIN + +/** This class helps determine upload conditions by determining connectivity. */ +@interface GDTCORReachability : NSObject + +/** The current set flags indicating network conditions */ ++ (GDTCORNetworkReachabilityFlags)currentFlags; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORRegistrar.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORRegistrar.h new file mode 100644 index 00000000..4f8d73e8 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORRegistrar.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +#import "GDTCORStorageProtocol.h" +#import "GDTCORTargets.h" +#import "GDTCORUploader.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the registration of targets with the transport SDK. */ +@interface GDTCORRegistrar : NSObject <GDTCORLifecycleProtocol> + +/** Creates and/or returns the singleton instance. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +/** Registers a backend implementation with the GoogleDataTransport infrastructure. + * + * @param backend The backend object to register. + * @param target The target this backend object will be responsible for. + */ +- (void)registerUploader:(id<GDTCORUploader>)backend target:(GDTCORTarget)target; + +/** Registers a storage implementation with the GoogleDataTransport infrastructure. + * + * @param storage The storage instance to be associated with this uploader and target. + * @param target The target this backend object will be responsible for. + */ +- (void)registerStorage:(id<GDTCORStorageProtocol>)storage target:(GDTCORTarget)target; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageEventSelector.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageEventSelector.h new file mode 100644 index 00000000..e839fb14 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageEventSelector.h @@ -0,0 +1,61 @@ +/* + * Copyright 2020 Google LLC + * + * 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 <Foundation/Foundation.h> + +#import "GDTCORTargets.h" + +NS_ASSUME_NONNULL_BEGIN + +/** This class enables the finding of events by matching events with the properties of this class. + */ +@interface GDTCORStorageEventSelector : NSObject + +/** The target to find events for. Required. */ +@property(readonly, nonatomic) GDTCORTarget selectedTarget; + +/** Finds a specific event. */ +@property(nullable, readonly, nonatomic) NSSet<NSString *> *selectedEventIDs; + +/** Finds all events of a mappingID. */ +@property(nullable, readonly, nonatomic) NSSet<NSString *> *selectedMappingIDs; + +/** Finds all events matching the qosTiers in this list. */ +@property(nullable, readonly, nonatomic) NSSet<NSNumber *> *selectedQosTiers; + +/** Initializes an event selector that will find all events for the given target. + * + * @param target The selected target. + * @return An immutable event selector instance. + */ ++ (instancetype)eventSelectorForTarget:(GDTCORTarget)target; + +/** Instantiates an event selector. + * + * @param target The selected target. + * @param eventIDs Optional param to find an event matching this eventID. + * @param mappingIDs Optional param to find events matching this mappingID. + * @param qosTiers Optional param to find events matching the given QoS tiers. + * @return An immutable event selector instance. + */ +- (instancetype)initWithTarget:(GDTCORTarget)target + eventIDs:(nullable NSSet<NSString *> *)eventIDs + mappingIDs:(nullable NSSet<NSString *> *)mappingIDs + qosTiers:(nullable NSSet<NSNumber *> *)qosTiers; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageProtocol.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageProtocol.h new file mode 100644 index 00000000..2c5af6dc --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORStorageProtocol.h @@ -0,0 +1,128 @@ +/* + * Copyright 2020 Google LLC + * + * 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 <Foundation/Foundation.h> + +#import "GDTCORLifecycle.h" +#import "GDTCORStorageEventSelector.h" +#import "GDTCORTargets.h" + +@class GDTCOREvent; +@class GDTCORClock; + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^GDTCORStorageBatchBlock)(NSNumber *_Nullable newBatchID, + NSSet<GDTCOREvent *> *_Nullable batchEvents); + +/** Defines the interface a storage subsystem is expected to implement. */ +@protocol GDTCORStorageProtocol <NSObject, GDTCORLifecycleProtocol> + +@required + +/** Stores an event and calls onComplete with a non-nil error if anything went wrong. + * + * @param event The event to store + * @param completion The completion block to call after an attempt to store the event has been made. + */ +- (void)storeEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion; + +/** Returns YES if some events have been stored for the given target, NO otherwise. + * + * @param onComplete The completion block to invoke when determining if there are events is done. + */ +- (void)hasEventsForTarget:(GDTCORTarget)target onComplete:(void (^)(BOOL hasEvents))onComplete; + +/** Constructs an event batch with the given event selector. Events in this batch will not be + * returned in any queries or other batches until the batch is removed. + * + * @param eventSelector The event selector used to find the events. + * @param expiration The expiration time of the batch. If removeBatchWithID:deleteEvents:onComplete: + * is not called within this time frame, the batch will be removed with its events deleted. + * @param onComplete The completion handler to be called when the events have been fetched. + */ +- (void)batchWithEventSelector:(nonnull GDTCORStorageEventSelector *)eventSelector + batchExpiration:(nonnull NSDate *)expiration + onComplete:(nonnull GDTCORStorageBatchBlock)onComplete; + +/** Removes the event batch. + * + * @param batchID The batchID to remove. + * @param deleteEvents If YES, the events in this batch are deleted. + * @param onComplete The completion handler to call when the batch removal process has completed. + */ +- (void)removeBatchWithID:(NSNumber *)batchID + deleteEvents:(BOOL)deleteEvents + onComplete:(void (^_Nullable)(void))onComplete; + +/** Finds the batchIDs for the given target and calls the callback block. + * + * @param target The target. + * @param onComplete The block to invoke with the set of current batchIDs. + */ +- (void)batchIDsForTarget:(GDTCORTarget)target + onComplete:(void (^)(NSSet<NSNumber *> *_Nullable batchIDs))onComplete; + +/** Checks the storage for expired events and batches, deletes them if they're expired. */ +- (void)checkForExpirations; + +/** Persists the given data with the given key. + * + * @param data The data to store. + * @param key The unique key to store it to. + * @param onComplete An block to be run when storage of the data is complete. + */ +- (void)storeLibraryData:(NSData *)data + forKey:(NSString *)key + onComplete:(nullable void (^)(NSError *_Nullable error))onComplete; + +/** Retrieves the stored data for the given key and optionally sets a new value. + * + * @param key The key corresponding to the desired data. + * @param onFetchComplete The callback to invoke with the data once it's retrieved. + * @param setValueBlock This optional block can provide a new value to set. + */ +- (void)libraryDataForKey:(nonnull NSString *)key + onFetchComplete:(nonnull void (^)(NSData *_Nullable data, + NSError *_Nullable error))onFetchComplete + setNewValue:(NSData *_Nullable (^_Nullable)(void))setValueBlock; + +/** Removes data from storage and calls the callback when complete. + * + * @param key The key of the data to remove. + * @param onComplete The callback that will be invoked when removing the data is complete. + */ +- (void)removeLibraryDataForKey:(NSString *)key + onComplete:(void (^)(NSError *_Nullable error))onComplete; + +/** Calculates and returns the total disk size that this storage consumes. + * + * @param onComplete The callback that will be invoked once storage size calculation is complete. + */ +- (void)storageSizeWithCallback:(void (^)(uint64_t storageSize))onComplete; + +@end + +/** Retrieves the storage instance for the given target. + * + * @param target The target. + * * @return The storage instance registered for the target, or nil if there is none. + */ +FOUNDATION_EXPORT +id<GDTCORStorageProtocol> _Nullable GDTCORStorageInstanceForTarget(GDTCORTarget target); + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTargets.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTargets.h new file mode 100644 index 00000000..5db8852e --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTargets.h @@ -0,0 +1,37 @@ +/* + * 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 <Foundation/Foundation.h> + +/** The list of targets supported by the shared transport infrastructure. If adding a new target, + * please use the previous value +1. + */ +typedef NS_ENUM(NSInteger, GDTCORTarget) { + + /** A target only used in testing. */ + kGDTCORTargetTest = 999, + + /** The CCT target. */ + kGDTCORTargetCCT = 1000, + + /** The FLL target. */ + kGDTCORTargetFLL = 1001, + + /** The CSH target. The CSH target is a special-purpose backend. Please do not use it without + * permission. + */ + kGDTCORTargetCSH = 1002 +}; diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTransport.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTransport.h new file mode 100644 index 00000000..e58248da --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTransport.h @@ -0,0 +1,92 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +#import "GDTCOREventTransformer.h" +#import "GDTCORTargets.h" + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransport : NSObject + +// Please use the designated initializer. +- (instancetype)init NS_UNAVAILABLE; + +/** Initializes a new transport that will send events to the given target backend. + * + * @param mappingID The mapping identifier used by the backend to map the data object transport + * bytes to a proto. + * @param transformers A list of transformers to be applied to events that are sent. + * @param target The target backend of this transport. + * @return A transport that will send events. + */ +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + transformers: + (nullable NSArray<id<GDTCOREventTransformer>> *)transformers + target:(GDTCORTarget)target NS_DESIGNATED_INITIALIZER; + +/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority, + * and sometimes won't be sent on their own. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendTelemetryEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion; + +/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority, + * and sometimes won't be sent on their own. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + */ +- (void)sendTelemetryEvent:(GDTCOREvent *)event; + +/** Copies and sends an SDK service data event. Events send using this API are higher in priority, + * and will cause a network request at some point in the relative near future. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendDataEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion; + +/** Copies and sends an SDK service data event. Events send using this API are higher in priority, + * and will cause a network request at some point in the relative near future. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + */ +- (void)sendDataEvent:(GDTCOREvent *)event; + +/** Creates an event for use by this transport. + * + * @return An event that is suited for use by this transport. + */ +- (GDTCOREvent *)eventForTransport; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORUploader.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORUploader.h new file mode 100644 index 00000000..3945cd3b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORUploader.h @@ -0,0 +1,59 @@ +/* + * Copyright 2018 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 <Foundation/Foundation.h> + +#import "GDTCORClock.h" +#import "GDTCORLifecycle.h" +#import "GDTCORTargets.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Options that define a set of upload conditions. This is used to help minimize end user data + * consumption impact. + */ +typedef NS_OPTIONS(NSInteger, GDTCORUploadConditions) { + + /** An upload shouldn't be attempted, because there's no network. */ + GDTCORUploadConditionNoNetwork = 1 << 0, + + /** An upload would likely use mobile data. */ + GDTCORUploadConditionMobileData = 1 << 1, + + /** An upload would likely use wifi data. */ + GDTCORUploadConditionWifiData = 1 << 2, + + /** An upload uses some sort of network connection, but it's unclear which. */ + GDTCORUploadConditionUnclearConnection = 1 << 3, + + /** A high priority event has occurred. */ + GDTCORUploadConditionHighPriority = 1 << 4, +}; + +/** This protocol defines the common interface for uploader implementations. */ +@protocol GDTCORUploader <NSObject, GDTCORLifecycleProtocol> + +@required + +/** Uploads events to the backend using this specific backend's chosen format. + * + * @param conditions The conditions that the upload attempt is likely to occur under. + */ +- (void)uploadTarget:(GDTCORTarget)target withConditions:(GDTCORUploadConditions)conditions; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GoogleDataTransport.h b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GoogleDataTransport.h new file mode 100644 index 00000000..3e8905f1 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GoogleDataTransport.h @@ -0,0 +1,26 @@ +/* + * Copyright 2018 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 "GDTCORClock.h" +#import "GDTCORConsoleLogger.h" +#import "GDTCOREvent.h" +#import "GDTCOREventDataObject.h" +#import "GDTCOREventTransformer.h" +#import "GDTCORLifecycle.h" +#import "GDTCORRegistrar.h" +#import "GDTCORTargets.h" +#import "GDTCORTransport.h" +#import "GDTCORUploader.h" diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/LICENSE b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/LICENSE new file mode 100644 index 00000000..fcce5066 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Firebase, Inc. + + 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. diff --git a/StoneIsland/platforms/ios/Pods/GoogleDataTransport/README.md b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/README.md new file mode 100644 index 00000000..c44a3f92 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/GoogleDataTransport/README.md @@ -0,0 +1,300 @@ +[](https://cocoapods.org/pods/Firebase) +[](https://cocoapods.org/pods/Firebase) +[](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-appdistribution-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`: + +``` +brew install clang-format +brew install swiftformat +``` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and add it to the Xcode project. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`FirebaseDatabase/Tests/Resources/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-appdistribution-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/appdistribution/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg |
