diff options
Diffstat (limited to 'Firebase/Utilities/Network')
-rw-r--r-- | Firebase/Utilities/Network/GULMutableDictionary.m | 97 | ||||
-rw-r--r-- | Firebase/Utilities/Network/GULNetwork.m | 388 | ||||
-rw-r--r-- | Firebase/Utilities/Network/GULNetworkConstants.m | 40 | ||||
-rw-r--r-- | Firebase/Utilities/Network/GULNetworkURLSession.m | 669 | ||||
-rw-r--r-- | Firebase/Utilities/Network/Private/GULMutableDictionary.h | 46 | ||||
-rw-r--r-- | Firebase/Utilities/Network/Private/GULNetwork.h | 87 | ||||
-rw-r--r-- | Firebase/Utilities/Network/Private/GULNetworkConstants.h | 79 | ||||
-rw-r--r-- | Firebase/Utilities/Network/Private/GULNetworkLoggerProtocol.h | 51 | ||||
-rw-r--r-- | Firebase/Utilities/Network/Private/GULNetworkMessageCode.h | 44 | ||||
-rw-r--r-- | Firebase/Utilities/Network/Private/GULNetworkURLSession.h | 60 |
10 files changed, 0 insertions, 1561 deletions
diff --git a/Firebase/Utilities/Network/GULMutableDictionary.m b/Firebase/Utilities/Network/GULMutableDictionary.m deleted file mode 100644 index d281eb4..0000000 --- a/Firebase/Utilities/Network/GULMutableDictionary.m +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2017 Google -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#import "Private/GULMutableDictionary.h" - -@implementation GULMutableDictionary { - /// The mutable dictionary. - NSMutableDictionary *_objects; - - /// Serial synchronization queue. All reads should use dispatch_sync, while writes use - /// dispatch_async. - dispatch_queue_t _queue; -} - -- (instancetype)init { - self = [super init]; - - if (self) { - _objects = [[NSMutableDictionary alloc] init]; - _queue = dispatch_queue_create("GULMutableDictionary", DISPATCH_QUEUE_SERIAL); - } - - return self; -} - -- (NSString *)description { - __block NSString *description; - dispatch_sync(_queue, ^{ - description = self->_objects.description; - }); - return description; -} - -- (id)objectForKey:(id)key { - __block id object; - dispatch_sync(_queue, ^{ - object = self->_objects[key]; - }); - return object; -} - -- (void)setObject:(id)object forKey:(id<NSCopying>)key { - dispatch_async(_queue, ^{ - self->_objects[key] = object; - }); -} - -- (void)removeObjectForKey:(id)key { - dispatch_async(_queue, ^{ - [self->_objects removeObjectForKey:key]; - }); -} - -- (void)removeAllObjects { - dispatch_async(_queue, ^{ - [self->_objects removeAllObjects]; - }); -} - -- (NSUInteger)count { - __block NSUInteger count; - dispatch_sync(_queue, ^{ - count = self->_objects.count; - }); - return count; -} - -- (id)objectForKeyedSubscript:(id<NSCopying>)key { - // The method this calls is already synchronized. - return [self objectForKey:key]; -} - -- (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key { - // The method this calls is already synchronized. - [self setObject:obj forKey:key]; -} - -- (NSDictionary *)dictionary { - __block NSDictionary *dictionary; - dispatch_sync(_queue, ^{ - dictionary = [self->_objects copy]; - }); - return dictionary; -} - -@end diff --git a/Firebase/Utilities/Network/GULNetwork.m b/Firebase/Utilities/Network/GULNetwork.m deleted file mode 100644 index 233500b..0000000 --- a/Firebase/Utilities/Network/GULNetwork.m +++ /dev/null @@ -1,388 +0,0 @@ -// Copyright 2017 Google -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#import "Private/GULNetwork.h" -#import "Private/GULNetworkMessageCode.h" - -#import <GoogleUtilities/GULLogger.h> -#import <GoogleUtilities/GULNSData+zlib.h> -#import <GoogleUtilities/GULReachabilityChecker.h> -#import "Private/GULMutableDictionary.h" -#import "Private/GULNetworkConstants.h" - -/// Constant string for request header Content-Encoding. -static NSString *const kGULNetworkContentCompressionKey = @"Content-Encoding"; - -/// Constant string for request header Content-Encoding value. -static NSString *const kGULNetworkContentCompressionValue = @"gzip"; - -/// Constant string for request header Content-Length. -static NSString *const kGULNetworkContentLengthKey = @"Content-Length"; - -/// Constant string for request header Content-Type. -static NSString *const kGULNetworkContentTypeKey = @"Content-Type"; - -/// Constant string for request header Content-Type value. -static NSString *const kGULNetworkContentTypeValue = @"application/x-www-form-urlencoded"; - -/// Constant string for GET request method. -static NSString *const kGULNetworkGETRequestMethod = @"GET"; - -/// Constant string for POST request method. -static NSString *const kGULNetworkPOSTRequestMethod = @"POST"; - -/// Default constant string as a prefix for network logger. -static NSString *const kGULNetworkLogTag = @"Google/Utilities/Network"; - -@interface GULNetwork () <GULReachabilityDelegate, GULNetworkLoggerDelegate> -@end - -@implementation GULNetwork { - /// Network reachability. - GULReachabilityChecker *_reachability; - - /// The dictionary of requests by session IDs { NSString : id }. - GULMutableDictionary *_requests; -} - -- (instancetype)init { - return [self initWithReachabilityHost:kGULNetworkReachabilityHost]; -} - -- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost { - self = [super init]; - if (self) { - // Setup reachability. - _reachability = [[GULReachabilityChecker alloc] initWithReachabilityDelegate:self - withHost:reachabilityHost]; - if (![_reachability start]) { - return nil; - } - - _requests = [[GULMutableDictionary alloc] init]; - _timeoutInterval = kGULNetworkTimeOutInterval; - } - return self; -} - -- (void)dealloc { - _reachability.reachabilityDelegate = nil; - [_reachability stop]; -} - -#pragma mark - External Methods - -+ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID - completionHandler:(GULNetworkSystemCompletionHandler)completionHandler { - [GULNetworkURLSession handleEventsForBackgroundURLSessionID:sessionID - completionHandler:completionHandler]; -} - -- (NSString *)postURL:(NSURL *)url - payload:(NSData *)payload - queue:(dispatch_queue_t)queue - usingBackgroundSession:(BOOL)usingBackgroundSession - completionHandler:(GULNetworkCompletionHandler)handler { - if (!url.absoluteString.length) { - [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; - return nil; - } - - NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; - - NSMutableURLRequest *request = - [[NSMutableURLRequest alloc] initWithURL:url - cachePolicy:NSURLRequestReloadIgnoringLocalCacheData - timeoutInterval:timeOutInterval]; - - if (!request) { - [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation - queue:queue - withHandler:handler]; - return nil; - } - - NSError *compressError = nil; - NSData *compressedData = [NSData gul_dataByGzippingData:payload error:&compressError]; - if (!compressedData || compressError) { - if (compressError || payload.length > 0) { - // If the payload is not empty but it fails to compress the payload, something has been wrong. - [self handleErrorWithCode:GULErrorCodeNetworkPayloadCompression - queue:queue - withHandler:handler]; - return nil; - } - compressedData = [[NSData alloc] init]; - } - - NSString *postLength = @(compressedData.length).stringValue; - - // Set up the request with the compressed data. - [request setValue:postLength forHTTPHeaderField:kGULNetworkContentLengthKey]; - request.HTTPBody = compressedData; - request.HTTPMethod = kGULNetworkPOSTRequestMethod; - [request setValue:kGULNetworkContentTypeValue forHTTPHeaderField:kGULNetworkContentTypeKey]; - [request setValue:kGULNetworkContentCompressionValue - forHTTPHeaderField:kGULNetworkContentCompressionKey]; - - GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; - fetcher.backgroundNetworkEnabled = usingBackgroundSession; - - __weak GULNetwork *weakSelf = self; - NSString *requestID = [fetcher - sessionIDFromAsyncPOSTRequest:request - completionHandler:^(NSHTTPURLResponse *response, NSData *data, - NSString *sessionID, NSError *error) { - GULNetwork *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); - dispatch_async(queueToDispatch, ^{ - if (sessionID.length) { - [strongSelf->_requests removeObjectForKey:sessionID]; - } - if (handler) { - handler(response, data, error); - } - }); - }]; - if (!requestID) { - [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation - queue:queue - withHandler:handler]; - return nil; - } - - [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug - messageCode:kGULNetworkMessageCodeNetwork000 - message:@"Uploading data. Host" - context:url]; - _requests[requestID] = fetcher; - return requestID; -} - -- (NSString *)getURL:(NSURL *)url - headers:(NSDictionary *)headers - queue:(dispatch_queue_t)queue - usingBackgroundSession:(BOOL)usingBackgroundSession - completionHandler:(GULNetworkCompletionHandler)handler { - if (!url.absoluteString.length) { - [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; - return nil; - } - - NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; - NSMutableURLRequest *request = - [[NSMutableURLRequest alloc] initWithURL:url - cachePolicy:NSURLRequestReloadIgnoringLocalCacheData - timeoutInterval:timeOutInterval]; - - if (!request) { - [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation - queue:queue - withHandler:handler]; - return nil; - } - - request.HTTPMethod = kGULNetworkGETRequestMethod; - request.allHTTPHeaderFields = headers; - - GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; - fetcher.backgroundNetworkEnabled = usingBackgroundSession; - - __weak GULNetwork *weakSelf = self; - NSString *requestID = [fetcher - sessionIDFromAsyncGETRequest:request - completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSString *sessionID, - NSError *error) { - GULNetwork *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); - dispatch_async(queueToDispatch, ^{ - if (sessionID.length) { - [strongSelf->_requests removeObjectForKey:sessionID]; - } - if (handler) { - handler(response, data, error); - } - }); - }]; - - if (!requestID) { - [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation - queue:queue - withHandler:handler]; - return nil; - } - - [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug - messageCode:kGULNetworkMessageCodeNetwork001 - message:@"Downloading data. Host" - context:url]; - _requests[requestID] = fetcher; - return requestID; -} - -- (BOOL)hasUploadInProgress { - return _requests.count > 0; -} - -#pragma mark - Network Reachability - -/// Tells reachability delegate to call reachabilityDidChangeToStatus: to notify the network -/// reachability has changed. -- (void)reachability:(GULReachabilityChecker *)reachability - statusChanged:(GULReachabilityStatus)status { - _networkConnected = (status == kGULReachabilityViaCellular || status == kGULReachabilityViaWifi); - [_reachabilityDelegate reachabilityDidChange]; -} - -#pragma mark - Network logger delegate - -- (void)setLoggerDelegate:(id<GULNetworkLoggerDelegate>)loggerDelegate { - // Explicitly check whether the delegate responds to the methods because conformsToProtocol does - // not work correctly even though the delegate does respond to the methods. - if (!loggerDelegate || - ![loggerDelegate - respondsToSelector:@selector(GULNetwork_logWithLevel:messageCode:message:contexts:)] || - ![loggerDelegate - respondsToSelector:@selector(GULNetwork_logWithLevel:messageCode:message:context:)] || - ! - [loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel:messageCode:message:)]) { - GULLogError(kGULLoggerNetwork, NO, - [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork002], - @"Cannot set the network logger delegate: delegate does not conform to the network " - "logger protocol."); - return; - } - _loggerDelegate = loggerDelegate; -} - -#pragma mark - Private methods - -/// Handles network error and calls completion handler with the error. -- (void)handleErrorWithCode:(NSInteger)code - queue:(dispatch_queue_t)queue - withHandler:(GULNetworkCompletionHandler)handler { - NSDictionary *userInfo = @{kGULNetworkErrorContext : @"Failed to create network request"}; - NSError *error = - [[NSError alloc] initWithDomain:kGULNetworkErrorDomain code:code userInfo:userInfo]; - [self GULNetwork_logWithLevel:kGULNetworkLogLevelWarning - messageCode:kGULNetworkMessageCodeNetwork002 - message:@"Failed to create network request. Code, error" - contexts:@[ @(code), error ]]; - if (handler) { - dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); - dispatch_async(queueToDispatch, ^{ - handler(nil, nil, error); - }); - } -} - -#pragma mark - Network logger - -- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel - messageCode:(GULNetworkMessageCode)messageCode - message:(NSString *)message - contexts:(NSArray *)contexts { - // Let the delegate log the message if there is a valid logger delegate. Otherwise, just log - // errors/warnings/info messages to the console log. - if (_loggerDelegate) { - [_loggerDelegate GULNetwork_logWithLevel:logLevel - messageCode:messageCode - message:message - contexts:contexts]; - return; - } - if (_isDebugModeEnabled || logLevel == kGULNetworkLogLevelError || - logLevel == kGULNetworkLogLevelWarning || logLevel == kGULNetworkLogLevelInfo) { - NSString *formattedMessage = GULStringWithLogMessage(message, logLevel, contexts); - NSLog(@"%@", formattedMessage); - GULLogBasic((GULLoggerLevel)logLevel, kGULLoggerNetwork, NO, - [NSString stringWithFormat:@"I-NET%06ld", (long)messageCode], formattedMessage, - NULL); - } -} - -- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel - messageCode:(GULNetworkMessageCode)messageCode - message:(NSString *)message - context:(id)context { - if (_loggerDelegate) { - [_loggerDelegate GULNetwork_logWithLevel:logLevel - messageCode:messageCode - message:message - context:context]; - return; - } - NSArray *contexts = context ? @[ context ] : @[]; - [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:contexts]; -} - -- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel - messageCode:(GULNetworkMessageCode)messageCode - message:(NSString *)message { - if (_loggerDelegate) { - [_loggerDelegate GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message]; - return; - } - [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:@[]]; -} - -/// Returns a string for the given log level (e.g. kGULNetworkLogLevelError -> @"ERROR"). -static NSString *GULLogLevelDescriptionFromLogLevel(GULNetworkLogLevel logLevel) { - static NSDictionary *levelNames = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - levelNames = @{ - @(kGULNetworkLogLevelError) : @"ERROR", - @(kGULNetworkLogLevelWarning) : @"WARNING", - @(kGULNetworkLogLevelInfo) : @"INFO", - @(kGULNetworkLogLevelDebug) : @"DEBUG" - }; - }); - return levelNames[@(logLevel)]; -} - -/// Returns a formatted string to be used for console logging. -static NSString *GULStringWithLogMessage(NSString *message, - GULNetworkLogLevel logLevel, - NSArray *contexts) { - if (!message) { - message = @"(Message was nil)"; - } else if (!message.length) { - message = @"(Message was empty)"; - } - NSMutableString *result = [[NSMutableString alloc] - initWithFormat:@"<%@/%@> %@", kGULNetworkLogTag, GULLogLevelDescriptionFromLogLevel(logLevel), - message]; - - if (!contexts.count) { - return result; - } - - NSMutableArray *formattedContexts = [[NSMutableArray alloc] init]; - for (id item in contexts) { - [formattedContexts addObject:(item != [NSNull null] ? item : @"(nil)")]; - } - - [result appendString:@": "]; - [result appendString:[formattedContexts componentsJoinedByString:@", "]]; - return result; -} - -@end diff --git a/Firebase/Utilities/Network/GULNetworkConstants.m b/Firebase/Utilities/Network/GULNetworkConstants.m deleted file mode 100644 index 90bd03d..0000000 --- a/Firebase/Utilities/Network/GULNetworkConstants.m +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2017 Google -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#import "Private/GULNetworkConstants.h" - -#import <Foundation/Foundation.h> - -NSString *const kGULNetworkBackgroundSessionConfigIDPrefix = @"com.gul.network.background-upload"; -NSString *const kGULNetworkApplicationSupportSubdirectory = @"GUL/Network"; -NSString *const kGULNetworkTempDirectoryName = @"GULNetworkTemporaryDirectory"; -const NSTimeInterval kGULNetworkTempFolderExpireTime = 60 * 60; // 1 hour -const NSTimeInterval kGULNetworkTimeOutInterval = 60; // 1 minute. -NSString *const kGULNetworkReachabilityHost = @"app-measurement.com"; -NSString *const kGULNetworkErrorContext = @"Context"; - -const int kGULNetworkHTTPStatusOK = 200; -const int kGULNetworkHTTPStatusNoContent = 204; -const int kGULNetworkHTTPStatusCodeMultipleChoices = 300; -const int kGULNetworkHTTPStatusCodeMovedPermanently = 301; -const int kGULNetworkHTTPStatusCodeFound = 302; -const int kGULNetworkHTTPStatusCodeNotModified = 304; -const int kGULNetworkHTTPStatusCodeMovedTemporarily = 307; -const int kGULNetworkHTTPStatusCodeNotFound = 404; -const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic = 429; -const int kGULNetworkHTTPStatusCodeUnavailable = 503; - -NSString *const kGULNetworkErrorDomain = @"com.gul.network.ErrorDomain"; - -GULLoggerService kGULLoggerNetwork = @"[GULNetwork]"; diff --git a/Firebase/Utilities/Network/GULNetworkURLSession.m b/Firebase/Utilities/Network/GULNetworkURLSession.m deleted file mode 100644 index cb8a204..0000000 --- a/Firebase/Utilities/Network/GULNetworkURLSession.m +++ /dev/null @@ -1,669 +0,0 @@ -// Copyright 2017 Google -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#import <Foundation/Foundation.h> - -#import "Private/GULNetworkURLSession.h" - -#import <GoogleUtilities/GULLogger.h> -#import "Private/GULMutableDictionary.h" -#import "Private/GULNetworkConstants.h" -#import "Private/GULNetworkMessageCode.h" - -@implementation GULNetworkURLSession { - /// The handler to be called when the request completes or error has occurs. - GULNetworkURLSessionCompletionHandler _completionHandler; - - /// Session ID generated randomly with a fixed prefix. - NSString *_sessionID; - - /// The session configuration. - NSURLSessionConfiguration *_sessionConfig; - - /// The path to the directory where all temporary files are stored before uploading. - NSURL *_networkDirectoryURL; - - /// The downloaded data from fetching. - NSData *_downloadedData; - - /// The path to the temporary file which stores the uploading data. - NSURL *_uploadingFileURL; - - /// The current request. - NSURLRequest *_request; -} - -#pragma mark - Init - -- (instancetype)initWithNetworkLoggerDelegate:(id<GULNetworkLoggerDelegate>)networkLoggerDelegate { - self = [super init]; - if (self) { - // Create URL to the directory where all temporary files to upload have to be stored. - NSArray *paths = - NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); - NSString *applicationSupportDirectory = paths.firstObject; - NSArray *tempPathComponents = @[ - applicationSupportDirectory, kGULNetworkApplicationSupportSubdirectory, - kGULNetworkTempDirectoryName - ]; - _networkDirectoryURL = [NSURL fileURLWithPathComponents:tempPathComponents]; - _sessionID = [NSString stringWithFormat:@"%@-%@", kGULNetworkBackgroundSessionConfigIDPrefix, - [[NSUUID UUID] UUIDString]]; - _loggerDelegate = networkLoggerDelegate; - } - return self; -} - -#pragma mark - External Methods - -#pragma mark - To be called from AppDelegate - -+ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID - completionHandler: - (GULNetworkSystemCompletionHandler)systemCompletionHandler { - // The session may not be Analytics background. Ignore those that do not have the prefix. - if (![sessionID hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { - return; - } - GULNetworkURLSession *fetcher = [self fetcherWithSessionIdentifier:sessionID]; - if (fetcher != nil) { - [fetcher addSystemCompletionHandler:systemCompletionHandler forSession:sessionID]; - } else { - GULLogError(kGULLoggerNetwork, NO, - [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork003], - @"Failed to retrieve background session with ID %@ after app is relaunched.", - sessionID); - } -} - -#pragma mark - External Methods - -/// Sends an async POST request using NSURLSession for iOS >= 7.0, and returns an ID of the -/// connection. -- (NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request - completionHandler:(GULNetworkURLSessionCompletionHandler)handler { - // NSURLSessionUploadTask does not work with NSData in the background. - // To avoid this issue, write the data to a temporary file to upload it. - // Make a temporary file with the data subset. - _uploadingFileURL = [self temporaryFilePathWithSessionID:_sessionID]; - NSError *writeError; - NSURLSessionUploadTask *postRequestTask; - NSURLSession *session; - BOOL didWriteFile = NO; - - // Clean up the entire temp folder to avoid temp files that remain in case the previous session - // crashed and did not clean up. - [self maybeRemoveTempFilesAtURL:_networkDirectoryURL - expiringTime:kGULNetworkTempFolderExpireTime]; - - // If there is no background network enabled, no need to write to file. This will allow default - // network session which runs on the foreground. - if (_backgroundNetworkEnabled && [self ensureTemporaryDirectoryExists]) { - didWriteFile = [request.HTTPBody writeToFile:_uploadingFileURL.path - options:NSDataWritingAtomic - error:&writeError]; - - if (writeError) { - [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError - messageCode:kGULNetworkMessageCodeURLSession000 - message:@"Failed to write request data to file" - context:writeError]; - } - } - - if (didWriteFile) { - // Exclude this file from backing up to iTunes. There are conflicting reports that excluding - // directory from backing up does not excluding files of that directory from backing up. - [self excludeFromBackupForURL:_uploadingFileURL]; - - _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; - [self populateSessionConfig:_sessionConfig withRequest:request]; - session = [NSURLSession sessionWithConfiguration:_sessionConfig - delegate:self - delegateQueue:[NSOperationQueue mainQueue]]; - postRequestTask = [session uploadTaskWithRequest:request fromFile:_uploadingFileURL]; - } else { - // If we cannot write to file, just send it in the foreground. - _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; - [self populateSessionConfig:_sessionConfig withRequest:request]; - _sessionConfig.URLCache = nil; - session = [NSURLSession sessionWithConfiguration:_sessionConfig - delegate:self - delegateQueue:[NSOperationQueue mainQueue]]; - postRequestTask = [session uploadTaskWithRequest:request fromData:request.HTTPBody]; - } - - if (!session || !postRequestTask) { - NSError *error = [[NSError alloc] - initWithDomain:kGULNetworkErrorDomain - code:GULErrorCodeNetworkRequestCreation - userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; - [self callCompletionHandler:handler withResponse:nil data:nil error:error]; - return nil; - } - - // Save the session into memory. - NSMapTable *sessionIdentifierToFetcherMap = [[self class] sessionIDToFetcherMap]; - [sessionIdentifierToFetcherMap setObject:self forKey:_sessionID]; - - _request = [request copy]; - - // Store completion handler because background session does not accept handler block but custom - // delegate. - _completionHandler = [handler copy]; - [postRequestTask resume]; - - return _sessionID; -} - -/// Sends an async GET request using NSURLSession for iOS >= 7.0, and returns an ID of the session. -- (NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request - completionHandler:(GULNetworkURLSessionCompletionHandler)handler { - if (_backgroundNetworkEnabled) { - _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; - } else { - _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; - } - - [self populateSessionConfig:_sessionConfig withRequest:request]; - - // Do not cache the GET request. - _sessionConfig.URLCache = nil; - - NSURLSession *session = [NSURLSession sessionWithConfiguration:_sessionConfig - delegate:self - delegateQueue:[NSOperationQueue mainQueue]]; - NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request]; - - if (!session || !downloadTask) { - NSError *error = [[NSError alloc] - initWithDomain:kGULNetworkErrorDomain - code:GULErrorCodeNetworkRequestCreation - userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; - [self callCompletionHandler:handler withResponse:nil data:nil error:error]; - return nil; - } - - // Save the session into memory. - NSMapTable *sessionIdentifierToFetcherMap = [[self class] sessionIDToFetcherMap]; - [sessionIdentifierToFetcherMap setObject:self forKey:_sessionID]; - - _request = [request copy]; - - _completionHandler = [handler copy]; - [downloadTask resume]; - - return _sessionID; -} - -#pragma mark - NSURLSessionTaskDelegate - -/// Called by the NSURLSession once the download task is completed. The file is saved in the -/// provided URL so we need to read the data and store into _downloadedData. Once the session is -/// completed, URLSession:task:didCompleteWithError will be called and the completion handler will -/// be called with the downloaded data. -- (void)URLSession:(NSURLSession *)session - downloadTask:(NSURLSessionDownloadTask *)task - didFinishDownloadingToURL:(NSURL *)url { - if (!url.path) { - [_loggerDelegate - GULNetwork_logWithLevel:kGULNetworkLogLevelError - messageCode:kGULNetworkMessageCodeURLSession001 - message:@"Unable to read downloaded data from empty temp path"]; - _downloadedData = nil; - return; - } - - NSError *error; - _downloadedData = [NSData dataWithContentsOfFile:url.path options:0 error:&error]; - - if (error) { - [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError - messageCode:kGULNetworkMessageCodeURLSession002 - message:@"Cannot read the content of downloaded data" - context:error]; - _downloadedData = nil; - } -} - -#if TARGET_OS_IOS || TARGET_OS_TV -- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { - [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug - messageCode:kGULNetworkMessageCodeURLSession003 - message:@"Background session finished" - context:session.configuration.identifier]; - [self callSystemCompletionHandler:session.configuration.identifier]; -} -#endif - -- (void)URLSession:(NSURLSession *)session - task:(NSURLSessionTask *)task - didCompleteWithError:(NSError *)error { - // Avoid any chance of recursive behavior leading to it being used repeatedly. - GULNetworkURLSessionCompletionHandler handler = _completionHandler; - _completionHandler = nil; - - if (task.response) { - // The following assertion should always be true for HTTP requests, see https://goo.gl/gVLxT7. - NSAssert([task.response isKindOfClass:[NSHTTPURLResponse class]], @"URL response must be HTTP"); - - // The server responded so ignore the error created by the system. - error = nil; - } else if (!error) { - error = [[NSError alloc] - initWithDomain:kGULNetworkErrorDomain - code:GULErrorCodeNetworkInvalidResponse - userInfo:@{kGULNetworkErrorContext : @"Network Error: Empty network response"}]; - } - - [self callCompletionHandler:handler - withResponse:(NSHTTPURLResponse *)task.response - data:_downloadedData - error:error]; - - // Remove the temp file to avoid trashing devices with lots of temp files. - [self removeTempItemAtURL:_uploadingFileURL]; - - // Try to clean up stale files again. - [self maybeRemoveTempFilesAtURL:_networkDirectoryURL - expiringTime:kGULNetworkTempFolderExpireTime]; -} - -- (void)URLSession:(NSURLSession *)session - task:(NSURLSessionTask *)task - didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge - completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, - NSURLCredential *credential))completionHandler { - // The handling is modeled after GTMSessionFetcher. - if ([challenge.protectionSpace.authenticationMethod - isEqualToString:NSURLAuthenticationMethodServerTrust]) { - SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; - if (serverTrust == NULL) { - [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug - messageCode:kGULNetworkMessageCodeURLSession004 - message:@"Received empty server trust for host. Host" - context:_request.URL]; - completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); - return; - } - NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; - if (!credential) { - [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning - messageCode:kGULNetworkMessageCodeURLSession005 - message:@"Unable to verify server identity. Host" - context:_request.URL]; - completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); - return; - } - - [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug - messageCode:kGULNetworkMessageCodeURLSession006 - message:@"Received SSL challenge for host. Host" - context:_request.URL]; - - void (^callback)(BOOL) = ^(BOOL allow) { - if (allow) { - completionHandler(NSURLSessionAuthChallengeUseCredential, credential); - } else { - [self->_loggerDelegate - GULNetwork_logWithLevel:kGULNetworkLogLevelDebug - messageCode:kGULNetworkMessageCodeURLSession007 - message:@"Cancelling authentication challenge for host. Host" - context:self->_request.URL]; - completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); - } - }; - - // Retain the trust object to avoid a SecTrustEvaluate() crash on iOS 7. - CFRetain(serverTrust); - - // Evaluate the certificate chain. - // - // The delegate queue may be the main thread. Trust evaluation could cause some - // blocking network activity, so we must evaluate async, as documented at - // https://developer.apple.com/library/ios/technotes/tn2232/ - dispatch_queue_t evaluateBackgroundQueue = - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - - dispatch_async(evaluateBackgroundQueue, ^{ - SecTrustResultType trustEval = kSecTrustResultInvalid; - BOOL shouldAllow; - OSStatus trustError; - - @synchronized([GULNetworkURLSession class]) { - trustError = SecTrustEvaluate(serverTrust, &trustEval); - } - - if (trustError != errSecSuccess) { - [self->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError - messageCode:kGULNetworkMessageCodeURLSession008 - message:@"Cannot evaluate server trust. Error, host" - contexts:@[ @(trustError), self->_request.URL ]]; - shouldAllow = NO; - } else { - // Having a trust level "unspecified" by the user is the usual result, described at - // https://developer.apple.com/library/mac/qa/qa1360 - shouldAllow = - (trustEval == kSecTrustResultUnspecified || trustEval == kSecTrustResultProceed); - } - - // Call the call back with the permission. - callback(shouldAllow); - - CFRelease(serverTrust); - }); - return; - } - - // Default handling for other Auth Challenges. - completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); -} - -#pragma mark - Internal Methods - -/// Stores system completion handler with session ID as key. -- (void)addSystemCompletionHandler:(GULNetworkSystemCompletionHandler)handler - forSession:(NSString *)identifier { - if (!handler) { - [_loggerDelegate - GULNetwork_logWithLevel:kGULNetworkLogLevelError - messageCode:kGULNetworkMessageCodeURLSession009 - message:@"Cannot store nil system completion handler in network"]; - return; - } - - if (!identifier.length) { - [_loggerDelegate - GULNetwork_logWithLevel:kGULNetworkLogLevelError - messageCode:kGULNetworkMessageCodeURLSession010 - message: - @"Cannot store system completion handler with empty network " - "session identifier"]; - return; - } - - GULMutableDictionary *systemCompletionHandlers = - [[self class] sessionIDToSystemCompletionHandlerDictionary]; - if (systemCompletionHandlers[identifier]) { - [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning - messageCode:kGULNetworkMessageCodeURLSession011 - message:@"Got multiple system handlers for a single session ID" - context:identifier]; - } - - systemCompletionHandlers[identifier] = handler; -} - -/// Calls the system provided completion handler with the session ID stored in the dictionary. -/// The handler will be removed from the dictionary after being called. -- (void)callSystemCompletionHandler:(NSString *)identifier { - GULMutableDictionary *systemCompletionHandlers = - [[self class] sessionIDToSystemCompletionHandlerDictionary]; - GULNetworkSystemCompletionHandler handler = [systemCompletionHandlers objectForKey:identifier]; - - if (handler) { - [systemCompletionHandlers removeObjectForKey:identifier]; - - dispatch_async(dispatch_get_main_queue(), ^{ - handler(); - }); - } -} - -/// Sets or updates the session ID of this session. -- (void)setSessionID:(NSString *)sessionID { - _sessionID = [sessionID copy]; -} - -/// Creates a background session configuration with the session ID using the supported method. -- (NSURLSessionConfiguration *)backgroundSessionConfigWithSessionID:(NSString *)sessionID { -#if (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ - MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10) || \ - TARGET_OS_TV || \ - (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0) - - // iOS 8/10.10 builds require the new backgroundSessionConfiguration method name. - return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; - -#elif (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10) || \ - (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0) - - // Do a runtime check to avoid a deprecation warning about using - // +backgroundSessionConfiguration: on iOS 8. - if ([NSURLSessionConfiguration - respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]) { - // Running on iOS 8+/OS X 10.10+. - return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; - } else { - // Running on iOS 7/OS X 10.9. - return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; - } - -#else - // Building with an SDK earlier than iOS 8/OS X 10.10. - return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; -#endif -} - -- (void)maybeRemoveTempFilesAtURL:(NSURL *)folderURL expiringTime:(NSTimeInterval)staleTime { - if (!folderURL.absoluteString.length) { - return; - } - - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSError *error = nil; - - NSArray *properties = @[ NSURLCreationDateKey ]; - NSArray *directoryContent = - [fileManager contentsOfDirectoryAtURL:folderURL - includingPropertiesForKeys:properties - options:NSDirectoryEnumerationSkipsSubdirectoryDescendants - error:&error]; - if (error && error.code != NSFileReadNoSuchFileError) { - [_loggerDelegate - GULNetwork_logWithLevel:kGULNetworkLogLevelDebug - messageCode:kGULNetworkMessageCodeURLSession012 - message:@"Cannot get files from the temporary network folder. Error" - context:error]; - return; - } - - if (!directoryContent.count) { - return; - } - - NSTimeInterval now = [NSDate date].timeIntervalSince1970; - for (NSURL *tempFile in directoryContent) { - NSDate *creationDate; - BOOL getCreationDate = - [tempFile getResourceValue:&creationDate forKey:NSURLCreationDateKey error:NULL]; - if (!getCreationDate) { - continue; - } - NSTimeInterval creationTimeInterval = creationDate.timeIntervalSince1970; - if (fabs(now - creationTimeInterval) > staleTime) { - [self removeTempItemAtURL:tempFile]; - } - } -} - -/// Removes the temporary file written to disk for sending the request. It has to be cleaned up -/// after the session is done. -- (void)removeTempItemAtURL:(NSURL *)fileURL { - if (!fileURL.absoluteString.length) { - return; - } - - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSError *error = nil; - - if (![fileManager removeItemAtURL:fileURL error:&error] && error.code != NSFileNoSuchFileError) { - [_loggerDelegate - GULNetwork_logWithLevel:kGULNetworkLogLevelError - messageCode:kGULNetworkMessageCodeURLSession013 - message:@"Failed to remove temporary uploading data file. Error" - context:error.localizedDescription]; - } -} - -/// Gets the fetcher with the session ID. -+ (instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier { - NSMapTable *sessionIdentifierToFetcherMap = [self sessionIDToFetcherMap]; - GULNetworkURLSession *session = [sessionIdentifierToFetcherMap objectForKey:sessionIdentifier]; - if (!session && [sessionIdentifier hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { - session = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:nil]; - [session setSessionID:sessionIdentifier]; - [sessionIdentifierToFetcherMap setObject:session forKey:sessionIdentifier]; - } - return session; -} - -/// Returns a map of the fetcher by session ID. Creates a map if it is not created. -+ (NSMapTable *)sessionIDToFetcherMap { - static NSMapTable *sessionIDToFetcherMap; - - static dispatch_once_t sessionMapOnceToken; - dispatch_once(&sessionMapOnceToken, ^{ - sessionIDToFetcherMap = [NSMapTable strongToWeakObjectsMapTable]; - }); - return sessionIDToFetcherMap; -} - -/// Returns a map of system provided completion handler by session ID. Creates a map if it is not -/// created. -+ (GULMutableDictionary *)sessionIDToSystemCompletionHandlerDictionary { - static GULMutableDictionary *systemCompletionHandlers; - - static dispatch_once_t systemCompletionHandlerOnceToken; - dispatch_once(&systemCompletionHandlerOnceToken, ^{ - systemCompletionHandlers = [[GULMutableDictionary alloc] init]; - }); - return systemCompletionHandlers; -} - -- (NSURL *)temporaryFilePathWithSessionID:(NSString *)sessionID { - NSString *tempName = [NSString stringWithFormat:@"GULUpload_temp_%@", sessionID]; - return [_networkDirectoryURL URLByAppendingPathComponent:tempName]; -} - -/// Makes sure that the directory to store temp files exists. If not, tries to create it and returns -/// YES. If there is anything wrong, returns NO. -- (BOOL)ensureTemporaryDirectoryExists { - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSError *error = nil; - - // Create a temporary directory if it does not exist or was deleted. - if ([_networkDirectoryURL checkResourceIsReachableAndReturnError:&error]) { - return YES; - } - - if (error && error.code != NSFileReadNoSuchFileError) { - [_loggerDelegate - GULNetwork_logWithLevel:kGULNetworkLogLevelWarning - messageCode:kGULNetworkMessageCodeURLSession014 - message:@"Error while trying to access Network temp folder. Error" - context:error]; - } - - NSError *writeError = nil; - - [fileManager createDirectoryAtURL:_networkDirectoryURL - withIntermediateDirectories:YES - attributes:nil - error:&writeError]; - if (writeError) { - [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError - messageCode:kGULNetworkMessageCodeURLSession015 - message:@"Cannot create temporary directory. Error" - context:writeError]; - return NO; - } - - // Set the iCloud exclusion attribute on the Documents URL. - [self excludeFromBackupForURL:_networkDirectoryURL]; - - return YES; -} - -- (void)excludeFromBackupForURL:(NSURL *)url { - if (!url.path) { - return; - } - - // Set the iCloud exclusion attribute on the Documents URL. - NSError *preventBackupError = nil; - [url setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:&preventBackupError]; - if (preventBackupError) { - [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError - messageCode:kGULNetworkMessageCodeURLSession016 - message:@"Cannot exclude temporary folder from iTunes backup"]; - } -} - -- (void)URLSession:(NSURLSession *)session - task:(NSURLSessionTask *)task - willPerformHTTPRedirection:(NSHTTPURLResponse *)response - newRequest:(NSURLRequest *)request - completionHandler:(void (^)(NSURLRequest *))completionHandler { - NSArray *nonAllowedRedirectionCodes = @[ - @(kGULNetworkHTTPStatusCodeFound), @(kGULNetworkHTTPStatusCodeMovedPermanently), - @(kGULNetworkHTTPStatusCodeMovedTemporarily), @(kGULNetworkHTTPStatusCodeMultipleChoices) - ]; - - // Allow those not in the non allowed list to be followed. - if (![nonAllowedRedirectionCodes containsObject:@(response.statusCode)]) { - completionHandler(request); - return; - } - - // Do not allow redirection if the response code is in the non-allowed list. - NSURLRequest *newRequest = request; - - if (response) { - newRequest = nil; - } - - completionHandler(newRequest); -} - -#pragma mark - Helper Methods - -- (void)callCompletionHandler:(GULNetworkURLSessionCompletionHandler)handler - withResponse:(NSHTTPURLResponse *)response - data:(NSData *)data - error:(NSError *)error { - if (error) { - [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError - messageCode:kGULNetworkMessageCodeURLSession017 - message:@"Encounter network error. Code, error" - contexts:@[ @(error.code), error ]]; - } - - if (handler) { - dispatch_async(dispatch_get_main_queue(), ^{ - handler(response, data, self->_sessionID, error); - }); - } -} - -- (void)populateSessionConfig:(NSURLSessionConfiguration *)sessionConfig - withRequest:(NSURLRequest *)request { - sessionConfig.HTTPAdditionalHeaders = request.allHTTPHeaderFields; - sessionConfig.timeoutIntervalForRequest = request.timeoutInterval; - sessionConfig.timeoutIntervalForResource = request.timeoutInterval; - sessionConfig.requestCachePolicy = request.cachePolicy; -} - -@end diff --git a/Firebase/Utilities/Network/Private/GULMutableDictionary.h b/Firebase/Utilities/Network/Private/GULMutableDictionary.h deleted file mode 100644 index a8cc45b..0000000 --- a/Firebase/Utilities/Network/Private/GULMutableDictionary.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import <Foundation/Foundation.h> - -/// A mutable dictionary that provides atomic accessor and mutators. -@interface GULMutableDictionary : NSObject - -/// Returns an object given a key in the dictionary or nil if not found. -- (id)objectForKey:(id)key; - -/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. -- (void)setObject:(id)object forKey:(id<NSCopying>)key; - -/// Removes the object given its session ID from the dictionary. -- (void)removeObjectForKey:(id)key; - -/// Removes all objects. -- (void)removeAllObjects; - -/// Returns the number of current objects in the dictionary. -- (NSUInteger)count; - -/// Returns an object given a key in the dictionary or nil if not found. -- (id)objectForKeyedSubscript:(id<NSCopying>)key; - -/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. -- (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key; - -/// Returns the immutable dictionary. -- (NSDictionary *)dictionary; - -@end diff --git a/Firebase/Utilities/Network/Private/GULNetwork.h b/Firebase/Utilities/Network/Private/GULNetwork.h deleted file mode 100644 index 0e75ae5..0000000 --- a/Firebase/Utilities/Network/Private/GULNetwork.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import <Foundation/Foundation.h> - -#import "GULNetworkConstants.h" -#import "GULNetworkLoggerProtocol.h" -#import "GULNetworkURLSession.h" - -/// Delegate protocol for GULNetwork events. -@protocol GULNetworkReachabilityDelegate - -/// Tells the delegate to handle events when the network reachability changes to connected or not -/// connected. -- (void)reachabilityDidChange; - -@end - -/// The Network component that provides network status and handles network requests and responses. -/// This is not thread safe. -/// -/// NOTE: -/// User must add FIRAnalytics handleEventsForBackgroundURLSessionID:completionHandler to the -/// AppDelegate application:handleEventsForBackgroundURLSession:completionHandler: -@interface GULNetwork : NSObject - -/// Indicates if network connectivity is available. -@property(nonatomic, readonly, getter=isNetworkConnected) BOOL networkConnected; - -/// Indicates if there are any uploads in progress. -@property(nonatomic, readonly, getter=hasUploadInProgress) BOOL uploadInProgress; - -/// An optional delegate that can be used in the event when network reachability changes. -@property(nonatomic, weak) id<GULNetworkReachabilityDelegate> reachabilityDelegate; - -/// An optional delegate that can be used to log messages, warnings or errors that occur in the -/// network operations. -@property(nonatomic, weak) id<GULNetworkLoggerDelegate> loggerDelegate; - -/// Indicates whether the logger should display debug messages. -@property(nonatomic, assign) BOOL isDebugModeEnabled; - -/// The time interval in seconds for the network request to timeout. -@property(nonatomic, assign) NSTimeInterval timeoutInterval; - -/// Initializes with the default reachability host. -- (instancetype)init; - -/// Initializes with a custom reachability host. -- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost; - -/// Handles events when background session with the given ID has finished. -+ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID - completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; - -/// Compresses and sends a POST request with the provided data to the URL. The session will be -/// background session if usingBackgroundSession is YES. Otherwise, the POST session is default -/// session. Returns a session ID or nil if an error occurs. -- (NSString *)postURL:(NSURL *)url - payload:(NSData *)payload - queue:(dispatch_queue_t)queue - usingBackgroundSession:(BOOL)usingBackgroundSession - completionHandler:(GULNetworkCompletionHandler)handler; - -/// Sends a GET request with the provided data to the URL. The session will be background session -/// if usingBackgroundSession is YES. Otherwise, the GET session is default session. Returns a -/// session ID or nil if an error occurs. -- (NSString *)getURL:(NSURL *)url - headers:(NSDictionary *)headers - queue:(dispatch_queue_t)queue - usingBackgroundSession:(BOOL)usingBackgroundSession - completionHandler:(GULNetworkCompletionHandler)handler; - -@end diff --git a/Firebase/Utilities/Network/Private/GULNetworkConstants.h b/Firebase/Utilities/Network/Private/GULNetworkConstants.h deleted file mode 100644 index 44d440b..0000000 --- a/Firebase/Utilities/Network/Private/GULNetworkConstants.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import <Foundation/Foundation.h> -#import <GoogleUtilities/GULLogger.h> - -/// Error codes in Firebase Network error domain. -/// Note: these error codes should never change. It would make it harder to decode the errors if -/// we inadvertently altered any of these codes in a future SDK version. -typedef NS_ENUM(NSInteger, GULNetworkErrorCode) { - /// Unknown error. - GULNetworkErrorCodeUnknown = 0, - /// Error occurs when the request URL is invalid. - GULErrorCodeNetworkInvalidURL = 1, - /// Error occurs when request cannot be constructed. - GULErrorCodeNetworkRequestCreation = 2, - /// Error occurs when payload cannot be compressed. - GULErrorCodeNetworkPayloadCompression = 3, - /// Error occurs when session task cannot be created. - GULErrorCodeNetworkSessionTaskCreation = 4, - /// Error occurs when there is no response. - GULErrorCodeNetworkInvalidResponse = 5 -}; - -#pragma mark - Network constants - -/// The prefix of the ID of the background session. -extern NSString *const kGULNetworkBackgroundSessionConfigIDPrefix; - -/// The sub directory to store the files of data that is being uploaded in the background. -extern NSString *const kGULNetworkApplicationSupportSubdirectory; - -/// Name of the temporary directory that stores files for background uploading. -extern NSString *const kGULNetworkTempDirectoryName; - -/// The period when the temporary uploading file can stay. -extern const NSTimeInterval kGULNetworkTempFolderExpireTime; - -/// The default network request timeout interval. -extern const NSTimeInterval kGULNetworkTimeOutInterval; - -/// The host to check the reachability of the network. -extern NSString *const kGULNetworkReachabilityHost; - -/// The key to get the error context of the UserInfo. -extern NSString *const kGULNetworkErrorContext; - -#pragma mark - Network Status Code - -extern const int kGULNetworkHTTPStatusOK; -extern const int kGULNetworkHTTPStatusNoContent; -extern const int kGULNetworkHTTPStatusCodeMultipleChoices; -extern const int kGULNetworkHTTPStatusCodeMovedPermanently; -extern const int kGULNetworkHTTPStatusCodeFound; -extern const int kGULNetworkHTTPStatusCodeNotModified; -extern const int kGULNetworkHTTPStatusCodeMovedTemporarily; -extern const int kGULNetworkHTTPStatusCodeNotFound; -extern const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic; -extern const int kGULNetworkHTTPStatusCodeUnavailable; - -#pragma mark - Error Domain - -extern NSString *const kGULNetworkErrorDomain; - -/// The logger service for GULNetwork. -extern GULLoggerService kGULLoggerNetwork; diff --git a/Firebase/Utilities/Network/Private/GULNetworkLoggerProtocol.h b/Firebase/Utilities/Network/Private/GULNetworkLoggerProtocol.h deleted file mode 100644 index f1be590..0000000 --- a/Firebase/Utilities/Network/Private/GULNetworkLoggerProtocol.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import <Foundation/Foundation.h> - -#import <GoogleUtilities/GULLoggerLevel.h> - -#import "GULNetworkMessageCode.h" - -/// The log levels used by GULNetworkLogger. -typedef NS_ENUM(NSInteger, GULNetworkLogLevel) { - kGULNetworkLogLevelError = GULLoggerLevelError, - kGULNetworkLogLevelWarning = GULLoggerLevelWarning, - kGULNetworkLogLevelInfo = GULLoggerLevelInfo, - kGULNetworkLogLevelDebug = GULLoggerLevelDebug, -}; - -@protocol GULNetworkLoggerDelegate <NSObject> - -@required -/// Tells the delegate to log a message with an array of contexts and the log level. -- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel - messageCode:(GULNetworkMessageCode)messageCode - message:(NSString *)message - contexts:(NSArray *)contexts; - -/// Tells the delegate to log a message with a context and the log level. -- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel - messageCode:(GULNetworkMessageCode)messageCode - message:(NSString *)message - context:(id)context; - -/// Tells the delegate to log a message with the log level. -- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel - messageCode:(GULNetworkMessageCode)messageCode - message:(NSString *)message; - -@end diff --git a/Firebase/Utilities/Network/Private/GULNetworkMessageCode.h b/Firebase/Utilities/Network/Private/GULNetworkMessageCode.h deleted file mode 100644 index ce78e60..0000000 --- a/Firebase/Utilities/Network/Private/GULNetworkMessageCode.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. -typedef NS_ENUM(NSInteger, GULNetworkMessageCode) { - // GULNetwork.m - kGULNetworkMessageCodeNetwork000 = 900000, // I-NET900000 - kGULNetworkMessageCodeNetwork001 = 900001, // I-NET900001 - kGULNetworkMessageCodeNetwork002 = 900002, // I-NET900002 - kGULNetworkMessageCodeNetwork003 = 900003, // I-NET900003 - // GULNetworkURLSession.m - kGULNetworkMessageCodeURLSession000 = 901000, // I-NET901000 - kGULNetworkMessageCodeURLSession001 = 901001, // I-NET901001 - kGULNetworkMessageCodeURLSession002 = 901002, // I-NET901002 - kGULNetworkMessageCodeURLSession003 = 901003, // I-NET901003 - kGULNetworkMessageCodeURLSession004 = 901004, // I-NET901004 - kGULNetworkMessageCodeURLSession005 = 901005, // I-NET901005 - kGULNetworkMessageCodeURLSession006 = 901006, // I-NET901006 - kGULNetworkMessageCodeURLSession007 = 901007, // I-NET901007 - kGULNetworkMessageCodeURLSession008 = 901008, // I-NET901008 - kGULNetworkMessageCodeURLSession009 = 901009, // I-NET901009 - kGULNetworkMessageCodeURLSession010 = 901010, // I-NET901010 - kGULNetworkMessageCodeURLSession011 = 901011, // I-NET901011 - kGULNetworkMessageCodeURLSession012 = 901012, // I-NET901012 - kGULNetworkMessageCodeURLSession013 = 901013, // I-NET901013 - kGULNetworkMessageCodeURLSession014 = 901014, // I-NET901014 - kGULNetworkMessageCodeURLSession015 = 901015, // I-NET901015 - kGULNetworkMessageCodeURLSession016 = 901016, // I-NET901016 - kGULNetworkMessageCodeURLSession017 = 901017, // I-NET901017 - kGULNetworkMessageCodeURLSession018 = 901018, // I-NET901018 -}; diff --git a/Firebase/Utilities/Network/Private/GULNetworkURLSession.h b/Firebase/Utilities/Network/Private/GULNetworkURLSession.h deleted file mode 100644 index 81190c6..0000000 --- a/Firebase/Utilities/Network/Private/GULNetworkURLSession.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import <Foundation/Foundation.h> - -#import "GULNetworkLoggerProtocol.h" - -typedef void (^GULNetworkCompletionHandler)(NSHTTPURLResponse *response, - NSData *data, - NSError *error); -typedef void (^GULNetworkURLSessionCompletionHandler)(NSHTTPURLResponse *response, - NSData *data, - NSString *sessionID, - NSError *error); -typedef void (^GULNetworkSystemCompletionHandler)(void); - -/// The protocol that uses NSURLSession for iOS >= 7.0 to handle requests and responses. -@interface GULNetworkURLSession - : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate> - -/// Indicates whether the background network is enabled. Default value is NO. -@property(nonatomic, getter=isBackgroundNetworkEnabled) BOOL backgroundNetworkEnabled; - -/// The logger delegate to log message, errors or warnings that occur during the network operations. -@property(nonatomic, weak) id<GULNetworkLoggerDelegate> loggerDelegate; - -/// Calls the system provided completion handler after the background session is finished. -+ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID - completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; - -/// Initializes with logger delegate. -- (instancetype)initWithNetworkLoggerDelegate:(id<GULNetworkLoggerDelegate>)networkLoggerDelegate - NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -/// Sends an asynchronous POST request and calls the provided completion handler when the request -/// completes or when errors occur, and returns an ID of the session/connection. -- (NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request - completionHandler:(GULNetworkURLSessionCompletionHandler)handler; - -/// Sends an asynchronous GET request and calls the provided completion handler when the request -/// completes or when errors occur, and returns an ID of the session. -- (NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request - completionHandler:(GULNetworkURLSessionCompletionHandler)handler; - -@end |