diff options
author | Paul Beusterien <paulbeusterien@google.com> | 2018-07-11 08:28:35 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-11 08:28:35 -0700 |
commit | c6b4b03fffc3cea7c9525e5c79dce28f52900521 (patch) | |
tree | 0e8a237940dcd4b4100c00b9fac428e657619ab8 /Firebase | |
parent | 25f8691970a9f765a87ab3125776598c92e02744 (diff) |
Move GoogleUtilities out of Firebase directory (#1516)
Diffstat (limited to 'Firebase')
21 files changed, 0 insertions, 2887 deletions
diff --git a/Firebase/Utilities/Environment/third_party/GULAppEnvironmentUtil.h b/Firebase/Utilities/Environment/third_party/GULAppEnvironmentUtil.h deleted file mode 100644 index 5b56271..0000000 --- a/Firebase/Utilities/Environment/third_party/GULAppEnvironmentUtil.h +++ /dev/null @@ -1,43 +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> - -@interface GULAppEnvironmentUtil : NSObject - -/// Indicates whether the app is from Apple Store or not. Returns NO if the app is on simulator, -/// development environment or sideloaded. -+ (BOOL)isFromAppStore; - -/// Indicates whether the app is a Testflight app. Returns YES if the app has sandbox receipt. -/// Returns NO otherwise. -+ (BOOL)isAppStoreReceiptSandbox; - -/// Indicates whether the app is on simulator or not at runtime depending on the device -/// architecture. -+ (BOOL)isSimulator; - -/// The current device model. Returns an empty string if device model cannot be retrieved. -+ (NSString *)deviceModel; - -/// The current operating system version. Returns an empty string if the system version cannot be -/// retrieved. -+ (NSString *)systemVersion; - -/// Indicates whether it is running inside an extension or an app. -+ (BOOL)isAppExtension; - -@end diff --git a/Firebase/Utilities/Environment/third_party/GULAppEnvironmentUtil.m b/Firebase/Utilities/Environment/third_party/GULAppEnvironmentUtil.m deleted file mode 100644 index e96ba70..0000000 --- a/Firebase/Utilities/Environment/third_party/GULAppEnvironmentUtil.m +++ /dev/null @@ -1,236 +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 "GULAppEnvironmentUtil.h" - -#import <Foundation/Foundation.h> -#import <dlfcn.h> -#import <mach-o/dyld.h> -#import <sys/utsname.h> - -/// The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from -/// the iPhoneOS or Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just -/// provide the definitions here. -#if TARGET_OS_SIMULATOR && !defined(LC_ENCRYPTION_INFO) -#define LC_ENCRYPTION_INFO 0x21 -struct encryption_info_command { - uint32_t cmd; - uint32_t cmdsize; - uint32_t cryptoff; - uint32_t cryptsize; - uint32_t cryptid; -}; -#endif - -@implementation GULAppEnvironmentUtil - -/// A key for the Info.plist to enable or disable checking if the App Store is running in a sandbox. -/// This will affect your data integrity when using Firebase Analytics, as it will disable some -/// necessary checks. -static NSString *const kFIRAppStoreReceiptURLCheckEnabledKey = - @"FirebaseAppStoreReceiptURLCheckEnabled"; - -/// The file name of the sandbox receipt. This is available on iOS >= 8.0 -static NSString *const kFIRAIdentitySandboxReceiptFileName = @"sandboxReceipt"; - -/// The following copyright from Landon J. Fuller applies to the isAppEncrypted function. -/// -/// Copyright (c) 2017 Landon J. Fuller <landon@landonf.org> -/// All rights reserved. -/// -/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software -/// and associated documentation files (the "Software"), to deal in the Software without -/// restriction, including without limitation the rights to use, copy, modify, merge, publish, -/// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the -/// Software is furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in all copies or -/// substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -/// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -/// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -/// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -/// -/// Comment from <a href="http://iphonedevwiki.net/index.php/Crack_prevention">iPhone Dev Wiki -/// Crack Prevention</a>: -/// App Store binaries are signed by both their developer and Apple. This encrypts the binary so -/// that decryption keys are needed in order to make the binary readable. When iOS executes the -/// binary, the decryption keys are used to decrypt the binary into a readable state where it is -/// then loaded into memory and executed. iOS can tell the encryption status of a binary via the -/// cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is a non-zero -/// value then the binary is encrypted. -/// -/// 'Cracking' works by letting the kernel decrypt the binary then siphoning the decrypted data into -/// a new binary file, resigning, and repackaging. This will only work on jailbroken devices as -/// codesignature validation has been removed. Resigning takes place because while the codesignature -/// doesn't have to be valid thanks to the jailbreak, it does have to be in place unless you have -/// AppSync or similar to disable codesignature checks. -/// -/// More information at <a href="http://landonf.org/2009/02/index.html">Landon Fuller's blog</a> -static BOOL IsAppEncrypted() { - const struct mach_header *executableHeader = NULL; - for (uint32_t i = 0; i < _dyld_image_count(); i++) { - const struct mach_header *header = _dyld_get_image_header(i); - if (header && header->filetype == MH_EXECUTE) { - executableHeader = header; - break; - } - } - - if (!executableHeader) { - return NO; - } - - BOOL is64bit = (executableHeader->magic == MH_MAGIC_64); - uintptr_t cursor = (uintptr_t)executableHeader + - (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header)); - const struct segment_command *segmentCommand = NULL; - uint32_t i = 0; - - while (i++ < executableHeader->ncmds) { - segmentCommand = (struct segment_command *)cursor; - - if (!segmentCommand) { - continue; - } - - if ((!is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO) || - (is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO_64)) { - if (is64bit) { - struct encryption_info_command_64 *cryptCmd = - (struct encryption_info_command_64 *)segmentCommand; - return cryptCmd && cryptCmd->cryptid != 0; - } else { - struct encryption_info_command *cryptCmd = (struct encryption_info_command *)segmentCommand; - return cryptCmd && cryptCmd->cryptid != 0; - } - } - cursor += segmentCommand->cmdsize; - } - - return NO; -} - -static BOOL HasSCInfoFolder() { -#if TARGET_OS_IOS || TARGET_OS_TV - NSString *bundlePath = [NSBundle mainBundle].bundlePath; - NSString *scInfoPath = [bundlePath stringByAppendingPathComponent:@"SC_Info"]; - return [[NSFileManager defaultManager] fileExistsAtPath:scInfoPath]; -#elif TARGET_OS_OSX - return NO; -#endif -} - -static BOOL HasEmbeddedMobileProvision() { -#if TARGET_OS_IOS || TARGET_OS_TV - return [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"].length > 0; -#elif TARGET_OS_OSX - return NO; -#endif -} - -+ (BOOL)isFromAppStore { - static dispatch_once_t isEncryptedOnce; - static BOOL isEncrypted = NO; - - dispatch_once(&isEncryptedOnce, ^{ - isEncrypted = IsAppEncrypted(); - }); - - if ([GULAppEnvironmentUtil isSimulator]) { - return NO; - } - - // If an app contain the sandboxReceipt file, it means its coming from TestFlight - // This must be checked before the SCInfo Folder check below since TestFlight apps may - // also have an SCInfo folder. - if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox]) { - return NO; - } - - if (HasSCInfoFolder()) { - // When iTunes downloads a .ipa, it also gets a customized .sinf file which is added to the - // main SC_Info directory. - return YES; - } - - // For iOS >= 8.0, iTunesMetadata.plist is moved outside of the sandbox. Any attempt to read - // the iTunesMetadata.plist outside of the sandbox will be rejected by Apple. - // If the app does not contain the embedded.mobileprovision which is stripped out by Apple when - // the app is submitted to store, then it is highly likely that it is from Apple Store. - return isEncrypted && !HasEmbeddedMobileProvision(); -} - -+ (BOOL)isAppStoreReceiptSandbox { - // Since checking the App Store's receipt URL can be memory intensive, check the option in the - // Info.plist if developers opted out of this check. - id enableSandboxCheck = - [[NSBundle mainBundle] objectForInfoDictionaryKey:kFIRAppStoreReceiptURLCheckEnabledKey]; - if (enableSandboxCheck && [enableSandboxCheck isKindOfClass:[NSNumber class]] && - ![enableSandboxCheck boolValue]) { - return NO; - } - - NSURL *appStoreReceiptURL = [NSBundle mainBundle].appStoreReceiptURL; - NSString *appStoreReceiptFileName = appStoreReceiptURL.lastPathComponent; - return [appStoreReceiptFileName isEqualToString:kFIRAIdentitySandboxReceiptFileName]; -} - -+ (BOOL)isSimulator { -#if TARGET_OS_IOS || TARGET_OS_TV - NSString *platform = [GULAppEnvironmentUtil deviceModel]; - return [platform isEqual:@"x86_64"] || [platform isEqual:@"i386"]; -#elif TARGET_OS_OSX - return NO; -#endif -} - -+ (NSString *)deviceModel { - static dispatch_once_t once; - static NSString *deviceModel; - - dispatch_once(&once, ^{ - struct utsname systemInfo; - if (uname(&systemInfo) == 0) { - deviceModel = [NSString stringWithUTF8String:systemInfo.machine]; - } - }); - return deviceModel; -} - -+ (NSString *)systemVersion { - // Assemble the systemVersion, excluding the patch version if it's 0. - NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion; - NSMutableString *versionString = [[NSMutableString alloc] - initWithFormat:@"%ld.%ld", (long)osVersion.majorVersion, (long)osVersion.minorVersion]; - if (osVersion.patchVersion != 0) { - [versionString appendFormat:@".%ld", (long)osVersion.patchVersion]; - } - - return versionString; -} - -+ (BOOL)isAppExtension { -#if TARGET_OS_IOS || TARGET_OS_TV - // Documented by <a href="https://goo.gl/RRB2Up">Apple</a> - BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; - return appExtension; -#elif TARGET_OS_OSX - return NO; -#endif -} - -@end diff --git a/Firebase/Utilities/Logger/GULLogger.m b/Firebase/Utilities/Logger/GULLogger.m deleted file mode 100644 index 5c808ea..0000000 --- a/Firebase/Utilities/Logger/GULLogger.m +++ /dev/null @@ -1,214 +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 "Private/GULLogger.h" - -#include <asl.h> - -#import <GoogleUtilities/GULAppEnvironmentUtil.h> -#import "Public/GULLoggerLevel.h" - -/// Key for the debug mode bit in NSUserDefaults. -NSString *const kGULPersistedDebugModeKey = @"/google/utilities/debug_mode"; - -/// ASL client facility name used by GULLogger. -const char *kGULLoggerASLClientFacilityName = "com.google.utilities.logger"; - -static dispatch_once_t sGULLoggerOnceToken; - -static aslclient sGULLoggerClient; - -static dispatch_queue_t sGULClientQueue; - -static BOOL sGULLoggerDebugMode; - -static GULLoggerLevel sGULLoggerMaximumLevel; - -// Allow clients to register a version to include in the log. -static const char *sVersion = ""; - -static GULLoggerService kGULLoggerLogger = @"[GULLogger]"; - -#ifdef DEBUG -/// The regex pattern for the message code. -static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; -static NSRegularExpression *sMessageCodeRegex; -#endif - -void GULLoggerInitializeASL(BOOL overrideSTDERR, BOOL forceDebugMode) { - dispatch_once(&sGULLoggerOnceToken, ^{ - NSInteger majorOSVersion = [[GULAppEnvironmentUtil systemVersion] integerValue]; - uint32_t aslOptions = ASL_OPT_STDERR; -#if TARGET_OS_SIMULATOR - // The iOS 11 simulator doesn't need the ASL_OPT_STDERR flag. - if (majorOSVersion >= 11) { - aslOptions = 0; - } -#else - // Devices running iOS 10 or higher don't need the ASL_OPT_STDERR flag. - if (majorOSVersion >= 10) { - aslOptions = 0; - } -#endif // TARGET_OS_SIMULATOR - - // Override the aslOptions to ASL_OPT_STDERR if the override argument is passed in. - if (overrideSTDERR) { - aslOptions = ASL_OPT_STDERR; - } - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" // asl is deprecated - // Initialize the ASL client handle. - sGULLoggerClient = asl_open(NULL, kGULLoggerASLClientFacilityName, aslOptions); - sGULLoggerDebugMode = forceDebugMode; - sGULLoggerMaximumLevel = GULLoggerLevelNotice; - - if (forceDebugMode) { - asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); - } else { - // Set the filter used by system/device log. Initialize in default mode. - asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE)); - } - - // We should disable debug mode if we are running from App Store. - if (sGULLoggerDebugMode && [GULAppEnvironmentUtil isFromAppStore]) { - sGULLoggerDebugMode = NO; - } - - sGULClientQueue = dispatch_queue_create("GULLoggingClientQueue", DISPATCH_QUEUE_SERIAL); - dispatch_set_target_queue(sGULClientQueue, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); - -#ifdef DEBUG - sMessageCodeRegex = - [NSRegularExpression regularExpressionWithPattern:kMessageCodePattern options:0 error:NULL]; -#endif - }); -} - -void GULSetLoggerLevel(GULLoggerLevel loggerLevel) { - if (loggerLevel < GULLoggerLevelMin || loggerLevel > GULLoggerLevelMax) { - GULLogError(kGULLoggerLogger, NO, @"I-COR000023", @"Invalid logger level, %ld", - (long)loggerLevel); - return; - } - GULLoggerInitializeASL(NO, NO); - // We should not raise the logger level if we are running from App Store. - if (loggerLevel >= GULLoggerLevelNotice && [GULAppEnvironmentUtil isFromAppStore]) { - return; - } - - sGULLoggerMaximumLevel = loggerLevel; - dispatch_async(sGULClientQueue, ^{ - asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(loggerLevel)); - }); -} - -/** - * Check if the level is high enough to be loggable. - */ -__attribute__((no_sanitize("thread"))) BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel) { - GULLoggerInitializeASL(NO, NO); - if (sGULLoggerDebugMode) { - return YES; - } - return (BOOL)(loggerLevel <= sGULLoggerMaximumLevel); -} - -#ifdef DEBUG -void GULResetLogger() { - sGULLoggerOnceToken = 0; -} - -aslclient getGULLoggerClient() { - return sGULLoggerClient; -} - -dispatch_queue_t getGULClientQueue() { - return sGULClientQueue; -} - -BOOL getGULLoggerDebugMode() { - return sGULLoggerDebugMode; -} -#endif - -void GULLoggerRegisterVersion(const char *version) { - sVersion = version; -} - -void GULLogBasic(GULLoggerLevel level, - GULLoggerService service, - BOOL forceLog, - NSString *messageCode, - NSString *message, - va_list args_ptr) { - GULLoggerInitializeASL(NO, NO); - if (!(level <= sGULLoggerMaximumLevel || sGULLoggerDebugMode || forceLog)) { - return; - } - -#ifdef DEBUG - NSCAssert(messageCode.length == 11, @"Incorrect message code length."); - NSRange messageCodeRange = NSMakeRange(0, messageCode.length); - NSUInteger numberOfMatches = - [sMessageCodeRegex numberOfMatchesInString:messageCode options:0 range:messageCodeRange]; - NSCAssert(numberOfMatches == 1, @"Incorrect message code format."); -#endif - NSString *logMsg = [[NSString alloc] initWithFormat:message arguments:args_ptr]; - logMsg = [NSString stringWithFormat:@"%s - %@[%@] %@", sVersion, service, messageCode, logMsg]; - dispatch_async(sGULClientQueue, ^{ - asl_log(sGULLoggerClient, NULL, level, "%s", logMsg.UTF8String); - }); -} -#pragma clang diagnostic pop - -/** - * Generates the logging functions using macros. - * - * Calling GULLogError(kGULLoggerCore, @"I-COR000001", @"Configure %@ failed.", @"blah") shows: - * yyyy-mm-dd hh:mm:ss.SSS sender[PID] <Error> [{service}][I-COR000001] Configure blah failed. - * Calling GULLogDebug(kGULLoggerCore, @"I-COR000001", @"Configure succeed.") shows: - * yyyy-mm-dd hh:mm:ss.SSS sender[PID] <Debug> [{service}][I-COR000001] Configure succeed. - */ -#define GUL_LOGGING_FUNCTION(level) \ - void GULLog##level(GULLoggerService service, BOOL force, NSString *messageCode, \ - NSString *message, ...) { \ - va_list args_ptr; \ - va_start(args_ptr, message); \ - GULLogBasic(GULLoggerLevel##level, service, force, messageCode, message, args_ptr); \ - va_end(args_ptr); \ - } - -GUL_LOGGING_FUNCTION(Error) -GUL_LOGGING_FUNCTION(Warning) -GUL_LOGGING_FUNCTION(Notice) -GUL_LOGGING_FUNCTION(Info) -GUL_LOGGING_FUNCTION(Debug) - -#undef GUL_MAKE_LOGGER - -#pragma mark - GULLoggerWrapper - -@implementation GULLoggerWrapper - -+ (void)logWithLevel:(GULLoggerLevel)level - withService:(GULLoggerService)service - withCode:(NSString *)messageCode - withMessage:(NSString *)message - withArgs:(va_list)args { - GULLogBasic(level, service, NO, messageCode, message, args); -} - -@end diff --git a/Firebase/Utilities/Logger/Private/GULLogger.h b/Firebase/Utilities/Logger/Private/GULLogger.h deleted file mode 100644 index c8b12e8..0000000 --- a/Firebase/Utilities/Logger/Private/GULLogger.h +++ /dev/null @@ -1,151 +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 <Foundation/Foundation.h> - -#import <GoogleUtilities/GULLoggerLevel.h> - -NS_ASSUME_NONNULL_BEGIN - -/** - * The services used in the logger. - */ -typedef NSString *const GULLoggerService; - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/** - * Initialize GULLogger. - * (required) overrideSTDERR Override the aslOptions to ASL_OPT_STDERR. - * (required) forceDebugMode Force the asl level to ASL_LEVEL_DEBUG. - */ -extern void GULLoggerInitializeASL(BOOL overrideSTDERR, BOOL forceDebugMode); - -/** - * Changes the default logging level of GULLoggerLevelNotice to a user-specified level. - * The default level cannot be set above GULLoggerLevelNotice if the app is running from App Store. - * (required) log level (one of the GULLoggerLevel enum values). - */ -extern void GULSetLoggerLevel(GULLoggerLevel loggerLevel); - -/** - * Checks if the specified logger level is loggable given the current settings. - * (required) log level (one of the GULLoggerLevel enum values). - */ -extern BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel); - -/** - * Register version to include in logs. - * (required) version - */ -extern void GULLoggerRegisterVersion(const char *version); - -/** - * Logs a message to the Xcode console and the device log. If running from AppStore, will - * not log any messages with a level higher than GULLoggerLevelNotice to avoid log spamming. - * (required) log level (one of the GULLoggerLevel enum values). - * (required) service name of type GULLoggerService. - * (required) message code starting with "I-" which means iOS, followed by a capitalized - * three-character service identifier and a six digit integer message ID that is unique - * within the service. - * An example of the message code is @"I-COR000001". - * (required) message string which can be a format string. - * (optional) variable arguments list obtained from calling va_start, used when message is a format - * string. - */ -extern void GULLogBasic(GULLoggerLevel level, - GULLoggerService service, - BOOL forceLog, - NSString *messageCode, - NSString *message, -// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable -// See: http://stackoverflow.com/q/29095469 -#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX - va_list args_ptr -#else - va_list _Nullable args_ptr -#endif -); - -/** - * The following functions accept the following parameters in order: - * (required) service name of type GULLoggerService. - * (required) message code starting from "I-" which means iOS, followed by a capitalized - * three-character service identifier and a six digit integer message ID that is unique - * within the service. - * An example of the message code is @"I-COR000001". - * See go/firebase-log-proposal for details. - * (required) message string which can be a format string. - * (optional) the list of arguments to substitute into the format string. - * Example usage: - * GULLogError(kGULLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); - */ -extern void GULLogError(GULLoggerService service, - BOOL force, - NSString *messageCode, - NSString *message, - ...) NS_FORMAT_FUNCTION(4, 5); -extern void GULLogWarning(GULLoggerService service, - BOOL force, - NSString *messageCode, - NSString *message, - ...) NS_FORMAT_FUNCTION(4, 5); -extern void GULLogNotice(GULLoggerService service, - BOOL force, - NSString *messageCode, - NSString *message, - ...) NS_FORMAT_FUNCTION(4, 5); -extern void GULLogInfo(GULLoggerService service, - BOOL force, - NSString *messageCode, - NSString *message, - ...) NS_FORMAT_FUNCTION(4, 5); -extern void GULLogDebug(GULLoggerService service, - BOOL force, - NSString *messageCode, - NSString *message, - ...) NS_FORMAT_FUNCTION(4, 5); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -@interface GULLoggerWrapper : NSObject - -/** - * Objective-C wrapper for GULLogBasic to allow weak linking to GULLogger - * (required) log level (one of the GULLoggerLevel enum values). - * (required) service name of type GULLoggerService. - * (required) message code starting with "I-" which means iOS, followed by a capitalized - * three-character service identifier and a six digit integer message ID that is unique - * within the service. - * An example of the message code is @"I-COR000001". - * (required) message string which can be a format string. - * (optional) variable arguments list obtained from calling va_start, used when message is a format - * string. - */ - -+ (void)logWithLevel:(GULLoggerLevel)level - withService:(GULLoggerService)service - withCode:(NSString *)messageCode - withMessage:(NSString *)message - withArgs:(va_list)args; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firebase/Utilities/Logger/Public/GULLoggerLevel.h b/Firebase/Utilities/Logger/Public/GULLoggerLevel.h deleted file mode 100644 index 81ff212..0000000 --- a/Firebase/Utilities/Logger/Public/GULLoggerLevel.h +++ /dev/null @@ -1,35 +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. - */ - -/** - * The log levels used by internal logging. - */ -typedef NS_ENUM(NSInteger, GULLoggerLevel) { - /** Error level, matches ASL_LEVEL_ERR. */ - GULLoggerLevelError = 3, - /** Warning level, matches ASL_LEVEL_WARNING. */ - GULLoggerLevelWarning = 4, - /** Notice level, matches ASL_LEVEL_NOTICE. */ - GULLoggerLevelNotice = 5, - /** Info level, matches ASL_LEVEL_INFO. */ - GULLoggerLevelInfo = 6, - /** Debug level, matches ASL_LEVEL_DEBUG. */ - GULLoggerLevelDebug = 7, - /** Minimum log level. */ - GULLoggerLevelMin = GULLoggerLevelError, - /** Maximum log level. */ - GULLoggerLevelMax = GULLoggerLevelDebug -} NS_SWIFT_NAME(GoogleLoggerLevel); diff --git a/Firebase/Utilities/NSData+zlib/GULNSData+zlib.h b/Firebase/Utilities/NSData+zlib/GULNSData+zlib.h deleted file mode 100644 index 36f94a7..0000000 --- a/Firebase/Utilities/NSData+zlib/GULNSData+zlib.h +++ /dev/null @@ -1,49 +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 <Foundation/Foundation.h> - -/// This is a copy of Google Toolbox for Mac library to avoid creating an extra framework. - -// NOTE: For 64bit, none of these apis handle input sizes >32bits, they will return nil when given -// such data. To handle data of that size you really should be streaming it rather then doing it all -// in memory. - -@interface NSData (GULGzip) - -/// Returns an data as the result of decompressing the payload of |data|.The data to decompress must -/// be a gzipped payloads. -+ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error; - -/// Returns an compressed data with the result of gzipping the payload of |data|. Uses the default -/// compression level. -+ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error; - -FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorDomain; -FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorKey; // NSNumber -FOUNDATION_EXPORT NSString *const GULNSDataZlibRemainingBytesKey; // NSNumber - -typedef NS_ENUM(NSInteger, GULNSDataZlibError) { - GULNSDataZlibErrorGreaterThan32BitsToCompress = 1024, - // An internal zlib error. - // GULNSDataZlibErrorKey will contain the error value. - // NSLocalizedDescriptionKey may contain an error string from zlib. - // Look in zlib.h for list of errors. - GULNSDataZlibErrorInternal, - // There was left over data in the buffer that was not used. - // GULNSDataZlibRemainingBytesKey will contain number of remaining bytes. - GULNSDataZlibErrorDataRemaining -}; - -@end diff --git a/Firebase/Utilities/NSData+zlib/GULNSData+zlib.m b/Firebase/Utilities/NSData+zlib/GULNSData+zlib.m deleted file mode 100644 index cd3394a..0000000 --- a/Firebase/Utilities/NSData+zlib/GULNSData+zlib.m +++ /dev/null @@ -1,207 +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 "GULNSData+zlib.h" - -#import <zlib.h> - -#define kChunkSize 1024 -#define Z_DEFAULT_COMPRESSION (-1) - -NSString *const GULNSDataZlibErrorDomain = @"com.google.GULNSDataZlibErrorDomain"; -NSString *const GULNSDataZlibErrorKey = @"GULNSDataZlibErrorKey"; -NSString *const GULNSDataZlibRemainingBytesKey = @"GULNSDataZlibRemainingBytesKey"; - -@implementation NSData (GULGzip) - -+ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error { - const void *bytes = [data bytes]; - NSUInteger length = [data length]; - if (!bytes || !length) { - return nil; - } - -#if defined(__LP64__) && __LP64__ - // Don't support > 32bit length for 64 bit, see note in header. - if (length > UINT_MAX) { - return nil; - } -#endif - - z_stream strm; - bzero(&strm, sizeof(z_stream)); - - // Setup the input. - strm.avail_in = (unsigned int)length; - strm.next_in = (unsigned char *)bytes; - - int windowBits = 15; // 15 to enable any window size - windowBits += 32; // and +32 to enable zlib or gzip header detection. - - int retCode; - if ((retCode = inflateInit2(&strm, windowBits)) != Z_OK) { - if (error) { - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] - forKey:GULNSDataZlibErrorKey]; - *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain - code:GULNSDataZlibErrorInternal - userInfo:userInfo]; - } - return nil; - } - - // Hint the size at 4x the input size. - NSMutableData *result = [NSMutableData dataWithCapacity:(length * 4)]; - unsigned char output[kChunkSize]; - - // Loop to collect the data. - do { - // Update what we're passing in. - strm.avail_out = kChunkSize; - strm.next_out = output; - retCode = inflate(&strm, Z_NO_FLUSH); - if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { - if (error) { - NSMutableDictionary *userInfo = - [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] - forKey:GULNSDataZlibErrorKey]; - if (strm.msg) { - NSString *message = [NSString stringWithUTF8String:strm.msg]; - if (message) { - [userInfo setObject:message forKey:NSLocalizedDescriptionKey]; - } - } - *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain - code:GULNSDataZlibErrorInternal - userInfo:userInfo]; - } - inflateEnd(&strm); - return nil; - } - // Collect what we got. - unsigned gotBack = kChunkSize - strm.avail_out; - if (gotBack > 0) { - [result appendBytes:output length:gotBack]; - } - - } while (retCode == Z_OK); - - // Make sure there wasn't more data tacked onto the end of a valid compressed stream. - if (strm.avail_in != 0) { - if (error) { - NSDictionary *userInfo = - [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:strm.avail_in] - forKey:GULNSDataZlibRemainingBytesKey]; - *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain - code:GULNSDataZlibErrorDataRemaining - userInfo:userInfo]; - } - result = nil; - } - // The only way out of the loop was by hitting the end of the stream. - NSAssert(retCode == Z_STREAM_END, - @"Thought we finished inflate w/o getting a result of stream end, code %d", retCode); - - // Clean up. - inflateEnd(&strm); - - return result; -} - -+ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error { - const void *bytes = [data bytes]; - NSUInteger length = [data length]; - - int level = Z_DEFAULT_COMPRESSION; - if (!bytes || !length) { - return nil; - } - -#if defined(__LP64__) && __LP64__ - // Don't support > 32bit length for 64 bit, see note in header. - if (length > UINT_MAX) { - if (error) { - *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain - code:GULNSDataZlibErrorGreaterThan32BitsToCompress - userInfo:nil]; - } - return nil; - } -#endif - - z_stream strm; - bzero(&strm, sizeof(z_stream)); - - int memLevel = 8; // Default. - int windowBits = 15 + 16; // Enable gzip header instead of zlib header. - - int retCode; - if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, - Z_DEFAULT_STRATEGY)) != Z_OK) { - if (error) { - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] - forKey:GULNSDataZlibErrorKey]; - *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain - code:GULNSDataZlibErrorInternal - userInfo:userInfo]; - } - return nil; - } - - // Hint the size at 1/4 the input size. - NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)]; - unsigned char output[kChunkSize]; - - // Setup the input. - strm.avail_in = (unsigned int)length; - strm.next_in = (unsigned char *)bytes; - - // Collect the data. - do { - // update what we're passing in - strm.avail_out = kChunkSize; - strm.next_out = output; - retCode = deflate(&strm, Z_FINISH); - if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { - if (error) { - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] - forKey:GULNSDataZlibErrorKey]; - *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain - code:GULNSDataZlibErrorInternal - userInfo:userInfo]; - } - deflateEnd(&strm); - return nil; - } - // Collect what we got. - unsigned gotBack = kChunkSize - strm.avail_out; - if (gotBack > 0) { - [result appendBytes:output length:gotBack]; - } - - } while (retCode == Z_OK); - - // If the loop exits, it used all input and the stream ended. - NSAssert(strm.avail_in == 0, - @"Should have finished deflating without using all input, %u bytes left", strm.avail_in); - NSAssert(retCode == Z_STREAM_END, - @"thought we finished deflate w/o getting a result of stream end, code %d", retCode); - - // Clean up. - deflateEnd(&strm); - - return result; -} - -@end 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 diff --git a/Firebase/Utilities/Reachability/GULReachabilityChecker+Internal.h b/Firebase/Utilities/Reachability/GULReachabilityChecker+Internal.h deleted file mode 100644 index 8883c4d..0000000 --- a/Firebase/Utilities/Reachability/GULReachabilityChecker+Internal.h +++ /dev/null @@ -1,47 +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 <GoogleUtilities/GULReachabilityChecker.h> - -typedef SCNetworkReachabilityRef (*GULReachabilityCreateWithNameFn)(CFAllocatorRef allocator, - const char *host); - -typedef Boolean (*GULReachabilitySetCallbackFn)(SCNetworkReachabilityRef target, - SCNetworkReachabilityCallBack callback, - SCNetworkReachabilityContext *context); -typedef Boolean (*GULReachabilityScheduleWithRunLoopFn)(SCNetworkReachabilityRef target, - CFRunLoopRef runLoop, - CFStringRef runLoopMode); -typedef Boolean (*GULReachabilityUnscheduleFromRunLoopFn)(SCNetworkReachabilityRef target, - CFRunLoopRef runLoop, - CFStringRef runLoopMode); - -typedef void (*GULReachabilityReleaseFn)(CFTypeRef cf); - -struct GULReachabilityApi { - GULReachabilityCreateWithNameFn createWithNameFn; - GULReachabilitySetCallbackFn setCallbackFn; - GULReachabilityScheduleWithRunLoopFn scheduleWithRunLoopFn; - GULReachabilityUnscheduleFromRunLoopFn unscheduleFromRunLoopFn; - GULReachabilityReleaseFn releaseFn; -}; - -@interface GULReachabilityChecker (Internal) - -- (const struct GULReachabilityApi *)reachabilityApi; -- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi; - -@end diff --git a/Firebase/Utilities/Reachability/GULReachabilityChecker.m b/Firebase/Utilities/Reachability/GULReachabilityChecker.m deleted file mode 100644 index 1ddacdf..0000000 --- a/Firebase/Utilities/Reachability/GULReachabilityChecker.m +++ /dev/null @@ -1,240 +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 "GULReachabilityChecker+Internal.h" -#import "Private/GULReachabilityChecker.h" -#import "Private/GULReachabilityMessageCode.h" - -#import <GoogleUtilities/GULLogger.h> -#import <GoogleUtilities/GULReachabilityChecker.h> - -static GULLoggerService kGULLoggerReachability = @"[GULReachability]"; - -static void ReachabilityCallback(SCNetworkReachabilityRef reachability, - SCNetworkReachabilityFlags flags, - void *info); - -static const struct GULReachabilityApi kGULDefaultReachabilityApi = { - SCNetworkReachabilityCreateWithName, - SCNetworkReachabilitySetCallback, - SCNetworkReachabilityScheduleWithRunLoop, - SCNetworkReachabilityUnscheduleFromRunLoop, - CFRelease, -}; - -static NSString *const kGULReachabilityUnknownStatus = @"Unknown"; -static NSString *const kGULReachabilityConnectedStatus = @"Connected"; -static NSString *const kGULReachabilityDisconnectedStatus = @"Disconnected"; - -@interface GULReachabilityChecker () - -@property(nonatomic, assign) const struct GULReachabilityApi *reachabilityApi; -@property(nonatomic, assign) GULReachabilityStatus reachabilityStatus; -@property(nonatomic, copy) NSString *host; -@property(nonatomic, assign) SCNetworkReachabilityRef reachability; - -@end - -@implementation GULReachabilityChecker - -@synthesize reachabilityApi = reachabilityApi_; -@synthesize reachability = reachability_; - -- (const struct GULReachabilityApi *)reachabilityApi { - return reachabilityApi_; -} - -- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi { - if (reachability_) { - GULLogError(kGULLoggerReachability, NO, - [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode000], - @"Cannot change reachability API while reachability is running. " - @"Call stop first."); - return; - } - reachabilityApi_ = reachabilityApi; -} - -@synthesize reachabilityStatus = reachabilityStatus_; -@synthesize host = host_; -@synthesize reachabilityDelegate = reachabilityDelegate_; - -- (BOOL)isActive { - return reachability_ != nil; -} - -- (void)setReachabilityDelegate:(id<GULReachabilityDelegate>)reachabilityDelegate { - if (reachabilityDelegate && - (![(NSObject *)reachabilityDelegate conformsToProtocol:@protocol(GULReachabilityDelegate)])) { - GULLogError(kGULLoggerReachability, NO, - [NSString stringWithFormat:@"I-NET%06ld", (long)kGULReachabilityMessageCode005], - @"Reachability delegate doesn't conform to Reachability protocol."); - return; - } - reachabilityDelegate_ = reachabilityDelegate; -} - -- (instancetype)initWithReachabilityDelegate:(id<GULReachabilityDelegate>)reachabilityDelegate - withHost:(NSString *)host { - self = [super init]; - - if (!host || !host.length) { - GULLogError(kGULLoggerReachability, NO, - [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode001], - @"Invalid host specified"); - return nil; - } - if (self) { - [self setReachabilityDelegate:reachabilityDelegate]; - reachabilityApi_ = &kGULDefaultReachabilityApi; - reachabilityStatus_ = kGULReachabilityUnknown; - host_ = [host copy]; - reachability_ = nil; - } - return self; -} - -- (void)dealloc { - reachabilityDelegate_ = nil; - [self stop]; -} - -- (BOOL)start { - if (!reachability_) { - reachability_ = reachabilityApi_->createWithNameFn(kCFAllocatorDefault, [host_ UTF8String]); - if (!reachability_) { - return NO; - } - SCNetworkReachabilityContext context = { - 0, /* version */ - (__bridge void *)(self), /* info (passed as last parameter to reachability callback) */ - NULL, /* retain */ - NULL, /* release */ - NULL /* copyDescription */ - }; - if (!reachabilityApi_->setCallbackFn(reachability_, ReachabilityCallback, &context) || - !reachabilityApi_->scheduleWithRunLoopFn(reachability_, CFRunLoopGetMain(), - kCFRunLoopCommonModes)) { - reachabilityApi_->releaseFn(reachability_); - reachability_ = nil; - - GULLogError(kGULLoggerReachability, NO, - [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode002], - @"Failed to start reachability handle"); - return NO; - } - } - GULLogDebug(kGULLoggerReachability, NO, - [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode003], - @"Monitoring the network status"); - return YES; -} - -- (void)stop { - if (reachability_) { - reachabilityStatus_ = kGULReachabilityUnknown; - reachabilityApi_->unscheduleFromRunLoopFn(reachability_, CFRunLoopGetMain(), - kCFRunLoopCommonModes); - reachabilityApi_->releaseFn(reachability_); - reachability_ = nil; - } -} - -- (GULReachabilityStatus)statusForFlags:(SCNetworkReachabilityFlags)flags { - GULReachabilityStatus status = kGULReachabilityNotReachable; - // If the Reachable flag is not set, we definitely don't have connectivity. - if (flags & kSCNetworkReachabilityFlagsReachable) { - // Reachable flag is set. Check further flags. - if (!(flags & kSCNetworkReachabilityFlagsConnectionRequired)) { -// Connection required flag is not set, so we have connectivity. -#if TARGET_OS_IOS || TARGET_OS_TV - status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular - : kGULReachabilityViaWifi; -#elif TARGET_OS_OSX - status = kGULReachabilityViaWifi; -#endif - } else if ((flags & (kSCNetworkReachabilityFlagsConnectionOnDemand | - kSCNetworkReachabilityFlagsConnectionOnTraffic)) && - !(flags & kSCNetworkReachabilityFlagsInterventionRequired)) { -// If the connection on demand or connection on traffic flag is set, and user intervention -// is not required, we have connectivity. -#if TARGET_OS_IOS || TARGET_OS_TV - status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular - : kGULReachabilityViaWifi; -#elif TARGET_OS_OSX - status = kGULReachabilityViaWifi; -#endif - } - } - return status; -} - -- (void)reachabilityFlagsChanged:(SCNetworkReachabilityFlags)flags { - GULReachabilityStatus status = [self statusForFlags:flags]; - if (reachabilityStatus_ != status) { - NSString *reachabilityStatusString; - if (status == kGULReachabilityUnknown) { - reachabilityStatusString = kGULReachabilityUnknownStatus; - } else { - reachabilityStatusString = (status == kGULReachabilityNotReachable) - ? kGULReachabilityDisconnectedStatus - : kGULReachabilityConnectedStatus; - } - - GULLogDebug(kGULLoggerReachability, NO, - [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode004], - @"Network status has changed. Code:%@, status:%@", @(status), - reachabilityStatusString); - reachabilityStatus_ = status; - [reachabilityDelegate_ reachability:self statusChanged:reachabilityStatus_]; - } -} - -@end - -static void ReachabilityCallback(SCNetworkReachabilityRef reachability, - SCNetworkReachabilityFlags flags, - void *info) { - GULReachabilityChecker *checker = (__bridge GULReachabilityChecker *)info; - [checker reachabilityFlagsChanged:flags]; -} - -// This function used to be at the top of the file, but it was moved here -// as a workaround for a suspected compiler bug. When compiled in Release mode -// and run on an iOS device with WiFi disabled, the reachability code crashed -// when calling SCNetworkReachabilityScheduleWithRunLoop, or shortly thereafter. -// After unsuccessfully trying to diagnose the cause of the crash, it was -// discovered that moving this function to the end of the file magically fixed -// the crash. If you are going to edit this file, exercise caution and make sure -// to test thoroughly with an iOS device under various network conditions. -const NSString *GULReachabilityStatusString(GULReachabilityStatus status) { - switch (status) { - case kGULReachabilityUnknown: - return @"Reachability Unknown"; - - case kGULReachabilityNotReachable: - return @"Not reachable"; - - case kGULReachabilityViaWifi: - return @"Reachable via Wifi"; - - case kGULReachabilityViaCellular: - return @"Reachable via Cellular Data"; - - default: - return [NSString stringWithFormat:@"Invalid reachability status %d", (int)status]; - } -} diff --git a/Firebase/Utilities/Reachability/Private/GULReachabilityChecker.h b/Firebase/Utilities/Reachability/Private/GULReachabilityChecker.h deleted file mode 100644 index b317a0b..0000000 --- a/Firebase/Utilities/Reachability/Private/GULReachabilityChecker.h +++ /dev/null @@ -1,77 +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 <SystemConfiguration/SystemConfiguration.h> - -/// Reachability Status -typedef enum { - kGULReachabilityUnknown, ///< Have not yet checked or been notified whether host is reachable. - kGULReachabilityNotReachable, ///< Host is not reachable. - kGULReachabilityViaWifi, ///< Host is reachable via Wifi. - kGULReachabilityViaCellular, ///< Host is reachable via cellular. -} GULReachabilityStatus; - -const NSString *GULReachabilityStatusString(GULReachabilityStatus status); - -@class GULReachabilityChecker; - -/// Google Analytics iOS Reachability Checker. -@protocol GULReachabilityDelegate -@required -/// Called when network status has changed. -- (void)reachability:(GULReachabilityChecker *)reachability - statusChanged:(GULReachabilityStatus)status; -@end - -/// Google Analytics iOS Network Status Checker. -@interface GULReachabilityChecker : NSObject - -/// The last known reachability status, or GULReachabilityStatusUnknown if the -/// checker is not active. -@property(nonatomic, readonly) GULReachabilityStatus reachabilityStatus; -/// The host to which reachability status is to be checked. -@property(nonatomic, copy, readonly) NSString *host; -/// The delegate to be notified of reachability status changes. -@property(nonatomic, weak) id<GULReachabilityDelegate> reachabilityDelegate; -/// `YES` if the reachability checker is active, `NO` otherwise. -@property(nonatomic, readonly) BOOL isActive; - -/// Initialize the reachability checker. Note that you must call start to begin checking for and -/// receiving notifications about network status changes. -/// -/// @param reachabilityDelegate The delegate to be notified when reachability status to host -/// changes. -/// -/// @param host The name of the host. -/// -- (instancetype)initWithReachabilityDelegate:(id<GULReachabilityDelegate>)reachabilityDelegate - withHost:(NSString *)host; - -- (instancetype)init NS_UNAVAILABLE; - -/// Start checking for reachability to the specified host. This has no effect if the status -/// checker is already checking for connectivity. -/// -/// @return `YES` if initiating status checking was successful or the status checking has already -/// been initiated, `NO` otherwise. -- (BOOL)start; - -/// Stop checking for reachability to the specified host. This has no effect if the status -/// checker is not checking for connectivity. -- (void)stop; - -@end diff --git a/Firebase/Utilities/Reachability/Private/GULReachabilityMessageCode.h b/Firebase/Utilities/Reachability/Private/GULReachabilityMessageCode.h deleted file mode 100644 index 283cdd5..0000000 --- a/Firebase/Utilities/Reachability/Private/GULReachabilityMessageCode.h +++ /dev/null @@ -1,27 +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, GULReachabilityMessageCode) { - // GULReachabilityChecker.m - kGULReachabilityMessageCode000 = 902000, // I-NET902000 - kGULReachabilityMessageCode001 = 902001, // I-NET902001 - kGULReachabilityMessageCode002 = 902002, // I-NET902002 - kGULReachabilityMessageCode003 = 902003, // I-NET902003 - kGULReachabilityMessageCode004 = 902004, // I-NET902004 - kGULReachabilityMessageCode005 = 902005, // I-NET902005 - kGULReachabilityMessageCode006 = 902006, // I-NET902006 -}; |