| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- /*
- * 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/GDTCORUploadPackage.h"
- #import <GoogleDataTransport/GDTCORClock.h>
- #import <GoogleDataTransport/GDTCORConsoleLogger.h>
- #import "GDTCORLibrary/Private/GDTCORStorage_Private.h"
- #import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
- #import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h"
- @implementation GDTCORUploadPackage {
- /** If YES, the package's -completeDelivery method has been called. */
- BOOL _isDelivered;
- /** If YES, is being handled by the handler. */
- BOOL _isHandled;
- /** A timer that will regularly check to see whether this package has expired or not. */
- NSTimer *_expirationTimer;
- }
- - (instancetype)initWithTarget:(GDTCORTarget)target {
- self = [super init];
- if (self) {
- _target = target;
- _storage = [GDTCORStorage sharedInstance];
- _deliverByTime = [GDTCORClock clockSnapshotInTheFuture:180000];
- _handler = [GDTCORUploadCoordinator sharedInstance];
- _expirationTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
- target:self
- selector:@selector(checkIfPackageIsExpired:)
- userInfo:nil
- repeats:YES];
- }
- GDTCORLogDebug("Upload package created %@", self);
- return self;
- }
- - (instancetype)copy {
- GDTCORUploadPackage *newPackage = [[GDTCORUploadPackage alloc] initWithTarget:_target];
- newPackage->_events = [_events copy];
- GDTCORLogDebug("Copying UploadPackage %@ to %@", self, newPackage);
- return newPackage;
- }
- - (NSUInteger)hash {
- return [_events hash];
- }
- - (BOOL)isEqual:(id)object {
- return [self hash] == [object hash];
- }
- - (void)dealloc {
- [_expirationTimer invalidate];
- }
- - (void)setStorage:(GDTCORStorage *)storage {
- if (storage != _storage) {
- _storage = storage;
- }
- }
- - (void)completeDelivery {
- if (_isDelivered) {
- GDTCORLogError(GDTCORMCEDeliverTwice, @"%@",
- @"It's an API violation to call -completeDelivery twice.");
- }
- _isDelivered = YES;
- if (!_isHandled && _handler &&
- [_handler respondsToSelector:@selector(packageDelivered:successful:)]) {
- [_expirationTimer invalidate];
- _isHandled = YES;
- [_handler packageDelivered:self successful:YES];
- }
- GDTCORLogDebug("Upload package delivered: %@", self);
- }
- - (void)retryDeliveryInTheFuture {
- if (!_isHandled && _handler &&
- [_handler respondsToSelector:@selector(packageDelivered:successful:)]) {
- [_expirationTimer invalidate];
- _isHandled = YES;
- [_handler packageDelivered:self successful:NO];
- }
- GDTCORLogDebug("Upload package will retry in the future: %@", self);
- }
- - (void)checkIfPackageIsExpired:(NSTimer *)timer {
- if ([[GDTCORClock snapshot] isAfter:_deliverByTime]) {
- if (_handler && [_handler respondsToSelector:@selector(packageExpired:)]) {
- _isHandled = YES;
- [_expirationTimer invalidate];
- GDTCORLogDebug("Upload package expired: %@", self);
- [_handler packageExpired:self];
- }
- }
- }
- #pragma mark - NSSecureCoding
- /** The keyed archiver key for the events property. */
- static NSString *const kEventsKey = @"GDTCORUploadPackageEventsKey";
- /** The keyed archiver key for the _isHandled property. */
- static NSString *const kDeliverByTimeKey = @"GDTCORUploadPackageDeliveryByTimeKey";
- /** The keyed archiver key for the _isHandled ivar. */
- static NSString *const kIsHandledKey = @"GDTCORUploadPackageIsHandledKey";
- /** The keyed archiver key for the handler property. */
- static NSString *const kHandlerKey = @"GDTCORUploadPackageHandlerKey";
- /** The keyed archiver key for the target property. */
- static NSString *const kTargetKey = @"GDTCORUploadPackageTargetKey";
- + (BOOL)supportsSecureCoding {
- return YES;
- }
- - (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
- [aCoder encodeObject:_events forKey:kEventsKey];
- [aCoder encodeObject:_deliverByTime forKey:kDeliverByTimeKey];
- [aCoder encodeBool:_isHandled forKey:kIsHandledKey];
- [aCoder encodeObject:_handler forKey:kHandlerKey];
- [aCoder encodeInteger:_target forKey:kTargetKey];
- }
- - (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
- // Sets a global translation mapping to decode GDTCORStoredEvent objects encoded as instances of
- // GDTCOREvent instead.
- [NSKeyedUnarchiver setClass:[GDTCOREvent class] forClassName:@"GDTCORStoredEvent"];
- GDTCORTarget target = [aDecoder decodeIntegerForKey:kTargetKey];
- self = [self initWithTarget:target];
- if (self) {
- NSSet *classes = [NSSet setWithObjects:[NSSet class], [GDTCOREvent class], nil];
- _events = [aDecoder decodeObjectOfClasses:classes forKey:kEventsKey];
- _deliverByTime = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kDeliverByTimeKey];
- _isHandled = [aDecoder decodeBoolForKey:kIsHandledKey];
- // _handler isn't technically NSSecureCoding, because we don't know the class of this object.
- // but it gets decoded anyway.
- }
- return self;
- }
- @end
|