Archived
Configured colours and added additional images to ready app for iOS 13 dark mode
This commit is contained in:
+7
-7
@@ -14,18 +14,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTLibrary/Private/GDTAssert.h"
|
||||
#import "GDTCORLibrary/Public/GDTCORAssert.h"
|
||||
|
||||
GDTAssertionBlock GDTAssertionBlockToRunInsteadOfNSAssert(void) {
|
||||
GDTCORAssertionBlock GDTCORAssertionBlockToRunInstead(void) {
|
||||
// This class is only compiled in by unit tests, and this should fail quickly in optimized builds.
|
||||
Class GDTAssertClass = NSClassFromString(@"GDTAssertHelper");
|
||||
if (__builtin_expect(!!GDTAssertClass, 0)) {
|
||||
Class GDTCORAssertClass = NSClassFromString(@"GDTCORAssertHelper");
|
||||
if (__builtin_expect(!!GDTCORAssertClass, 0)) {
|
||||
SEL assertionBlockSEL = NSSelectorFromString(@"assertionBlock");
|
||||
if (assertionBlockSEL) {
|
||||
IMP assertionBlockIMP = [GDTAssertClass methodForSelector:assertionBlockSEL];
|
||||
IMP assertionBlockIMP = [GDTCORAssertClass methodForSelector:assertionBlockSEL];
|
||||
if (assertionBlockIMP) {
|
||||
GDTAssertionBlock assertionBlock =
|
||||
((GDTAssertionBlock(*)(id, SEL))assertionBlockIMP)(GDTAssertClass, assertionBlockSEL);
|
||||
GDTCORAssertionBlock assertionBlock = ((GDTCORAssertionBlock(*)(id, SEL))assertionBlockIMP)(
|
||||
GDTCORAssertClass, assertionBlockSEL);
|
||||
if (assertionBlock) {
|
||||
return assertionBlock;
|
||||
}
|
||||
+18
-18
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTLibrary/Public/GDTClock.h"
|
||||
#import "GDTCORLibrary/Public/GDTCORClock.h"
|
||||
|
||||
#import <sys/sysctl.h>
|
||||
|
||||
@@ -74,7 +74,7 @@ static int64_t UptimeInNanoseconds() {
|
||||
}
|
||||
|
||||
// TODO: Consider adding a 'trustedTime' property that can be populated by the response from a BE.
|
||||
@implementation GDTClock
|
||||
@implementation GDTCORClock
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
@@ -90,17 +90,17 @@ static int64_t UptimeInNanoseconds() {
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (GDTClock *)snapshot {
|
||||
return [[GDTClock alloc] init];
|
||||
+ (GDTCORClock *)snapshot {
|
||||
return [[GDTCORClock alloc] init];
|
||||
}
|
||||
|
||||
+ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture {
|
||||
GDTClock *snapshot = [self snapshot];
|
||||
GDTCORClock *snapshot = [self snapshot];
|
||||
snapshot->_timeMillis += millisInTheFuture;
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
- (BOOL)isAfter:(GDTClock *)otherClock {
|
||||
- (BOOL)isAfter:(GDTCORClock *)otherClock {
|
||||
// These clocks are trivially comparable when they share a kernel boot time.
|
||||
if (_kernelBootTime == otherClock->_kernelBootTime) {
|
||||
int64_t timeDiff = (_timeMillis + _timezoneOffsetSeconds) -
|
||||
@@ -126,16 +126,16 @@ static int64_t UptimeInNanoseconds() {
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
/** NSKeyedCoder key for timeMillis property. */
|
||||
static NSString *const kGDTClockTimeMillisKey = @"GDTClockTimeMillis";
|
||||
static NSString *const kGDTCORClockTimeMillisKey = @"GDTCORClockTimeMillis";
|
||||
|
||||
/** NSKeyedCoder key for timezoneOffsetMillis property. */
|
||||
static NSString *const kGDTClockTimezoneOffsetSeconds = @"GDTClockTimezoneOffsetSeconds";
|
||||
static NSString *const kGDTCORClockTimezoneOffsetSeconds = @"GDTCORClockTimezoneOffsetSeconds";
|
||||
|
||||
/** NSKeyedCoder key for _kernelBootTime ivar. */
|
||||
static NSString *const kGDTClockKernelBootTime = @"GDTClockKernelBootTime";
|
||||
static NSString *const kGDTCORClockKernelBootTime = @"GDTCORClockKernelBootTime";
|
||||
|
||||
/** NSKeyedCoder key for _uptime ivar. */
|
||||
static NSString *const kGDTClockUptime = @"GDTClockUptime";
|
||||
static NSString *const kGDTCORClockUptime = @"GDTCORClockUptime";
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
@@ -146,19 +146,19 @@ static NSString *const kGDTClockUptime = @"GDTClockUptime";
|
||||
if (self) {
|
||||
// TODO: If the kernelBootTime is more recent, we need to change the kernel boot time and
|
||||
// uptimeMillis ivars
|
||||
_timeMillis = [aDecoder decodeInt64ForKey:kGDTClockTimeMillisKey];
|
||||
_timezoneOffsetSeconds = [aDecoder decodeInt64ForKey:kGDTClockTimezoneOffsetSeconds];
|
||||
_kernelBootTime = [aDecoder decodeInt64ForKey:kGDTClockKernelBootTime];
|
||||
_uptime = [aDecoder decodeInt64ForKey:kGDTClockUptime];
|
||||
_timeMillis = [aDecoder decodeInt64ForKey:kGDTCORClockTimeMillisKey];
|
||||
_timezoneOffsetSeconds = [aDecoder decodeInt64ForKey:kGDTCORClockTimezoneOffsetSeconds];
|
||||
_kernelBootTime = [aDecoder decodeInt64ForKey:kGDTCORClockKernelBootTime];
|
||||
_uptime = [aDecoder decodeInt64ForKey:kGDTCORClockUptime];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||
[aCoder encodeInt64:_timeMillis forKey:kGDTClockTimeMillisKey];
|
||||
[aCoder encodeInt64:_timezoneOffsetSeconds forKey:kGDTClockTimezoneOffsetSeconds];
|
||||
[aCoder encodeInt64:_kernelBootTime forKey:kGDTClockKernelBootTime];
|
||||
[aCoder encodeInt64:_uptime forKey:kGDTClockUptime];
|
||||
[aCoder encodeInt64:_timeMillis forKey:kGDTCORClockTimeMillisKey];
|
||||
[aCoder encodeInt64:_timezoneOffsetSeconds forKey:kGDTCORClockTimezoneOffsetSeconds];
|
||||
[aCoder encodeInt64:_kernelBootTime forKey:kGDTCORClockKernelBootTime];
|
||||
[aCoder encodeInt64:_uptime forKey:kGDTCORClockUptime];
|
||||
}
|
||||
|
||||
@end
|
||||
+7
-7
@@ -14,20 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTLibrary/Public/GDTConsoleLogger.h"
|
||||
#import "GDTCORLibrary/Public/GDTCORConsoleLogger.h"
|
||||
|
||||
/** The console logger prefix. */
|
||||
static NSString *kGDTConsoleLogger = @"[GoogleDataTransport]";
|
||||
static NSString *kGDTCORConsoleLogger = @"[GoogleDataTransport]";
|
||||
|
||||
NSString *GDTMessageCodeEnumToString(GDTMessageCode code) {
|
||||
return [[NSString alloc] initWithFormat:@"I-GDT%06ld", (long)code];
|
||||
NSString *GDTCORMessageCodeEnumToString(GDTCORMessageCode code) {
|
||||
return [[NSString alloc] initWithFormat:@"I-GDTCOR%06ld", (long)code];
|
||||
}
|
||||
|
||||
void GDTLog(GDTMessageCode code, NSString *format, ...) {
|
||||
void GDTCORLog(GDTCORMessageCode code, NSString *format, ...) {
|
||||
// Don't log anything in not debug builds.
|
||||
#ifndef NDEBUG
|
||||
NSString *logFormat = [NSString
|
||||
stringWithFormat:@"%@[%@] %@", kGDTConsoleLogger, GDTMessageCodeEnumToString(code), format];
|
||||
NSString *logFormat = [NSString stringWithFormat:@"%@[%@] %@", kGDTCORConsoleLogger,
|
||||
GDTCORMessageCodeEnumToString(code), format];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
NSLogv(logFormat, args);
|
||||
+8
-8
@@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <GoogleDataTransport/GDTDataFuture.h>
|
||||
#import <GoogleDataTransport/GDTCORDataFuture.h>
|
||||
|
||||
@implementation GDTDataFuture
|
||||
@implementation GDTCORDataFuture
|
||||
|
||||
- (instancetype)initWithFileURL:(NSURL *)fileURL {
|
||||
self = [super init];
|
||||
@@ -38,25 +38,25 @@
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
/** Coding key for _fileURL ivar. */
|
||||
static NSString *kGDTDataFutureFileURLKey = @"GDTDataFutureFileURLKey";
|
||||
static NSString *kGDTCORDataFutureFileURLKey = @"GDTCORDataFutureFileURLKey";
|
||||
|
||||
/** Coding key for _data ivar. */
|
||||
static NSString *kGDTDataFutureDataKey = @"GDTDataFutureDataKey";
|
||||
static NSString *kGDTCORDataFutureDataKey = @"GDTCORDataFutureDataKey";
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
|
||||
[aCoder encodeObject:_fileURL forKey:kGDTDataFutureFileURLKey];
|
||||
[aCoder encodeObject:_originalData forKey:kGDTDataFutureDataKey];
|
||||
[aCoder encodeObject:_fileURL forKey:kGDTCORDataFutureFileURLKey];
|
||||
[aCoder encodeObject:_originalData forKey:kGDTCORDataFutureDataKey];
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
|
||||
self = [self init];
|
||||
if (self) {
|
||||
_fileURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kGDTDataFutureFileURLKey];
|
||||
_originalData = [aDecoder decodeObjectOfClass:[NSData class] forKey:kGDTDataFutureDataKey];
|
||||
_fileURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kGDTCORDataFutureFileURLKey];
|
||||
_originalData = [aDecoder decodeObjectOfClass:[NSData class] forKey:kGDTCORDataFutureDataKey];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
+16
-13
@@ -14,29 +14,32 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <GoogleDataTransport/GDTEvent.h>
|
||||
#import <GoogleDataTransport/GDTCOREvent.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTStoredEvent.h>
|
||||
#import <GoogleDataTransport/GDTCORAssert.h>
|
||||
#import <GoogleDataTransport/GDTCORStoredEvent.h>
|
||||
|
||||
#import "GDTLibrary/Private/GDTAssert.h"
|
||||
#import "GDTLibrary/Private/GDTEvent_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCOREvent_Private.h"
|
||||
|
||||
@implementation GDTEvent
|
||||
@implementation GDTCOREvent
|
||||
|
||||
- (instancetype)initWithMappingID:(NSString *)mappingID target:(NSInteger)target {
|
||||
GDTAssert(mappingID.length > 0, @"Please give a valid mapping ID");
|
||||
GDTAssert(target > 0, @"A target cannot be negative or 0");
|
||||
GDTCORAssert(mappingID.length > 0, @"Please give a valid mapping ID");
|
||||
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;
|
||||
_target = target;
|
||||
_qosTier = GDTEventQosDefault;
|
||||
_qosTier = GDTCOREventQosDefault;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)copy {
|
||||
GDTEvent *copy = [[GDTEvent alloc] initWithMappingID:_mappingID target:_target];
|
||||
GDTCOREvent *copy = [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target];
|
||||
copy.dataObject = _dataObject;
|
||||
copy.dataObjectTransportBytes = _dataObjectTransportBytes;
|
||||
copy.qosTier = _qosTier;
|
||||
@@ -57,7 +60,7 @@
|
||||
return [self hash] == [object hash];
|
||||
}
|
||||
|
||||
- (void)setDataObject:(id<GDTEventDataObject>)dataObject {
|
||||
- (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.
|
||||
@@ -67,8 +70,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (GDTStoredEvent *)storedEventWithDataFuture:(GDTDataFuture *)dataFuture {
|
||||
return [[GDTStoredEvent alloc] initWithEvent:self dataFuture:dataFuture];
|
||||
- (GDTCORStoredEvent *)storedEventWithDataFuture:(GDTCORDataFuture *)dataFuture {
|
||||
return [[GDTCORStoredEvent alloc] initWithEvent:self dataFuture:dataFuture];
|
||||
}
|
||||
|
||||
#pragma mark - NSSecureCoding and NSCoding Protocols
|
||||
@@ -100,7 +103,7 @@ static NSString *clockSnapshotKey = @"_clockSnapshot";
|
||||
_dataObjectTransportBytes = [aDecoder decodeObjectOfClass:[NSData class]
|
||||
forKey:dataObjectTransportBytesKey];
|
||||
_qosTier = [aDecoder decodeIntegerForKey:qosTierKey];
|
||||
_clockSnapshot = [aDecoder decodeObjectOfClass:[GDTClock class] forKey:clockSnapshotKey];
|
||||
_clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:clockSnapshotKey];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
+119
@@ -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 "GDTCORLibrary/Public/GDTCORLifecycle.h"
|
||||
|
||||
#import <GoogleDataTransport/GDTCOREvent.h>
|
||||
|
||||
#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORStorage_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORTransformer_Private.h"
|
||||
#import "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:)]) {
|
||||
[[GDTCORTransformer sharedInstance] appWillBackground:application];
|
||||
}
|
||||
if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[[GDTCORStorage sharedInstance] appWillBackground:application];
|
||||
}
|
||||
if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[[GDTCORUploadCoordinator sharedInstance] appWillBackground:application];
|
||||
}
|
||||
if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[[GDTCORRegistrar sharedInstance] appWillBackground:application];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(NSNotification *)notification {
|
||||
GDTCORApplication *application = [GDTCORApplication sharedApplication];
|
||||
if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[[GDTCORTransformer sharedInstance] appWillForeground:application];
|
||||
}
|
||||
if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[[GDTCORStorage sharedInstance] appWillForeground:application];
|
||||
}
|
||||
if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[[GDTCORUploadCoordinator sharedInstance] appWillForeground:application];
|
||||
}
|
||||
if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[[GDTCORRegistrar sharedInstance] appWillForeground:application];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)notification {
|
||||
GDTCORApplication *application = [GDTCORApplication sharedApplication];
|
||||
if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[[GDTCORTransformer sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[[GDTCORStorage sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[[GDTCORUploadCoordinator sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[[GDTCORRegistrar sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
+41
-22
@@ -14,20 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <GoogleDataTransport/GDTPlatform.h>
|
||||
#import <GoogleDataTransport/GDTCORPlatform.h>
|
||||
|
||||
const GDTBackgroundIdentifier GDTBackgroundIdentifierInvalid = 0;
|
||||
#import <GoogleDataTransport/GDTCORAssert.h>
|
||||
|
||||
NSString *const kGDTApplicationDidEnterBackgroundNotification =
|
||||
@"GDTApplicationDidEnterBackgroundNotification";
|
||||
const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid = 0;
|
||||
|
||||
NSString *const kGDTApplicationWillEnterForegroundNotification =
|
||||
@"GDTApplicationWillEnterForegroundNotification";
|
||||
NSString *const kGDTCORApplicationDidEnterBackgroundNotification =
|
||||
@"GDTCORApplicationDidEnterBackgroundNotification";
|
||||
|
||||
NSString *const kGDTApplicationWillTerminateNotification =
|
||||
@"GDTApplicationWillTerminateNotification";
|
||||
NSString *const kGDTCORApplicationWillEnterForegroundNotification =
|
||||
@"GDTCORApplicationWillEnterForegroundNotification";
|
||||
|
||||
BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
|
||||
NSString *const kGDTCORApplicationWillTerminateNotification =
|
||||
@"GDTCORApplicationWillTerminateNotification";
|
||||
|
||||
BOOL GDTCORReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
|
||||
#if TARGET_OS_IOS
|
||||
return (flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN;
|
||||
#else
|
||||
@@ -35,22 +37,23 @@ BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
|
||||
#endif // TARGET_OS_IOS
|
||||
}
|
||||
|
||||
@implementation GDTApplication
|
||||
@implementation GDTCORApplication
|
||||
|
||||
+ (void)load {
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
// If this asserts, please file a bug at https://github.com/firebase/firebase-ios-sdk/issues.
|
||||
NSAssert(GDTBackgroundIdentifierInvalid == UIBackgroundTaskInvalid,
|
||||
@"GDTBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same.");
|
||||
GDTCORFatalAssert(
|
||||
GDTCORBackgroundIdentifierInvalid == UIBackgroundTaskInvalid,
|
||||
@"GDTCORBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same.");
|
||||
#endif
|
||||
[self sharedApplication];
|
||||
}
|
||||
|
||||
+ (nullable GDTApplication *)sharedApplication {
|
||||
static GDTApplication *application;
|
||||
+ (nullable GDTCORApplication *)sharedApplication {
|
||||
static GDTCORApplication *application;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
application = [[GDTApplication alloc] init];
|
||||
application = [[GDTCORApplication alloc] init];
|
||||
});
|
||||
return application;
|
||||
}
|
||||
@@ -74,6 +77,20 @@ BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
|
||||
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
|
||||
@@ -85,13 +102,15 @@ BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
|
||||
return self;
|
||||
}
|
||||
|
||||
- (GDTBackgroundIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler {
|
||||
- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler {
|
||||
return
|
||||
[[self sharedApplicationForBackgroundTask] beginBackgroundTaskWithExpirationHandler:handler];
|
||||
}
|
||||
|
||||
- (void)endBackgroundTask:(GDTBackgroundIdentifier)bgID {
|
||||
[[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID];
|
||||
- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID {
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - App environment helpers
|
||||
@@ -131,17 +150,17 @@ BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
- (void)iOSApplicationDidEnterBackground:(NSNotification *)notif {
|
||||
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
|
||||
[notifCenter postNotificationName:kGDTApplicationDidEnterBackgroundNotification object:nil];
|
||||
[notifCenter postNotificationName:kGDTCORApplicationDidEnterBackgroundNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)iOSApplicationWillEnterForeground:(NSNotification *)notif {
|
||||
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
|
||||
[notifCenter postNotificationName:kGDTApplicationWillEnterForegroundNotification object:nil];
|
||||
[notifCenter postNotificationName:kGDTCORApplicationWillEnterForegroundNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)iOSApplicationWillTerminate:(NSNotification *)notif {
|
||||
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
|
||||
[notifCenter postNotificationName:kGDTApplicationWillTerminateNotification object:nil];
|
||||
[notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil];
|
||||
}
|
||||
#endif // TARGET_OS_IOS || TARGET_OS_TV
|
||||
|
||||
@@ -150,7 +169,7 @@ BOOL GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) {
|
||||
#if TARGET_OS_OSX
|
||||
- (void)macOSApplicationWillTerminate:(NSNotification *)notif {
|
||||
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
|
||||
[notifCenter postNotificationName:kGDTApplicationWillTerminateNotification object:nil];
|
||||
[notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil];
|
||||
}
|
||||
#endif // TARGET_OS_OSX
|
||||
|
||||
+21
-19
@@ -14,10 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTLibrary/Private/GDTReachability.h"
|
||||
#import "GDTLibrary/Private/GDTReachability_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORReachability.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORReachability_Private.h"
|
||||
|
||||
#import <GoogleDataTransport/GDTConsoleLogger.h>
|
||||
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
|
||||
|
||||
#import <netinet/in.h>
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
* @param flags The new flag values.
|
||||
* @param info Any data that might be passed in by the callback.
|
||||
*/
|
||||
static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
|
||||
SCNetworkReachabilityFlags flags,
|
||||
void *info);
|
||||
static void GDTCORReachabilityCallback(SCNetworkReachabilityRef reachability,
|
||||
SCNetworkReachabilityFlags flags,
|
||||
void *info);
|
||||
|
||||
@implementation GDTReachability {
|
||||
@implementation GDTCORReachability {
|
||||
/** The reachability object. */
|
||||
SCNetworkReachabilityRef _reachabilityRef;
|
||||
|
||||
@@ -47,18 +47,18 @@ static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTReachability *sharedInstance;
|
||||
static GDTCORReachability *sharedInstance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[GDTReachability alloc] init];
|
||||
sharedInstance = [[GDTCORReachability alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
+ (SCNetworkReachabilityFlags)currentFlags {
|
||||
__block SCNetworkReachabilityFlags currentFlags;
|
||||
dispatch_sync([GDTReachability sharedInstance] -> _reachabilityQueue, ^{
|
||||
GDTReachability *reachability = [GDTReachability sharedInstance];
|
||||
dispatch_sync([GDTCORReachability sharedInstance] -> _reachabilityQueue, ^{
|
||||
GDTCORReachability *reachability = [GDTCORReachability sharedInstance];
|
||||
currentFlags = reachability->_flags ? reachability->_flags : reachability->_callbackFlags;
|
||||
});
|
||||
return currentFlags;
|
||||
@@ -72,16 +72,18 @@ static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
|
||||
zeroAddress.sin_len = sizeof(zeroAddress);
|
||||
zeroAddress.sin_family = AF_INET;
|
||||
|
||||
_reachabilityQueue = dispatch_queue_create("com.google.GDTReachability", DISPATCH_QUEUE_SERIAL);
|
||||
_reachabilityQueue =
|
||||
dispatch_queue_create("com.google.GDTCORReachability", DISPATCH_QUEUE_SERIAL);
|
||||
_reachabilityRef = SCNetworkReachabilityCreateWithAddress(
|
||||
kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress);
|
||||
Boolean success = SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _reachabilityQueue);
|
||||
if (!success) {
|
||||
GDTLogWarning(GDTMCWReachabilityFailed, @"%@", @"The reachability queue wasn't set.");
|
||||
GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", @"The reachability queue wasn't set.");
|
||||
}
|
||||
success = SCNetworkReachabilitySetCallback(_reachabilityRef, GDTReachabilityCallback, NULL);
|
||||
success = SCNetworkReachabilitySetCallback(_reachabilityRef, GDTCORReachabilityCallback, NULL);
|
||||
if (!success) {
|
||||
GDTLogWarning(GDTMCWReachabilityFailed, @"%@", @"The reachability callback wasn't set.");
|
||||
GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@",
|
||||
@"The reachability callback wasn't set.");
|
||||
}
|
||||
|
||||
// Get the initial set of flags.
|
||||
@@ -103,8 +105,8 @@ static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
|
||||
|
||||
@end
|
||||
|
||||
static void GDTReachabilityCallback(SCNetworkReachabilityRef reachability,
|
||||
SCNetworkReachabilityFlags flags,
|
||||
void *info) {
|
||||
[[GDTReachability sharedInstance] setCallbackFlags:flags];
|
||||
static void GDTCORReachabilityCallback(SCNetworkReachabilityRef reachability,
|
||||
SCNetworkReachabilityFlags flags,
|
||||
void *info) {
|
||||
[[GDTCORReachability sharedInstance] setCallbackFlags:flags];
|
||||
}
|
||||
+33
-32
@@ -14,23 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTLibrary/Public/GDTRegistrar.h"
|
||||
#import "GDTCORLibrary/Public/GDTCORRegistrar.h"
|
||||
|
||||
#import "GDTLibrary/Private/GDTRegistrar_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
|
||||
|
||||
@implementation GDTRegistrar {
|
||||
@implementation GDTCORRegistrar {
|
||||
/** Backing ivar for targetToUploader property. */
|
||||
NSMutableDictionary<NSNumber *, id<GDTUploader>> *_targetToUploader;
|
||||
NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *_targetToUploader;
|
||||
|
||||
/** Backing ivar for targetToPrioritizer property. */
|
||||
NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *_targetToPrioritizer;
|
||||
NSMutableDictionary<NSNumber *, id<GDTCORPrioritizer>> *_targetToPrioritizer;
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTRegistrar *sharedInstance;
|
||||
static GDTCORRegistrar *sharedInstance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[GDTRegistrar alloc] init];
|
||||
sharedInstance = [[GDTCORRegistrar alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
@@ -38,38 +38,39 @@
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_registrarQueue = dispatch_queue_create("com.google.GDTRegistrar", DISPATCH_QUEUE_CONCURRENT);
|
||||
_registrarQueue =
|
||||
dispatch_queue_create("com.google.GDTCORRegistrar", DISPATCH_QUEUE_CONCURRENT);
|
||||
_targetToPrioritizer = [[NSMutableDictionary alloc] init];
|
||||
_targetToUploader = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)registerUploader:(id<GDTUploader>)backend target:(GDTTarget)target {
|
||||
__weak GDTRegistrar *weakSelf = self;
|
||||
- (void)registerUploader:(id<GDTCORUploader>)backend target:(GDTCORTarget)target {
|
||||
__weak GDTCORRegistrar *weakSelf = self;
|
||||
dispatch_barrier_async(_registrarQueue, ^{
|
||||
GDTRegistrar *strongSelf = weakSelf;
|
||||
GDTCORRegistrar *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
strongSelf->_targetToUploader[@(target)] = backend;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)registerPrioritizer:(id<GDTPrioritizer>)prioritizer target:(GDTTarget)target {
|
||||
__weak GDTRegistrar *weakSelf = self;
|
||||
- (void)registerPrioritizer:(id<GDTCORPrioritizer>)prioritizer target:(GDTCORTarget)target {
|
||||
__weak GDTCORRegistrar *weakSelf = self;
|
||||
dispatch_barrier_async(_registrarQueue, ^{
|
||||
GDTRegistrar *strongSelf = weakSelf;
|
||||
GDTCORRegistrar *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
strongSelf->_targetToPrioritizer[@(target)] = prioritizer;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (NSMutableDictionary<NSNumber *, id<GDTUploader>> *)targetToUploader {
|
||||
__block NSMutableDictionary<NSNumber *, id<GDTUploader>> *targetToUploader;
|
||||
__weak GDTRegistrar *weakSelf = self;
|
||||
- (NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *)targetToUploader {
|
||||
__block NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *targetToUploader;
|
||||
__weak GDTCORRegistrar *weakSelf = self;
|
||||
dispatch_sync(_registrarQueue, ^{
|
||||
GDTRegistrar *strongSelf = weakSelf;
|
||||
GDTCORRegistrar *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
targetToUploader = strongSelf->_targetToUploader;
|
||||
}
|
||||
@@ -77,11 +78,11 @@
|
||||
return targetToUploader;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *)targetToPrioritizer {
|
||||
__block NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *targetToPrioritizer;
|
||||
__weak GDTRegistrar *weakSelf = self;
|
||||
- (NSMutableDictionary<NSNumber *, id<GDTCORPrioritizer>> *)targetToPrioritizer {
|
||||
__block NSMutableDictionary<NSNumber *, id<GDTCORPrioritizer>> *targetToPrioritizer;
|
||||
__weak GDTCORRegistrar *weakSelf = self;
|
||||
dispatch_sync(_registrarQueue, ^{
|
||||
GDTRegistrar *strongSelf = weakSelf;
|
||||
GDTCORRegistrar *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
targetToPrioritizer = strongSelf->_targetToPrioritizer;
|
||||
}
|
||||
@@ -89,16 +90,16 @@
|
||||
return targetToPrioritizer;
|
||||
}
|
||||
|
||||
#pragma mark - GDTLifecycleProtocol
|
||||
#pragma mark - GDTCORLifecycleProtocol
|
||||
|
||||
- (void)appWillBackground:(nonnull GDTApplication *)app {
|
||||
- (void)appWillBackground:(nonnull GDTCORApplication *)app {
|
||||
dispatch_async(_registrarQueue, ^{
|
||||
for (id<GDTUploader> uploader in [self->_targetToUploader allValues]) {
|
||||
for (id<GDTCORUploader> uploader in [self->_targetToUploader allValues]) {
|
||||
if ([uploader respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[uploader appWillBackground:app];
|
||||
}
|
||||
}
|
||||
for (id<GDTPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
|
||||
for (id<GDTCORPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
|
||||
if ([prioritizer respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[prioritizer appWillBackground:app];
|
||||
}
|
||||
@@ -106,14 +107,14 @@
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillForeground:(nonnull GDTApplication *)app {
|
||||
- (void)appWillForeground:(nonnull GDTCORApplication *)app {
|
||||
dispatch_async(_registrarQueue, ^{
|
||||
for (id<GDTUploader> uploader in [self->_targetToUploader allValues]) {
|
||||
for (id<GDTCORUploader> uploader in [self->_targetToUploader allValues]) {
|
||||
if ([uploader respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[uploader appWillForeground:app];
|
||||
}
|
||||
}
|
||||
for (id<GDTPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
|
||||
for (id<GDTCORPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
|
||||
if ([prioritizer respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[prioritizer appWillForeground:app];
|
||||
}
|
||||
@@ -121,14 +122,14 @@
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillTerminate:(nonnull GDTApplication *)app {
|
||||
- (void)appWillTerminate:(nonnull GDTCORApplication *)app {
|
||||
dispatch_sync(_registrarQueue, ^{
|
||||
for (id<GDTUploader> uploader in [self->_targetToUploader allValues]) {
|
||||
for (id<GDTCORUploader> uploader in [self->_targetToUploader allValues]) {
|
||||
if ([uploader respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[uploader appWillTerminate:app];
|
||||
}
|
||||
}
|
||||
for (id<GDTPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
|
||||
for (id<GDTCORPrioritizer> prioritizer in [self->_targetToPrioritizer allValues]) {
|
||||
if ([prioritizer respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[prioritizer appWillTerminate:app];
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* 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 "GDTCORLibrary/Private/GDTCORStorage.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORStorage_Private.h"
|
||||
|
||||
#import <GoogleDataTransport/GDTCORAssert.h>
|
||||
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
|
||||
#import <GoogleDataTransport/GDTCORLifecycle.h>
|
||||
#import <GoogleDataTransport/GDTCORPrioritizer.h>
|
||||
#import <GoogleDataTransport/GDTCORStoredEvent.h>
|
||||
|
||||
#import "GDTCORLibrary/Private/GDTCOREvent_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
|
||||
|
||||
/** Creates and/or returns a singleton NSString that is the shared storage path.
|
||||
*
|
||||
* @return The SDK event storage path.
|
||||
*/
|
||||
static NSString *GDTCORStoragePath() {
|
||||
static NSString *storagePath;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *cachePath =
|
||||
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
|
||||
storagePath = [NSString stringWithFormat:@"%@/google-sdks-events", cachePath];
|
||||
});
|
||||
return storagePath;
|
||||
}
|
||||
|
||||
@implementation GDTCORStorage
|
||||
|
||||
+ (NSString *)archivePath {
|
||||
static NSString *archivePath;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
archivePath = [GDTCORStoragePath() stringByAppendingPathComponent:@"GDTCORStorageArchive"];
|
||||
});
|
||||
return archivePath;
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTCORStorage *sharedStorage;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedStorage = [[GDTCORStorage alloc] init];
|
||||
});
|
||||
return sharedStorage;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_storageQueue = dispatch_queue_create("com.google.GDTCORStorage", DISPATCH_QUEUE_SERIAL);
|
||||
_targetToEventSet = [[NSMutableDictionary alloc] init];
|
||||
_storedEvents = [[NSMutableOrderedSet alloc] init];
|
||||
_uploadCoordinator = [GDTCORUploadCoordinator sharedInstance];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)storeEvent:(GDTCOREvent *)event {
|
||||
if (event == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self createEventDirectoryIfNotExists];
|
||||
|
||||
__block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
if (_runningInBackground) {
|
||||
bgID = [[GDTCORApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[[GDTCORApplication sharedApplication] endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
dispatch_async(_storageQueue, ^{
|
||||
// Check that a backend implementation is available for this target.
|
||||
NSInteger target = event.target;
|
||||
|
||||
// Check that a prioritizer is available for this target.
|
||||
id<GDTCORPrioritizer> prioritizer =
|
||||
[GDTCORRegistrar sharedInstance].targetToPrioritizer[@(target)];
|
||||
GDTCORAssert(prioritizer, @"There's no prioritizer registered for the given target.");
|
||||
|
||||
// Write the transport bytes to disk, get a filename.
|
||||
GDTCORAssert(event.dataObjectTransportBytes, @"The event should have been serialized to bytes");
|
||||
NSURL *eventFile = [self saveEventBytesToDisk:event.dataObjectTransportBytes
|
||||
eventHash:event.hash];
|
||||
GDTCORDataFuture *dataFuture = [[GDTCORDataFuture alloc] initWithFileURL:eventFile];
|
||||
GDTCORStoredEvent *storedEvent = [event storedEventWithDataFuture:dataFuture];
|
||||
|
||||
// Add event to tracking collections.
|
||||
[self addEventToTrackingCollections:storedEvent];
|
||||
|
||||
// Have the prioritizer prioritize the event.
|
||||
[prioritizer prioritizeEvent:storedEvent];
|
||||
|
||||
// Check the QoS, if it's high priority, notify the target that it has a high priority event.
|
||||
if (event.qosTier == GDTCOREventQoSFast) {
|
||||
[self.uploadCoordinator forceUploadForTarget:target];
|
||||
}
|
||||
|
||||
// Write state to disk.
|
||||
if (self->_runningInBackground) {
|
||||
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
|
||||
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self
|
||||
requiringSecureCoding:YES
|
||||
error:nil];
|
||||
[data writeToFile:[GDTCORStorage archivePath] atomically:YES];
|
||||
} else {
|
||||
#if !defined(TARGET_OS_MACCATALYST)
|
||||
[NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// If running in the background, save state to disk and end the associated background task.
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[[GDTCORApplication sharedApplication] endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)removeEvents:(NSSet<GDTCORStoredEvent *> *)events {
|
||||
NSSet<GDTCORStoredEvent *> *eventsToRemove = [events copy];
|
||||
dispatch_async(_storageQueue, ^{
|
||||
for (GDTCORStoredEvent *event in eventsToRemove) {
|
||||
// Remove from disk, first and foremost.
|
||||
NSError *error;
|
||||
if (event.dataFuture.fileURL) {
|
||||
NSURL *fileURL = event.dataFuture.fileURL;
|
||||
[[NSFileManager defaultManager] removeItemAtURL:fileURL error:&error];
|
||||
GDTCORAssert(error == nil, @"There was an error removing an event file: %@", error);
|
||||
}
|
||||
|
||||
// Remove from the tracking collections.
|
||||
[self.storedEvents removeObject:event];
|
||||
[self.targetToEventSet[event.target] removeObject:event];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Private helper methods
|
||||
|
||||
/** Creates the storage directory if it does not exist. */
|
||||
- (void)createEventDirectoryIfNotExists {
|
||||
NSError *error;
|
||||
BOOL result = [[NSFileManager defaultManager] createDirectoryAtPath:GDTCORStoragePath()
|
||||
withIntermediateDirectories:YES
|
||||
attributes:0
|
||||
error:&error];
|
||||
if (!result || error) {
|
||||
GDTCORLogError(GDTCORMCEDirectoryCreationError, @"Error creating the directory: %@", error);
|
||||
}
|
||||
}
|
||||
|
||||
/** Saves the event's dataObjectTransportBytes to a file using NSData mechanisms.
|
||||
*
|
||||
* @note This method should only be called from a method within a block on _storageQueue to maintain
|
||||
* thread safety.
|
||||
*
|
||||
* @param transportBytes The transport bytes of the event.
|
||||
* @param eventHash The hash value of the event.
|
||||
* @return The filename
|
||||
*/
|
||||
- (NSURL *)saveEventBytesToDisk:(NSData *)transportBytes eventHash:(NSUInteger)eventHash {
|
||||
NSString *storagePath = GDTCORStoragePath();
|
||||
NSString *event = [NSString stringWithFormat:@"event-%lu", (unsigned long)eventHash];
|
||||
NSURL *eventFilePath = [NSURL fileURLWithPath:[storagePath stringByAppendingPathComponent:event]];
|
||||
|
||||
GDTCORAssert(![[NSFileManager defaultManager] fileExistsAtPath:eventFilePath.path],
|
||||
@"An event shouldn't already exist at this path: %@", eventFilePath.path);
|
||||
|
||||
BOOL writingSuccess = [transportBytes writeToURL:eventFilePath atomically:YES];
|
||||
if (!writingSuccess) {
|
||||
GDTCORLogError(GDTCORMCEFileWriteError, @"An event file could not be written: %@",
|
||||
eventFilePath);
|
||||
}
|
||||
|
||||
return eventFilePath;
|
||||
}
|
||||
|
||||
/** Adds the event to internal tracking collections.
|
||||
*
|
||||
* @note This method should only be called from a method within a block on _storageQueue to maintain
|
||||
* thread safety.
|
||||
*
|
||||
* @param event The event to track.
|
||||
*/
|
||||
- (void)addEventToTrackingCollections:(GDTCORStoredEvent *)event {
|
||||
[_storedEvents addObject:event];
|
||||
NSMutableSet<GDTCORStoredEvent *> *events = self.targetToEventSet[event.target];
|
||||
events = events ? events : [[NSMutableSet alloc] init];
|
||||
[events addObject:event];
|
||||
_targetToEventSet[event.target] = events;
|
||||
}
|
||||
|
||||
#pragma mark - GDTCORLifecycleProtocol
|
||||
|
||||
- (void)appWillForeground:(GDTCORApplication *)app {
|
||||
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
|
||||
NSData *data = [NSData dataWithContentsOfFile:[GDTCORStorage archivePath]];
|
||||
[NSKeyedUnarchiver unarchivedObjectOfClass:[GDTCORStorage class] fromData:data error:nil];
|
||||
} else {
|
||||
#if !defined(TARGET_OS_MACCATALYST)
|
||||
[NSKeyedUnarchiver unarchiveObjectWithFile:[GDTCORStorage archivePath]];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
- (void)appWillBackground:(GDTCORApplication *)app {
|
||||
self->_runningInBackground = YES;
|
||||
dispatch_async(_storageQueue, ^{
|
||||
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
|
||||
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self
|
||||
requiringSecureCoding:YES
|
||||
error:nil];
|
||||
[data writeToFile:[GDTCORStorage archivePath] atomically:YES];
|
||||
} else {
|
||||
#if !defined(TARGET_OS_MACCATALYST)
|
||||
[NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]];
|
||||
#endif
|
||||
}
|
||||
});
|
||||
|
||||
// Create an immediate background task to run until the end of the current queue of work.
|
||||
__block GDTCORBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[app endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
}];
|
||||
dispatch_async(_storageQueue, ^{
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[app endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillTerminate:(GDTCORApplication *)application {
|
||||
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
|
||||
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self
|
||||
requiringSecureCoding:YES
|
||||
error:nil];
|
||||
[data writeToFile:[GDTCORStorage archivePath] atomically:YES];
|
||||
} else {
|
||||
#if !defined(TARGET_OS_MACCATALYST)
|
||||
[NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
/** The NSKeyedCoder key for the storedEvents property. */
|
||||
static NSString *const kGDTCORStorageStoredEventsKey = @"GDTCORStorageStoredEventsKey";
|
||||
|
||||
/** The NSKeyedCoder key for the targetToEventSet property. */
|
||||
static NSString *const kGDTCORStorageTargetToEventSetKey = @"GDTCORStorageTargetToEventSetKey";
|
||||
|
||||
/** The NSKeyedCoder key for the uploadCoordinator property. */
|
||||
static NSString *const kGDTCORStorageUploadCoordinatorKey = @"GDTCORStorageUploadCoordinatorKey";
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
// Create the singleton and populate its ivars.
|
||||
GDTCORStorage *sharedInstance = [self.class sharedInstance];
|
||||
dispatch_sync(sharedInstance.storageQueue, ^{
|
||||
NSSet *classes =
|
||||
[NSSet setWithObjects:[NSMutableOrderedSet class], [GDTCORStoredEvent class], nil];
|
||||
sharedInstance->_storedEvents = [aDecoder decodeObjectOfClasses:classes
|
||||
forKey:kGDTCORStorageStoredEventsKey];
|
||||
classes = [NSSet setWithObjects:[NSMutableDictionary class], [NSMutableSet class],
|
||||
[GDTCORStoredEvent class], nil];
|
||||
sharedInstance->_targetToEventSet =
|
||||
[aDecoder decodeObjectOfClasses:classes forKey:kGDTCORStorageTargetToEventSetKey];
|
||||
sharedInstance->_uploadCoordinator =
|
||||
[aDecoder decodeObjectOfClass:[GDTCORUploadCoordinator class]
|
||||
forKey:kGDTCORStorageUploadCoordinatorKey];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||
GDTCORStorage *sharedInstance = [self.class sharedInstance];
|
||||
NSMutableOrderedSet<GDTCORStoredEvent *> *storedEvents = sharedInstance->_storedEvents;
|
||||
if (storedEvents) {
|
||||
[aCoder encodeObject:storedEvents forKey:kGDTCORStorageStoredEventsKey];
|
||||
}
|
||||
NSMutableDictionary<NSNumber *, NSMutableSet<GDTCORStoredEvent *> *> *targetToEventSet =
|
||||
sharedInstance->_targetToEventSet;
|
||||
if (targetToEventSet) {
|
||||
[aCoder encodeObject:targetToEventSet forKey:kGDTCORStorageTargetToEventSetKey];
|
||||
}
|
||||
GDTCORUploadCoordinator *uploadCoordinator = sharedInstance->_uploadCoordinator;
|
||||
if (uploadCoordinator) {
|
||||
[aCoder encodeObject:uploadCoordinator forKey:kGDTCORStorageUploadCoordinatorKey];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
+15
-14
@@ -14,15 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <GoogleDataTransport/GDTStoredEvent.h>
|
||||
#import <GoogleDataTransport/GDTCORStoredEvent.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTClock.h>
|
||||
#import <GoogleDataTransport/GDTCORClock.h>
|
||||
|
||||
#import "GDTLibrary/Private/GDTStorage_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORStorage_Private.h"
|
||||
|
||||
@implementation GDTStoredEvent
|
||||
@implementation GDTCORStoredEvent
|
||||
|
||||
- (instancetype)initWithEvent:(GDTEvent *)event dataFuture:(nonnull GDTDataFuture *)dataFuture {
|
||||
- (instancetype)initWithEvent:(GDTCOREvent *)event
|
||||
dataFuture:(nonnull GDTCORDataFuture *)dataFuture {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_dataFuture = dataFuture;
|
||||
@@ -38,22 +39,22 @@
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
/** Coding key for the dataFuture ivar. */
|
||||
static NSString *kDataFutureKey = @"GDTStoredEventDataFutureKey";
|
||||
static NSString *kDataFutureKey = @"GDTCORStoredEventDataFutureKey";
|
||||
|
||||
/** Coding key for mappingID ivar. */
|
||||
static NSString *kMappingIDKey = @"GDTStoredEventMappingIDKey";
|
||||
static NSString *kMappingIDKey = @"GDTCORStoredEventMappingIDKey";
|
||||
|
||||
/** Coding key for target ivar. */
|
||||
static NSString *kTargetKey = @"GDTStoredEventTargetKey";
|
||||
static NSString *kTargetKey = @"GDTCORStoredEventTargetKey";
|
||||
|
||||
/** Coding key for qosTier ivar. */
|
||||
static NSString *kQosTierKey = @"GDTStoredEventQosTierKey";
|
||||
static NSString *kQosTierKey = @"GDTCORStoredEventQosTierKey";
|
||||
|
||||
/** Coding key for clockSnapshot ivar. */
|
||||
static NSString *kClockSnapshotKey = @"GDTStoredEventClockSnapshotKey";
|
||||
static NSString *kClockSnapshotKey = @"GDTCORStoredEventClockSnapshotKey";
|
||||
|
||||
/** Coding key for customPrioritizationParams ivar. */
|
||||
static NSString *kCustomPrioritizationParamsKey = @"GDTStoredEventcustomPrioritizationParamsKey";
|
||||
static NSString *kCustomPrioritizationParamsKey = @"GDTCORStoredEventcustomPrioritizationParamsKey";
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
@@ -71,19 +72,19 @@ static NSString *kCustomPrioritizationParamsKey = @"GDTStoredEventcustomPrioriti
|
||||
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
|
||||
self = [self init];
|
||||
if (self) {
|
||||
_dataFuture = [aDecoder decodeObjectOfClass:[GDTDataFuture class] forKey:kDataFutureKey];
|
||||
_dataFuture = [aDecoder decodeObjectOfClass:[GDTCORDataFuture class] forKey:kDataFutureKey];
|
||||
_mappingID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kMappingIDKey];
|
||||
_target = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:kTargetKey];
|
||||
NSNumber *qosTier = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:kQosTierKey];
|
||||
_qosTier = [qosTier intValue];
|
||||
_clockSnapshot = [aDecoder decodeObjectOfClass:[GDTClock class] forKey:kClockSnapshotKey];
|
||||
_clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kClockSnapshotKey];
|
||||
_customPrioritizationParams = [aDecoder decodeObjectOfClass:[NSDictionary class]
|
||||
forKey:kCustomPrioritizationParamsKey];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(GDTStoredEvent *)other {
|
||||
- (BOOL)isEqual:(GDTCORStoredEvent *)other {
|
||||
return [self hash] == [other hash];
|
||||
}
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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 "GDTCORLibrary/Private/GDTCORTransformer.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORTransformer_Private.h"
|
||||
|
||||
#import <GoogleDataTransport/GDTCORAssert.h>
|
||||
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
|
||||
#import <GoogleDataTransport/GDTCOREventTransformer.h>
|
||||
#import <GoogleDataTransport/GDTCORLifecycle.h>
|
||||
|
||||
#import "GDTCORLibrary/Private/GDTCORStorage.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);
|
||||
_storageInstance = [GDTCORStorage sharedInstance];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)transformEvent:(GDTCOREvent *)event
|
||||
withTransformers:(NSArray<id<GDTCOREventTransformer>> *)transformers {
|
||||
GDTCORAssert(event, @"You can't write a nil event");
|
||||
|
||||
__block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
if (_runningInBackground) {
|
||||
bgID = [[GDTCORApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[[GDTCORApplication sharedApplication] endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
}];
|
||||
}
|
||||
dispatch_async(_eventWritingQueue, ^{
|
||||
GDTCOREvent *transformedEvent = event;
|
||||
for (id<GDTCOREventTransformer> transformer in transformers) {
|
||||
if ([transformer respondsToSelector:@selector(transform:)]) {
|
||||
transformedEvent = [transformer transform:transformedEvent];
|
||||
if (!transformedEvent) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
GDTCORLogError(GDTCORMCETransformerDoesntImplementTransform,
|
||||
@"Transformer doesn't implement transform: %@", transformer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
[self.storageInstance storeEvent:transformedEvent];
|
||||
if (self->_runningInBackground) {
|
||||
[[GDTCORApplication sharedApplication] endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - GDTCORLifecycleProtocol
|
||||
|
||||
- (void)appWillForeground:(GDTCORApplication *)app {
|
||||
dispatch_async(_eventWritingQueue, ^{
|
||||
self->_runningInBackground = NO;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillBackground:(GDTCORApplication *)app {
|
||||
// Create an immediate background task to run until the end of the current queue of work.
|
||||
__block GDTCORBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[app endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
}];
|
||||
dispatch_async(_eventWritingQueue, ^{
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[app endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillTerminate:(GDTCORApplication *)application {
|
||||
// Flush the queue immediately.
|
||||
dispatch_sync(_eventWritingQueue, ^{
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
+68
@@ -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 <GoogleDataTransport/GDTCORTransport.h>
|
||||
#import "GDTCORLibrary/Private/GDTCORTransport_Private.h"
|
||||
|
||||
#import <GoogleDataTransport/GDTCORAssert.h>
|
||||
#import <GoogleDataTransport/GDTCORClock.h>
|
||||
#import <GoogleDataTransport/GDTCOREvent.h>
|
||||
|
||||
#import "GDTCORLibrary/Private/GDTCORTransformer.h"
|
||||
|
||||
@implementation GDTCORTransport
|
||||
|
||||
- (instancetype)initWithMappingID:(NSString *)mappingID
|
||||
transformers:(nullable NSArray<id<GDTCOREventTransformer>> *)transformers
|
||||
target:(NSInteger)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];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)sendTelemetryEvent:(GDTCOREvent *)event {
|
||||
// TODO: Determine if sending an event before registration is allowed.
|
||||
GDTCORAssert(event, @"You can't send a nil event");
|
||||
GDTCOREvent *copiedEvent = [event copy];
|
||||
copiedEvent.qosTier = GDTCOREventQoSTelemetry;
|
||||
copiedEvent.clockSnapshot = [GDTCORClock snapshot];
|
||||
[self.transformerInstance transformEvent:copiedEvent withTransformers:_transformers];
|
||||
}
|
||||
|
||||
- (void)sendDataEvent:(GDTCOREvent *)event {
|
||||
// TODO: Determine if sending an event before registration is allowed.
|
||||
GDTCORAssert(event, @"You can't send a nil event");
|
||||
GDTCORAssert(event.qosTier != GDTCOREventQoSTelemetry, @"Use -sendTelemetryEvent, please.");
|
||||
GDTCOREvent *copiedEvent = [event copy];
|
||||
copiedEvent.clockSnapshot = [GDTCORClock snapshot];
|
||||
[self.transformerInstance transformEvent:copiedEvent withTransformers:_transformers];
|
||||
}
|
||||
|
||||
- (GDTCOREvent *)eventForTransport {
|
||||
return [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target];
|
||||
}
|
||||
|
||||
@end
|
||||
+93
-60
@@ -14,23 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTLibrary/Private/GDTUploadCoordinator.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
|
||||
|
||||
#import <GoogleDataTransport/GDTClock.h>
|
||||
#import <GoogleDataTransport/GDTConsoleLogger.h>
|
||||
#import <GoogleDataTransport/GDTCORAssert.h>
|
||||
#import <GoogleDataTransport/GDTCORClock.h>
|
||||
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
|
||||
|
||||
#import "GDTLibrary/Private/GDTAssert.h"
|
||||
#import "GDTLibrary/Private/GDTReachability.h"
|
||||
#import "GDTLibrary/Private/GDTRegistrar_Private.h"
|
||||
#import "GDTLibrary/Private/GDTStorage.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORReachability.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORStorage.h"
|
||||
|
||||
@implementation GDTUploadCoordinator
|
||||
@implementation GDTCORUploadCoordinator
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTUploadCoordinator *sharedUploader;
|
||||
static GDTCORUploadCoordinator *sharedUploader;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedUploader = [[GDTUploadCoordinator alloc] init];
|
||||
sharedUploader = [[GDTCORUploadCoordinator alloc] init];
|
||||
[sharedUploader startTimer];
|
||||
});
|
||||
return sharedUploader;
|
||||
@@ -40,8 +40,8 @@
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_coordinationQueue =
|
||||
dispatch_queue_create("com.google.GDTUploadCoordinator", DISPATCH_QUEUE_SERIAL);
|
||||
_registrar = [GDTRegistrar sharedInstance];
|
||||
dispatch_queue_create("com.google.GDTCORUploadCoordinator", DISPATCH_QUEUE_SERIAL);
|
||||
_registrar = [GDTCORRegistrar sharedInstance];
|
||||
_timerInterval = 30 * NSEC_PER_SEC;
|
||||
_timerLeeway = 5 * NSEC_PER_SEC;
|
||||
_targetToInFlightPackages = [[NSMutableDictionary alloc] init];
|
||||
@@ -49,21 +49,21 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)forceUploadForTarget:(GDTTarget)target {
|
||||
- (void)forceUploadForTarget:(GDTCORTarget)target {
|
||||
dispatch_async(_coordinationQueue, ^{
|
||||
GDTUploadConditions conditions = [self uploadConditions];
|
||||
conditions |= GDTUploadConditionHighPriority;
|
||||
GDTCORUploadConditions conditions = [self uploadConditions];
|
||||
conditions |= GDTCORUploadConditionHighPriority;
|
||||
[self uploadTargets:@[ @(target) ] conditions:conditions];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Property overrides
|
||||
|
||||
// GDTStorage and GDTUploadCoordinator +sharedInstance methods call each other, so this breaks
|
||||
// GDTCORStorage and GDTCORUploadCoordinator +sharedInstance methods call each other, so this breaks
|
||||
// the loop.
|
||||
- (GDTStorage *)storage {
|
||||
- (GDTCORStorage *)storage {
|
||||
if (!_storage) {
|
||||
_storage = [GDTStorage sharedInstance];
|
||||
_storage = [GDTCORStorage sharedInstance];
|
||||
}
|
||||
return _storage;
|
||||
}
|
||||
@@ -81,7 +81,7 @@
|
||||
self->_timerLeeway);
|
||||
dispatch_source_set_event_handler(self->_timer, ^{
|
||||
if (!self->_runningInBackground) {
|
||||
GDTUploadConditions conditions = [self uploadConditions];
|
||||
GDTCORUploadConditions conditions = [self uploadConditions];
|
||||
[self uploadTargets:[self.registrar.targetToUploader allKeys] conditions:conditions];
|
||||
}
|
||||
});
|
||||
@@ -101,9 +101,9 @@
|
||||
* @param targets An array of targets to trigger.
|
||||
* @param conditions The set of upload conditions.
|
||||
*/
|
||||
- (void)uploadTargets:(NSArray<NSNumber *> *)targets conditions:(GDTUploadConditions)conditions {
|
||||
- (void)uploadTargets:(NSArray<NSNumber *> *)targets conditions:(GDTCORUploadConditions)conditions {
|
||||
dispatch_async(_coordinationQueue, ^{
|
||||
if ((conditions & GDTUploadConditionNoNetwork) == GDTUploadConditionNoNetwork) {
|
||||
if ((conditions & GDTCORUploadConditionNoNetwork) == GDTCORUploadConditionNoNetwork) {
|
||||
return;
|
||||
}
|
||||
for (NSNumber *target in targets) {
|
||||
@@ -112,10 +112,10 @@
|
||||
continue;
|
||||
}
|
||||
// Ask the uploader if they can upload and do so, if it can.
|
||||
id<GDTUploader> uploader = self.registrar.targetToUploader[target];
|
||||
id<GDTCORUploader> uploader = self.registrar.targetToUploader[target];
|
||||
if ([uploader readyToUploadWithConditions:conditions]) {
|
||||
id<GDTPrioritizer> prioritizer = self.registrar.targetToPrioritizer[target];
|
||||
GDTUploadPackage *package = [prioritizer uploadPackageWithConditions:conditions];
|
||||
id<GDTCORPrioritizer> prioritizer = self.registrar.targetToPrioritizer[target];
|
||||
GDTCORUploadPackage *package = [prioritizer uploadPackageWithConditions:conditions];
|
||||
if (package.events.count) {
|
||||
self->_targetToInFlightPackages[target] = package;
|
||||
[uploader uploadPackage:package];
|
||||
@@ -131,8 +131,8 @@
|
||||
*
|
||||
* @return The current upload conditions.
|
||||
*/
|
||||
- (GDTUploadConditions)uploadConditions {
|
||||
SCNetworkReachabilityFlags currentFlags = [GDTReachability currentFlags];
|
||||
- (GDTCORUploadConditions)uploadConditions {
|
||||
SCNetworkReachabilityFlags currentFlags = [GDTCORReachability currentFlags];
|
||||
BOOL reachable =
|
||||
(currentFlags & kSCNetworkReachabilityFlagsReachable) == kSCNetworkReachabilityFlagsReachable;
|
||||
BOOL connectionRequired = (currentFlags & kSCNetworkReachabilityFlagsConnectionRequired) ==
|
||||
@@ -140,14 +140,14 @@
|
||||
BOOL networkConnected = reachable && !connectionRequired;
|
||||
|
||||
if (!networkConnected) {
|
||||
return GDTUploadConditionNoNetwork;
|
||||
return GDTCORUploadConditionNoNetwork;
|
||||
}
|
||||
|
||||
BOOL isWWAN = GDTReachabilityFlagsContainWWAN(currentFlags);
|
||||
BOOL isWWAN = GDTCORReachabilityFlagsContainWWAN(currentFlags);
|
||||
if (isWWAN) {
|
||||
return GDTUploadConditionMobileData;
|
||||
return GDTCORUploadConditionMobileData;
|
||||
} else {
|
||||
return GDTUploadConditionWifiData;
|
||||
return GDTCORUploadConditionWifiData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,35 +155,42 @@
|
||||
|
||||
/** The NSKeyedCoder key for the targetToInFlightPackages property. */
|
||||
static NSString *const ktargetToInFlightPackagesKey =
|
||||
@"GDTUploadCoordinatortargetToInFlightPackages";
|
||||
@"GDTCORUploadCoordinatortargetToInFlightPackages";
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
GDTUploadCoordinator *sharedCoordinator = [GDTUploadCoordinator sharedInstance];
|
||||
sharedCoordinator->_targetToInFlightPackages =
|
||||
[aDecoder decodeObjectOfClass:[NSMutableDictionary class]
|
||||
forKey:ktargetToInFlightPackagesKey];
|
||||
GDTCORUploadCoordinator *sharedCoordinator = [GDTCORUploadCoordinator sharedInstance];
|
||||
@try {
|
||||
sharedCoordinator->_targetToInFlightPackages =
|
||||
[aDecoder decodeObjectOfClass:[NSMutableDictionary class]
|
||||
forKey:ktargetToInFlightPackagesKey];
|
||||
|
||||
} @catch (NSException *exception) {
|
||||
sharedCoordinator->_targetToInFlightPackages = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return sharedCoordinator;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||
// All packages that have been given to uploaders need to be tracked so that their expiration
|
||||
// timers can be called.
|
||||
[aCoder encodeObject:_targetToInFlightPackages forKey:ktargetToInFlightPackagesKey];
|
||||
if (_targetToInFlightPackages.count > 0) {
|
||||
[aCoder encodeObject:_targetToInFlightPackages forKey:ktargetToInFlightPackagesKey];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - GDTLifecycleProtocol
|
||||
#pragma mark - GDTCORLifecycleProtocol
|
||||
|
||||
- (void)appWillForeground:(GDTApplication *)app {
|
||||
- (void)appWillForeground:(GDTCORApplication *)app {
|
||||
// Not entirely thread-safe, but it should be fine.
|
||||
self->_runningInBackground = NO;
|
||||
[self startTimer];
|
||||
}
|
||||
|
||||
- (void)appWillBackground:(GDTApplication *)app {
|
||||
- (void)appWillBackground:(GDTCORApplication *)app {
|
||||
// Not entirely thread-safe, but it should be fine.
|
||||
self->_runningInBackground = YES;
|
||||
|
||||
@@ -191,49 +198,75 @@ static NSString *const ktargetToInFlightPackagesKey =
|
||||
[self stopTimer];
|
||||
|
||||
// Create an immediate background task to run until the end of the current queue of work.
|
||||
__block GDTBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
|
||||
[app endBackgroundTask:bgID];
|
||||
__block GDTCORBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[app endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
}];
|
||||
dispatch_async(_coordinationQueue, ^{
|
||||
[app endBackgroundTask:bgID];
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[app endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillTerminate:(GDTApplication *)application {
|
||||
- (void)appWillTerminate:(GDTCORApplication *)application {
|
||||
dispatch_sync(_coordinationQueue, ^{
|
||||
[self stopTimer];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - GDTUploadPackageProtocol
|
||||
#pragma mark - GDTCORUploadPackageProtocol
|
||||
|
||||
- (void)packageDelivered:(GDTUploadPackage *)package successful:(BOOL)successful {
|
||||
- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful {
|
||||
if (!_coordinationQueue) {
|
||||
return;
|
||||
}
|
||||
dispatch_async(_coordinationQueue, ^{
|
||||
NSNumber *targetNumber = @(package.target);
|
||||
[self->_targetToInFlightPackages removeObjectForKey:targetNumber];
|
||||
id<GDTPrioritizer> prioritizer = self->_registrar.targetToPrioritizer[targetNumber];
|
||||
if (!prioritizer) {
|
||||
GDTLogError(GDTMCEPrioritizerError, @"A prioritizer should be registered for this target: %@",
|
||||
targetNumber);
|
||||
NSMutableDictionary<NSNumber *, GDTCORUploadPackage *> *targetToInFlightPackages =
|
||||
self->_targetToInFlightPackages;
|
||||
GDTCORRegistrar *registrar = self->_registrar;
|
||||
if (targetToInFlightPackages) {
|
||||
[targetToInFlightPackages removeObjectForKey:targetNumber];
|
||||
}
|
||||
if ([prioritizer respondsToSelector:@selector(packageDelivered:successful:)]) {
|
||||
[prioritizer packageDelivered:package successful:successful];
|
||||
if (registrar) {
|
||||
id<GDTCORPrioritizer> prioritizer = registrar.targetToPrioritizer[targetNumber];
|
||||
if (!prioritizer) {
|
||||
GDTCORLogError(GDTCORMCEPrioritizerError,
|
||||
@"A prioritizer should be registered for this target: %@", targetNumber);
|
||||
}
|
||||
if ([prioritizer respondsToSelector:@selector(packageDelivered:successful:)]) {
|
||||
[prioritizer packageDelivered:package successful:successful];
|
||||
}
|
||||
}
|
||||
[self.storage removeEvents:package.events];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)packageExpired:(GDTUploadPackage *)package {
|
||||
- (void)packageExpired:(GDTCORUploadPackage *)package {
|
||||
if (!_coordinationQueue) {
|
||||
return;
|
||||
}
|
||||
dispatch_async(_coordinationQueue, ^{
|
||||
NSNumber *targetNumber = @(package.target);
|
||||
[self->_targetToInFlightPackages removeObjectForKey:targetNumber];
|
||||
id<GDTPrioritizer> prioritizer = self->_registrar.targetToPrioritizer[targetNumber];
|
||||
id<GDTUploader> uploader = self->_registrar.targetToUploader[targetNumber];
|
||||
if ([prioritizer respondsToSelector:@selector(packageExpired:)]) {
|
||||
[prioritizer packageExpired:package];
|
||||
NSMutableDictionary<NSNumber *, GDTCORUploadPackage *> *targetToInFlightPackages =
|
||||
self->_targetToInFlightPackages;
|
||||
GDTCORRegistrar *registrar = self->_registrar;
|
||||
if (targetToInFlightPackages) {
|
||||
[targetToInFlightPackages removeObjectForKey:targetNumber];
|
||||
}
|
||||
if ([uploader respondsToSelector:@selector(packageExpired:)]) {
|
||||
[uploader packageExpired:package];
|
||||
if (registrar) {
|
||||
id<GDTCORPrioritizer> prioritizer = registrar.targetToPrioritizer[targetNumber];
|
||||
id<GDTCORUploader> uploader = registrar.targetToUploader[targetNumber];
|
||||
if ([prioritizer respondsToSelector:@selector(packageExpired:)]) {
|
||||
[prioritizer packageExpired:package];
|
||||
}
|
||||
if ([uploader respondsToSelector:@selector(packageExpired:)]) {
|
||||
[uploader packageExpired:package];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
+28
-26
@@ -14,16 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <GoogleDataTransport/GDTUploadPackage.h>
|
||||
#import <GoogleDataTransport/GDTCORUploadPackage.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTClock.h>
|
||||
#import <GoogleDataTransport/GDTConsoleLogger.h>
|
||||
#import <GoogleDataTransport/GDTCORClock.h>
|
||||
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
|
||||
#import <GoogleDataTransport/GDTCORStoredEvent.h>
|
||||
|
||||
#import "GDTLibrary/Private/GDTStorage_Private.h"
|
||||
#import "GDTLibrary/Private/GDTUploadCoordinator.h"
|
||||
#import "GDTLibrary/Private/GDTUploadPackage_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORStorage_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h"
|
||||
|
||||
@implementation GDTUploadPackage {
|
||||
@implementation GDTCORUploadPackage {
|
||||
/** If YES, the package's -completeDelivery method has been called. */
|
||||
BOOL _isDelivered;
|
||||
|
||||
@@ -34,13 +35,13 @@
|
||||
NSTimer *_expirationTimer;
|
||||
}
|
||||
|
||||
- (instancetype)initWithTarget:(GDTTarget)target {
|
||||
- (instancetype)initWithTarget:(GDTCORTarget)target {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_target = target;
|
||||
_storage = [GDTStorage sharedInstance];
|
||||
_deliverByTime = [GDTClock clockSnapshotInTheFuture:180000];
|
||||
_handler = [GDTUploadCoordinator sharedInstance];
|
||||
_storage = [GDTCORStorage sharedInstance];
|
||||
_deliverByTime = [GDTCORClock clockSnapshotInTheFuture:180000];
|
||||
_handler = [GDTCORUploadCoordinator sharedInstance];
|
||||
_expirationTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
|
||||
target:self
|
||||
selector:@selector(checkIfPackageIsExpired:)
|
||||
@@ -51,7 +52,7 @@
|
||||
}
|
||||
|
||||
- (instancetype)copy {
|
||||
GDTUploadPackage *newPackage = [[GDTUploadPackage alloc] initWithTarget:_target];
|
||||
GDTCORUploadPackage *newPackage = [[GDTCORUploadPackage alloc] initWithTarget:_target];
|
||||
newPackage->_events = [_events copy];
|
||||
return newPackage;
|
||||
}
|
||||
@@ -68,7 +69,7 @@
|
||||
[_expirationTimer invalidate];
|
||||
}
|
||||
|
||||
- (void)setStorage:(GDTStorage *)storage {
|
||||
- (void)setStorage:(GDTCORStorage *)storage {
|
||||
if (storage != _storage) {
|
||||
_storage = storage;
|
||||
}
|
||||
@@ -76,8 +77,8 @@
|
||||
|
||||
- (void)completeDelivery {
|
||||
if (_isDelivered) {
|
||||
GDTLogError(GDTMCEDeliverTwice, @"%@",
|
||||
@"It's an API violation to call -completeDelivery twice.");
|
||||
GDTCORLogError(GDTCORMCEDeliverTwice, @"%@",
|
||||
@"It's an API violation to call -completeDelivery twice.");
|
||||
}
|
||||
_isDelivered = YES;
|
||||
if (!_isHandled && _handler &&
|
||||
@@ -98,7 +99,7 @@
|
||||
}
|
||||
|
||||
- (void)checkIfPackageIsExpired:(NSTimer *)timer {
|
||||
if ([[GDTClock snapshot] isAfter:_deliverByTime]) {
|
||||
if ([[GDTCORClock snapshot] isAfter:_deliverByTime]) {
|
||||
if (_handler && [_handler respondsToSelector:@selector(packageExpired:)]) {
|
||||
_isHandled = YES;
|
||||
[_expirationTimer invalidate];
|
||||
@@ -110,19 +111,19 @@
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
/** The keyed archiver key for the events property. */
|
||||
static NSString *const kEventsKey = @"GDTUploadPackageEventsKey";
|
||||
static NSString *const kEventsKey = @"GDTCORUploadPackageEventsKey";
|
||||
|
||||
/** The keyed archiver key for the _isHandled property. */
|
||||
static NSString *const kDeliverByTimeKey = @"GDTUploadPackageDeliveryByTimeKey";
|
||||
static NSString *const kDeliverByTimeKey = @"GDTCORUploadPackageDeliveryByTimeKey";
|
||||
|
||||
/** The keyed archiver key for the _isHandled ivar. */
|
||||
static NSString *const kIsHandledKey = @"GDTUploadPackageIsHandledKey";
|
||||
static NSString *const kIsHandledKey = @"GDTCORUploadPackageIsHandledKey";
|
||||
|
||||
/** The keyed archiver key for the handler property. */
|
||||
static NSString *const kHandlerKey = @"GDTUploadPackageHandlerKey";
|
||||
static NSString *const kHandlerKey = @"GDTCORUploadPackageHandlerKey";
|
||||
|
||||
/** The keyed archiver key for the target property. */
|
||||
static NSString *const kTargetKey = @"GDTUploadPackageTargetKey";
|
||||
static NSString *const kTargetKey = @"GDTCORUploadPackageTargetKey";
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
@@ -137,14 +138,15 @@ static NSString *const kTargetKey = @"GDTUploadPackageTargetKey";
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
|
||||
GDTTarget target = [aDecoder decodeIntegerForKey:kTargetKey];
|
||||
GDTCORTarget target = [aDecoder decodeIntegerForKey:kTargetKey];
|
||||
self = [self initWithTarget:target];
|
||||
if (self) {
|
||||
_events = [aDecoder decodeObjectOfClass:[NSSet class] forKey:kEventsKey];
|
||||
_deliverByTime = [aDecoder decodeObjectOfClass:[GDTClock class] forKey:kDeliverByTimeKey];
|
||||
NSSet *classes = [NSSet setWithObjects:[NSSet class], [GDTCORStoredEvent class], nil];
|
||||
_events = [aDecoder decodeObjectOfClasses:classes forKey:kEventsKey];
|
||||
_deliverByTime = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kDeliverByTimeKey];
|
||||
_isHandled = [aDecoder decodeBoolForKey:kIsHandledKey];
|
||||
// Isn't technically NSSecureCoding, because we don't know the class of this object.
|
||||
_handler = [aDecoder decodeObjectForKey:kHandlerKey];
|
||||
// _handler isn't technically NSSecureCoding, because we don't know the class of this object.
|
||||
// but it gets decoded anyway.
|
||||
}
|
||||
return self;
|
||||
}
|
||||
+3
-3
@@ -14,13 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <GoogleDataTransport/GDTEvent.h>
|
||||
#import <GoogleDataTransport/GDTCOREvent.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTClock.h>
|
||||
#import <GoogleDataTransport/GDTCORClock.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTEvent ()
|
||||
@interface GDTCOREvent ()
|
||||
|
||||
/** The serialized bytes of the event data object. */
|
||||
@property(nonatomic) NSData *dataObjectTransportBytes;
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class helps determine upload conditions by determining connectivity. */
|
||||
@interface GDTReachability : NSObject
|
||||
@interface GDTCORReachability : NSObject
|
||||
|
||||
/** The current set flags indicating network conditions */
|
||||
+ (SCNetworkReachabilityFlags)currentFlags;
|
||||
+2
-2
@@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTLibrary/Private/GDTReachability.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORReachability.h"
|
||||
|
||||
@interface GDTReachability ()
|
||||
@interface GDTCORReachability ()
|
||||
|
||||
/** Allows manually setting the flags for testing purposes. */
|
||||
@property(nonatomic, readwrite) SCNetworkReachabilityFlags flags;
|
||||
+4
-4
@@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <GoogleDataTransport/GDTRegistrar.h>
|
||||
#import <GoogleDataTransport/GDTCORRegistrar.h>
|
||||
|
||||
@interface GDTRegistrar ()
|
||||
@interface GDTCORRegistrar ()
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -24,11 +24,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property(nonatomic, readonly) dispatch_queue_t registrarQueue;
|
||||
|
||||
/** A map of targets to backend implementations. */
|
||||
@property(atomic, readonly) NSMutableDictionary<NSNumber *, id<GDTUploader>> *targetToUploader;
|
||||
@property(atomic, readonly) NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *targetToUploader;
|
||||
|
||||
/** A map of targets to prioritizer implementations. */
|
||||
@property(atomic, readonly)
|
||||
NSMutableDictionary<NSNumber *, id<GDTPrioritizer>> *targetToPrioritizer;
|
||||
NSMutableDictionary<NSNumber *, id<GDTCORPrioritizer>> *targetToPrioritizer;
|
||||
|
||||
@end
|
||||
|
||||
+7
-7
@@ -16,15 +16,15 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTLifecycle.h>
|
||||
#import <GoogleDataTransport/GDTCORLifecycle.h>
|
||||
|
||||
@class GDTEvent;
|
||||
@class GDTStoredEvent;
|
||||
@class GDTCOREvent;
|
||||
@class GDTCORStoredEvent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Manages the storage of events. This class is thread-safe. */
|
||||
@interface GDTStorage : NSObject <NSSecureCoding, GDTLifecycleProtocol>
|
||||
@interface GDTCORStorage : NSObject <NSSecureCoding, GDTCORLifecycleProtocol>
|
||||
|
||||
/** Creates and/or returns the storage singleton.
|
||||
*
|
||||
@@ -33,17 +33,17 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
/** Stores event.dataObjectTransportBytes into a shared on-device folder and tracks the event via
|
||||
* a GDTStoredEvent instance.
|
||||
* a GDTCORStoredEvent instance.
|
||||
*
|
||||
* @param event The event to store.
|
||||
*/
|
||||
- (void)storeEvent:(GDTEvent *)event;
|
||||
- (void)storeEvent:(GDTCOREvent *)event;
|
||||
|
||||
/** Removes a set of events from storage specified by their hash.
|
||||
*
|
||||
* @param events The set of stored events to remove.
|
||||
*/
|
||||
- (void)removeEvents:(NSSet<GDTStoredEvent *> *)events;
|
||||
- (void)removeEvents:(NSSet<GDTCORStoredEvent *> *)events;
|
||||
|
||||
@end
|
||||
|
||||
+7
-7
@@ -14,30 +14,30 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTLibrary/Private/GDTStorage.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORStorage.h"
|
||||
|
||||
@class GDTUploadCoordinator;
|
||||
@class GDTCORUploadCoordinator;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTStorage ()
|
||||
@interface GDTCORStorage ()
|
||||
|
||||
/** The queue on which all storage work will occur. */
|
||||
@property(nonatomic) dispatch_queue_t storageQueue;
|
||||
|
||||
/** A map of targets to a set of stored events. */
|
||||
@property(nonatomic)
|
||||
NSMutableDictionary<NSNumber *, NSMutableSet<GDTStoredEvent *> *> *targetToEventSet;
|
||||
NSMutableDictionary<NSNumber *, NSMutableSet<GDTCORStoredEvent *> *> *targetToEventSet;
|
||||
|
||||
/** All the events that have been stored. */
|
||||
@property(readonly, nonatomic) NSMutableOrderedSet<GDTStoredEvent *> *storedEvents;
|
||||
@property(readonly, nonatomic) NSMutableOrderedSet<GDTCORStoredEvent *> *storedEvents;
|
||||
|
||||
/** The upload coordinator instance used by this storage instance. */
|
||||
@property(nonatomic) GDTUploadCoordinator *uploadCoordinator;
|
||||
@property(nonatomic) GDTCORUploadCoordinator *uploadCoordinator;
|
||||
|
||||
/** If YES, every call to -storeLog results in background task and serializes the singleton to disk.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL runningInBackground;
|
||||
@property(nonatomic) BOOL runningInBackground;
|
||||
|
||||
/** Returns the path to the keyed archive of the singleton. This is where the singleton is saved
|
||||
* to disk during certain app lifecycle events.
|
||||
+6
-6
@@ -16,11 +16,11 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTLifecycle.h>
|
||||
#import <GoogleDataTransport/GDTCORLifecycle.h>
|
||||
|
||||
@class GDTEvent;
|
||||
@class GDTCOREvent;
|
||||
|
||||
@protocol GDTEventTransformer;
|
||||
@protocol GDTCOREventTransformer;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* 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 GDTTransformer : NSObject <GDTLifecycleProtocol>
|
||||
@interface GDTCORTransformer : NSObject <GDTCORLifecycleProtocol>
|
||||
|
||||
/** Instantiates or returns the event transformer singleton.
|
||||
*
|
||||
@@ -46,8 +46,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* @param event The event to apply transformers on.
|
||||
* @param transformers The list of transformers to apply.
|
||||
*/
|
||||
- (void)transformEvent:(GDTEvent *)event
|
||||
withTransformers:(nullable NSArray<id<GDTEventTransformer>> *)transformers;
|
||||
- (void)transformEvent:(GDTCOREvent *)event
|
||||
withTransformers:(nullable NSArray<id<GDTCOREventTransformer>> *)transformers;
|
||||
|
||||
@end
|
||||
|
||||
+4
-4
@@ -14,19 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTLibrary/Private/GDTTransformer.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORTransformer.h"
|
||||
|
||||
@class GDTStorage;
|
||||
@class GDTCORStorage;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTTransformer ()
|
||||
@interface GDTCORTransformer ()
|
||||
|
||||
/** The queue on which all work will occur. */
|
||||
@property(nonatomic) dispatch_queue_t eventWritingQueue;
|
||||
|
||||
/** The storage instance used to store events. Should only be used to inject a testing fake. */
|
||||
@property(nonatomic) GDTStorage *storageInstance;
|
||||
@property(nonatomic) GDTCORStorage *storageInstance;
|
||||
|
||||
/** If YES, every call to -transformEvent will result in a background task. */
|
||||
@property(nonatomic, readonly) BOOL runningInBackground;
|
||||
+5
-5
@@ -14,25 +14,25 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <GoogleDataTransport/GDTTransport.h>
|
||||
#import <GoogleDataTransport/GDTCORTransport.h>
|
||||
|
||||
@class GDTTransformer;
|
||||
@class GDTCORTransformer;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTTransport ()
|
||||
@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<GDTEventTransformer>> *transformers;
|
||||
@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) GDTTransformer *transformerInstance;
|
||||
@property(nonatomic) GDTCORTransformer *transformerInstance;
|
||||
|
||||
@end
|
||||
|
||||
+11
-11
@@ -16,21 +16,21 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTLifecycle.h>
|
||||
#import <GoogleDataTransport/GDTRegistrar.h>
|
||||
#import <GoogleDataTransport/GDTCORLifecycle.h>
|
||||
#import <GoogleDataTransport/GDTCORRegistrar.h>
|
||||
|
||||
#import "GDTLibrary/Private/GDTUploadPackage_Private.h"
|
||||
#import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h"
|
||||
|
||||
@class GDTClock;
|
||||
@class GDTStorage;
|
||||
@class GDTCORClock;
|
||||
@class GDTCORStorage;
|
||||
|
||||
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 GDTUploadCoordinator
|
||||
: NSObject <NSSecureCoding, GDTLifecycleProtocol, GDTUploadPackageProtocol>
|
||||
@interface GDTCORUploadCoordinator
|
||||
: NSObject <NSSecureCoding, GDTCORLifecycleProtocol, GDTCORUploadPackageProtocol>
|
||||
|
||||
/** The queue on which all upload coordination will occur. Also used by a dispatch timer. */
|
||||
/** Creates and/or returrns the singleton.
|
||||
@@ -51,13 +51,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** The map of targets to in-flight packages. */
|
||||
@property(nonatomic, readonly)
|
||||
NSMutableDictionary<NSNumber *, GDTUploadPackage *> *targetToInFlightPackages;
|
||||
NSMutableDictionary<NSNumber *, GDTCORUploadPackage *> *targetToInFlightPackages;
|
||||
|
||||
/** The storage object the coordinator will use. Generally used for testing. */
|
||||
@property(nonatomic) GDTStorage *storage;
|
||||
@property(nonatomic) GDTCORStorage *storage;
|
||||
|
||||
/** The registrar object the coordinator will use. Generally used for testing. */
|
||||
@property(nonatomic) GDTRegistrar *registrar;
|
||||
@property(nonatomic) GDTCORRegistrar *registrar;
|
||||
|
||||
/** If YES, completion and other operations will result in serializing the singleton to disk. */
|
||||
@property(nonatomic, readonly) BOOL runningInBackground;
|
||||
@@ -67,7 +67,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*
|
||||
* @param target The target that should force an upload.
|
||||
*/
|
||||
- (void)forceUploadForTarget:(GDTTarget)target;
|
||||
- (void)forceUploadForTarget:(GDTCORTarget)target;
|
||||
|
||||
/** Starts the upload timer. */
|
||||
- (void)startTimer;
|
||||
+5
-5
@@ -14,16 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <GoogleDataTransport/GDTUploadPackage.h>
|
||||
#import <GoogleDataTransport/GDTCORUploadPackage.h>
|
||||
|
||||
@class GDTStorage;
|
||||
@class GDTCORStorage;
|
||||
|
||||
@interface GDTUploadPackage ()
|
||||
@interface GDTCORUploadPackage ()
|
||||
|
||||
/** The storage object this upload package will use to resolve event hashes to files. */
|
||||
@property(nonatomic) GDTStorage *storage;
|
||||
@property(nonatomic) GDTCORStorage *storage;
|
||||
|
||||
/** A handler that will receive callbacks for certain events. */
|
||||
@property(nonatomic) id<NSSecureCoding, GDTUploadPackageProtocol> handler;
|
||||
@property(nonatomic) id<NSSecureCoding, GDTCORUploadPackageProtocol> handler;
|
||||
|
||||
@end
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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/GDTCORConsoleLogger.h>
|
||||
|
||||
/** 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, ...) \
|
||||
do { \
|
||||
if (__builtin_expect(!(condition), 0)) { \
|
||||
GDTCORAssertionBlock assertionBlock = GDTCORAssertionBlockToRunInstead(); \
|
||||
if (assertionBlock) { \
|
||||
assertionBlock(); \
|
||||
} else { \
|
||||
__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
|
||||
NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \
|
||||
__assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; \
|
||||
GDTCORLogError(GDTCORMCEGeneralError, @"Assertion failed (%@:%d): %s,", __assert_file__, \
|
||||
__LINE__, ##__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, ...) \
|
||||
do { \
|
||||
__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
|
||||
if (__builtin_expect(!(condition), 0)) { \
|
||||
NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \
|
||||
__assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; \
|
||||
GDTCORLogError(GDTCORMCEFatalAssertion, \
|
||||
@"Fatal assertion encountered, please open an issue at " \
|
||||
"https://github.com/firebase/firebase-ios-sdk/issues " \
|
||||
"(%@:%d): %s,", \
|
||||
__assert_file__, __LINE__, ##__VA_ARGS__); \
|
||||
[[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \
|
||||
object:self \
|
||||
file:__assert_file__ \
|
||||
lineNumber:__LINE__ \
|
||||
description:@"%@", ##__VA_ARGS__]; \
|
||||
} \
|
||||
__PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \
|
||||
} while (0);
|
||||
|
||||
#endif // defined(NS_BLOCK_ASSERTIONS)
|
||||
+5
-5
@@ -19,7 +19,7 @@
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class manages the device clock and produces snapshots of the current time. */
|
||||
@interface GDTClock : NSObject <NSSecureCoding>
|
||||
@interface GDTCORClock : NSObject <NSSecureCoding>
|
||||
|
||||
/** The wallclock time, UTC, in milliseconds. */
|
||||
@property(nonatomic, readonly) int64_t timeMillis;
|
||||
@@ -33,13 +33,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/** The device uptime when this clock was created. */
|
||||
@property(nonatomic, readonly) int64_t uptime;
|
||||
|
||||
/** Creates a GDTClock object using the current time and offsets.
|
||||
/** Creates a GDTCORClock object using the current time and offsets.
|
||||
*
|
||||
* @return A new GDTClock object representing the current time state.
|
||||
* @return A new GDTCORClock object representing the current time state.
|
||||
*/
|
||||
+ (instancetype)snapshot;
|
||||
|
||||
/** Creates a GDTClock object representing a time in the future, relative to now.
|
||||
/** 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.
|
||||
@@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*
|
||||
* @return YES if the calling clock's time is after the given clock's time.
|
||||
*/
|
||||
- (BOOL)isAfter:(GDTClock *)otherClock;
|
||||
- (BOOL)isAfter:(GDTCORClock *)otherClock;
|
||||
|
||||
@end
|
||||
|
||||
+23
-18
@@ -23,57 +23,62 @@
|
||||
* - MCW => MessageCodeWarning
|
||||
* - MCE => MessageCodeError
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, GDTMessageCode) {
|
||||
typedef NS_ENUM(NSInteger, GDTCORMessageCode) {
|
||||
|
||||
/** For warning messages concerning transportBytes: not being implemented by a data object. */
|
||||
GDTMCWDataObjectMissingBytesImpl = 1,
|
||||
GDTCORMCWDataObjectMissingBytesImpl = 1,
|
||||
|
||||
/** For warning messages concerning a failed event upload. */
|
||||
GDTMCWUploadFailed = 2,
|
||||
GDTCORMCWUploadFailed = 2,
|
||||
|
||||
/** For warning messages concerning a forced event upload. */
|
||||
GDTMCWForcedUpload = 3,
|
||||
GDTCORMCWForcedUpload = 3,
|
||||
|
||||
/** For warning messages concerning a failed reachability call. */
|
||||
GDTMCWReachabilityFailed = 4,
|
||||
GDTCORMCWReachabilityFailed = 4,
|
||||
|
||||
/** For error messages concerning transform: not being implemented by an event transformer. */
|
||||
GDTMCETransformerDoesntImplementTransform = 1000,
|
||||
GDTCORMCETransformerDoesntImplementTransform = 1000,
|
||||
|
||||
/** For error messages concerning the creation of a directory failing. */
|
||||
GDTMCEDirectoryCreationError = 1001,
|
||||
GDTCORMCEDirectoryCreationError = 1001,
|
||||
|
||||
/** For error messages concerning the writing of a event file. */
|
||||
GDTMCEFileWriteError = 1002,
|
||||
GDTCORMCEFileWriteError = 1002,
|
||||
|
||||
/** For error messages concerning the lack of a prioritizer for a given backend. */
|
||||
GDTMCEPrioritizerError = 1003,
|
||||
GDTCORMCEPrioritizerError = 1003,
|
||||
|
||||
/** For error messages concerning a package delivery API violation. */
|
||||
GDTMCEDeliverTwice = 1004,
|
||||
GDTCORMCEDeliverTwice = 1004,
|
||||
|
||||
/** For error messages concerning an error in an implementation of -transportBytes. */
|
||||
GDTMCETransportBytesError = 1005,
|
||||
GDTCORMCETransportBytesError = 1005,
|
||||
|
||||
/** For general purpose error messages in a dependency. */
|
||||
GDTMCEGeneralError = 1006
|
||||
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
|
||||
};
|
||||
|
||||
/** */
|
||||
FOUNDATION_EXPORT
|
||||
void GDTLog(GDTMessageCode code, NSString *_Nonnull format, ...);
|
||||
void GDTCORLog(GDTCORMessageCode code, NSString *_Nonnull format, ...);
|
||||
|
||||
/** 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 GDTMessageCodeEnumToString(GDTMessageCode code);
|
||||
FOUNDATION_EXPORT NSString *_Nonnull GDTCORMessageCodeEnumToString(GDTCORMessageCode code);
|
||||
|
||||
// A define to wrap GULLogWarning with slightly more convenient usage.
|
||||
#define GDTLogWarning(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
|
||||
GDTLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__);
|
||||
#define GDTCORLogWarning(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
|
||||
GDTCORLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__);
|
||||
|
||||
// A define to wrap GULLogError with slightly more convenient usage and a failing assert.
|
||||
#define GDTLogError(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
|
||||
GDTLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__);
|
||||
#define GDTCORLogError(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
|
||||
GDTCORLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__);
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class represents a future data object, determined at instantiation time. */
|
||||
@interface GDTDataFuture : NSObject <NSSecureCoding>
|
||||
@interface GDTCORDataFuture : NSObject <NSSecureCoding>
|
||||
|
||||
/** The data, computed on-demand, depending on the initializer. */
|
||||
@property(nullable, readonly, nonatomic) NSData *data;
|
||||
+19
-19
@@ -16,36 +16,36 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTEventDataObject.h>
|
||||
#import <GoogleDataTransport/GDTCOREventDataObject.h>
|
||||
|
||||
@class GDTClock;
|
||||
@class GDTDataFuture;
|
||||
@class GDTStoredEvent;
|
||||
@class GDTCORClock;
|
||||
@class GDTCORDataFuture;
|
||||
@class GDTCORStoredEvent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** The different possible quality of service specifiers. High values indicate high priority. */
|
||||
typedef NS_ENUM(NSInteger, GDTEventQoS) {
|
||||
typedef NS_ENUM(NSInteger, GDTCOREventQoS) {
|
||||
/** The QoS tier wasn't set, and won't ever be sent. */
|
||||
GDTEventQoSUnknown = 0,
|
||||
GDTCOREventQoSUnknown = 0,
|
||||
|
||||
/** This event is internal telemetry data that should not be sent on its own if possible. */
|
||||
GDTEventQoSTelemetry = 1,
|
||||
GDTCOREventQoSTelemetry = 1,
|
||||
|
||||
/** This event should be sent, but in a batch only roughly once per day. */
|
||||
GDTEventQoSDaily = 2,
|
||||
GDTCOREventQoSDaily = 2,
|
||||
|
||||
/** This event should be sent when requested by the uploader. */
|
||||
GDTEventQosDefault = 3,
|
||||
GDTCOREventQosDefault = 3,
|
||||
|
||||
/** This event should be sent immediately along with any other data that can be batched. */
|
||||
GDTEventQoSFast = 4,
|
||||
GDTCOREventQoSFast = 4,
|
||||
|
||||
/** This event should only be uploaded on wifi. */
|
||||
GDTEventQoSWifiOnly = 5,
|
||||
GDTCOREventQoSWifiOnly = 5,
|
||||
};
|
||||
|
||||
@interface GDTEvent : NSObject <NSSecureCoding>
|
||||
@interface GDTCOREvent : NSObject <NSSecureCoding>
|
||||
|
||||
/** The mapping identifier, to allow backends to map the transport bytes to a proto. */
|
||||
@property(readonly, nonatomic) NSString *mappingID;
|
||||
@@ -54,14 +54,14 @@ typedef NS_ENUM(NSInteger, GDTEventQoS) {
|
||||
@property(readonly, nonatomic) NSInteger target;
|
||||
|
||||
/** The data object encapsulated in the transport of your choice, as long as it implements
|
||||
* the GDTEventDataObject protocol. */
|
||||
@property(nullable, nonatomic) id<GDTEventDataObject> dataObject;
|
||||
* the GDTCOREventDataObject protocol. */
|
||||
@property(nullable, nonatomic) id<GDTCOREventDataObject> dataObject;
|
||||
|
||||
/** The quality of service tier this event belongs to. */
|
||||
@property(nonatomic) GDTEventQoS qosTier;
|
||||
@property(nonatomic) GDTCOREventQoS qosTier;
|
||||
|
||||
/** The clock snapshot at the time of the event. */
|
||||
@property(nonatomic) GDTClock *clockSnapshot;
|
||||
@property(nonatomic) GDTCORClock *clockSnapshot;
|
||||
|
||||
/** A dictionary provided to aid prioritizers by allowing the passing of arbitrary data. It will be
|
||||
* retained by a copy in -copy, but not used for -hash.
|
||||
@@ -82,12 +82,12 @@ typedef NS_ENUM(NSInteger, GDTEventQoS) {
|
||||
- (instancetype)initWithMappingID:(NSString *)mappingID
|
||||
target:(NSInteger)target NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** Returns the GDTStoredEvent equivalent of self.
|
||||
/** Returns the GDTCORStoredEvent equivalent of self.
|
||||
*
|
||||
* @param dataFuture The data future representing the transport bytes of the original event.
|
||||
* @return An equivalent GDTStoredEvent.
|
||||
* @return An equivalent GDTCORStoredEvent.
|
||||
*/
|
||||
- (GDTStoredEvent *)storedEventWithDataFuture:(GDTDataFuture *)dataFuture;
|
||||
- (GDTCORStoredEvent *)storedEventWithDataFuture:(GDTCORDataFuture *)dataFuture;
|
||||
|
||||
@end
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ 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 GDTEventDataObject <NSObject>
|
||||
@protocol GDTCOREventDataObject <NSObject>
|
||||
|
||||
@required
|
||||
|
||||
+3
-3
@@ -16,12 +16,12 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class GDTEvent;
|
||||
@class GDTCOREvent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Defines the API that event transformers must adopt. */
|
||||
@protocol GDTEventTransformer <NSObject>
|
||||
@protocol GDTCOREventTransformer <NSObject>
|
||||
|
||||
@required
|
||||
|
||||
@@ -31,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* @param event The event to transform.
|
||||
* @return A transformed event, or nil if the transformation dropped the event.
|
||||
*/
|
||||
- (GDTEvent *)transform:(GDTEvent *)event;
|
||||
- (GDTCOREvent *)transform:(GDTCOREvent *)event;
|
||||
|
||||
@end
|
||||
|
||||
+15
-14
@@ -16,35 +16,36 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTPlatform.h>
|
||||
#import <GoogleDataTransport/GDTCORPlatform.h>
|
||||
|
||||
@class GDTEvent;
|
||||
@class GDTCOREvent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** A protocol defining the lifecycle events objects in the library must respond to immediately. */
|
||||
@protocol GDTLifecycleProtocol <NSObject>
|
||||
@protocol GDTCORLifecycleProtocol <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
/** Indicates an imminent app termination in the rare occurrence when -applicationWillTerminate: has
|
||||
* been called.
|
||||
*
|
||||
* @param app The GDTApplication instance.
|
||||
* @param app The GDTCORApplication instance.
|
||||
*/
|
||||
- (void)appWillTerminate:(GDTApplication *)app;
|
||||
- (void)appWillTerminate:(GDTCORApplication *)app;
|
||||
|
||||
/** Indicates that the app is moving to background and eventual suspension.
|
||||
/** Indicates that the app is moving to background and eventual suspension or the current UIScene is
|
||||
* deactivating.
|
||||
*
|
||||
* @param app The GDTApplication instance.
|
||||
* @param app The GDTCORApplication instance.
|
||||
*/
|
||||
- (void)appWillBackground:(GDTApplication *)app;
|
||||
- (void)appWillBackground:(GDTCORApplication *)app;
|
||||
|
||||
/** Indicates that the app is resuming operation.
|
||||
/** Indicates that the app is resuming operation or a UIScene is activating.
|
||||
*
|
||||
* @param app The GDTApplication instance.
|
||||
* @param app The GDTCORApplication instance.
|
||||
*/
|
||||
- (void)appWillForeground:(GDTApplication *)app;
|
||||
- (void)appWillForeground:(GDTCORApplication *)app;
|
||||
|
||||
@end
|
||||
|
||||
@@ -52,10 +53,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*
|
||||
* 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 (GDTStorage and GDTUploadCoordinator singletons) will deserialize themselves from and to
|
||||
* disk before and after every operation, respectively.
|
||||
* library (GDTCORStorage and GDTCORUploadCoordinator singletons) will deserialize themselves from
|
||||
* and to disk before and after every operation, respectively.
|
||||
*/
|
||||
@interface GDTLifecycle : NSObject <GDTApplicationDelegate>
|
||||
@interface GDTCORLifecycle : NSObject <GDTCORApplicationDelegate>
|
||||
|
||||
@end
|
||||
|
||||
+15
-15
@@ -26,61 +26,61 @@
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** A notification sent out if the app is backgrounding. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTApplicationDidEnterBackgroundNotification;
|
||||
FOUNDATION_EXPORT NSString *const kGDTCORApplicationDidEnterBackgroundNotification;
|
||||
|
||||
/** A notification sent out if the app is foregrounding. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTApplicationWillEnterForegroundNotification;
|
||||
FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillEnterForegroundNotification;
|
||||
|
||||
/** A notification sent out if the app is terminating. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTApplicationWillTerminateNotification;
|
||||
FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillTerminateNotification;
|
||||
|
||||
/** 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 GDTReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags);
|
||||
BOOL GDTCORReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags);
|
||||
|
||||
/** A typedef identify background identifiers. */
|
||||
typedef NSUInteger GDTBackgroundIdentifier;
|
||||
typedef volatile NSUInteger GDTCORBackgroundIdentifier;
|
||||
|
||||
/** A background task's invalid sentinel value. */
|
||||
FOUNDATION_EXPORT const GDTBackgroundIdentifier GDTBackgroundIdentifierInvalid;
|
||||
FOUNDATION_EXPORT const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid;
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
/** A protocol that wraps UIApplicationDelegate or NSObject protocol, depending on the platform. */
|
||||
@protocol GDTApplicationDelegate <UIApplicationDelegate>
|
||||
@protocol GDTCORApplicationDelegate <UIApplicationDelegate>
|
||||
#elif TARGET_OS_OSX
|
||||
@protocol GDTApplicationDelegate <NSApplicationDelegate>
|
||||
@protocol GDTCORApplicationDelegate <NSApplicationDelegate>
|
||||
#else
|
||||
@protocol GDTApplicationDelegate <NSObject>
|
||||
@protocol GDTCORApplicationDelegate <NSObject>
|
||||
#endif // TARGET_OS_IOS || TARGET_OS_TV
|
||||
|
||||
@end
|
||||
|
||||
/** A cross-platform application class. */
|
||||
@interface GDTApplication : NSObject <GDTApplicationDelegate>
|
||||
@interface GDTCORApplication : NSObject <GDTCORApplicationDelegate>
|
||||
|
||||
/** Creates and/or returns the shared application instance.
|
||||
*
|
||||
* @return The shared application instance.
|
||||
*/
|
||||
+ (nullable GDTApplication *)sharedApplication;
|
||||
+ (nullable GDTCORApplication *)sharedApplication;
|
||||
|
||||
/** Creates a background task with the returned identifier if on a suitable platform.
|
||||
*
|
||||
* @param handler The handler block that is called if the background task expires.
|
||||
* @return An identifier for the background task, or GDTBackgroundIdentifierInvalid if one couldn't
|
||||
* be created.
|
||||
* @return An identifier for the background task, or GDTCORBackgroundIdentifierInvalid if one
|
||||
* couldn't be created.
|
||||
*/
|
||||
- (GDTBackgroundIdentifier)beginBackgroundTaskWithExpirationHandler:
|
||||
- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithExpirationHandler:
|
||||
(void (^__nullable)(void))handler;
|
||||
|
||||
/** Ends the background task if the identifier is valid.
|
||||
*
|
||||
* @param bgID The background task to end.
|
||||
*/
|
||||
- (void)endBackgroundTask:(GDTBackgroundIdentifier)bgID;
|
||||
- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID;
|
||||
|
||||
@end
|
||||
|
||||
+12
-12
@@ -16,39 +16,39 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTLifecycle.h>
|
||||
#import <GoogleDataTransport/GDTUploadPackage.h>
|
||||
#import <GoogleDataTransport/GDTCORLifecycle.h>
|
||||
#import <GoogleDataTransport/GDTCORUploadPackage.h>
|
||||
|
||||
@class GDTStoredEvent;
|
||||
@class GDTCORStoredEvent;
|
||||
|
||||
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, GDTUploadConditions) {
|
||||
typedef NS_OPTIONS(NSInteger, GDTCORUploadConditions) {
|
||||
|
||||
/** An upload shouldn't be attempted, because there's no network. */
|
||||
GDTUploadConditionNoNetwork = 1 << 0,
|
||||
GDTCORUploadConditionNoNetwork = 1 << 0,
|
||||
|
||||
/** An upload would likely use mobile data. */
|
||||
GDTUploadConditionMobileData = 1 << 1,
|
||||
GDTCORUploadConditionMobileData = 1 << 1,
|
||||
|
||||
/** An upload would likely use wifi data. */
|
||||
GDTUploadConditionWifiData = 1 << 2,
|
||||
GDTCORUploadConditionWifiData = 1 << 2,
|
||||
|
||||
/** An upload uses some sort of network connection, but it's unclear which. */
|
||||
GDTUploadConditionUnclearConnection = 1 << 3,
|
||||
GDTCORUploadConditionUnclearConnection = 1 << 3,
|
||||
|
||||
/** A high priority event has occurred. */
|
||||
GDTUploadConditionHighPriority = 1 << 4,
|
||||
GDTCORUploadConditionHighPriority = 1 << 4,
|
||||
};
|
||||
|
||||
/** This protocol defines the common interface of event prioritization. Prioritizers are
|
||||
* stateful objects that prioritize events upon insertion into storage and remain prepared to return
|
||||
* a set of filenames to the storage system.
|
||||
*/
|
||||
@protocol GDTPrioritizer <NSObject, GDTLifecycleProtocol, GDTUploadPackageProtocol>
|
||||
@protocol GDTCORPrioritizer <NSObject, GDTCORLifecycleProtocol, GDTCORUploadPackageProtocol>
|
||||
|
||||
@required
|
||||
|
||||
@@ -58,7 +58,7 @@ typedef NS_OPTIONS(NSInteger, GDTUploadConditions) {
|
||||
*
|
||||
* @param event The event to prioritize.
|
||||
*/
|
||||
- (void)prioritizeEvent:(GDTStoredEvent *)event;
|
||||
- (void)prioritizeEvent:(GDTCORStoredEvent *)event;
|
||||
|
||||
/** Returns a set of events to upload given a set of conditions.
|
||||
*
|
||||
@@ -66,7 +66,7 @@ typedef NS_OPTIONS(NSInteger, GDTUploadConditions) {
|
||||
* @return An object to be used by the uploader to determine file URLs to upload with respect to the
|
||||
* current conditions.
|
||||
*/
|
||||
- (GDTUploadPackage *)uploadPackageWithConditions:(GDTUploadConditions)conditions;
|
||||
- (GDTCORUploadPackage *)uploadPackageWithConditions:(GDTCORUploadConditions)conditions;
|
||||
|
||||
@end
|
||||
|
||||
+6
-6
@@ -16,14 +16,14 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTPrioritizer.h>
|
||||
#import <GoogleDataTransport/GDTTargets.h>
|
||||
#import <GoogleDataTransport/GDTUploader.h>
|
||||
#import <GoogleDataTransport/GDTCORPrioritizer.h>
|
||||
#import <GoogleDataTransport/GDTCORTargets.h>
|
||||
#import <GoogleDataTransport/GDTCORUploader.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Manages the registration of targets with the transport SDK. */
|
||||
@interface GDTRegistrar : NSObject <GDTLifecycleProtocol>
|
||||
@interface GDTCORRegistrar : NSObject <GDTCORLifecycleProtocol>
|
||||
|
||||
/** Creates and/or returns the singleton instance.
|
||||
*
|
||||
@@ -36,14 +36,14 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* @param backend The backend object to register.
|
||||
* @param target The target this backend object will be responsible for.
|
||||
*/
|
||||
- (void)registerUploader:(id<GDTUploader>)backend target:(GDTTarget)target;
|
||||
- (void)registerUploader:(id<GDTCORUploader>)backend target:(GDTCORTarget)target;
|
||||
|
||||
/** Registers a event prioritizer implementation with the GoogleDataTransport infrastructure.
|
||||
*
|
||||
* @param prioritizer The prioritizer object to register.
|
||||
* @param target The target this prioritizer object will be responsible for.
|
||||
*/
|
||||
- (void)registerPrioritizer:(id<GDTPrioritizer>)prioritizer target:(GDTTarget)target;
|
||||
- (void)registerPrioritizer:(id<GDTCORPrioritizer>)prioritizer target:(GDTCORTarget)target;
|
||||
|
||||
@end
|
||||
|
||||
+8
-8
@@ -15,17 +15,17 @@
|
||||
*/
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTDataFuture.h>
|
||||
#import <GoogleDataTransport/GDTEvent.h>
|
||||
#import <GoogleDataTransport/GDTCORDataFuture.h>
|
||||
#import <GoogleDataTransport/GDTCOREvent.h>
|
||||
|
||||
@class GDTEvent;
|
||||
@class GDTCOREvent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTStoredEvent : NSObject <NSSecureCoding>
|
||||
@interface GDTCORStoredEvent : NSObject <NSSecureCoding>
|
||||
|
||||
/** The data future representing the original event's transport bytes. */
|
||||
@property(readonly, nonatomic) GDTDataFuture *dataFuture;
|
||||
@property(readonly, nonatomic) GDTCORDataFuture *dataFuture;
|
||||
|
||||
/** The mapping identifier, to allow backends to map the transport bytes to a proto. */
|
||||
@property(readonly, nonatomic) NSString *mappingID;
|
||||
@@ -34,10 +34,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property(readonly, nonatomic) NSNumber *target;
|
||||
|
||||
/** The quality of service tier this event belongs to. */
|
||||
@property(readonly, nonatomic) GDTEventQoS qosTier;
|
||||
@property(readonly, nonatomic) GDTCOREventQoS qosTier;
|
||||
|
||||
/** The clock snapshot at the time of the event. */
|
||||
@property(readonly, nonatomic) GDTClock *clockSnapshot;
|
||||
@property(readonly, nonatomic) GDTCORClock *clockSnapshot;
|
||||
|
||||
/** A dictionary provided to aid prioritizers by allowing the passing of arbitrary data.
|
||||
*
|
||||
@@ -51,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* @param dataFuture The dataFuture this event represents.
|
||||
* @return An instance of this class.
|
||||
*/
|
||||
- (instancetype)initWithEvent:(GDTEvent *)event dataFuture:(GDTDataFuture *)dataFuture;
|
||||
- (instancetype)initWithEvent:(GDTCOREvent *)event dataFuture:(GDTCORDataFuture *)dataFuture;
|
||||
|
||||
@end
|
||||
|
||||
+3
-3
@@ -19,11 +19,11 @@
|
||||
/** 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, GDTTarget) {
|
||||
typedef NS_ENUM(NSInteger, GDTCORTarget) {
|
||||
|
||||
/** A target only used in testing. */
|
||||
kGDTTargetTest = 999,
|
||||
kGDTCORTargetTest = 999,
|
||||
|
||||
/** The CCT target. */
|
||||
kGDTTargetCCT = 1000,
|
||||
kGDTCORTargetCCT = 1000,
|
||||
};
|
||||
+7
-7
@@ -16,13 +16,13 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTEventTransformer.h>
|
||||
#import <GoogleDataTransport/GDTCOREventTransformer.h>
|
||||
|
||||
@class GDTEvent;
|
||||
@class GDTCOREvent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTTransport : NSObject
|
||||
@interface GDTCORTransport : NSObject
|
||||
|
||||
// Please use the designated initializer.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
@@ -36,7 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* @return A transport that will send events.
|
||||
*/
|
||||
- (instancetype)initWithMappingID:(NSString *)mappingID
|
||||
transformers:(nullable NSArray<id<GDTEventTransformer>> *)transformers
|
||||
transformers:(nullable NSArray<id<GDTCOREventTransformer>> *)transformers
|
||||
target:(NSInteger)target NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority,
|
||||
@@ -46,7 +46,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*
|
||||
* @param event The event to send.
|
||||
*/
|
||||
- (void)sendTelemetryEvent:(GDTEvent *)event;
|
||||
- (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.
|
||||
@@ -55,13 +55,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*
|
||||
* @param event The event to send.
|
||||
*/
|
||||
- (void)sendDataEvent:(GDTEvent *)event;
|
||||
- (void)sendDataEvent:(GDTCOREvent *)event;
|
||||
|
||||
/** Creates an event for use by this transport.
|
||||
*
|
||||
* @return An event that is suited for use by this transport.
|
||||
*/
|
||||
- (GDTEvent *)eventForTransport;
|
||||
- (GDTCOREvent *)eventForTransport;
|
||||
|
||||
@end
|
||||
|
||||
+13
-13
@@ -16,14 +16,14 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTTargets.h>
|
||||
#import <GoogleDataTransport/GDTCORTargets.h>
|
||||
|
||||
@class GDTClock;
|
||||
@class GDTStoredEvent;
|
||||
@class GDTUploadPackage;
|
||||
@class GDTCORClock;
|
||||
@class GDTCORStoredEvent;
|
||||
@class GDTCORUploadPackage;
|
||||
|
||||
/** A protocol that allows a handler to respond to package lifecycle events. */
|
||||
@protocol GDTUploadPackageProtocol <NSObject>
|
||||
@protocol GDTCORUploadPackageProtocol <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
@@ -33,37 +33,37 @@
|
||||
*
|
||||
* @param package The package that has expired.
|
||||
*/
|
||||
- (void)packageExpired:(GDTUploadPackage *)package;
|
||||
- (void)packageExpired:(GDTCORUploadPackage *)package;
|
||||
|
||||
/** Indicates that the package was successfully delivered.
|
||||
*
|
||||
* @param package The package that was delivered.
|
||||
*/
|
||||
- (void)packageDelivered:(GDTUploadPackage *)package successful:(BOOL)successful;
|
||||
- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful;
|
||||
|
||||
@end
|
||||
|
||||
/** This class is a container that's handed off to uploaders. */
|
||||
@interface GDTUploadPackage : NSObject <NSSecureCoding>
|
||||
@interface GDTCORUploadPackage : NSObject <NSSecureCoding>
|
||||
|
||||
/** The set of stored events in this upload package. */
|
||||
@property(nonatomic) NSSet<GDTStoredEvent *> *events;
|
||||
@property(nonatomic) NSSet<GDTCORStoredEvent *> *events;
|
||||
|
||||
/** The expiration time. If [[GDTClock snapshot] isAfter:deliverByTime] this package has expired.
|
||||
/** The expiration time. If [[GDTCORClock snapshot] isAfter:deliverByTime] this package has expired.
|
||||
*
|
||||
* @note By default, the expiration time will be 3 minutes from creation.
|
||||
*/
|
||||
@property(nonatomic) GDTClock *deliverByTime;
|
||||
@property(nonatomic) GDTCORClock *deliverByTime;
|
||||
|
||||
/** The target of this package. */
|
||||
@property(nonatomic, readonly) GDTTarget target;
|
||||
@property(nonatomic, readonly) GDTCORTarget target;
|
||||
|
||||
/** Initializes a package instance.
|
||||
*
|
||||
* @param target The target/destination of this package.
|
||||
* @return An instance of this class.
|
||||
*/
|
||||
- (instancetype)initWithTarget:(GDTTarget)target NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithTarget:(GDTCORTarget)target NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
// Please use the designated initializer.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+8
-8
@@ -16,16 +16,16 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <GoogleDataTransport/GDTClock.h>
|
||||
#import <GoogleDataTransport/GDTLifecycle.h>
|
||||
#import <GoogleDataTransport/GDTPrioritizer.h>
|
||||
#import <GoogleDataTransport/GDTTargets.h>
|
||||
#import <GoogleDataTransport/GDTUploadPackage.h>
|
||||
#import <GoogleDataTransport/GDTCORClock.h>
|
||||
#import <GoogleDataTransport/GDTCORLifecycle.h>
|
||||
#import <GoogleDataTransport/GDTCORPrioritizer.h>
|
||||
#import <GoogleDataTransport/GDTCORTargets.h>
|
||||
#import <GoogleDataTransport/GDTCORUploadPackage.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This protocol defines the common interface for uploader implementations. */
|
||||
@protocol GDTUploader <NSObject, GDTLifecycleProtocol, GDTUploadPackageProtocol>
|
||||
@protocol GDTCORUploader <NSObject, GDTCORLifecycleProtocol, GDTCORUploadPackageProtocol>
|
||||
|
||||
@required
|
||||
|
||||
@@ -34,13 +34,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* @param conditions The conditions that the upload attempt is likely to occur under.
|
||||
* @return YES if the uploader can make an upload attempt, NO otherwise.
|
||||
*/
|
||||
- (BOOL)readyToUploadWithConditions:(GDTUploadConditions)conditions;
|
||||
- (BOOL)readyToUploadWithConditions:(GDTCORUploadConditions)conditions;
|
||||
|
||||
/** Uploads events to the backend using this specific backend's chosen format.
|
||||
*
|
||||
* @param package The event package to upload. Make sure to call -completeDelivery.
|
||||
*/
|
||||
- (void)uploadPackage:(GDTUploadPackage *)package;
|
||||
- (void)uploadPackage:(GDTCORUploadPackage *)package;
|
||||
|
||||
@end
|
||||
|
||||
+14
-14
@@ -14,17 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTClock.h"
|
||||
#import "GDTConsoleLogger.h"
|
||||
#import "GDTDataFuture.h"
|
||||
#import "GDTEvent.h"
|
||||
#import "GDTEventDataObject.h"
|
||||
#import "GDTEventTransformer.h"
|
||||
#import "GDTLifecycle.h"
|
||||
#import "GDTPrioritizer.h"
|
||||
#import "GDTRegistrar.h"
|
||||
#import "GDTStoredEvent.h"
|
||||
#import "GDTTargets.h"
|
||||
#import "GDTTransport.h"
|
||||
#import "GDTUploadPackage.h"
|
||||
#import "GDTUploader.h"
|
||||
#import "GDTCORClock.h"
|
||||
#import "GDTCORConsoleLogger.h"
|
||||
#import "GDTCORDataFuture.h"
|
||||
#import "GDTCOREvent.h"
|
||||
#import "GDTCOREventDataObject.h"
|
||||
#import "GDTCOREventTransformer.h"
|
||||
#import "GDTCORLifecycle.h"
|
||||
#import "GDTCORPrioritizer.h"
|
||||
#import "GDTCORRegistrar.h"
|
||||
#import "GDTCORStoredEvent.h"
|
||||
#import "GDTCORTargets.h"
|
||||
#import "GDTCORTransport.h"
|
||||
#import "GDTCORUploadPackage.h"
|
||||
#import "GDTCORUploader.h"
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* 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 "GDTLibrary/Public/GDTLifecycle.h"
|
||||
|
||||
#import <GoogleDataTransport/GDTEvent.h>
|
||||
|
||||
#import "GDTLibrary/Private/GDTRegistrar_Private.h"
|
||||
#import "GDTLibrary/Private/GDTStorage_Private.h"
|
||||
#import "GDTLibrary/Private/GDTTransformer_Private.h"
|
||||
#import "GDTLibrary/Private/GDTUploadCoordinator.h"
|
||||
|
||||
@implementation GDTLifecycle
|
||||
|
||||
+ (void)load {
|
||||
[self sharedInstance];
|
||||
}
|
||||
|
||||
/** Creates/returns the singleton instance of this class.
|
||||
*
|
||||
* @return The singleton instance of this class.
|
||||
*/
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTLifecycle *sharedInstance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[GDTLifecycle alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(applicationDidEnterBackground:)
|
||||
name:kGDTApplicationDidEnterBackgroundNotification
|
||||
object:nil];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(applicationWillEnterForeground:)
|
||||
name:kGDTApplicationWillEnterForegroundNotification
|
||||
object:nil];
|
||||
|
||||
NSString *name = kGDTApplicationWillTerminateNotification;
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(applicationWillTerminate:)
|
||||
name:name
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(NSNotification *)notification {
|
||||
GDTApplication *application = [GDTApplication sharedApplication];
|
||||
if ([[GDTTransformer sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[[GDTTransformer sharedInstance] appWillBackground:application];
|
||||
}
|
||||
if ([[GDTStorage sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[[GDTStorage sharedInstance] appWillBackground:application];
|
||||
}
|
||||
if ([[GDTUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[[GDTUploadCoordinator sharedInstance] appWillBackground:application];
|
||||
}
|
||||
if ([[GDTRegistrar sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[[GDTRegistrar sharedInstance] appWillBackground:application];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(NSNotification *)notification {
|
||||
GDTApplication *application = [GDTApplication sharedApplication];
|
||||
if ([[GDTTransformer sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[[GDTTransformer sharedInstance] appWillForeground:application];
|
||||
}
|
||||
if ([[GDTStorage sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[[GDTStorage sharedInstance] appWillForeground:application];
|
||||
}
|
||||
if ([[GDTUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[[GDTUploadCoordinator sharedInstance] appWillForeground:application];
|
||||
}
|
||||
if ([[GDTRegistrar sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[[GDTRegistrar sharedInstance] appWillForeground:application];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)notification {
|
||||
GDTApplication *application = [GDTApplication sharedApplication];
|
||||
if ([[GDTTransformer sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[[GDTTransformer sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
if ([[GDTStorage sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[[GDTStorage sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
if ([[GDTUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[[GDTUploadCoordinator sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
if ([[GDTRegistrar sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[[GDTRegistrar sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,256 +0,0 @@
|
||||
/*
|
||||
* 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 "GDTLibrary/Private/GDTStorage.h"
|
||||
#import "GDTLibrary/Private/GDTStorage_Private.h"
|
||||
|
||||
#import <GoogleDataTransport/GDTConsoleLogger.h>
|
||||
#import <GoogleDataTransport/GDTLifecycle.h>
|
||||
#import <GoogleDataTransport/GDTPrioritizer.h>
|
||||
#import <GoogleDataTransport/GDTStoredEvent.h>
|
||||
|
||||
#import "GDTLibrary/Private/GDTAssert.h"
|
||||
#import "GDTLibrary/Private/GDTEvent_Private.h"
|
||||
#import "GDTLibrary/Private/GDTRegistrar_Private.h"
|
||||
#import "GDTLibrary/Private/GDTUploadCoordinator.h"
|
||||
|
||||
/** Creates and/or returns a singleton NSString that is the shared storage path.
|
||||
*
|
||||
* @return The SDK event storage path.
|
||||
*/
|
||||
static NSString *GDTStoragePath() {
|
||||
static NSString *storagePath;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *cachePath =
|
||||
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
|
||||
storagePath = [NSString stringWithFormat:@"%@/google-sdks-events", cachePath];
|
||||
});
|
||||
return storagePath;
|
||||
}
|
||||
|
||||
@implementation GDTStorage
|
||||
|
||||
+ (NSString *)archivePath {
|
||||
static NSString *archivePath;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
archivePath = [GDTStoragePath() stringByAppendingPathComponent:@"GDTStorageArchive"];
|
||||
});
|
||||
return archivePath;
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTStorage *sharedStorage;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedStorage = [[GDTStorage alloc] init];
|
||||
});
|
||||
return sharedStorage;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_storageQueue = dispatch_queue_create("com.google.GDTStorage", DISPATCH_QUEUE_SERIAL);
|
||||
_targetToEventSet = [[NSMutableDictionary alloc] init];
|
||||
_storedEvents = [[NSMutableOrderedSet alloc] init];
|
||||
_uploadCoordinator = [GDTUploadCoordinator sharedInstance];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)storeEvent:(GDTEvent *)event {
|
||||
[self createEventDirectoryIfNotExists];
|
||||
|
||||
__block GDTBackgroundIdentifier bgID = GDTBackgroundIdentifierInvalid;
|
||||
if (_runningInBackground) {
|
||||
bgID = [[GDTApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
|
||||
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
|
||||
}];
|
||||
}
|
||||
|
||||
dispatch_async(_storageQueue, ^{
|
||||
// Check that a backend implementation is available for this target.
|
||||
NSInteger target = event.target;
|
||||
|
||||
// Check that a prioritizer is available for this target.
|
||||
id<GDTPrioritizer> prioritizer = [GDTRegistrar sharedInstance].targetToPrioritizer[@(target)];
|
||||
GDTAssert(prioritizer, @"There's no prioritizer registered for the given target.");
|
||||
|
||||
// Write the transport bytes to disk, get a filename.
|
||||
GDTAssert(event.dataObjectTransportBytes, @"The event should have been serialized to bytes");
|
||||
NSURL *eventFile = [self saveEventBytesToDisk:event.dataObjectTransportBytes
|
||||
eventHash:event.hash];
|
||||
GDTDataFuture *dataFuture = [[GDTDataFuture alloc] initWithFileURL:eventFile];
|
||||
GDTStoredEvent *storedEvent = [event storedEventWithDataFuture:dataFuture];
|
||||
|
||||
// Add event to tracking collections.
|
||||
[self addEventToTrackingCollections:storedEvent];
|
||||
|
||||
// Have the prioritizer prioritize the event.
|
||||
[prioritizer prioritizeEvent:storedEvent];
|
||||
|
||||
// Check the QoS, if it's high priority, notify the target that it has a high priority event.
|
||||
if (event.qosTier == GDTEventQoSFast) {
|
||||
[self.uploadCoordinator forceUploadForTarget:target];
|
||||
}
|
||||
|
||||
// If running in the background, save state to disk and end the associated background task.
|
||||
if (bgID != GDTBackgroundIdentifierInvalid) {
|
||||
[NSKeyedArchiver archiveRootObject:self toFile:[GDTStorage archivePath]];
|
||||
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)removeEvents:(NSSet<GDTStoredEvent *> *)events {
|
||||
NSSet<GDTStoredEvent *> *eventsToRemove = [events copy];
|
||||
dispatch_async(_storageQueue, ^{
|
||||
for (GDTStoredEvent *event in eventsToRemove) {
|
||||
// Remove from disk, first and foremost.
|
||||
NSError *error;
|
||||
if (event.dataFuture.fileURL) {
|
||||
NSURL *fileURL = event.dataFuture.fileURL;
|
||||
[[NSFileManager defaultManager] removeItemAtURL:fileURL error:&error];
|
||||
GDTAssert(error == nil, @"There was an error removing an event file: %@", error);
|
||||
}
|
||||
|
||||
// Remove from the tracking collections.
|
||||
[self.storedEvents removeObject:event];
|
||||
[self.targetToEventSet[event.target] removeObject:event];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Private helper methods
|
||||
|
||||
/** Creates the storage directory if it does not exist. */
|
||||
- (void)createEventDirectoryIfNotExists {
|
||||
NSError *error;
|
||||
BOOL result = [[NSFileManager defaultManager] createDirectoryAtPath:GDTStoragePath()
|
||||
withIntermediateDirectories:YES
|
||||
attributes:0
|
||||
error:&error];
|
||||
if (!result || error) {
|
||||
GDTLogError(GDTMCEDirectoryCreationError, @"Error creating the directory: %@", error);
|
||||
}
|
||||
}
|
||||
|
||||
/** Saves the event's dataObjectTransportBytes to a file using NSData mechanisms.
|
||||
*
|
||||
* @note This method should only be called from a method within a block on _storageQueue to maintain
|
||||
* thread safety.
|
||||
*
|
||||
* @param transportBytes The transport bytes of the event.
|
||||
* @param eventHash The hash value of the event.
|
||||
* @return The filename
|
||||
*/
|
||||
- (NSURL *)saveEventBytesToDisk:(NSData *)transportBytes eventHash:(NSUInteger)eventHash {
|
||||
NSString *storagePath = GDTStoragePath();
|
||||
NSString *event = [NSString stringWithFormat:@"event-%lu", (unsigned long)eventHash];
|
||||
NSURL *eventFilePath = [NSURL fileURLWithPath:[storagePath stringByAppendingPathComponent:event]];
|
||||
|
||||
GDTAssert(![[NSFileManager defaultManager] fileExistsAtPath:eventFilePath.path],
|
||||
@"An event shouldn't already exist at this path: %@", eventFilePath.path);
|
||||
|
||||
BOOL writingSuccess = [transportBytes writeToURL:eventFilePath atomically:YES];
|
||||
if (!writingSuccess) {
|
||||
GDTLogError(GDTMCEFileWriteError, @"An event file could not be written: %@", eventFilePath);
|
||||
}
|
||||
|
||||
return eventFilePath;
|
||||
}
|
||||
|
||||
/** Adds the event to internal tracking collections.
|
||||
*
|
||||
* @note This method should only be called from a method within a block on _storageQueue to maintain
|
||||
* thread safety.
|
||||
*
|
||||
* @param event The event to track.
|
||||
*/
|
||||
- (void)addEventToTrackingCollections:(GDTStoredEvent *)event {
|
||||
[_storedEvents addObject:event];
|
||||
NSMutableSet<GDTStoredEvent *> *events = self.targetToEventSet[event.target];
|
||||
events = events ? events : [[NSMutableSet alloc] init];
|
||||
[events addObject:event];
|
||||
_targetToEventSet[event.target] = events;
|
||||
}
|
||||
|
||||
#pragma mark - GDTLifecycleProtocol
|
||||
|
||||
- (void)appWillForeground:(GDTApplication *)app {
|
||||
[NSKeyedUnarchiver unarchiveObjectWithFile:[GDTStorage archivePath]];
|
||||
self->_runningInBackground = NO;
|
||||
}
|
||||
|
||||
- (void)appWillBackground:(GDTApplication *)app {
|
||||
self->_runningInBackground = YES;
|
||||
[NSKeyedArchiver archiveRootObject:self toFile:[GDTStorage archivePath]];
|
||||
// Create an immediate background task to run until the end of the current queue of work.
|
||||
__block GDTBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
|
||||
[app endBackgroundTask:bgID];
|
||||
}];
|
||||
dispatch_async(_storageQueue, ^{
|
||||
[app endBackgroundTask:bgID];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillTerminate:(GDTApplication *)application {
|
||||
[NSKeyedArchiver archiveRootObject:self toFile:[GDTStorage archivePath]];
|
||||
}
|
||||
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
/** The NSKeyedCoder key for the storedEvents property. */
|
||||
static NSString *const kGDTStorageStoredEventsKey = @"GDTStorageStoredEventsKey";
|
||||
|
||||
/** The NSKeyedCoder key for the targetToEventSet property. */
|
||||
static NSString *const kGDTStorageTargetToEventSetKey = @"GDTStorageTargetToEventSetKey";
|
||||
|
||||
/** The NSKeyedCoder key for the uploadCoordinator property. */
|
||||
static NSString *const kGDTStorageUploadCoordinatorKey = @"GDTStorageUploadCoordinatorKey";
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
// Create the singleton and populate its ivars.
|
||||
GDTStorage *sharedInstance = [self.class sharedInstance];
|
||||
dispatch_sync(sharedInstance.storageQueue, ^{
|
||||
sharedInstance->_storedEvents = [aDecoder decodeObjectOfClass:[NSMutableOrderedSet class]
|
||||
forKey:kGDTStorageStoredEventsKey];
|
||||
sharedInstance->_targetToEventSet =
|
||||
[aDecoder decodeObjectOfClass:[NSMutableDictionary class]
|
||||
forKey:kGDTStorageTargetToEventSetKey];
|
||||
sharedInstance->_uploadCoordinator =
|
||||
[aDecoder decodeObjectOfClass:[GDTUploadCoordinator class]
|
||||
forKey:kGDTStorageUploadCoordinatorKey];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||
GDTStorage *sharedInstance = [self.class sharedInstance];
|
||||
dispatch_sync(sharedInstance.storageQueue, ^{
|
||||
[aCoder encodeObject:sharedInstance->_storedEvents forKey:kGDTStorageStoredEventsKey];
|
||||
[aCoder encodeObject:sharedInstance->_targetToEventSet forKey:kGDTStorageTargetToEventSetKey];
|
||||
[aCoder encodeObject:sharedInstance->_uploadCoordinator forKey:kGDTStorageUploadCoordinatorKey];
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* 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 "GDTLibrary/Private/GDTTransformer.h"
|
||||
#import "GDTLibrary/Private/GDTTransformer_Private.h"
|
||||
|
||||
#import <GoogleDataTransport/GDTConsoleLogger.h>
|
||||
#import <GoogleDataTransport/GDTEventTransformer.h>
|
||||
#import <GoogleDataTransport/GDTLifecycle.h>
|
||||
|
||||
#import "GDTLibrary/Private/GDTAssert.h"
|
||||
#import "GDTLibrary/Private/GDTStorage.h"
|
||||
|
||||
@implementation GDTTransformer
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTTransformer *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.GDTTransformer", DISPATCH_QUEUE_SERIAL);
|
||||
_storageInstance = [GDTStorage sharedInstance];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)transformEvent:(GDTEvent *)event
|
||||
withTransformers:(NSArray<id<GDTEventTransformer>> *)transformers {
|
||||
GDTAssert(event, @"You can't write a nil event");
|
||||
|
||||
__block GDTBackgroundIdentifier bgID = GDTBackgroundIdentifierInvalid;
|
||||
if (_runningInBackground) {
|
||||
bgID = [[GDTApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
|
||||
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
|
||||
}];
|
||||
}
|
||||
dispatch_async(_eventWritingQueue, ^{
|
||||
GDTEvent *transformedEvent = event;
|
||||
for (id<GDTEventTransformer> transformer in transformers) {
|
||||
if ([transformer respondsToSelector:@selector(transform:)]) {
|
||||
transformedEvent = [transformer transform:transformedEvent];
|
||||
if (!transformedEvent) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
GDTLogError(GDTMCETransformerDoesntImplementTransform,
|
||||
@"Transformer doesn't implement transform: %@", transformer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
[self.storageInstance storeEvent:transformedEvent];
|
||||
if (self->_runningInBackground) {
|
||||
[[GDTApplication sharedApplication] endBackgroundTask:bgID];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - GDTLifecycleProtocol
|
||||
|
||||
- (void)appWillForeground:(GDTApplication *)app {
|
||||
dispatch_async(_eventWritingQueue, ^{
|
||||
self->_runningInBackground = NO;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillBackground:(GDTApplication *)app {
|
||||
// Create an immediate background task to run until the end of the current queue of work.
|
||||
__block GDTBackgroundIdentifier bgID = [app beginBackgroundTaskWithExpirationHandler:^{
|
||||
[app endBackgroundTask:bgID];
|
||||
}];
|
||||
dispatch_async(_eventWritingQueue, ^{
|
||||
[app endBackgroundTask:bgID];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillTerminate:(GDTApplication *)application {
|
||||
// Flush the queue immediately.
|
||||
dispatch_sync(_eventWritingQueue, ^{
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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/GDTTransport.h>
|
||||
#import "GDTLibrary/Private/GDTTransport_Private.h"
|
||||
|
||||
#import <GoogleDataTransport/GDTClock.h>
|
||||
#import <GoogleDataTransport/GDTEvent.h>
|
||||
|
||||
#import "GDTLibrary/Private/GDTAssert.h"
|
||||
#import "GDTLibrary/Private/GDTTransformer.h"
|
||||
|
||||
@implementation GDTTransport
|
||||
|
||||
- (instancetype)initWithMappingID:(NSString *)mappingID
|
||||
transformers:(nullable NSArray<id<GDTEventTransformer>> *)transformers
|
||||
target:(NSInteger)target {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
GDTAssert(mappingID.length > 0, @"A mapping ID cannot be nil or empty");
|
||||
GDTAssert(target > 0, @"A target cannot be negative or 0");
|
||||
_mappingID = mappingID;
|
||||
_transformers = transformers;
|
||||
_target = target;
|
||||
_transformerInstance = [GDTTransformer sharedInstance];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)sendTelemetryEvent:(GDTEvent *)event {
|
||||
// TODO: Determine if sending an event before registration is allowed.
|
||||
GDTAssert(event, @"You can't send a nil event");
|
||||
GDTEvent *copiedEvent = [event copy];
|
||||
copiedEvent.qosTier = GDTEventQoSTelemetry;
|
||||
copiedEvent.clockSnapshot = [GDTClock snapshot];
|
||||
[self.transformerInstance transformEvent:copiedEvent withTransformers:_transformers];
|
||||
}
|
||||
|
||||
- (void)sendDataEvent:(GDTEvent *)event {
|
||||
// TODO: Determine if sending an event before registration is allowed.
|
||||
GDTAssert(event, @"You can't send a nil event");
|
||||
GDTAssert(event.qosTier != GDTEventQoSTelemetry, @"Use -sendTelemetryEvent, please.");
|
||||
GDTEvent *copiedEvent = [event copy];
|
||||
copiedEvent.clockSnapshot = [GDTClock snapshot];
|
||||
[self.transformerInstance transformEvent:copiedEvent withTransformers:_transformers];
|
||||
}
|
||||
|
||||
- (GDTEvent *)eventForTransport {
|
||||
return [[GDTEvent alloc] initWithMappingID:_mappingID target:_target];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
/** A block type that could be run instead of NSAssert. No return type, no params. */
|
||||
typedef void (^GDTAssertionBlock)(void);
|
||||
|
||||
/** Returns the result of executing a soft-linked method present in unit tests that allows a block
|
||||
* to be run in lieu of a call to NSAssert. This helps ameliorate issues with catching exceptions
|
||||
* that occur on a dispatch_queue.
|
||||
*
|
||||
* @return A block that can be run instead of calling NSAssert, or nil.
|
||||
*/
|
||||
FOUNDATION_EXPORT GDTAssertionBlock _Nullable GDTAssertionBlockToRunInsteadOfNSAssert(void);
|
||||
|
||||
#if !defined(NS_BLOCK_ASSERTIONS)
|
||||
|
||||
/** Asserts using NSAssert, unless a block was specified to be run instead.
|
||||
*
|
||||
* @param condition The condition you'd expect to be YES.
|
||||
*/
|
||||
#define GDTAssert(condition, ...) \
|
||||
do { \
|
||||
if (__builtin_expect(!(condition), 0)) { \
|
||||
GDTAssertionBlock assertionBlock = GDTAssertionBlockToRunInsteadOfNSAssert(); \
|
||||
if (assertionBlock) { \
|
||||
assertionBlock(); \
|
||||
} else { \
|
||||
NSAssert(condition, __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#else
|
||||
|
||||
#define GDTAssert(condition, ...) \
|
||||
do { \
|
||||
} while (0);
|
||||
|
||||
#endif // !defined(NS_BLOCK_ASSERTIONS)
|
||||
Generated
+17
-10
@@ -1,9 +1,10 @@
|
||||
# Firebase iOS Open Source Development [](https://travis-ci.org/firebase/firebase-ios-sdk)
|
||||
|
||||
This repository contains a subset of the Firebase iOS SDK source. It currently
|
||||
includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore,
|
||||
FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
|
||||
FirebaseInAppMessagingDisplay, FirebaseMessaging and FirebaseStorage.
|
||||
includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase,
|
||||
FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging,
|
||||
FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and
|
||||
FirebaseStorage.
|
||||
|
||||
The repository also includes GoogleUtilities source. The
|
||||
[GoogleUtilities](GoogleUtilities/README.md) pod is
|
||||
@@ -80,9 +81,8 @@ For the pod that you want to develop:
|
||||
|
||||
`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open`
|
||||
|
||||
Firestore and Functions have self contained Xcode projects. See
|
||||
[Firestore/README.md](Firestore/README.md) and
|
||||
[Functions/README.md](Functions/README.md).
|
||||
Firestore has a self contained Xcode project. See
|
||||
[Firestore/README.md](Firestore/README.md).
|
||||
|
||||
### Adding a New Firebase Pod
|
||||
|
||||
@@ -99,13 +99,17 @@ Travis will verify that any code changes are done in a style compliant way. Inst
|
||||
These commands will get the right versions:
|
||||
|
||||
```
|
||||
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/773cb75d360b58f32048f5964038d09825a507c8/Formula/clang-format.rb
|
||||
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/3dfea1004e0736754bbf49673cca8aaed8a94089/Formula/swiftformat.rb
|
||||
brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb
|
||||
brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb
|
||||
```
|
||||
|
||||
Note: if you already have a newer version of these installed you may need to
|
||||
`brew switch` to this version.
|
||||
|
||||
To update this section, find the versions of clang-format and swiftformat.rb to
|
||||
match the versions in the CI failure logs
|
||||
[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula).
|
||||
|
||||
### Running Unit Tests
|
||||
|
||||
Select a scheme and press Command-u to build a component and run its unit tests.
|
||||
@@ -179,8 +183,9 @@ very grateful! We'd like to empower as many developers as we can to be able to
|
||||
participate in the Firebase community.
|
||||
|
||||
### macOS and tvOS
|
||||
Thanks to contributions from the community, FirebaseAuth, FirebaseCore, FirebaseDatabase, FirebaseMessaging,
|
||||
FirebaseFirestore, FirebaseFunctions and FirebaseStorage now compile, run unit tests, and work on
|
||||
Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore,
|
||||
FirebaseDatabase, FirebaseMessaging, FirebaseFirestore,
|
||||
FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on
|
||||
macOS and tvOS.
|
||||
|
||||
For tvOS, checkout the [Sample](Example/tvOSSample).
|
||||
@@ -195,12 +200,14 @@ Note that the Firebase pod is not available for macOS and tvOS.
|
||||
To install, add a subset of the following to the Podfile:
|
||||
|
||||
```
|
||||
pod 'FirebaseABTesting'
|
||||
pod 'FirebaseAuth'
|
||||
pod 'FirebaseCore'
|
||||
pod 'FirebaseDatabase'
|
||||
pod 'FirebaseFirestore'
|
||||
pod 'FirebaseFunctions'
|
||||
pod 'FirebaseMessaging'
|
||||
pod 'FirebaseRemoteConfig'
|
||||
pod 'FirebaseStorage'
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user