diff options
Diffstat (limited to 'Firebase/Core/FIRNetwork.m')
-rw-r--r-- | Firebase/Core/FIRNetwork.m | 390 |
1 files changed, 0 insertions, 390 deletions
diff --git a/Firebase/Core/FIRNetwork.m b/Firebase/Core/FIRNetwork.m deleted file mode 100644 index ff292fc..0000000 --- a/Firebase/Core/FIRNetwork.m +++ /dev/null @@ -1,390 +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/FIRNetwork.h" -#import "Private/FIRNetworkMessageCode.h" - -#import "Private/FIRLogger.h" -#import "Private/FIRMutableDictionary.h" -#import "Private/FIRNetworkConstants.h" -#import "Private/FIRReachabilityChecker.h" - -#import <GoogleToolboxForMac/GTMNSData+zlib.h> - -/// Constant string for request header Content-Encoding. -static NSString *const kFIRNetworkContentCompressionKey = @"Content-Encoding"; - -/// Constant string for request header Content-Encoding value. -static NSString *const kFIRNetworkContentCompressionValue = @"gzip"; - -/// Constant string for request header Content-Length. -static NSString *const kFIRNetworkContentLengthKey = @"Content-Length"; - -/// Constant string for request header Content-Type. -static NSString *const kFIRNetworkContentTypeKey = @"Content-Type"; - -/// Constant string for request header Content-Type value. -static NSString *const kFIRNetworkContentTypeValue = @"application/x-www-form-urlencoded"; - -/// Constant string for GET request method. -static NSString *const kFIRNetworkGETRequestMethod = @"GET"; - -/// Constant string for POST request method. -static NSString *const kFIRNetworkPOSTRequestMethod = @"POST"; - -/// Default constant string as a prefix for network logger. -static NSString *const kFIRNetworkLogTag = @"Firebase/Network"; - -@interface FIRNetwork () <FIRReachabilityDelegate, FIRNetworkLoggerDelegate> -@end - -@implementation FIRNetwork { - /// Network reachability. - FIRReachabilityChecker *_reachability; - - /// The dictionary of requests by session IDs { NSString : id }. - FIRMutableDictionary *_requests; -} - -- (instancetype)init { - return [self initWithReachabilityHost:kFIRNetworkReachabilityHost]; -} - -- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost { - self = [super init]; - if (self) { - // Setup reachability. - _reachability = [[FIRReachabilityChecker alloc] initWithReachabilityDelegate:self - loggerDelegate:self - withHost:reachabilityHost]; - if (![_reachability start]) { - return nil; - } - - _requests = [[FIRMutableDictionary alloc] init]; - _timeoutInterval = kFIRNetworkTimeOutInterval; - } - return self; -} - -- (void)dealloc { - _reachability.reachabilityDelegate = nil; - [_reachability stop]; -} - -#pragma mark - External Methods - -+ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID - completionHandler:(FIRNetworkSystemCompletionHandler)completionHandler { - [FIRNetworkURLSession handleEventsForBackgroundURLSessionID:sessionID - completionHandler:completionHandler]; -} - -- (NSString *)postURL:(NSURL *)url - payload:(NSData *)payload - queue:(dispatch_queue_t)queue - usingBackgroundSession:(BOOL)usingBackgroundSession - completionHandler:(FIRNetworkCompletionHandler)handler { - if (!url.absoluteString.length) { - [self handleErrorWithCode:FIRErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; - return nil; - } - - NSTimeInterval timeOutInterval = _timeoutInterval ?: kFIRNetworkTimeOutInterval; - - NSMutableURLRequest *request = - [[NSMutableURLRequest alloc] initWithURL:url - cachePolicy:NSURLRequestReloadIgnoringLocalCacheData - timeoutInterval:timeOutInterval]; - - if (!request) { - [self handleErrorWithCode:FIRErrorCodeNetworkSessionTaskCreation - queue:queue - withHandler:handler]; - return nil; - } - - NSError *compressError = nil; - NSData *compressedData = [NSData gtm_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:FIRErrorCodeNetworkPayloadCompression - 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:kFIRNetworkContentLengthKey]; - request.HTTPBody = compressedData; - request.HTTPMethod = kFIRNetworkPOSTRequestMethod; - [request setValue:kFIRNetworkContentTypeValue forHTTPHeaderField:kFIRNetworkContentTypeKey]; - [request setValue:kFIRNetworkContentCompressionValue - forHTTPHeaderField:kFIRNetworkContentCompressionKey]; - - FIRNetworkURLSession *fetcher = [[FIRNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; - fetcher.backgroundNetworkEnabled = usingBackgroundSession; - - __weak FIRNetwork *weakSelf = self; - NSString *requestID = [fetcher - sessionIDFromAsyncPOSTRequest:request - completionHandler:^(NSHTTPURLResponse *response, NSData *data, - NSString *sessionID, NSError *error) { - FIRNetwork *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:FIRErrorCodeNetworkSessionTaskCreation - queue:queue - withHandler:handler]; - return nil; - } - - [self firNetwork_logWithLevel:kFIRNetworkLogLevelDebug - messageCode:kFIRNetworkMessageCodeNetwork000 - 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:(FIRNetworkCompletionHandler)handler { - if (!url.absoluteString.length) { - [self handleErrorWithCode:FIRErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; - return nil; - } - - NSTimeInterval timeOutInterval = _timeoutInterval ?: kFIRNetworkTimeOutInterval; - NSMutableURLRequest *request = - [[NSMutableURLRequest alloc] initWithURL:url - cachePolicy:NSURLRequestReloadIgnoringLocalCacheData - timeoutInterval:timeOutInterval]; - - if (!request) { - [self handleErrorWithCode:FIRErrorCodeNetworkSessionTaskCreation - queue:queue - withHandler:handler]; - return nil; - } - - request.HTTPMethod = kFIRNetworkGETRequestMethod; - request.allHTTPHeaderFields = headers; - - FIRNetworkURLSession *fetcher = [[FIRNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; - fetcher.backgroundNetworkEnabled = usingBackgroundSession; - - __weak FIRNetwork *weakSelf = self; - NSString *requestID = [fetcher - sessionIDFromAsyncGETRequest:request - completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSString *sessionID, - NSError *error) { - FIRNetwork *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:FIRErrorCodeNetworkSessionTaskCreation - queue:queue - withHandler:handler]; - return nil; - } - - [self firNetwork_logWithLevel:kFIRNetworkLogLevelDebug - messageCode:kFIRNetworkMessageCodeNetwork001 - 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:(FIRReachabilityChecker *)reachability - statusChanged:(FIRReachabilityStatus)status { - _networkConnected = (status == kFIRReachabilityViaCellular || status == kFIRReachabilityViaWifi); - [_reachabilityDelegate reachabilityDidChange]; -} - -#pragma mark - Network logger delegate - -- (void)setLoggerDelegate:(id<FIRNetworkLoggerDelegate>)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(firNetwork_logWithLevel:messageCode:message:contexts:)] || - ![loggerDelegate - respondsToSelector:@selector(firNetwork_logWithLevel:messageCode:message:context:)] || - ! - [loggerDelegate respondsToSelector:@selector(firNetwork_logWithLevel:messageCode:message:)]) { - FIRLogError(kFIRLoggerAnalytics, - [NSString stringWithFormat:@"I-NET%06ld", (long)kFIRNetworkMessageCodeNetwork002], - @"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:(FIRNetworkCompletionHandler)handler { - NSDictionary *userInfo = @{kFIRNetworkErrorContext : @"Failed to create network request"}; - NSError *error = - [[NSError alloc] initWithDomain:kFIRNetworkErrorDomain code:code userInfo:userInfo]; - [self firNetwork_logWithLevel:kFIRNetworkLogLevelWarning - messageCode:kFIRNetworkMessageCodeNetwork002 - 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)firNetwork_logWithLevel:(FIRNetworkLogLevel)logLevel - messageCode:(FIRNetworkMessageCode)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 firNetwork_logWithLevel:logLevel - messageCode:messageCode - message:message - contexts:contexts]; - return; - } - if (_isDebugModeEnabled || logLevel == kFIRNetworkLogLevelError || - logLevel == kFIRNetworkLogLevelWarning || logLevel == kFIRNetworkLogLevelInfo) { - NSString *formattedMessage = FIRStringWithLogMessage(message, logLevel, contexts); - NSLog(@"%@", formattedMessage); - FIRLogBasic((FIRLoggerLevel)logLevel, kFIRLoggerCore, - [NSString stringWithFormat:@"I-NET%06ld", (long)messageCode], formattedMessage, - NULL); - } -} - -- (void)firNetwork_logWithLevel:(FIRNetworkLogLevel)logLevel - messageCode:(FIRNetworkMessageCode)messageCode - message:(NSString *)message - context:(id)context { - if (_loggerDelegate) { - [_loggerDelegate firNetwork_logWithLevel:logLevel - messageCode:messageCode - message:message - context:context]; - return; - } - NSArray *contexts = context ? @[ context ] : @[]; - [self firNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:contexts]; -} - -- (void)firNetwork_logWithLevel:(FIRNetworkLogLevel)logLevel - messageCode:(FIRNetworkMessageCode)messageCode - message:(NSString *)message { - if (_loggerDelegate) { - [_loggerDelegate firNetwork_logWithLevel:logLevel messageCode:messageCode message:message]; - return; - } - [self firNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:@[]]; -} - -/// Returns a string for the given log level (e.g. kFIRNetworkLogLevelError -> @"ERROR"). -static NSString *FIRLogLevelDescriptionFromLogLevel(FIRNetworkLogLevel logLevel) { - static NSDictionary *levelNames = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - levelNames = @{ - @(kFIRNetworkLogLevelError) : @"ERROR", - @(kFIRNetworkLogLevelWarning) : @"WARNING", - @(kFIRNetworkLogLevelInfo) : @"INFO", - @(kFIRNetworkLogLevelDebug) : @"DEBUG" - }; - }); - return levelNames[@(logLevel)]; -} - -/// Returns a formatted string to be used for console logging. -static NSString *FIRStringWithLogMessage(NSString *message, - FIRNetworkLogLevel logLevel, - NSArray *contexts) { - if (!message) { - message = @"(Message was nil)"; - } else if (!message.length) { - message = @"(Message was empty)"; - } - NSMutableString *result = [[NSMutableString alloc] - initWithFormat:@"<%@/%@> %@", kFIRNetworkLogTag, FIRLogLevelDescriptionFromLogLevel(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 |