Skip to content

Commit 8322b22

Browse files
authored
Make the prioritizer save state between app launches (#5120)
1 parent dd70b46 commit 8322b22

File tree

2 files changed

+138
-1
lines changed

2 files changed

+138
-1
lines changed

GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,21 @@
2525

2626
const static int64_t kMillisPerDay = 8.64e+7;
2727

28+
/** Creates and/or returns a singleton NSString that is the NSCoding file location.
29+
*
30+
* @return The NSCoding file path.
31+
*/
32+
static NSString *ArchivePath() {
33+
static NSString *archivePath;
34+
static dispatch_once_t onceToken;
35+
dispatch_once(&onceToken, ^{
36+
NSString *cachePath =
37+
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
38+
archivePath = [NSString stringWithFormat:@"%@/google-sdks-events/GDTCCTPrioritizer", cachePath];
39+
});
40+
return archivePath;
41+
}
42+
2843
@implementation GDTCCTPrioritizer
2944

3045
+ (void)load {
@@ -34,6 +49,10 @@ + (void)load {
3449
[[GDTCORRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTCORTargetCSH];
3550
}
3651

52+
+ (BOOL)supportsSecureCoding {
53+
return YES;
54+
}
55+
3756
+ (instancetype)sharedInstance {
3857
static GDTCCTPrioritizer *sharedInstance;
3958
static dispatch_once_t onceToken;
@@ -238,9 +257,127 @@ typedef NS_ENUM(NSInteger, GDTCCTQoSTier) {
238257
}];
239258
}
240259

260+
#pragma mark - NSSecureCoding
261+
262+
/** NSSecureCoding key for the CCTEvents property. */
263+
static NSString *const GDTCCTUploaderCCTEventsKey = @"GDTCCTUploaderCCTEventsKey";
264+
265+
/** NSSecureCoding key for the CCTEvents property. */
266+
static NSString *const GDTCCTUploaderFLLEventsKey = @"GDTCCTUploaderFLLEventsKey";
267+
268+
/** NSSecureCoding key for the CCTEvents property. */
269+
static NSString *const GDTCCTUploaderCSHEventsKey = @"GDTCCTUploaderCSHEventsKey";
270+
271+
- (instancetype)initWithCoder:(NSCoder *)coder {
272+
GDTCCTPrioritizer *sharedInstance = [GDTCCTPrioritizer sharedInstance];
273+
if (sharedInstance) {
274+
NSSet *classes = [NSSet setWithObjects:[NSMutableSet class], [GDTCOREvent class], nil];
275+
NSMutableSet *decodedCCTEvents = [coder decodeObjectOfClasses:classes
276+
forKey:GDTCCTUploaderCCTEventsKey];
277+
if (decodedCCTEvents) {
278+
sharedInstance->_CCTEvents = decodedCCTEvents;
279+
}
280+
NSMutableSet *decodedFLLEvents = [coder decodeObjectOfClasses:classes
281+
forKey:GDTCCTUploaderFLLEventsKey];
282+
if (decodedFLLEvents) {
283+
sharedInstance->_FLLEvents = decodedFLLEvents;
284+
}
285+
NSMutableSet *decodedCSHEvents = [coder decodeObjectOfClasses:classes
286+
forKey:GDTCCTUploaderCSHEventsKey];
287+
if (decodedCSHEvents) {
288+
sharedInstance->_CSHEvents = decodedCSHEvents;
289+
}
290+
}
291+
return sharedInstance;
292+
}
293+
294+
- (void)encodeWithCoder:(NSCoder *)coder {
295+
GDTCCTPrioritizer *sharedInstance = [GDTCCTPrioritizer sharedInstance];
296+
NSMutableSet<GDTCOREvent *> *CCTEvents = sharedInstance->_CCTEvents;
297+
if (CCTEvents) {
298+
[coder encodeObject:CCTEvents forKey:GDTCCTUploaderCCTEventsKey];
299+
}
300+
NSMutableSet<GDTCOREvent *> *FLLEvents = sharedInstance->_FLLEvents;
301+
if (FLLEvents) {
302+
[coder encodeObject:FLLEvents forKey:GDTCCTUploaderFLLEventsKey];
303+
}
304+
NSMutableSet<GDTCOREvent *> *CSHEvents = sharedInstance->_CSHEvents;
305+
if (CSHEvents) {
306+
[coder encodeObject:CSHEvents forKey:GDTCCTUploaderCSHEventsKey];
307+
}
308+
}
309+
310+
#pragma mark - GDTCORLifecycleProtocol
311+
312+
- (void)appWillForeground:(GDTCORApplication *)app {
313+
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
314+
NSError *error;
315+
NSData *data = [NSData dataWithContentsOfFile:ArchivePath()];
316+
if (data) {
317+
[NSKeyedUnarchiver unarchivedObjectOfClass:[GDTCCTPrioritizer class]
318+
fromData:data
319+
error:&error];
320+
}
321+
} else {
322+
#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH
323+
[NSKeyedUnarchiver unarchiveObjectWithFile:ArchivePath()];
324+
#endif
325+
}
326+
}
327+
328+
- (void)appWillBackground:(GDTCORApplication *)app {
329+
dispatch_async(_queue, ^{
330+
// Immediately request a background task to run until the end of the current queue of work, and
331+
// cancel it once the work is done.
332+
__block GDTCORBackgroundIdentifier bgID =
333+
[app beginBackgroundTaskWithName:@"GDTStorage"
334+
expirationHandler:^{
335+
[app endBackgroundTask:bgID];
336+
bgID = GDTCORBackgroundIdentifierInvalid;
337+
}];
338+
339+
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
340+
NSError *error;
341+
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self
342+
requiringSecureCoding:YES
343+
error:&error];
344+
[data writeToFile:ArchivePath() atomically:YES];
345+
} else {
346+
#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH
347+
[NSKeyedArchiver archiveRootObject:self toFile:ArchivePath()];
348+
#endif
349+
}
350+
351+
// End the background task if it's still valid.
352+
[app endBackgroundTask:bgID];
353+
bgID = GDTCORBackgroundIdentifierInvalid;
354+
});
355+
}
356+
357+
- (void)appWillTerminate:(GDTCORApplication *)application {
358+
dispatch_sync(_queue, ^{
359+
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
360+
NSError *error;
361+
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self
362+
requiringSecureCoding:YES
363+
error:&error];
364+
[data writeToFile:ArchivePath() atomically:YES];
365+
} else {
366+
#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH
367+
[NSKeyedArchiver archiveRootObject:self toFile:ArchivePath()];
368+
#endif
369+
}
370+
});
371+
}
372+
241373
#pragma mark - GDTCORUploadPackageProtocol
242374

243375
- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful {
376+
// If sending the package wasn't successful, we should keep track of these events.
377+
if (!successful) {
378+
return;
379+
}
380+
244381
dispatch_async(_queue, ^{
245382
NSSet<GDTCOREvent *> *events = [package.events copy];
246383
for (GDTCOREvent *event in events) {

GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
NS_ASSUME_NONNULL_BEGIN
2525

2626
/** Manages the prioritization of events from GoogleDataTransport. */
27-
@interface GDTCCTPrioritizer : NSObject <GDTCORPrioritizer>
27+
@interface GDTCCTPrioritizer : NSObject <NSSecureCoding, GDTCORPrioritizer>
2828

2929
/** The queue on which this prioritizer operates. */
3030
@property(nonatomic) dispatch_queue_t queue;

0 commit comments

Comments
 (0)